From b7449926afc432410250f29da55cb8b66758fd66 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Sun, 23 Sep 2018 10:36:11 -0700 Subject: [PATCH] New upstream version 1.30.0~beta.7+dfsg1 --- CONTRIBUTING.md | 8 +- COPYRIGHT | 4 +- README.md | 6 +- RELEASES.md | 8 +- config.toml.example | 26 +- git-commit-hash | 2 +- src/Cargo.lock | 1454 +++--- src/bootstrap/Cargo.toml | 8 +- src/bootstrap/README.md | 18 +- src/bootstrap/bin/rustc.rs | 13 +- src/bootstrap/bin/rustdoc.rs | 2 + src/bootstrap/bootstrap.py | 9 +- src/bootstrap/builder.rs | 87 +- src/bootstrap/cc_detect.rs | 4 +- src/bootstrap/channel.rs | 2 +- src/bootstrap/check.rs | 40 +- src/bootstrap/compile.rs | 117 +- src/bootstrap/config.rs | 17 +- src/bootstrap/configure.py | 3 +- src/bootstrap/dist.rs | 179 +- src/bootstrap/doc.rs | 14 +- src/bootstrap/flags.rs | 16 +- src/bootstrap/job.rs | 2 +- src/bootstrap/lib.rs | 91 +- src/bootstrap/native.rs | 57 +- src/bootstrap/sanity.rs | 4 +- src/bootstrap/test.rs | 20 +- src/bootstrap/tool.rs | 60 +- src/bootstrap/util.rs | 2 +- .../dist-armebv7r-none-eabihf/Dockerfile | 36 - src/ci/docker/dist-various-1/Dockerfile | 11 +- src/ci/docker/dist-x86_64-linux/Dockerfile | 5 +- .../docker/dist-x86_64-linux/build-clang.sh | 6 + src/ci/docker/run.sh | 4 - src/ci/docker/scripts/musl.sh | 2 +- src/ci/docker/x86_64-gnu-tools/checktools.sh | 10 +- src/ci/run.sh | 3 +- .../2018-edition/src/appendix-01-keywords.md | 53 +- .../src/appendix-03-derivable-traits.md | 4 +- .../src/ch03-01-variables-and-mutability.md | 3 +- .../2018-edition/src/ch03-02-data-types.md | 2 +- .../2018-edition/src/ch08-03-hash-maps.md | 4 +- .../ch09-02-recoverable-errors-with-result.md | 5 +- .../src/ch09-03-to-panic-or-not-to-panic.md | 27 +- .../book/2018-edition/src/ch10-02-traits.md | 10 +- .../2018-edition/src/ch11-01-writing-tests.md | 12 +- .../src/ch12-02-reading-a-file.md | 13 +- ...improving-error-handling-and-modularity.md | 22 +- .../book/2018-edition/src/ch15-02-deref.md | 4 +- .../src/ch17-03-oo-design-patterns.md | 3 + .../2018-edition/src/ch19-01-unsafe-rust.md | 10 +- .../src/ch19-03-advanced-traits.md | 2 +- .../2018-edition/src/ch20-02-multithreaded.md | 9 +- src/doc/book/2018-edition/src/foreword.md | 2 +- src/doc/book/README.md | 4 +- .../src/ch17-02-trait-objects.md | 16 +- .../second-edition/src/ch19-01-unsafe-rust.md | 2 +- src/doc/index.md | 9 +- src/doc/man/rustdoc.1 | 2 +- src/doc/nomicon/src/SUMMARY.md | 2 + src/doc/nomicon/src/beneath-std.md | 10 + src/doc/nomicon/src/destructors.md | 6 +- src/doc/nomicon/src/ffi.md | 21 +- src/doc/nomicon/src/panic-handler.md | 83 + src/doc/nomicon/src/vec-final.md | 77 +- src/doc/nomicon/src/vec-layout.md | 2 +- src/doc/nomicon/src/what-unsafe-does.md | 1 + src/doc/reference/src/SUMMARY.md | 2 + src/doc/reference/src/attributes.md | 219 +- .../src/behavior-considered-undefined.md | 11 + .../reference/src/conditional-compilation.md | 102 + .../reference/src/crates-and-source-files.md | 10 +- src/doc/reference/src/expressions.md | 2 +- .../reference/src/expressions/block-expr.md | 105 +- .../reference/src/expressions/match-expr.md | 44 +- .../src/expressions/method-call-expr.md | 1 + src/doc/reference/src/identifiers.md | 11 +- src/doc/reference/src/introduction.md | 131 +- .../reference/src/items/associated-items.md | 1 + src/doc/reference/src/items/enumerations.md | 3 + src/doc/reference/src/items/functions.md | 22 +- .../reference/src/items/implementations.md | 61 +- src/doc/reference/src/items/static-items.md | 2 +- src/doc/reference/src/items/traits.md | 4 +- src/doc/reference/src/keywords.md | 2 +- src/doc/reference/src/linkage.md | 31 +- src/doc/reference/src/macros-by-example.md | 2 + src/doc/reference/src/memory-model.md | 11 +- src/doc/reference/src/procedural-macros.md | 297 +- src/doc/reference/src/statements.md | 2 +- src/doc/reference/src/tokens.md | 124 +- src/doc/reference/src/type-layout.md | 20 +- src/doc/reference/src/types.md | 33 +- src/doc/reference/src/undocumented.md | 9 +- src/doc/reference/src/unsafety.md | 4 +- src/doc/rust-by-example/src/SUMMARY.md | 7 +- src/doc/rust-by-example/src/compatibility.md | 7 + .../src/compatibility/raw_identifiers.md | 42 + .../src/custom_types/constants.md | 14 +- .../src/flow_control/match/binding.md | 2 +- src/doc/rust-by-example/src/hello/print.md | 2 +- src/doc/rust-by-example/src/index.md | 6 +- .../rust-by-example/src/macros/designators.md | 1 + src/doc/rust-by-example/src/mod/use.md | 22 +- .../rust-by-example/src/primitives/array.md | 2 +- .../rust-by-example/src/std_misc/channels.md | 12 +- src/doc/rustc/src/codegen-options/index.md | 2 +- src/doc/rustc/src/lints/index.md | 2 +- src/doc/rustc/src/lints/levels.md | 15 +- .../src/lints/listing/deny-by-default.md | 4 +- .../src/lints/listing/warn-by-default.md | 4 +- src/doc/rustdoc/src/command-line-arguments.md | 14 + src/doc/rustdoc/src/unstable-features.md | 36 +- .../src/language-features/attr-literals.md | 30 - .../src/language-features/catch-expr.md | 30 - .../src/language-features/crate-in-paths.md | 54 - .../custom-test-frameworks.md | 33 + .../src/language-features/doc-cfg.md | 8 +- .../extern-absolute-paths.md | 43 - .../infer-outlives-requirements.md | 67 - .../infer-static-outlives-requirements.md | 4 +- .../language-features/macro-vis-matcher.md | 14 - .../src/language-features/on-unimplemented.md | 97 +- .../src/language-features/plugin.md | 1 - .../src/language-features/self-in-typedefs.md | 24 + .../src/language-features/self-struct-ctor.md | 33 + .../src/language-features/tool-attributes.md | 26 - .../src/language-features/try-blocks.md | 32 + .../src/language-features/unsized-locals.md | 180 + .../src/language-features/used.md | 157 - .../future-atomic-orderings.md | 5 - .../library-features/io-error-internals.md | 5 - src/etc/debugger_pretty_printers_common.py | 76 + src/etc/gdb_rust_pretty_printing.py | 81 + src/etc/rust-gdb | 2 +- src/etc/rust-gdbgui | 65 + src/etc/rust-lldb | 45 +- src/etc/test-float-parse/many-digits.rs | 2 - src/etc/test-float-parse/rand-f64.rs | 2 - src/liballoc/Cargo.toml | 7 +- src/liballoc/alloc.rs | 33 +- src/liballoc/benches/lib.rs | 1 - src/liballoc/benches/vec_deque_append.rs | 48 + src/liballoc/borrow.rs | 35 + src/liballoc/boxed.rs | 255 +- src/liballoc/collections/btree/node.rs | 48 +- src/liballoc/collections/linked_list.rs | 2 +- src/liballoc/collections/vec_deque.rs | 127 +- src/liballoc/lib.rs | 24 +- src/liballoc/pin.rs | 302 ++ src/liballoc/raw_vec.rs | 6 +- src/liballoc/rc.rs | 35 +- src/liballoc/slice.rs | 24 +- src/liballoc/str.rs | 15 +- src/liballoc/string.rs | 30 +- src/liballoc/sync.rs | 24 +- src/liballoc/task.rs | 15 +- src/liballoc/tests/lib.rs | 7 +- src/liballoc/tests/slice.rs | 5 +- src/liballoc/tests/str.rs | 68 +- src/liballoc/tests/vec_deque.rs | 101 + src/liballoc/vec.rs | 63 +- src/liballoc_jemalloc/build.rs | 9 +- src/liballoc_jemalloc/lib.rs | 9 +- src/liballoc_system/lib.rs | 16 +- src/libarena/lib.rs | 5 +- src/libcompiler_builtins/Cargo.toml | 2 +- src/libcompiler_builtins/README.md | 6 +- .../compiler-rt/CMakeLists.txt | 41 +- .../compiler-rt/lib/builtins/CMakeLists.txt | 10 + .../lib/builtins/Darwin-excludes/10.4.txt | 137 - .../compiler-rt/lib/builtins/arm/chkstk.S | 34 + .../compiler-rt/lib/cfi/cfi.cc | 6 +- .../compiler-rt/lib/cfi/cfi_blacklist.txt | 6 +- .../compiler-rt/lib/safestack/CMakeLists.txt | 27 +- .../compiler-rt/lib/safestack/safestack.cc | 90 +- .../ubsan_minimal/ubsan_minimal_handlers.cc | 1 + .../crates/panic-handler/Cargo.toml | 6 + .../crates/panic-handler/src/lib.rs | 11 + .../crates/panic-implementation/Cargo.toml | 6 - .../crates/panic-implementation/src/lib.rs | 11 - .../examples/intrinsics.rs | 6 +- src/libcompiler_builtins/src/arm_linux.rs | 6 +- src/libcompiler_builtins/src/float/conv.rs | 19 +- src/libcompiler_builtins/src/lib.rs | 3 + src/libcompiler_builtins/src/riscv32.rs | 18 + src/libcore/Cargo.toml | 2 +- src/libcore/alloc.rs | 16 +- src/libcore/benches/any.rs | 2 +- src/libcore/cell.rs | 6 +- src/libcore/char/decode.rs | 127 - src/libcore/char/methods.rs | 28 +- src/libcore/char/mod.rs | 9 +- src/libcore/cmp.rs | 87 +- src/libcore/convert.rs | 60 + src/libcore/ffi.rs | 42 + src/libcore/fmt/mod.rs | 68 +- src/libcore/future/future.rs | 2 +- src/libcore/future/future_obj.rs | 9 +- src/libcore/intrinsics.rs | 4 +- src/libcore/iter/iterator.rs | 25 +- src/libcore/iter/mod.rs | 12 +- src/libcore/iter/range.rs | 12 +- src/libcore/lib.rs | 17 +- src/libcore/macros.rs | 30 +- src/libcore/manually_drop_stage0.rs | 195 - src/libcore/marker.rs | 37 +- src/libcore/mem.rs | 249 +- src/libcore/nonzero.rs | 3 +- src/libcore/num/dec2flt/parse.rs | 2 +- src/libcore/num/dec2flt/rawfp.rs | 6 +- src/libcore/num/diy_float.rs | 4 +- src/libcore/num/flt2dec/decoder.rs | 4 +- src/libcore/num/flt2dec/mod.rs | 36 +- src/libcore/num/flt2dec/strategy/grisu.rs | 2 +- src/libcore/num/mod.rs | 1281 +++-- src/libcore/ops/function.rs | 15 + src/libcore/ops/unsize.rs | 2 +- src/libcore/option.rs | 46 +- src/libcore/pin.rs | 160 + src/libcore/ptr.rs | 162 +- src/libcore/result.rs | 86 +- src/libcore/slice/memchr.rs | 30 +- src/libcore/slice/mod.rs | 481 +- src/libcore/slice/rotate.rs | 14 +- src/libcore/slice/sort.rs | 6 +- src/libcore/str/lossy.rs | 2 +- src/libcore/str/mod.rs | 226 +- src/libcore/sync/atomic.rs | 458 +- src/libcore/task/context.rs | 44 +- src/libcore/task/executor.rs | 96 - src/libcore/task/mod.rs | 6 +- src/libcore/task/spawn.rs | 93 + src/libcore/task/wake.rs | 8 +- src/libcore/tests/char.rs | 54 +- src/libcore/tests/lib.rs | 8 +- src/libcore/tests/manually_drop.rs | 5 + src/libcore/tests/num/flt2dec/random.rs | 16 +- src/libcore/tests/option.rs | 17 + src/libcore/tests/result.rs | 93 + src/libcore/tests/slice.rs | 144 +- src/libcore/time.rs | 8 +- src/libcore/unicode/tables.rs | 72 +- src/libcore/unicode/unicode.py | 2 +- src/libfmt_macros/lib.rs | 16 +- src/libgraphviz/lib.rs | 12 +- src/liblibc/.travis.yml | 22 +- src/liblibc/Cargo.lock | 126 +- src/liblibc/Cargo.toml | 3 +- src/liblibc/README.md | 14 +- .../aarch64-unknown-linux-musl/Dockerfile | 12 +- .../arm-unknown-linux-musleabihf/Dockerfile | 12 +- .../docker/i686-unknown-linux-musl/Dockerfile | 13 +- .../sparc64-unknown-linux-gnu/Dockerfile | 5 +- .../x86_64-unknown-linux-musl/Dockerfile | 12 +- .../ci/ios/deploy_and_run_on_ios_simulator.rs | 1 + src/liblibc/ci/run.sh | 12 +- src/liblibc/libc-test/Cargo.toml | 3 +- src/liblibc/libc-test/build.rs | 85 +- src/liblibc/src/fuchsia/aarch64.rs | 4 +- src/liblibc/src/fuchsia/mod.rs | 159 +- src/liblibc/src/fuchsia/powerpc64.rs | 79 - src/liblibc/src/lib.rs | 8 +- src/liblibc/src/macros.rs | 21 +- src/liblibc/src/redox/net.rs | 2 + src/liblibc/src/switch.rs | 48 + src/liblibc/src/unix/bsd/apple/b32.rs | 6 + src/liblibc/src/unix/bsd/apple/b64.rs | 6 +- src/liblibc/src/unix/bsd/apple/mod.rs | 23 +- .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 24 + .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 28 + src/liblibc/src/unix/bsd/mod.rs | 1 + src/liblibc/src/unix/bsd/netbsdlike/mod.rs | 13 - .../src/unix/bsd/netbsdlike/netbsd/aarch64.rs | 3 + .../src/unix/bsd/netbsdlike/netbsd/arm.rs | 3 + .../src/unix/bsd/netbsdlike/netbsd/mod.rs | 43 +- .../bsd/netbsdlike/netbsd/other/b32/mod.rs | 2 - .../bsd/netbsdlike/netbsd/other/b64/mod.rs | 2 - .../unix/bsd/netbsdlike/netbsd/other/mod.rs | 14 - .../src/unix/bsd/netbsdlike/netbsd/powerpc.rs | 3 + .../src/unix/bsd/netbsdlike/netbsd/sparc64.rs | 3 + .../src/unix/bsd/netbsdlike/netbsd/x86.rs | 3 + .../src/unix/bsd/netbsdlike/netbsd/x86_64.rs | 3 + .../unix/bsd/netbsdlike/openbsdlike/mod.rs | 12 +- .../bsd/netbsdlike/openbsdlike/openbsd/mod.rs | 204 +- src/liblibc/src/unix/hermit/aarch64.rs | 2 + src/liblibc/src/unix/hermit/mod.rs | 736 +++ src/liblibc/src/unix/hermit/x86_64.rs | 2 + src/liblibc/src/unix/mod.rs | 15 +- src/liblibc/src/unix/newlib/mod.rs | 95 +- src/liblibc/src/unix/notbsd/android/mod.rs | 7 + src/liblibc/src/unix/notbsd/emscripten.rs | 39 +- .../src/unix/notbsd/linux/mips/mips32.rs | 106 +- .../src/unix/notbsd/linux/mips/mips64.rs | 106 +- src/liblibc/src/unix/notbsd/linux/mips/mod.rs | 5 + src/liblibc/src/unix/notbsd/linux/mod.rs | 170 +- .../src/unix/notbsd/linux/musl/b32/arm.rs | 85 + .../src/unix/notbsd/linux/musl/b32/mips.rs | 85 + .../src/unix/notbsd/linux/musl/b32/mod.rs | 88 +- .../src/unix/notbsd/linux/musl/b32/powerpc.rs | 866 ++++ .../src/unix/notbsd/linux/musl/b32/x86.rs | 85 + src/liblibc/src/unix/notbsd/linux/musl/mod.rs | 3 +- .../src/unix/notbsd/linux/other/b32/mod.rs | 106 +- .../unix/notbsd/linux/other/b64/aarch64.rs | 55 +- .../unix/notbsd/linux/other/b64/not_x32.rs | 106 +- .../unix/notbsd/linux/other/b64/powerpc64.rs | 106 +- .../unix/notbsd/linux/other/b64/sparc64.rs | 49 +- .../src/unix/notbsd/linux/other/b64/x32.rs | 49 +- .../src/unix/notbsd/linux/other/mod.rs | 5 + src/liblibc/src/unix/notbsd/linux/s390x.rs | 54 +- src/liblibc/src/unix/solaris/mod.rs | 4 + src/liblibc/src/unix/uclibc/mips/mips32.rs | 5 + src/liblibc/src/unix/uclibc/mips/mips64.rs | 5 + src/liblibc/src/unix/uclibc/mod.rs | 95 +- src/liblibc/src/unix/uclibc/x86_64/mod.rs | 78 +- src/libpanic_abort/lib.rs | 5 +- src/libpanic_unwind/{wasm32.rs => dummy.rs} | 0 src/libpanic_unwind/dwarf/mod.rs | 2 +- src/libpanic_unwind/lib.rs | 57 +- src/libpanic_unwind/macros.rs | 45 + src/libpanic_unwind/seh.rs | 8 +- src/libpanic_unwind/seh64_gnu.rs | 2 +- src/libpanic_unwind/windows.rs | 2 +- src/libproc_macro/diagnostic.rs | 133 +- src/libproc_macro/lib.rs | 84 +- src/libproc_macro/rustc.rs | 5 +- src/libprofiler_builtins/lib.rs | 1 + src/librustc/Cargo.toml | 6 +- src/librustc/cfg/construct.rs | 24 +- src/librustc/dep_graph/dep_node.rs | 8 +- src/librustc/dep_graph/graph.rs | 18 +- src/librustc/dep_graph/serialized.rs | 4 +- src/librustc/diagnostics.rs | 115 +- src/librustc/hir/check_attr.rs | 4 +- src/librustc/hir/def.rs | 44 +- src/librustc/hir/def_id.rs | 111 +- src/librustc/hir/intravisit.rs | 55 +- src/librustc/hir/lowering.rs | 186 +- src/librustc/hir/map/blocks.rs | 46 +- src/librustc/hir/map/collector.rs | 129 +- src/librustc/hir/map/def_collector.rs | 66 +- src/librustc/hir/map/definitions.rs | 25 +- src/librustc/hir/map/hir_id_validator.rs | 4 +- src/librustc/hir/map/mod.rs | 634 +-- src/librustc/hir/mod.rs | 159 +- src/librustc/hir/print.rs | 105 +- src/librustc/ich/caching_codemap_view.rs | 28 +- src/librustc/ich/hcx.rs | 59 +- src/librustc/ich/impls_hir.rs | 39 +- src/librustc/ich/impls_mir.rs | 17 +- src/librustc/ich/impls_syntax.rs | 34 +- src/librustc/ich/impls_ty.rs | 131 +- src/librustc/ich/mod.rs | 7 +- src/librustc/infer/anon_types/mod.rs | 861 ---- src/librustc/infer/canonical/canonicalizer.rs | 72 +- src/librustc/infer/canonical/mod.rs | 42 +- src/librustc/infer/canonical/query_result.rs | 21 +- src/librustc/infer/canonical/substitute.rs | 2 +- src/librustc/infer/combine.rs | 26 +- src/librustc/infer/equate.rs | 6 +- src/librustc/infer/error_reporting/mod.rs | 137 +- .../infer/error_reporting/need_type_info.rs | 8 +- .../nice_region_error/find_anon_type.rs | 8 +- .../error_reporting/nice_region_error/mod.rs | 8 +- .../nice_region_error/named_anon_conflict.rs | 12 +- .../nice_region_error/outlives_closure.rs | 4 +- .../nice_region_error/static_impl_trait.rs | 2 +- .../error_reporting/nice_region_error/util.rs | 18 +- src/librustc/infer/freshen.rs | 62 +- src/librustc/infer/fudge.rs | 2 +- src/librustc/infer/higher_ranked/mod.rs | 2 +- src/librustc/infer/lattice.rs | 4 +- src/librustc/infer/mod.rs | 759 +-- src/librustc/infer/opaque_types/mod.rs | 865 ++++ src/librustc/infer/outlives/obligations.rs | 16 +- src/librustc/infer/region_constraints/mod.rs | 2 +- src/librustc/infer/resolve.rs | 10 +- src/librustc/infer/sub.rs | 8 +- src/librustc/infer/type_variable.rs | 2 +- src/librustc/infer/unify_key.rs | 4 +- src/librustc/lib.rs | 26 +- src/librustc/lint/builtin.rs | 31 +- src/librustc/lint/context.rs | 165 +- src/librustc/lint/levels.rs | 87 +- src/librustc/lint/mod.rs | 62 +- src/librustc/macros.rs | 6 +- src/librustc/middle/cstore.rs | 141 +- src/librustc/middle/dead.rs | 50 +- src/librustc/middle/dependency_format.rs | 20 +- src/librustc/middle/entry.rs | 9 +- src/librustc/middle/expr_use_visitor.rs | 30 +- src/librustc/middle/intrinsicck.rs | 4 +- src/librustc/middle/lang_items.rs | 8 +- src/librustc/middle/lib_features.rs | 157 + src/librustc/middle/liveness.rs | 13 +- src/librustc/middle/mem_categorization.rs | 32 +- src/librustc/middle/privacy.rs | 4 +- src/librustc/middle/reachable.rs | 81 +- src/librustc/middle/region.rs | 198 +- src/librustc/middle/resolve_lifetime.rs | 61 +- src/librustc/middle/stability.rs | 128 +- src/librustc/middle/weak_lang_items.rs | 19 +- src/librustc/mir/cache.rs | 7 +- src/librustc/mir/interpret/error.rs | 71 +- src/librustc/mir/interpret/mod.rs | 116 +- src/librustc/mir/interpret/value.rs | 473 +- src/librustc/mir/mod.rs | 356 +- src/librustc/mir/mono.rs | 114 +- src/librustc/mir/tcx.rs | 24 +- src/librustc/mir/traversal.rs | 12 +- src/librustc/mir/visit.rs | 46 +- src/librustc/session/code_stats.rs | 15 +- src/librustc/session/config.rs | 400 +- src/librustc/session/filesearch.rs | 8 +- src/librustc/session/mod.rs | 204 +- src/librustc/traits/auto_trait.rs | 122 +- src/librustc/traits/coherence.rs | 58 +- src/librustc/traits/error_reporting.rs | 167 +- src/librustc/traits/fulfill.rs | 7 +- src/librustc/traits/mod.rs | 14 +- src/librustc/traits/object_safety.rs | 4 +- src/librustc/traits/on_unimplemented.rs | 44 +- src/librustc/traits/project.rs | 28 +- src/librustc/traits/query/dropck_outlives.rs | 66 +- .../traits/query/evaluate_obligation.rs | 2 +- src/librustc/traits/query/normalize.rs | 29 +- src/librustc/traits/query/outlives_bounds.rs | 6 +- src/librustc/traits/query/type_op/custom.rs | 12 +- .../query/type_op/implied_outlives_bounds.rs | 80 + src/librustc/traits/query/type_op/mod.rs | 3 +- .../traits/query/type_op/prove_predicate.rs | 18 +- src/librustc/traits/select.rs | 231 +- src/librustc/traits/specialize/mod.rs | 6 +- .../traits/specialize/specialization_graph.rs | 24 +- src/librustc/traits/structural_impls.rs | 13 +- src/librustc/traits/util.rs | 4 + src/librustc/ty/_match.rs | 12 +- src/librustc/ty/cast.rs | 22 +- src/librustc/ty/codec.rs | 16 +- src/librustc/ty/context.rs | 429 +- src/librustc/ty/error.rs | 73 +- src/librustc/ty/fast_reject.rs | 52 +- src/librustc/ty/flags.rs | 58 +- src/librustc/ty/fold.rs | 2 +- .../ty/inhabitedness/def_id_forest.rs | 12 +- src/librustc/ty/inhabitedness/mod.rs | 14 +- src/librustc/ty/instance.rs | 4 +- src/librustc/ty/item_path.rs | 70 +- src/librustc/ty/layout.rs | 182 +- src/librustc/ty/mod.rs | 257 +- src/librustc/ty/outlives.rs | 50 +- src/librustc/ty/query/config.rs | 32 +- src/librustc/ty/query/job.rs | 13 +- src/librustc/ty/query/mod.rs | 32 +- src/librustc/ty/query/on_disk_cache.rs | 71 +- src/librustc/ty/query/plumbing.rs | 54 +- src/librustc/ty/relate.rs | 70 +- src/librustc/ty/steal.rs | 4 +- src/librustc/ty/structural_impls.rs | 109 +- src/librustc/ty/sty.rs | 355 +- src/librustc/ty/subst.rs | 70 +- src/librustc/ty/trait_def.rs | 65 +- src/librustc/ty/util.rs | 92 +- src/librustc/ty/walk.rs | 39 +- src/librustc/ty/wf.rs | 56 +- src/librustc/util/bug.rs | 51 + src/librustc/util/common.rs | 19 +- src/librustc/util/fs.rs | 111 - src/librustc/util/ppaux.rs | 109 +- src/librustc/util/profiling.rs | 248 + src/librustc/util/time_graph.rs | 6 +- src/librustc_allocator/Cargo.toml | 2 + src/librustc_allocator/expand.rs | 31 +- src/librustc_allocator/lib.rs | 4 + src/librustc_apfloat/ieee.rs | 97 +- src/librustc_apfloat/lib.rs | 1 + src/librustc_asan/lib.rs | 1 + src/librustc_borrowck/borrowck/check_loans.rs | 24 +- .../borrowck/gather_loans/gather_moves.rs | 18 +- .../borrowck/gather_loans/lifetime.rs | 3 +- .../borrowck/gather_loans/mod.rs | 24 +- .../borrowck/gather_loans/move_error.rs | 15 +- .../borrowck/gather_loans/restrictions.rs | 2 +- src/librustc_borrowck/borrowck/mod.rs | 91 +- src/librustc_borrowck/borrowck/move_data.rs | 43 +- src/librustc_borrowck/borrowck/unused.rs | 13 +- .../middle => librustc_borrowck}/dataflow.rs | 38 +- src/librustc_borrowck/graphviz.rs | 4 +- src/librustc_borrowck/lib.rs | 4 +- src/librustc_codegen_llvm/Cargo.toml | 28 +- src/librustc_codegen_llvm/abi.rs | 127 +- src/librustc_codegen_llvm/allocator.rs | 14 +- src/librustc_codegen_llvm/asm.rs | 13 +- src/librustc_codegen_llvm/attributes.rs | 112 +- src/librustc_codegen_llvm/back/archive.rs | 26 +- src/librustc_codegen_llvm/back/link.rs | 190 +- src/librustc_codegen_llvm/back/linker.rs | 32 +- src/librustc_codegen_llvm/back/lto.rs | 587 ++- src/librustc_codegen_llvm/back/rpath.rs | 4 +- .../back/symbol_export.rs | 32 +- src/librustc_codegen_llvm/back/write.rs | 993 ++-- src/librustc_codegen_llvm/base.rs | 577 +-- src/librustc_codegen_llvm/builder.rs | 732 +-- src/librustc_codegen_llvm/callee.rs | 27 +- src/librustc_codegen_llvm/common.rs | 142 +- src/librustc_codegen_llvm/consts.rs | 96 +- src/librustc_codegen_llvm/context.rs | 215 +- .../debuginfo/create_scope_map.rs | 40 +- src/librustc_codegen_llvm/debuginfo/gdb.rs | 18 +- .../debuginfo/metadata.rs | 584 ++- src/librustc_codegen_llvm/debuginfo/mod.rs | 154 +- .../debuginfo/namespace.rs | 9 +- .../debuginfo/source_loc.rs | 28 +- .../debuginfo/type_names.rs | 50 +- src/librustc_codegen_llvm/debuginfo/utils.rs | 16 +- src/librustc_codegen_llvm/declare.rs | 91 +- src/librustc_codegen_llvm/glue.rs | 21 +- src/librustc_codegen_llvm/intrinsic.rs | 305 +- src/librustc_codegen_llvm/lib.rs | 100 +- src/librustc_codegen_llvm/llvm/archive_ro.rs | 131 + .../llvm}/diagnostic.rs | 80 +- src/librustc_codegen_llvm/llvm/ffi.rs | 1651 ++++++ src/librustc_codegen_llvm/llvm/mod.rs | 282 ++ src/librustc_codegen_llvm/llvm_util.rs | 31 +- src/librustc_codegen_llvm/metadata.rs | 10 +- src/librustc_codegen_llvm/meth.rs | 26 +- src/librustc_codegen_llvm/mir/analyze.rs | 22 +- src/librustc_codegen_llvm/mir/block.rs | 126 +- src/librustc_codegen_llvm/mir/constant.rs | 65 +- src/librustc_codegen_llvm/mir/mod.rs | 168 +- src/librustc_codegen_llvm/mir/operand.rs | 154 +- src/librustc_codegen_llvm/mir/place.rs | 138 +- src/librustc_codegen_llvm/mir/rvalue.rs | 217 +- src/librustc_codegen_llvm/mir/statement.rs | 15 +- src/librustc_codegen_llvm/mono_item.rs | 5 +- src/librustc_codegen_llvm/type_.rs | 238 +- src/librustc_codegen_llvm/type_of.rs | 88 +- src/librustc_codegen_llvm/value.rs | 21 +- src/librustc_codegen_utils/Cargo.toml | 1 + src/librustc_codegen_utils/codegen_backend.rs | 19 +- src/librustc_codegen_utils/lib.rs | 2 + src/librustc_codegen_utils/link.rs | 41 +- src/librustc_codegen_utils/symbol_names.rs | 23 +- src/librustc_cratesio_shim/Cargo.toml | 1 + src/librustc_cratesio_shim/src/lib.rs | 3 + src/librustc_data_structures/Cargo.toml | 3 +- .../accumulate_vec.rs | 242 - src/librustc_data_structures/array_vec.rs | 6 +- src/librustc_data_structures/base_n.rs | 5 +- src/librustc_data_structures/bitslice.rs | 145 - src/librustc_data_structures/bitvec.rs | 417 +- src/librustc_data_structures/const_cstr.rs | 42 + .../fingerprint.rs | 11 +- src/librustc_data_structures/flock.rs | 590 +-- .../graph/dominators/mod.rs | 7 +- .../graph/implementation/mod.rs | 16 +- src/librustc_data_structures/graph/test.rs | 18 +- src/librustc_data_structures/indexed_set.rs | 466 +- src/librustc_data_structures/indexed_vec.rs | 217 +- src/librustc_data_structures/lib.rs | 19 +- .../obligation_forest/mod.rs | 2 +- src/librustc_data_structures/small_c_str.rs | 122 + src/librustc_data_structures/small_vec.rs | 212 +- .../snapshot_map/mod.rs | 10 +- .../snapshot_map/test.rs | 8 +- src/librustc_data_structures/stable_hasher.rs | 38 +- .../hir => librustc_data_structures}/svh.rs | 18 +- src/librustc_data_structures/sync.rs | 10 +- .../thin_vec.rs | 0 src/librustc_data_structures/tiny_list.rs | 84 +- .../transitive_relation.rs | 14 +- .../vec_linked_list.rs | 83 + src/librustc_data_structures/work_queue.rs | 8 +- src/librustc_driver/driver.rs | 114 +- src/librustc_driver/lib.rs | 82 +- src/librustc_driver/pretty.rs | 166 +- src/librustc_driver/profile/trace.rs | 10 +- src/librustc_driver/test.rs | 45 +- src/librustc_errors/Cargo.toml | 3 +- src/librustc_errors/diagnostic_builder.rs | 83 +- src/librustc_errors/emitter.rs | 32 +- src/librustc_errors/lib.rs | 22 +- src/librustc_errors/lock.rs | 4 +- src/librustc_errors/registry.rs | 4 +- src/librustc_fs_util/Cargo.toml | 11 + src/librustc_fs_util/lib.rs | 128 + src/librustc_incremental/Cargo.toml | 3 +- .../assert_module_sources.rs | 55 +- src/librustc_incremental/lib.rs | 4 +- .../persist/dirty_clean.rs | 26 +- src/librustc_incremental/persist/fs.rs | 12 +- src/librustc_incremental/persist/load.rs | 4 +- src/librustc_incremental/persist/mod.rs | 1 + .../persist/work_product.rs | 2 +- src/librustc_lint/builtin.rs | 275 +- src/librustc_lint/lib.rs | 45 +- .../{bad_style.rs => nonstandard_style.rs} | 0 src/librustc_lint/types.rs | 140 +- src/librustc_lint/unused.rs | 16 +- src/librustc_llvm/Cargo.toml | 5 - src/librustc_llvm/archive_ro.rs | 150 - src/librustc_llvm/build.rs | 7 +- src/librustc_llvm/ffi.rs | 1800 ------- src/librustc_llvm/lib.rs | 325 +- src/librustc_lsan/lib.rs | 1 + src/librustc_metadata/Cargo.toml | 1 + src/librustc_metadata/creader.rs | 140 +- src/librustc_metadata/cstore.rs | 21 +- src/librustc_metadata/cstore_impl.rs | 182 +- src/librustc_metadata/decoder.rs | 288 +- src/librustc_metadata/encoder.rs | 132 +- src/librustc_metadata/lib.rs | 4 +- src/librustc_metadata/locator.rs | 23 +- src/librustc_metadata/native_libs.rs | 4 +- src/librustc_metadata/schema.rs | 9 +- src/librustc_metadata_utils/Cargo.toml | 14 + src/librustc_metadata_utils/lib.rs | 42 + src/librustc_mir/Cargo.toml | 1 + src/librustc_mir/borrow_check/borrow_set.rs | 62 +- .../borrow_check/error_reporting.rs | 710 ++- src/librustc_mir/borrow_check/flows.rs | 26 +- src/librustc_mir/borrow_check/location.rs | 6 +- src/librustc_mir/borrow_check/mod.rs | 418 +- src/librustc_mir/borrow_check/move_errors.rs | 306 +- .../borrow_check/mutability_errors.rs | 219 +- .../borrow_check/nll/constraint_generation.rs | 7 +- .../borrow_check/nll/constraints/graph.rs | 186 +- .../borrow_check/nll/constraints/mod.rs | 37 +- .../nll/explain_borrow/find_use.rs | 32 +- .../borrow_check/nll/explain_borrow/mod.rs | 195 +- src/librustc_mir/borrow_check/nll/facts.rs | 12 - .../borrow_check/nll/invalidation.rs | 14 +- .../borrow_check/nll/liveness_map.rs | 77 - src/librustc_mir/borrow_check/nll/mod.rs | 113 +- .../nll/region_infer/annotation.rs | 56 - .../nll/region_infer/error_reporting/mod.rs | 104 +- .../error_reporting/region_name.rs | 219 +- .../region_infer/error_reporting/var_name.rs | 2 +- .../borrow_check/nll/region_infer/graphviz.rs | 1 - .../borrow_check/nll/region_infer/mod.rs | 180 +- .../borrow_check/nll/region_infer/values.rs | 134 +- src/librustc_mir/borrow_check/nll/renumber.rs | 11 +- .../nll/type_check/free_region_relations.rs | 29 +- .../nll/type_check/input_output.rs | 37 +- .../borrow_check/nll/type_check/liveness.rs | 246 - .../nll/type_check/liveness/liveness_map.rs | 102 + .../nll/type_check/liveness/local_use_map.rs | 161 + .../nll/type_check/liveness/mod.rs | 95 + .../nll/type_check/liveness/trace.rs | 553 +++ .../borrow_check/nll/type_check/mod.rs | 273 +- .../borrow_check/nll/type_check/relate_tys.rs | 356 +- .../borrow_check/nll/universal_regions.rs | 114 +- src/librustc_mir/borrow_check/place_ext.rs | 63 +- .../borrow_check/places_conflict.rs | 21 +- src/librustc_mir/borrow_check/prefixes.rs | 8 +- src/librustc_mir/build/block.rs | 16 +- src/librustc_mir/build/cfg.rs | 2 +- src/librustc_mir/build/expr/as_constant.rs | 32 +- src/librustc_mir/build/expr/as_operand.rs | 50 +- src/librustc_mir/build/expr/as_place.rs | 173 +- src/librustc_mir/build/expr/as_rvalue.rs | 372 +- src/librustc_mir/build/expr/as_temp.rs | 68 +- src/librustc_mir/build/expr/category.rs | 84 +- src/librustc_mir/build/expr/into.rs | 252 +- src/librustc_mir/build/expr/mod.rs | 2 +- src/librustc_mir/build/expr/stmt.rs | 90 +- src/librustc_mir/build/matches/mod.rs | 887 ++-- src/librustc_mir/build/matches/simplify.rs | 14 +- src/librustc_mir/build/matches/test.rs | 32 +- src/librustc_mir/build/misc.rs | 4 + src/librustc_mir/build/mod.rs | 36 +- src/librustc_mir/build/scope.rs | 7 +- src/librustc_mir/const_eval.rs | 448 ++ src/librustc_mir/dataflow/at_location.rs | 35 +- .../dataflow/drop_flag_effects.rs | 6 +- src/librustc_mir/dataflow/graphviz.rs | 53 +- .../dataflow/impls/borrowed_locals.rs | 16 +- src/librustc_mir/dataflow/impls/borrows.rs | 143 +- src/librustc_mir/dataflow/impls/mod.rs | 131 +- src/librustc_mir/dataflow/mod.rs | 169 +- .../dataflow/move_paths/builder.rs | 36 +- src/librustc_mir/dataflow/move_paths/mod.rs | 36 +- src/librustc_mir/diagnostics.rs | 112 +- src/librustc_mir/hair/cx/block.rs | 44 +- src/librustc_mir/hair/cx/expr.rs | 218 +- src/librustc_mir/hair/cx/mod.rs | 38 +- src/librustc_mir/hair/mod.rs | 28 +- src/librustc_mir/hair/pattern/_match.rs | 786 ++- src/librustc_mir/hair/pattern/check_match.rs | 43 +- src/librustc_mir/hair/pattern/mod.rs | 175 +- src/librustc_mir/interpret/cast.rs | 434 +- src/librustc_mir/interpret/const_eval.rs | 588 --- src/librustc_mir/interpret/eval_context.rs | 1803 ++----- src/librustc_mir/interpret/intrinsics.rs | 222 + src/librustc_mir/interpret/machine.rs | 146 +- src/librustc_mir/interpret/memory.rs | 793 ++- src/librustc_mir/interpret/mod.rs | 65 +- src/librustc_mir/interpret/operand.rs | 614 +++ src/librustc_mir/interpret/operator.rs | 401 +- src/librustc_mir/interpret/place.rs | 1057 ++-- src/librustc_mir/interpret/snapshot.rs | 410 ++ src/librustc_mir/interpret/step.rs | 235 +- src/librustc_mir/interpret/terminator.rs | 451 ++ src/librustc_mir/interpret/terminator/drop.rs | 86 - src/librustc_mir/interpret/terminator/mod.rs | 406 -- src/librustc_mir/interpret/traits.rs | 54 +- src/librustc_mir/interpret/validity.rs | 509 ++ src/librustc_mir/lib.rs | 30 +- src/librustc_mir/monomorphize/collector.rs | 47 +- src/librustc_mir/monomorphize/item.rs | 76 +- src/librustc_mir/monomorphize/partitioning.rs | 498 +- src/librustc_mir/shim.rs | 19 +- src/librustc_mir/transform/add_validation.rs | 12 +- src/librustc_mir/transform/check_unsafety.rs | 46 +- .../transform/cleanup_post_borrowck.rs | 20 +- src/librustc_mir/transform/const_prop.rs | 146 +- src/librustc_mir/transform/deaggregator.rs | 2 +- src/librustc_mir/transform/elaborate_drops.rs | 14 +- src/librustc_mir/transform/generator.rs | 59 +- src/librustc_mir/transform/inline.rs | 18 +- src/librustc_mir/transform/instcombine.rs | 6 +- src/librustc_mir/transform/lower_128bit.rs | 8 +- src/librustc_mir/transform/mod.rs | 5 +- src/librustc_mir/transform/promote_consts.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 225 +- .../transform/qualify_min_const_fn.rs | 358 ++ .../transform/remove_noop_landing_pads.rs | 8 +- src/librustc_mir/transform/rustc_peek.rs | 25 +- src/librustc_mir/transform/simplify.rs | 14 +- .../transform/uniform_array_move_out.rs | 16 +- src/librustc_mir/util/alignment.rs | 2 +- src/librustc_mir/util/borrowck_errors.rs | 33 +- src/librustc_mir/util/elaborate_drops.rs | 32 +- src/librustc_mir/util/graphviz.rs | 2 - src/librustc_mir/util/liveness.rs | 197 +- src/librustc_mir/util/mod.rs | 8 +- src/librustc_mir/util/pretty.rs | 32 +- src/librustc_msan/lib.rs | 1 + src/librustc_passes/ast_validation.rs | 119 +- src/librustc_passes/diagnostics.rs | 22 +- src/librustc_passes/hir_stats.rs | 28 +- src/librustc_passes/lib.rs | 1 + src/librustc_passes/loops.rs | 20 +- src/librustc_passes/mir_stats.rs | 43 +- src/librustc_passes/rvalue_promotion.rs | 105 +- src/librustc_platform_intrinsics/lib.rs | 4 +- src/librustc_plugin/lib.rs | 1 + src/librustc_plugin/registry.rs | 17 +- src/librustc_privacy/lib.rs | 137 +- src/librustc_resolve/Cargo.toml | 1 + src/librustc_resolve/build_reduced_graph.rs | 336 +- src/librustc_resolve/check_unused.rs | 27 +- src/librustc_resolve/diagnostics.rs | 9 +- src/librustc_resolve/lib.rs | 1077 ++-- src/librustc_resolve/macros.rs | 1077 ++-- src/librustc_resolve/resolve_imports.rs | 617 ++- src/librustc_save_analysis/Cargo.toml | 2 +- src/librustc_save_analysis/dump_visitor.rs | 82 +- src/librustc_save_analysis/json_dumper.rs | 2 +- src/librustc_save_analysis/lib.rs | 75 +- src/librustc_save_analysis/sig.rs | 4 +- src/librustc_save_analysis/span_utils.rs | 24 +- src/librustc_target/abi/call/amdgpu.rs | 42 + src/librustc_target/abi/call/mips64.rs | 2 +- src/librustc_target/abi/call/mod.rs | 41 +- src/librustc_target/abi/call/riscv.rs | 59 + src/librustc_target/abi/call/x86.rs | 3 +- src/librustc_target/abi/call/x86_64.rs | 6 +- src/librustc_target/abi/mod.rs | 63 +- src/librustc_target/lib.rs | 12 +- src/librustc_target/spec/aarch64_apple_ios.rs | 2 +- src/librustc_target/spec/aarch64_fuchsia.rs | 4 +- .../spec/aarch64_linux_android.rs | 2 +- .../spec/aarch64_pc_windows_msvc.rs | 35 + .../spec/aarch64_unknown_cloudabi.rs | 2 +- .../spec/aarch64_unknown_freebsd.rs | 2 +- .../spec/aarch64_unknown_hermit.rs | 32 + .../spec/aarch64_unknown_netbsd.rs | 31 + .../spec/aarch64_unknown_none.rs | 46 + .../spec/aarch64_unknown_openbsd.rs | 2 +- src/librustc_target/spec/abi.rs | 12 +- src/librustc_target/spec/apple_base.rs | 2 +- src/librustc_target/spec/apple_ios_base.rs | 12 +- .../spec/arm_linux_androideabi.rs | 2 +- .../spec/armebv7r_none_eabi.rs | 40 + .../spec/armebv7r_none_eabihf.rs | 13 +- src/librustc_target/spec/armv7_apple_ios.rs | 2 +- .../spec/armv7_linux_androideabi.rs | 2 +- .../spec/armv7_unknown_cloudabi_eabihf.rs | 2 +- src/librustc_target/spec/armv7r_none_eabi.rs | 40 + .../spec/armv7r_none_eabihf.rs | 41 + src/librustc_target/spec/armv7s_apple_ios.rs | 2 +- .../spec/asmjs_unknown_emscripten.rs | 2 +- src/librustc_target/spec/hermit_base.rs | 37 + src/librustc_target/spec/i386_apple_ios.rs | 2 +- src/librustc_target/spec/i686_apple_darwin.rs | 2 +- .../spec/i686_linux_android.rs | 2 +- .../spec/i686_unknown_cloudabi.rs | 2 +- .../spec/i686_unknown_dragonfly.rs | 2 +- .../spec/i686_unknown_freebsd.rs | 2 +- .../spec/i686_unknown_haiku.rs | 2 +- .../spec/i686_unknown_netbsd.rs | 2 +- .../spec/i686_unknown_openbsd.rs | 2 +- src/librustc_target/spec/mod.rs | 99 +- src/librustc_target/spec/msp430_none_elf.rs | 4 +- .../spec/powerpc_unknown_netbsd.rs | 2 +- .../spec/riscv32imac_unknown_none_elf.rs | 41 + .../spec/riscv32imc_unknown_none_elf.rs | 42 + src/librustc_target/spec/riscv_base.rs | 30 + .../spec/sparc64_unknown_netbsd.rs | 2 +- .../spec/sparcv9_sun_solaris.rs | 2 +- src/librustc_target/spec/thumb_base.rs | 5 +- .../spec/thumbv6m_none_eabi.rs | 8 +- .../spec/thumbv7a_pc_windows_msvc.rs | 50 + .../spec/thumbv7em_none_eabi.rs | 8 +- .../spec/thumbv7em_none_eabihf.rs | 8 +- .../spec/thumbv7m_none_eabi.rs | 8 +- .../spec/wasm32_experimental_emscripten.rs | 2 +- .../spec/wasm32_unknown_emscripten.rs | 2 +- .../spec/wasm32_unknown_unknown.rs | 8 +- src/librustc_target/spec/windows_base.rs | 4 +- src/librustc_target/spec/windows_msvc_base.rs | 4 +- .../spec/x86_64_apple_darwin.rs | 2 +- src/librustc_target/spec/x86_64_apple_ios.rs | 2 +- src/librustc_target/spec/x86_64_fuchsia.rs | 4 +- .../spec/x86_64_linux_android.rs | 2 +- .../spec/x86_64_rumprun_netbsd.rs | 2 +- .../spec/x86_64_sun_solaris.rs | 2 +- .../spec/x86_64_unknown_bitrig.rs | 2 +- .../spec/x86_64_unknown_cloudabi.rs | 2 +- .../spec/x86_64_unknown_dragonfly.rs | 2 +- .../spec/x86_64_unknown_freebsd.rs | 2 +- .../spec/x86_64_unknown_haiku.rs | 2 +- .../spec/x86_64_unknown_hermit.rs | 33 + .../spec/x86_64_unknown_netbsd.rs | 2 +- .../spec/x86_64_unknown_openbsd.rs | 2 +- .../spec/x86_64_unknown_redox.rs | 2 +- src/librustc_traits/Cargo.toml | 3 +- src/librustc_traits/chalk_context.rs | 4 +- src/librustc_traits/dropck_outlives.rs | 52 +- src/librustc_traits/evaluate_obligation.rs | 2 +- .../implied_outlives_bounds.rs | 2 +- src/librustc_traits/lib.rs | 7 +- src/librustc_traits/lowering.rs | 6 +- src/librustc_tsan/lib.rs | 1 + src/librustc_typeck/Cargo.toml | 7 +- src/librustc_typeck/astconv.rs | 674 ++- src/librustc_typeck/check/_match.rs | 98 +- src/librustc_typeck/check/autoderef.rs | 2 +- src/librustc_typeck/check/callee.rs | 26 +- src/librustc_typeck/check/cast.rs | 56 +- src/librustc_typeck/check/closure.rs | 16 +- src/librustc_typeck/check/coercion.rs | 40 +- src/librustc_typeck/check/compare_method.rs | 26 +- src/librustc_typeck/check/demand.rs | 298 +- src/librustc_typeck/check/dropck.rs | 2 +- .../check/generator_interior.rs | 10 +- src/librustc_typeck/check/intrinsic.rs | 91 +- src/librustc_typeck/check/method/confirm.rs | 90 +- src/librustc_typeck/check/method/probe.rs | 63 +- src/librustc_typeck/check/method/suggest.rs | 47 +- src/librustc_typeck/check/mod.rs | 910 ++-- src/librustc_typeck/check/op.rs | 87 +- src/librustc_typeck/check/regionck.rs | 63 +- src/librustc_typeck/check/upvar.rs | 6 +- src/librustc_typeck/check/wfcheck.rs | 46 +- src/librustc_typeck/check/writeback.rs | 135 +- src/librustc_typeck/check_unused.rs | 40 +- src/librustc_typeck/coherence/builtin.rs | 30 +- .../coherence/inherent_impls.rs | 50 +- src/librustc_typeck/coherence/mod.rs | 6 +- src/librustc_typeck/coherence/orphan.rs | 6 +- src/librustc_typeck/collect.rs | 1539 +++--- .../constrained_type_params.rs | 4 +- src/librustc_typeck/diagnostics.rs | 90 +- src/librustc_typeck/impl_wf_check.rs | 2 +- src/librustc_typeck/lib.rs | 25 +- .../outlives/implicit_infer.rs | 55 +- src/librustc_typeck/outlives/mod.rs | 13 +- src/librustc_typeck/structured_errors.rs | 13 +- src/librustc_typeck/variance/constraints.rs | 44 +- src/librustc_typeck/variance/mod.rs | 11 +- src/librustc_typeck/variance/solve.rs | 2 +- src/librustdoc/Cargo.toml | 2 +- src/librustdoc/clean/auto_trait.rs | 255 +- src/librustdoc/clean/blanket_impl.rs | 161 + src/librustdoc/clean/cfg.rs | 4 +- src/librustdoc/clean/def_ctor.rs | 65 + src/librustdoc/clean/inline.rs | 33 +- src/librustdoc/clean/mod.rs | 740 +-- src/librustdoc/clean/simplify.rs | 6 +- src/librustdoc/core.rs | 267 +- src/librustdoc/doctree.rs | 2 +- src/librustdoc/externalfiles.rs | 14 +- src/librustdoc/html/format.rs | 2 +- src/librustdoc/html/highlight.rs | 78 +- src/librustdoc/html/layout.rs | 6 +- src/librustdoc/html/markdown.rs | 269 +- src/librustdoc/html/render.rs | 476 +- src/librustdoc/html/static/main.js | 121 +- src/librustdoc/html/static/rustdoc.css | 72 +- src/librustdoc/html/static/themes/dark.css | 10 +- src/librustdoc/html/static/themes/light.css | 10 +- src/librustdoc/lib.rs | 144 +- src/librustdoc/markdown.rs | 22 +- src/librustdoc/passes/collapse_docs.rs | 5 + .../passes/collect_intra_doc_links.rs | 597 +++ src/librustdoc/passes/mod.rs | 155 +- src/librustdoc/passes/propagate_doc_cfg.rs | 5 + src/librustdoc/passes/strip_hidden.rs | 9 +- src/librustdoc/passes/strip_priv_imports.rs | 8 +- src/librustdoc/passes/strip_private.rs | 10 +- src/librustdoc/passes/unindent_comments.rs | 5 + src/librustdoc/test.rs | 83 +- src/librustdoc/theme.rs | 10 +- src/librustdoc/visit_ast.rs | 28 +- src/librustdoc/visit_lib.rs | 10 +- src/libserialize/Cargo.toml | 3 + src/libserialize/collection_impls.rs | 64 +- src/libserialize/hex.rs | 2 +- src/libserialize/json.rs | 68 +- src/libserialize/leb128.rs | 5 +- src/libserialize/lib.rs | 3 + src/libserialize/opaque.rs | 5 +- src/libserialize/serialize.rs | 217 +- src/libstd/Cargo.toml | 3 +- src/libstd/alloc.rs | 11 +- src/libstd/ascii.rs | 310 -- src/libstd/build.rs | 4 + src/libstd/collections/hash/map.rs | 16 +- src/libstd/collections/hash/table.rs | 8 +- src/libstd/error.rs | 67 +- src/libstd/ffi/c_str.rs | 102 +- src/libstd/ffi/mod.rs | 3 + src/libstd/ffi/os_str.rs | 27 +- src/libstd/fs.rs | 12 +- src/libstd/future.rs | 8 +- src/libstd/io/buffered.rs | 54 +- src/libstd/io/cursor.rs | 20 - src/libstd/io/error.rs | 11 +- src/libstd/io/lazy.rs | 39 +- src/libstd/io/mod.rs | 170 +- src/libstd/io/stdio.rs | 22 +- src/libstd/io/util.rs | 5 + src/libstd/keyword_docs.rs | 53 +- src/libstd/lib.rs | 40 +- src/libstd/macros.rs | 31 +- src/libstd/memchr.rs | 2 +- src/libstd/net/ip.rs | 235 +- src/libstd/os/hermit/fs.rs | 389 ++ src/libstd/os/hermit/mod.rs | 16 + src/libstd/os/hermit/raw.rs | 27 + src/libstd/os/mod.rs | 5 +- src/libstd/os/raw/mod.rs | 43 +- src/libstd/panic.rs | 2 +- src/libstd/panicking.rs | 4 +- src/libstd/path.rs | 4 +- src/libstd/primitive_docs.rs | 1 + src/libstd/process.rs | 43 + src/libstd/sync/mpsc/mod.rs | 28 + src/libstd/sync/mutex.rs | 2 - src/libstd/sync/once.rs | 87 +- src/libstd/sync/rwlock.rs | 4 +- src/libstd/sys/cloudabi/abi/cloudabi.rs | 18 +- src/libstd/sys/cloudabi/backtrace.rs | 18 +- src/libstd/sys/cloudabi/condvar.rs | 8 +- src/libstd/sys/cloudabi/rwlock.rs | 8 +- src/libstd/sys/mod.rs | 4 +- src/libstd/sys/redox/backtrace/tracing.rs | 18 +- src/libstd/sys/redox/mod.rs | 2 +- src/libstd/sys/redox/net/netc.rs | 2 +- src/libstd/sys/unix/args.rs | 5 +- .../sys/unix/backtrace/tracing/gcc_s.rs | 18 +- src/libstd/sys/unix/condvar.rs | 13 +- src/libstd/sys/unix/env.rs | 11 + src/libstd/sys/unix/fast_thread_local.rs | 2 +- src/libstd/sys/unix/fd.rs | 9 +- src/libstd/sys/unix/fs.rs | 12 +- src/libstd/sys/unix/mod.rs | 33 +- src/libstd/sys/unix/mutex.rs | 9 +- src/libstd/sys/unix/net.rs | 29 +- src/libstd/sys/unix/os.rs | 38 +- src/libstd/sys/unix/rand.rs | 66 +- src/libstd/sys/unix/thread.rs | 3 +- src/libstd/sys/unix/time.rs | 4 +- src/libstd/sys/wasm/net.rs | 2 +- src/libstd/sys/windows/backtrace/mod.rs | 55 +- src/libstd/sys/windows/c.rs | 108 +- src/libstd/sys/windows/ext/ffi.rs | 3 +- src/libstd/sys/windows/mod.rs | 12 +- src/libstd/sys/windows/mutex.rs | 2 + src/libstd/sys/windows/os.rs | 2 +- src/libstd/sys/windows/pipe.rs | 2 +- src/libstd/sys/windows/thread.rs | 3 +- src/libstd/sys_common/at_exit_imp.rs | 5 + src/libstd/sys_common/io.rs | 2 +- src/libstd/sys_common/mutex.rs | 6 + src/libstd/sys_common/net.rs | 5 +- src/libstd/sys_common/thread_local.rs | 2 + src/libstd/sys_common/wtf8.rs | 2 +- src/libstd/tests/env.rs | 7 +- src/libstd/thread/mod.rs | 13 +- src/libstd_unicode/Cargo.toml | 14 - src/libstd_unicode/lib.rs | 36 - src/libsyntax/Cargo.toml | 1 + src/libsyntax/ast.rs | 43 +- src/libsyntax/attr/builtin.rs | 26 +- src/libsyntax/attr/mod.rs | 61 +- src/libsyntax/codemap.rs | 1235 ----- src/libsyntax/config.rs | 31 +- src/libsyntax/diagnostic_list.rs | 24 +- src/libsyntax/diagnostics/metadata.rs | 2 +- src/libsyntax/diagnostics/plugin.rs | 10 +- src/libsyntax/ext/base.rs | 103 +- src/libsyntax/ext/build.rs | 15 +- src/libsyntax/ext/derive.rs | 6 +- src/libsyntax/ext/expand.rs | 284 +- src/libsyntax/ext/placeholders.rs | 47 +- src/libsyntax/ext/quote.rs | 37 +- src/libsyntax/ext/source_util.rs | 20 +- src/libsyntax/ext/tt/macro_parser.rs | 56 +- src/libsyntax/ext/tt/macro_rules.rs | 75 +- src/libsyntax/ext/tt/quoted.rs | 22 +- src/libsyntax/ext/tt/transcribe.rs | 30 +- src/libsyntax/feature_gate.rs | 514 +- src/libsyntax/fold.rs | 71 +- src/libsyntax/json.rs | 16 +- src/libsyntax/lib.rs | 28 +- src/libsyntax/parse/attr.rs | 36 +- src/libsyntax/parse/classify.rs | 2 +- src/libsyntax/parse/lexer/comments.rs | 36 +- src/libsyntax/parse/lexer/mod.rs | 274 +- src/libsyntax/parse/lexer/tokentrees.rs | 83 +- src/libsyntax/parse/lexer/unicode_chars.rs | 10 +- src/libsyntax/parse/mod.rs | 75 +- src/libsyntax/parse/parser.rs | 333 +- src/libsyntax/parse/token.rs | 11 +- src/libsyntax/print/pprust.rs | 84 +- src/libsyntax/ptr.rs | 8 +- src/libsyntax/source_map.rs | 1247 +++++ src/libsyntax/std_inject.rs | 41 +- src/libsyntax/test.rs | 598 +-- src/libsyntax/test_snippet.rs | 6 +- src/libsyntax/tokenstream.rs | 272 +- src/libsyntax/util/lev_distance.rs | 42 +- src/libsyntax/util/move_map.rs | 5 +- src/libsyntax/util/parser.rs | 4 +- src/libsyntax/util/parser_testing.rs | 8 +- src/libsyntax/util/rc_vec.rs | 90 + src/libsyntax/util/small_vector.rs | 81 - src/libsyntax/visit.rs | 8 +- src/libsyntax_ext/Cargo.toml | 4 +- src/libsyntax_ext/asm.rs | 4 +- src/libsyntax_ext/assert.rs | 2 +- src/libsyntax_ext/concat_idents.rs | 4 +- src/libsyntax_ext/deriving/custom.rs | 2 +- src/libsyntax_ext/deriving/debug.rs | 4 +- src/libsyntax_ext/deriving/default.rs | 4 +- src/libsyntax_ext/deriving/generic/mod.rs | 9 +- src/libsyntax_ext/deriving/generic/ty.rs | 2 +- src/libsyntax_ext/deriving/mod.rs | 11 - src/libsyntax_ext/env.rs | 2 +- src/libsyntax_ext/format.rs | 157 +- src/libsyntax_ext/format_foreign.rs | 80 +- src/libsyntax_ext/global_asm.rs | 8 +- src/libsyntax_ext/lib.rs | 15 +- src/libsyntax_ext/proc_macro_impl.rs | 2 +- src/libsyntax_ext/proc_macro_registrar.rs | 2 +- src/libsyntax_ext/test.rs | 340 ++ src/libsyntax_ext/test_case.rs | 75 + src/libsyntax_pos/analyze_filemap.rs | 436 -- src/libsyntax_pos/analyze_source_file.rs | 436 ++ src/libsyntax_pos/edition.rs | 2 +- src/libsyntax_pos/hygiene.rs | 20 +- src/libsyntax_pos/lib.rs | 75 +- src/libsyntax_pos/symbol.rs | 22 +- src/libterm/lib.rs | 1 + src/libterm/terminfo/mod.rs | 16 +- src/libterm/terminfo/parm.rs | 84 +- src/libterm/win.rs | 4 +- src/libtest/formatters/json.rs | 6 +- src/libtest/formatters/terse.rs | 6 +- src/libtest/lib.rs | 15 +- src/libtest/stats.rs | 3 +- src/libunwind/lib.rs | 1 + src/libunwind/libunwind.rs | 2 +- src/rustc/libc_shim/Cargo.toml | 3 +- src/rustllvm/ArchiveWrapper.cpp | 2 +- src/rustllvm/PassWrapper.cpp | 87 +- src/rustllvm/RustWrapper.cpp | 22 +- src/rustllvm/llvm-rebuild-trigger | 2 +- src/stage0.txt | 6 +- src/test/COMPILER_TESTS.md | 186 +- .../cross-crate-trait-method.rs | 2 +- .../drop_in_place_intrinsic.rs | 6 +- .../item-collection/generic-drop-glue.rs | 12 +- .../instantiation-through-vtable.rs | 4 +- .../item-collection/non-generic-drop-glue.rs | 4 +- .../item-collection/transitive-drop-glue.rs | 18 +- .../item-collection/tuple-drop-glue.rs | 8 +- .../item-collection/unreferenced-const-fn.rs | 2 +- .../codegen-units/item-collection/unsizing.rs | 8 +- .../partitioning/extern-generic.rs | 4 +- .../partitioning/shared-generics.rs | 2 +- src/test/codegen/consts.rs | 4 +- src/test/codegen/issue-13018.rs | 21 + src/test/codegen/link-dead-code.rs | 2 +- src/test/codegen/no-assumes-on-casts.rs | 29 + .../codegen/no-dllimport-w-cross-lang-lto.rs | 23 + src/test/codegen/remap_path_prefix/main.rs | 2 +- .../codegen/slice-position-bounds-check.rs | 42 + src/test/codegen/sparc-struct-abi.rs | 1 + src/test/codegen/target-cpu-on-functions.rs | 29 + src/test/codegen/vec-clear.rs | 22 + src/test/codegen/vec-iter-collect-len.rs | 1 + src/test/codegen/vec-optimizes-away.rs | 1 + .../auxiliary/lint_for_crate.rs | 2 +- .../auxiliary/lint_group_plugin_test.rs | 4 +- .../auxiliary/lint_plugin_test.rs | 2 +- .../auxiliary/pub_and_stability.rs | 32 +- src/test/compile-fail-fulldeps/issue-48941.rs | 5 +- .../proc-macro/attr-invalid-exprs.rs | 2 +- .../proc-macro/attr-stmt-expr.rs | 2 +- .../proc-macro/attribute-with-error.rs | 2 +- .../proc-macro/attributes-included.rs | 1 - .../proc-macro/auxiliary/more-gates.rs | 11 - .../proc-macro/issue-41211.rs | 5 +- .../proc-macro/issue-50493.rs | 2 - .../proc-macro/lints_in_proc_macros.rs | 2 +- .../proc-macro/macros-in-extern.rs | 8 +- .../proc-macro/more-gates.rs | 9 +- .../proc-macro/no-macro-use-attr.rs | 3 +- .../proc-macro/proc-macro-attributes.rs | 8 +- .../proc-macro-custom-attr-mutex.rs | 25 - .../proc-macro/proc-macro-gates.rs | 17 +- .../proc-macro/proc-macro-gates2.rs | 2 +- src/test/compile-fail-fulldeps/qquote.rs | 2 +- .../compile-fail/anon-params-deprecated.rs | 25 - .../compile-fail/auxiliary/const_fn_lib.rs | 16 - .../auxiliary/lint_output_format.rs | 30 - .../compile-fail/auxiliary/lint_stability.rs | 198 - .../auxiliary/lint_stability_fields.rs | 61 - .../auxiliary/panic-runtime-lang-items.rs | 0 .../auxiliary/panic-runtime-unwind.rs | 0 .../auxiliary/panic-runtime-unwind2.rs | 0 .../compile-fail/auxiliary/some-panic-impl.rs | 3 +- .../auxiliary/stability_attribute_issue.rs | 19 - .../compile-fail/auxiliary/stability_cfg2.rs | 15 - .../compile-fail/auxiliary/unstable-macros.rs | 16 - .../auxiliary/wants-panic-runtime-unwind.rs | 0 src/test/compile-fail/borrow-tuple-fields.rs | 42 - .../borrowck/borrowck-closures-two-mut.rs | 60 - .../borrowck/borrowck-closures-unique.rs | 50 - .../borrowck/borrowck-object-lifetime.rs | 39 - .../borrowck-overloaded-index-autoderef.rs | 93 - .../compile-fail/cast-ptr-to-int-const.rs | 15 - src/test/compile-fail/catch-bad-lifetime.rs | 42 - src/test/compile-fail/catch-bad-type.rs | 28 - src/test/compile-fail/catch-in-match.rs | 15 - src/test/compile-fail/catch-in-while.rs | 15 - .../compile-fail/catch-maybe-bad-lifetime.rs | 49 - src/test/compile-fail/catch-opt-init.rs | 25 - .../mod_file_not_owning.rs | 15 - .../unowned_mod_with_path.rs | 15 - .../compile-fail/dollar-crate-is-keyword.rs | 24 - .../compile-fail/enum-discrim-autosizing.rs | 20 - .../feature-gate-tool_attributes.rs | 15 - src/test/compile-fail/gated-attr-literals.rs | 47 - src/test/compile-fail/invalid-crate-type.rs | 16 - src/test/compile-fail/issue-43733-2.rs | 2 +- src/test/compile-fail/lint-renamed-cmdline.rs | 18 - .../compile-fail/macro-with-seps-err-msg.rs | 19 - src/test/compile-fail/macros-in-extern.rs | 42 - .../meta-expected-error-wrong-rev.rs | 2 + .../compile-fail/method-call-lifetime-args.rs | 82 - .../compile-fail/panic-handler-missing.rs | 18 + src/test/compile-fail/panic-handler-twice.rs | 28 + .../panic-implementation-bad-signature-1.rs | 24 - .../panic-implementation-bad-signature-2.rs | 25 - .../panic-implementation-bad-signature-3.rs | 22 - .../panic-implementation-bad-signature-4.rs | 23 - .../panic-implementation-duplicate.rs | 28 - .../panic-implementation-missing.rs | 18 - ...anic-implementation-requires-panic-info.rs | 26 - .../compile-fail/panic-implementation-std.rs | 22 - .../panic-implementation-twice.rs | 29 - src/test/compile-fail/regions-enum-not-wf.rs | 38 - src/test/compile-fail/regions-static-bound.rs | 33 - .../compile-fail/regions-struct-not-wf.rs | 40 - .../non-existent-1.rs | 17 - .../non-existent-2.rs | 17 - .../non-existent-3.rs | 17 - .../single-segment.rs | 25 - .../non-existent-1.rs | 15 - .../non-existent-2.rs | 15 - .../non-existent-3.rs | 15 - .../single-segment.rs | 23 - .../compile-fail/stability-attribute-issue.rs | 21 - .../{panic-runtime => }/two-panic-runtimes.rs | 0 src/test/compile-fail/union-ub-fat-ptr.rs | 89 - src/test/compile-fail/unknown-tool-name.rs | 16 - .../compile-fail/unknown_tool_attributes-1.rs | 18 - .../unsized-locals/unsized-exprs.rs | 36 + .../unsized-locals/unsized-exprs2.rs | 36 + .../want-abort-got-unwind.rs | 0 .../want-abort-got-unwind2.rs | 0 src/test/compile-fail/weak-lang-item.rs | 2 +- .../wf-outlives-ty-in-fn-or-trait.rs | 32 - src/test/debuginfo/constant-debug-locs.rs | 1 - src/test/debuginfo/pretty-std-collections.rs | 60 + .../auxiliary/issue_49482_macro_def.rs | 49 + .../auxiliary/issue_49482_reexport.rs | 16 + .../auxiliary/issue_54059.rs | 59 + src/test/incremental-fulldeps/issue-49482.rs | 41 + src/test/incremental-fulldeps/issue-54059.rs | 19 + .../incremental/hashes/let_expressions.rs | 2 +- .../issue-39828/auxiliary/generic.rs | 2 +- .../incremental/issue-49595/issue_49595.rs | 5 +- src/test/incremental/issue-51409.rs | 2 - .../incremental/remove_source_file/main.rs | 2 +- src/test/incremental/span_hash_stable/main.rs | 2 +- src/test/mir-opt/basic_assignment.rs | 81 +- .../end_region_destruction_extents_1.rs | 8 +- src/test/mir-opt/lower_128bit_debug_test.rs | 2 +- src/test/mir-opt/lower_128bit_test.rs | 154 +- src/test/mir-opt/nll/named-lifetimes-basic.rs | 18 +- src/test/mir-opt/nll/reborrow-basic.rs | 38 - .../mir-opt/storage_live_dead_in_statics.rs | 4 +- src/test/mir-opt/validate_1.rs | 6 +- src/test/mir-opt/validate_3.rs | 8 +- src/test/parse-fail/attr-bad-meta-2.rs | 12 + src/test/parse-fail/attr-bad-meta-3.rs | 12 + src/test/parse-fail/attr-bad-meta.rs | 5 +- src/test/parse-fail/do-catch-suggests-try.rs | 17 + .../keyword-try-as-identifier-edition2018.rs | 15 + src/test/pretty/attr-literals.rs | 4 +- src/test/pretty/cast-lt.pp | 2 +- src/test/pretty/issue-4264.pp | 2 +- src/test/run-fail-fulldeps/qquote.rs | 4 +- src/test/run-fail/args-panic.rs | 1 - src/test/run-fail/issue-29798.rs | 2 +- src/test/run-fail/panic-macro-any.rs | 1 - src/test/run-fail/panic-set-handler.rs | 2 - src/test/run-fail/panic-set-unset-handler.rs | 2 - src/test/run-fail/panic-take-handler-nop.rs | 2 - src/test/run-fail/run-unexported-tests.rs | 4 +- .../allow-warnings-cmdline-stability/bar.rs | 4 +- .../allow-warnings-cmdline-stability/foo.rs | 2 +- .../codegen-options-parsing/Makefile | 6 +- .../cross-lang-lto-upstream-rlibs/Makefile | 23 + .../staticlib.rs | 18 + .../cross-lang-lto-upstream-rlibs/upstream.rs | 13 + .../run-make-fulldeps/cross-lang-lto/Makefile | 9 +- .../exit-code/lint-failure.rs | 2 +- .../run-make-fulldeps/extern-prelude/Makefile | 1 - .../extern-prelude/feature-gate.rs | 13 - .../extra-filename-with-temp-outputs/Makefile | 2 +- src/test/run-make-fulldeps/hir-tree/Makefile | 2 +- .../hotplug_codegen_backend/the_backend.rs | 2 +- src/test/run-make-fulldeps/issue-19371/foo.rs | 6 +- src/test/run-make-fulldeps/issue-51671/app.rs | 3 +- .../run-make-fulldeps/issue-53964/Makefile | 5 + src/test/run-make-fulldeps/issue-53964/app.rs | 8 + .../run-make-fulldeps/issue-53964/panic.rs | 20 + .../libtest-json/output.json | 4 +- .../run-make-fulldeps/link-path-order/main.rs | 2 +- src/test/run-make-fulldeps/lto-smoke/Makefile | 26 +- .../panic-impl-provider.rs | 3 +- .../rustdoc-error-lines/Makefile | 2 +- .../sanitizer-cdylib-link/Makefile | 2 +- .../sanitizer-dylib-link/Makefile | 2 +- .../save-analysis-rfc2126/Makefile | 6 +- .../extern_absolute_paths.rs | 2 - .../symbols-are-reasonable/Makefile | 13 - .../symbols-are-reasonable/lib.rs | 21 - .../target-cpu-native/Makefile | 19 +- .../use-suggestions-rust-2018/Makefile | 7 + .../ep-nested-lib.rs | 17 + .../use-suggestions.rs | 13 + src/test/run-make-fulldeps/used/used.rs | 1 - src/test/run-make/git_clone_sha1.sh | 33 + .../run-make/thumb-none-cortex-m/Makefile | 38 + src/test/run-make/wasm-custom-section/bar.rs | 1 - src/test/run-make/wasm-custom-section/foo.rs | 1 - .../wasm-symbols-not-exported/Makefile | 16 + .../run-make/wasm-symbols-not-exported/bar.rs | 45 + .../run-make/wasm-symbols-not-exported/foo.rs | 17 + .../verify-exported-symbols.js | 31 + .../wasm-symbols-not-imported/Makefile | 16 + .../run-make/wasm-symbols-not-imported/foo.rs | 26 + .../verify-no-imports.js | 20 + .../run-pass-fulldeps/ast_stmt_expr_attr.rs | 2 +- .../auxiliary/cond_plugin.rs | 2 +- .../auxiliary/custom_derive_partial_eq.rs | 2 +- .../auxiliary/hello_macro.rs | 2 +- .../auxiliary/issue-16723.rs | 6 +- .../auxiliary/lint_for_crate.rs | 2 +- .../auxiliary/macro_crate_test.rs | 2 +- .../auxiliary/proc_macro_def.rs | 4 +- .../auxiliary/procedural_mbe_matching.rs | 3 +- src/test/run-pass-fulldeps/compiler-calls.rs | 12 +- .../deriving-encodable-decodable-box.rs | 1 - src/test/run-pass-fulldeps/deriving-global.rs | 2 +- .../macro-crate-multi-decorator-literals.rs | 2 +- .../run-pass-fulldeps/macro-quote-cond.rs | 2 +- .../run-pass-fulldeps/macro-quote-test.rs | 2 +- .../mod_dir_path_canonicalized.rs | 2 +- src/test/run-pass-fulldeps/myriad-closures.rs | 2 +- src/test/run-pass-fulldeps/newtype_index.rs | 20 + .../pprust-expr-roundtrip.rs | 7 +- .../run-pass-fulldeps/proc-macro/attr-args.rs | 1 - .../run-pass-fulldeps/proc-macro/attr-cfg.rs | 2 - .../proc-macro/attr-on-trait.rs | 2 - .../proc-macro/attr-stmt-expr.rs | 2 +- .../auxiliary/count_compound_ops.rs | 2 +- .../proc-macro/auxiliary/derive-b.rs | 2 +- .../proc-macro/auxiliary/hygiene_example.rs | 2 - .../auxiliary/hygiene_example_codegen.rs | 2 +- .../auxiliary/issue-40001-plugin.rs | 9 +- .../proc-macro/bang-macro.rs | 2 +- .../run-pass-fulldeps/proc-macro/call-site.rs | 2 +- .../proc-macro/count_compound_ops.rs | 2 +- .../proc-macro/derive-attr-cfg.rs | 2 - .../run-pass-fulldeps/proc-macro/derive-b.rs | 4 +- .../proc-macro/derive-two-attrs.rs | 2 - .../proc-macro/gen-lifetime-token.rs | 2 - .../proc-macro/hygiene_example.rs | 2 +- .../proc-macro/issue-39889.rs | 3 - .../proc-macro/issue-42708.rs | 2 +- .../proc-macro/issue-50061.rs | 2 +- .../run-pass-fulldeps/proc-macro/lifetimes.rs | 2 - .../proc-macro/macros-in-extern.rs | 2 +- .../proc-macro/modify-ast.rs | 2 - .../run-pass-fulldeps/proc-macro/not-joint.rs | 2 - .../proc-macro/span-api-tests.rs | 2 - src/test/run-pass-fulldeps/proc_macro.rs | 2 +- src/test/run-pass-fulldeps/qquote.rs | 2 +- src/test/run-pass-valgrind/coerce-match.rs | 1 - .../long-live-the-unsized-temporary.rs | 65 + src/test/run-pass/align-with-extern-c-fn.rs | 1 - src/test/run-pass/alignment-gep-tup-like-1.rs | 1 - .../run-pass/allocator/auxiliary/custom.rs | 31 - src/test/run-pass/allocator/custom.rs | 66 - src/test/run-pass/async-await.rs | 67 +- src/test/run-pass/attr-shebang.rs | 4 +- src/test/run-pass/auxiliary/const_fn_lib.rs | 16 - .../auxiliary/edition-kw-macro-2015.rs | 2 - .../auxiliary/edition-kw-macro-2018.rs | 2 - src/test/run-pass/auxiliary/issue-36954.rs | 18 - .../auxiliary/typeid-intrinsic-aux1.rs | 2 - .../auxiliary/typeid-intrinsic-aux2.rs | 2 - .../run-pass/auxiliary/unstable-macros.rs | 16 - src/test/run-pass/borrow-tuple-fields.rs | 47 - src/test/run-pass/c-stack-returning-int64.rs | 2 +- .../cancel-clean-via-immediate-rvalue-ref.rs | 1 - src/test/run-pass/catch-expr.rs | 79 - src/test/run-pass/child-outlives-parent.rs | 2 - src/test/run-pass/cleanup-arm-conditional.rs | 1 - .../cleanup-rvalue-during-if-and-while.rs | 3 - ...nup-rvalue-temp-during-incomplete-alloc.rs | 1 - src/test/run-pass/clone-with-exterior.rs | 3 +- .../close-over-big-then-small-data.rs | 1 - src/test/run-pass/command-before-exec.rs | 2 +- src/test/run-pass/const-int-conversion.rs | 34 + src/test/run-pass/const-int-overflowing.rs | 47 + src/test/run-pass/const-int-rotate.rs | 23 + src/test/run-pass/const-int-sign.rs | 23 + src/test/run-pass/const-int-wrapping.rs | 47 + src/test/run-pass/core-run-destroy.rs | 2 +- .../crate-method-reexport-grrrrrrr.rs | 1 - src/test/run-pass/ctfe/promotion.rs | 17 - src/test/run-pass/deref-lval.rs | 1 - src/test/run-pass/deref.rs | 1 - src/test/run-pass/dyn-trait.rs | 26 - .../run-pass/edition-keywords-2015-2015.rs | 2 - .../run-pass/edition-keywords-2015-2018.rs | 2 - .../run-pass/edition-keywords-2018-2015.rs | 2 - .../run-pass/edition-keywords-2018-2018.rs | 2 - src/test/run-pass/enum-discrim-autosizing.rs | 59 - src/test/run-pass/env-home-dir.rs | 2 - src/test/run-pass/env-null-vars.rs | 29 + .../run-pass/expr-block-generic-unique1.rs | 1 - .../run-pass/expr-block-generic-unique2.rs | 2 - src/test/run-pass/expr-block-unique.rs | 3 - src/test/run-pass/expr-if-unique.rs | 4 - src/test/run-pass/float.rs | 18 - src/test/run-pass/fn-abi.rs | 27 - src/test/run-pass/fsu-moves-and-copies.rs | 2 - src/test/run-pass/futures-api.rs | 20 +- src/test/run-pass/generator/panic-safe.rs | 37 - src/test/run-pass/generator/xcrate.rs | 37 - src/test/run-pass/hashmap-memory.rs | 3 - .../hygiene/auxiliary/legacy_interaction.rs | 19 - src/test/run-pass/hygiene/auxiliary/xcrate.rs | 38 - src/test/run-pass/hygiene/items.rs | 36 - .../run-pass/hygiene/legacy_interaction.rs | 50 - src/test/run-pass/hygiene/xcrate.rs | 21 - src/test/run-pass/ifmt.rs | 2 +- src/test/run-pass/impl-trait/xcrate.rs | 19 - .../import-crate-with-invalid-spans/main.rs | 22 - src/test/run-pass/init-large-type.rs | 2 +- src/test/run-pass/invalid_const_promotion.rs | 4 +- src/test/run-pass/issue-18804/main.rs | 23 - src/test/run-pass/issue-36954.rs | 17 - src/test/run-pass/issue-37291/main.rs | 29 - src/test/run-pass/issue-38715.rs | 20 - src/test/run-pass/issue-48006.rs | 23 + src/test/run-pass/issue-53728.rs | 26 + .../issue24687-embed-debuginfo/main.rs | 22 - .../run-pass/issue_26873_multifile/A/mod.rs | 15 - .../run-pass/issue_26873_multifile/mod.rs | 14 - .../kindck-implicit-close-over-mut-var.rs | 2 - src/test/run-pass/last-use-is-capture.rs | 1 - src/test/run-pass/leak-unique-as-tydesc.rs | 1 - src/test/run-pass/list.rs | 1 - src/test/run-pass/macros-in-extern.rs | 39 - src/test/run-pass/mod_dir_implicit_aux/mod.rs | 11 - src/test/run-pass/mod_dir_simple/test.rs | 11 - src/test/run-pass/mut-function-arguments.rs | 2 - src/test/run-pass/new-box.rs | 1 - .../run-pass/non_modrs_mods/non_modrs_mods.rs | 26 - .../nullable-pointer-iotareduction.rs | 2 - ...owned-object-borrowed-method-headerless.rs | 2 - .../objects-owned-object-owned-method.rs | 2 - src/test/run-pass/operator-overloading.rs | 2 - src/test/run-pass/output-slot-variants.rs | 1 - src/test/run-pass/panic-safe.rs | 60 - src/test/run-pass/pure-sum.rs | 1 - src/test/run-pass/rcvr-borrowed-to-region.rs | 1 - src/test/run-pass/realloc-16687.rs | 10 +- src/test/run-pass/regions-static-bound.rs | 28 - .../rfc-2005-default-binding-mode/slice.rs | 35 - .../auxiliary/enums.rs | 19 - .../auxiliary/structs.rs | 23 - .../auxiliary/variants.rs | 18 - .../run-pass/rfc-2008-non-exhaustive/enums.rs | 33 - .../rfc-2008-non-exhaustive/structs.rs | 27 - .../rfc-2008-non-exhaustive/variants.rs | 31 - .../rfc-2126-extern-absolute-paths/basic.rs | 32 - .../rfc-2126-extern-absolute-paths/test.rs | 22 - .../rfc-2151-raw-identifiers/basic.rs | 31 - .../rfc-2151-raw-identifiers/items.rs | 43 - .../rfc-2151-raw-identifiers/macros.rs | 48 - .../rfc-2175-or-if-while-let/basic.rs | 30 - src/test/run-pass/running-with-no-runtime.rs | 2 +- .../signal-alternate-stack-cleanup.rs | 2 +- src/test/run-pass/slice.rs | 91 - src/test/run-pass/spawn.rs | 19 - src/test/run-pass/tool_attributes.rs | 1 - src/test/run-pass/try-block.rs | 81 + .../run-pass/try-from-int-error-partial-eq.rs | 21 + .../run-pass/try-is-identifier-edition2015.rs | 18 + src/test/run-pass/try-macro.rs | 57 - src/test/run-pass/type-id-higher-rank.rs | 3 - src/test/run-pass/type-param-constraints.rs | 1 - .../run-pass/typeclasses-eq-example-static.rs | 2 - src/test/run-pass/typeclasses-eq-example.rs | 1 - .../uniform-paths/auxiliary/issue-53691.rs | 19 + .../run-pass/uniform-paths/issue-53691.rs | 18 + .../run-pass/union/union-const-eval-field.rs | 53 - src/test/run-pass/unsized2.rs | 1 - src/test/run-pass/unused-move-capture.rs | 1 - src/test/run-pass/unused-move.rs | 1 - src/test/run-pass/unwind-unique.rs | 1 - src/test/run-pass/utf8_chars.rs | 3 - ...ariance-intersection-of-ref-and-opt-ref.rs | 2 - src/test/run-pass/x86stdcall2.rs | 2 - src/test/rustdoc-js/pinbox-new.js | 4 +- src/test/rustdoc-js/substring.js | 20 + src/test/rustdoc-js/vec-new.js | 2 +- .../rustdoc-ui/failed-doctest-output.stdout | 4 +- src/test/rustdoc-ui/intra-doc-alias-ice.rs | 16 + .../rustdoc-ui/intra-doc-alias-ice.stderr | 13 + src/test/rustdoc/assoc-consts.rs | 14 - src/test/rustdoc/async-fn.rs | 24 + .../auxiliary/intra-link-extern-crate.rs | 13 + src/test/rustdoc/auxiliary/issue-27362.rs | 2 +- src/test/rustdoc/auxiliary/issue-53689.rs | 11 + .../rustdoc/auxiliary/rustdoc-default-impl.rs | 1 - src/test/rustdoc/blanket-reexport-item.rs | 18 + src/test/rustdoc/const-doc.rs | 2 +- src/test/rustdoc/const-evalutation-ice.rs | 2 - src/test/rustdoc/const-fn.rs | 2 +- src/test/rustdoc/const.rs | 2 +- src/test/rustdoc/cross-crate-links.rs | 2 - src/test/rustdoc/doc-cfg.rs | 2 +- src/test/rustdoc/escape-rust-expr.rs | 2 +- src/test/rustdoc/extern-html-root-url.rs | 18 + src/test/rustdoc/generic-impl.rs | 26 + src/test/rustdoc/impl-everywhere.rs | 40 + src/test/rustdoc/inline_cross/assoc-items.rs | 5 - .../inline_cross/auxiliary/macro-vis.rs | 2 +- src/test/rustdoc/inline_cross/macro-vis.rs | 2 - src/test/rustdoc/inline_cross/macros.rs | 1 - src/test/rustdoc/intra-link-extern-crate.rs | 19 + src/test/rustdoc/intra-link-private.rs | 18 + src/test/rustdoc/intra-links.rs | 2 +- src/test/rustdoc/issue-28478.rs | 1 - src/test/rustdoc/issue-29503.rs | 4 +- src/test/rustdoc/issue-33302.rs | 9 +- src/test/rustdoc/issue-51236.rs | 24 + src/test/rustdoc/issue-53689.rs | 26 + src/test/rustdoc/issue-53812.rs | 30 + src/test/rustdoc/primitive-generic-impl.rs | 18 + .../primitive/primitive-generic-impl.rs | 13 + src/test/rustdoc/pub-use-extern-macros.rs | 2 - .../rustdoc/synthetic_auto/static-region.rs | 20 + src/test/rustdoc/traits-in-bodies.rs | 29 + .../ui-fulldeps/attribute-order-restricted.rs | 32 + .../attribute-order-restricted.stderr | 32 + .../ui-fulldeps/auxiliary/attr_proc_macro.rs | 2 +- .../ui-fulldeps/auxiliary/bang_proc_macro.rs | 2 +- src/test/ui-fulldeps/auxiliary/lifetimes.rs | 1 - .../auxiliary/lint_group_plugin_test.rs | 4 +- .../ui-fulldeps/auxiliary/lint_plugin_test.rs | 2 +- .../ui-fulldeps/auxiliary/lint_tool_test.rs | 53 + .../ui-fulldeps/invalid-punct-ident-4.stderr | 2 +- src/test/ui-fulldeps/lifetimes.rs | 2 +- .../ui-fulldeps/lint_tool_cmdline_allow.rs | 23 + .../lint_tool_cmdline_allow.stderr | 25 + src/test/ui-fulldeps/lint_tool_test.rs | 40 + src/test/ui-fulldeps/lint_tool_test.stderr | 62 + .../ambiguous-builtin-attrs-test.rs | 20 + .../ambiguous-builtin-attrs-test.stderr | 9 + .../proc-macro/ambiguous-builtin-attrs.rs | 31 + .../proc-macro/ambiguous-builtin-attrs.stderr | 100 + .../proc-macro/attribute-spans-preserved.rs | 4 +- .../attribute-spans-preserved.stderr | 8 +- .../attribute-spans-preserved.stdout | 2 +- .../proc-macro/auxiliary/attr_proc_macro.rs | 0 .../proc-macro/auxiliary/bang_proc_macro.rs | 0 .../proc-macro/auxiliary/builtin-attrs.rs | 36 + .../auxiliary/derive-helper-shadowed-2.rs | 2 + .../auxiliary/derive-helper-shadowed.rs | 11 + .../auxiliary/derive-helper-shadowing.rs | 16 + .../proc-macro/auxiliary/generate-mod.rs | 1 - .../proc-macro/auxiliary/issue-53481.rs | 12 + .../proc-macro/auxiliary/multispan.rs | 46 + .../proc-macro/derive-helper-shadowed.rs | 16 + .../proc-macro/derive-helper-shadowing.rs | 10 + .../proc-macro/derive-helper-shadowing.stderr | 21 + .../ui-fulldeps/proc-macro/generate-mod.rs | 2 - .../proc-macro/generate-mod.stderr | 16 +- .../proc-macro/invalid-attributes.rs | 1 - .../proc-macro/invalid-attributes.stderr | 12 +- .../ui-fulldeps/proc-macro/issue-53481.rs | 22 + .../ui-fulldeps/proc-macro/macro-brackets.rs | 2 - .../proc-macro/macro-brackets.stderr | 2 +- .../proc-macro/macro-namespace-reserved-2.rs | 1 - .../macro-namespace-reserved-2.stderr | 30 +- .../proc-macro/macro-namespace-reserved.rs | 2 +- .../proc-macro/macro-use-attr.rs | 3 +- .../proc-macro/macro-use-bang.rs | 2 +- src/test/ui-fulldeps/proc-macro/multispan.rs | 38 + .../ui-fulldeps/proc-macro/multispan.stderr | 86 + .../proc-macro/nested-item-spans.rs | 2 - .../proc-macro/nested-item-spans.stderr | 4 +- src/test/ui-fulldeps/proc-macro/non-root.rs | 1 - .../ui-fulldeps/proc-macro/non-root.stderr | 2 +- .../proc-macro/parent-source-spans.rs | 2 +- .../proc-macro/reserved-macro-names.rs | 22 + .../proc-macro/reserved-macro-names.stderr | 20 + .../ui-fulldeps/proc-macro/three-equals.rs | 2 +- src/test/ui-fulldeps/resolve-error.rs | 8 +- src/test/ui-fulldeps/resolve-error.stderr | 28 +- .../suggestions-not-always-applicable.rs | 22 + .../suggestions-not-always-applicable.fixed | 37 + .../suggestions-not-always-applicable.rs | 37 + .../suggestions-not-always-applicable.stderr | 24 + .../ui-fulldeps/unnecessary-extern-crate.rs | 4 +- src/test/ui/E0501.ast.nll.stderr | 31 + src/test/ui/E0501.ast.stderr | 31 + src/test/ui/E0501.mir.stderr | 31 + src/test/{compile-fail => ui}/E0501.rs | 0 src/test/ui/E0506.ast.nll.stderr | 14 + src/test/ui/E0506.ast.stderr | 11 + src/test/ui/E0506.mir.stderr | 14 + src/test/{compile-fail => ui}/E0506.rs | 0 src/test/ui/E0508-fail.ast.nll.stderr | 12 + src/test/ui/E0508-fail.ast.stderr | 12 + src/test/ui/E0508-fail.mir.stderr | 12 + .../E0508.rs => ui/E0508-fail.rs} | 0 src/test/ui/E0508.ast.stderr | 12 + src/test/ui/E0508.mir.stderr | 12 + src/test/ui/E0508.nll.stderr | 12 + src/test/{compile-fail => ui}/E0583.rs | 0 src/test/ui/E0583.stderr | 11 + src/test/ui/E0594.ast.nll.stderr | 9 + src/test/ui/E0594.ast.stderr | 9 + src/test/ui/E0594.mir.stderr | 9 + src/test/{compile-fail => ui}/E0594.rs | 0 src/test/ui/E0596.ast.nll.stderr | 11 + src/test/ui/E0596.ast.stderr | 11 + src/test/ui/E0596.mir.stderr | 11 + src/test/{compile-fail => ui}/E0596.rs | 0 src/test/ui/E0642.rs | 24 + src/test/ui/E0642.stderr | 23 + src/test/ui/E0660.rs | 2 - src/test/ui/E0660.stderr | 4 +- src/test/ui/E0661.rs | 2 - src/test/ui/E0661.stderr | 2 +- src/test/ui/E0662.rs | 2 - src/test/ui/E0662.stderr | 2 +- src/test/ui/E0663.rs | 2 - src/test/ui/E0663.stderr | 2 +- src/test/ui/E0664.rs | 2 - src/test/ui/E0664.stderr | 2 +- src/test/ui/E0665.rs | 2 - src/test/ui/E0665.stderr | 2 +- src/test/ui/E0705.rs | 17 + src/test/ui/E0705.stderr | 6 + .../absolute-paths-in-nested-use-groups.rs | 0 ...absolute-paths-in-nested-use-groups.stderr | 21 + .../ui/access-mode-in-closures.nll.stderr | 18 + .../access-mode-in-closures.rs | 0 src/test/ui/access-mode-in-closures.stderr | 11 + .../alloc-error-handler-bad-signature-1.rs | 4 +- ...alloc-error-handler-bad-signature-1.stderr | 14 + .../alloc-error-handler-bad-signature-2.rs | 4 +- ...alloc-error-handler-bad-signature-2.stderr | 14 + .../alloc-error-handler-bad-signature-3.rs | 4 +- ...alloc-error-handler-bad-signature-3.stderr | 8 + .../allocator/auxiliary/system-allocator.rs | 0 .../allocator/auxiliary/system-allocator2.rs | 0 .../allocator/function-allocator.rs | 0 .../ui/allocator/function-allocator.stderr | 8 + .../allocator/not-an-allocator.rs | 0 src/test/ui/allocator/not-an-allocator.stderr | 35 + .../allocator/two-allocators.rs | 0 src/test/ui/allocator/two-allocators.stderr | 8 + .../allocator/two-allocators2.rs | 0 src/test/ui/allocator/two-allocators2.stderr | 4 + .../allocator/two-allocators3.rs | 0 src/test/ui/allocator/two-allocators3.stderr | 4 + src/test/ui/anon-params-denied-2018.rs | 12 + src/test/ui/anon-params-denied-2018.stderr | 14 + src/test/ui/anon-params-deprecated.fixed | 19 + src/test/ui/anon-params-deprecated.rs | 19 + src/test/ui/anon-params-deprecated.stderr | 32 + .../arg-count-mismatch.rs | 0 src/test/ui/arg-count-mismatch.stderr | 12 + .../{compile-fail => ui}/arg-type-mismatch.rs | 0 src/test/ui/arg-type-mismatch.stderr | 12 + .../{compile-fail => ui}/array-not-vector.rs | 0 src/test/ui/array-not-vector.stderr | 21 + .../array_const_index-0.rs | 0 src/test/ui/array_const_index-0.stderr | 12 + .../array_const_index-1.rs | 0 src/test/ui/array_const_index-1.stderr | 12 + .../asm}/asm-bad-clobber.rs | 0 src/test/ui/asm/asm-bad-clobber.stderr | 9 + .../asm}/asm-in-bad-modifier.rs | 0 src/test/ui/asm/asm-in-bad-modifier.stderr | 16 + .../asm}/asm-misplaced-option.rs | 0 src/test/ui/asm/asm-misplaced-option.stderr | 26 + .../{ => asm}/asm-out-assign-imm.nll.stderr | 4 +- src/test/ui/{ => asm}/asm-out-assign-imm.rs | 1 + .../ui/{ => asm}/asm-out-assign-imm.stderr | 2 +- .../asm}/asm-out-no-modifier.rs | 0 src/test/ui/asm/asm-out-no-modifier.stderr | 9 + .../ui/asm/asm-out-read-uninit.ast.stderr | 9 + .../ui/asm/asm-out-read-uninit.mir.stderr | 9 + .../asm}/asm-out-read-uninit.rs | 0 .../ui/assign-imm-local-twice.ast.nll.stderr | 15 + src/test/ui/assign-imm-local-twice.ast.stderr | 12 + src/test/ui/assign-imm-local-twice.mir.stderr | 15 + .../assign-imm-local-twice.rs | 3 +- .../{compile-fail => ui}/assign-to-method.rs | 0 src/test/ui/assign-to-method.stderr | 11 + .../assignment-operator-unimplemented.rs | 0 .../assignment-operator-unimplemented.stderr | 13 + .../{compile-fail => ui}/assoc-inherent.rs | 0 src/test/ui/assoc-inherent.stderr | 9 + .../associated-const-ambiguity-report.rs | 0 .../associated-const-ambiguity-report.stderr | 20 + .../associated-const-array-len.rs | 0 .../associated-const-array-len.stderr | 15 + .../associated-const-dead-code.rs | 0 .../associated-const-dead-code.stderr | 14 + .../associated-const-generic-obligations.rs | 0 ...ssociated-const-generic-obligations.stderr | 11 + .../associated-const-impl-wrong-lifetime.rs | 0 ...ssociated-const-impl-wrong-lifetime.stderr | 0 .../associated-const-impl-wrong-type.rs | 0 .../associated-const-impl-wrong-type.stderr | 0 .../associated-const-in-trait.rs | 0 .../associated-const-in-trait.stderr | 11 + .../associated-const-no-item.rs | 0 .../associated-const-no-item.stderr | 13 + .../associated-const-private-impl.rs | 0 .../associated-const-private-impl.stderr | 9 + .../associated-const-type-parameter-arms.rs | 0 ...ssociated-const-type-parameter-arms.stderr | 15 + ...ssociated-const-type-parameter-arrays-2.rs | 0 ...iated-const-type-parameter-arrays-2.stderr | 16 + .../associated-const-type-parameter-arrays.rs | 0 ...ociated-const-type-parameter-arrays.stderr | 16 + .../associated-const-upper-case-lint.rs | 0 .../associated-const-upper-case-lint.stderr | 14 + .../associated-item-duplicate-names-2.rs | 0 .../associated-item-duplicate-names-2.stderr | 11 + .../associated-item-duplicate-names-3.rs | 0 .../associated-item-duplicate-names-3.stderr | 11 + .../associated-item-duplicate-names.rs | 0 .../associated-item-duplicate-names.stderr | 19 + .../associated-path-shl.rs | 0 src/test/ui/associated-path-shl.stderr | 43 + ...on-ambig-between-bound-and-where-clause.rs | 0 ...mbig-between-bound-and-where-clause.stderr | 75 + ...pe-projection-from-multiple-supertraits.rs | 0 ...rojection-from-multiple-supertraits.stderr | 0 ...ociated-type-projection-from-supertrait.rs | 0 ...ted-type-projection-from-supertrait.stderr | 39 + ...ed-types-ICE-when-projecting-out-of-err.rs | 0 ...ypes-ICE-when-projecting-out-of-err.stderr | 0 ...s-binding-to-type-defined-in-supertrait.rs | 0 ...nding-to-type-defined-in-supertrait.stderr | 31 + .../associated-types-bound-failure.rs | 0 .../associated-types-bound-failure.stderr | 16 + .../associated-types-coherence-failure.rs | 0 .../associated-types-coherence-failure.stderr | 21 + .../associated-types-eq-1.rs | 0 .../associated-types-eq-1.stderr | 9 + .../associated-types-eq-2.rs | 0 .../associated-types-eq-2.stderr | 9 + .../associated-types-eq-3.rs | 0 .../associated-types-eq-3.stderr | 37 + .../associated-types-eq-expr-path.rs | 0 .../associated-types-eq-expr-path.stderr | 9 + .../associated-types-eq-hr.rs | 0 .../associated-types-eq-hr.stderr | 126 + .../associated-types-for-unimpl-trait.rs | 0 .../associated-types-for-unimpl-trait.stderr | 11 + .../associated-types-in-ambiguous-context.rs | 0 ...sociated-types-in-ambiguous-context.stderr | 0 .../associated-types-incomplete-object.rs | 2 +- .../associated-types-incomplete-object.stderr | 27 + ...ted-types-invalid-trait-ref-issue-18865.rs | 0 ...types-invalid-trait-ref-issue-18865.stderr | 11 + .../associated-types-issue-17359.rs | 0 .../associated-types-issue-17359.stderr | 12 + .../associated-types-issue-20346.rs | 0 .../associated-types-issue-20346.stderr | 17 + ...sociated-types-multiple-types-one-trait.rs | 0 ...ated-types-multiple-types-one-trait.stderr | 31 + .../associated-types-no-suitable-bound.rs | 0 .../associated-types-no-suitable-bound.stderr | 11 + ...sociated-types-no-suitable-supertrait-2.rs | 0 ...ated-types-no-suitable-supertrait-2.stderr | 11 + ...associated-types-no-suitable-supertrait.rs | 0 ...ciated-types-no-suitable-supertrait.stderr | 17 + .../associated-types-outlives.nll.stderr | 13 + .../associated-types-outlives.rs | 0 .../associated-types-outlives.stderr | 11 + .../associated-types-overridden-default.rs | 0 ...associated-types-overridden-default.stderr | 9 + .../associated-types-path-1.rs | 0 .../associated-types-path-1.stderr | 22 + .../associated-types-path-2.rs | 0 .../associated-types-path-2.stderr | 52 + ...es-project-from-hrtb-in-fn-body.nll.stderr | 24 + ...ated-types-project-from-hrtb-in-fn-body.rs | 0 ...-types-project-from-hrtb-in-fn-body.stderr | 14 + ...ssociated-types-project-from-hrtb-in-fn.rs | 0 ...iated-types-project-from-hrtb-in-fn.stderr | 9 + ...iated-types-project-from-hrtb-in-struct.rs | 0 ...d-types-project-from-hrtb-in-struct.stderr | 9 + ...types-project-from-hrtb-in-trait-method.rs | 0 ...s-project-from-hrtb-in-trait-method.stderr | 9 + ...related-trait-in-method-without-default.rs | 0 ...ted-trait-in-method-without-default.stderr | 11 + .../associated-types-subtyping-1.rs | 10 +- .../associated-types-subtyping-1.stderr | 21 + .../associated-types-unconstrained.rs | 0 .../associated-types-unconstrained.stderr | 9 + .../associated-types-unsized.rs | 0 .../associated-types-unsized.stderr | 15 + .../bound-lifetime-constrained.clause.stderr | 15 + .../bound-lifetime-constrained.func.stderr | 15 + .../bound-lifetime-constrained.object.stderr | 15 + .../bound-lifetime-constrained.rs | 0 ...ound-lifetime-in-binding-only.angle.stderr | 27 + ...nd-lifetime-in-binding-only.elision.stderr | 12 + .../bound-lifetime-in-binding-only.ok.stderr | 8 + ...ound-lifetime-in-binding-only.paren.stderr | 27 + .../bound-lifetime-in-binding-only.rs | 0 ...und-lifetime-in-return-only.elision.stderr | 12 + ...bound-lifetime-in-return-only.local.stderr | 9 + .../bound-lifetime-in-return-only.ok.stderr | 8 + .../bound-lifetime-in-return-only.rs | 0 .../bound-lifetime-in-return-only.sig.stderr | 15 + ...d-lifetime-in-return-only.structure.stderr | 9 + .../associated-types/cache/chrono-scan.rs | 0 .../associated-types/cache/chrono-scan.stderr | 8 + .../associated-types/cache/elision.rs | 0 .../ui/associated-types/cache/elision.stderr | 8 + ...fn-ret-contravariant.krisskross.nll.stderr | 23 + ...ect-fn-ret-contravariant.krisskross.stderr | 25 + .../project-fn-ret-contravariant.ok.stderr | 8 + ...project-fn-ret-contravariant.oneuse.stderr | 8 + .../cache/project-fn-ret-contravariant.rs | 0 ...-fn-ret-contravariant.transmute.nll.stderr | 20 + ...ject-fn-ret-contravariant.transmute.stderr | 26 + ...ect-fn-ret-invariant.krisskross.nll.stderr | 23 + ...project-fn-ret-invariant.krisskross.stderr | 24 + .../cache/project-fn-ret-invariant.ok.stderr | 8 + ...project-fn-ret-invariant.oneuse.nll.stderr | 24 + .../project-fn-ret-invariant.oneuse.stderr | 14 + .../cache/project-fn-ret-invariant.rs | 0 ...ject-fn-ret-invariant.transmute.nll.stderr | 22 + .../project-fn-ret-invariant.transmute.stderr | 22 + .../higher-ranked-projection.bad.stderr | 17 + .../higher-ranked-projection.good.stderr | 12 + .../higher-ranked-projection.rs | 0 .../associated-types/issue-36499.rs | 0 .../ui/associated-types/issue-36499.stderr | 8 + src/test/ui/async-matches-expr.rs | 23 + .../attempted-access-non-fatal.rs | 0 src/test/ui/attempted-access-non-fatal.stderr | 15 + .../attr-bad-crate-attr.rc | 0 src/test/ui/attr-eq-token-tree.rs | 16 + .../{compile-fail => ui}/attr-usage-inline.rs | 0 src/test/ui/attr-usage-inline.stderr | 11 + src/test/ui/attr-usage-repr.rs | 1 - src/test/ui/attr-usage-repr.stderr | 10 +- .../attrs-with-no-formal-in-generics-1.rs | 0 .../attrs-with-no-formal-in-generics-1.stderr | 8 + .../attrs-with-no-formal-in-generics-2.rs | 0 .../attrs-with-no-formal-in-generics-2.stderr | 8 + .../attrs-with-no-formal-in-generics-3.rs | 0 .../attrs-with-no-formal-in-generics-3.stderr | 8 + src/test/ui/augmented-assignments.nll.stderr | 4 +- src/test/ui/augmented-assignments.rs | 3 +- src/test/ui/augmented-assignments.stderr | 6 +- .../auto-ref-slice-plus-ref.rs | 0 src/test/ui/auto-ref-slice-plus-ref.stderr | 44 + .../auto-trait-validation.rs | 0 src/test/ui/auto-trait-validation.stderr | 22 + .../autoderef-full-lval.rs | 0 src/test/ui/autoderef-full-lval.stderr | 19 + .../auxiliary/cdylib-dep.rs | 0 src/test/ui/auxiliary/coherence_lib.rs | 25 - .../default_ty_param_cross_crate_crate.rs | 0 .../auxiliary/define_macro.rs | 0 .../auxiliary/extern-statics.rs | 0 src/test/ui/auxiliary/lint_output_format.rs | 30 - .../ui/auxiliary/lto-duplicate-symbols1.rs | 16 + .../ui/auxiliary/lto-duplicate-symbols2.rs | 16 + src/test/ui/auxiliary/macro-in-other-crate.rs | 14 - .../auxiliary/namespaced_enums.rs | 0 .../auxiliary/noexporttypelib.rs | 0 .../auxiliary/orphan_check_diagnostics.rs | 0 .../auxiliary/rmeta_meta.rs | 0 .../auxiliary/rmeta_rlib.rs | 0 src/test/ui/auxiliary/stability_cfg2.rs | 15 + src/test/ui/auxiliary/weak-lang-items.rs | 32 + .../auxiliary/xc_private_method_lib.rs | 0 .../bad}/bad-const-type.rs | 0 src/test/ui/bad/bad-const-type.stderr | 15 + src/test/ui/{ => bad}/bad-crate-name.rs | 0 src/test/ui/{ => bad}/bad-crate-name.stderr | 0 .../bad}/bad-env-capture.rs | 0 src/test/ui/bad/bad-env-capture.stderr | 24 + .../bad}/bad-env-capture2.rs | 0 src/test/ui/bad/bad-env-capture2.stderr | 24 + .../bad}/bad-env-capture3.rs | 0 src/test/ui/bad/bad-env-capture3.stderr | 24 + .../{compile-fail => ui/bad}/bad-expr-lhs.rs | 0 src/test/ui/bad/bad-expr-lhs.stderr | 34 + .../{compile-fail => ui/bad}/bad-expr-path.rs | 0 src/test/ui/bad/bad-expr-path.stderr | 31 + .../bad}/bad-expr-path2.rs | 0 src/test/ui/bad/bad-expr-path2.stderr | 31 + .../bad}/bad-extern-link-attrs.rs | 0 src/test/ui/bad/bad-extern-link-attrs.stderr | 24 + .../bad}/bad-intrinsic-monomorphization.rs | 0 .../bad/bad-intrinsic-monomorphization.stderr | 21 + .../{compile-fail => ui/bad}/bad-lint-cap.rs | 0 src/test/ui/bad/bad-lint-cap.stderr | 2 + .../{compile-fail => ui/bad}/bad-lint-cap2.rs | 0 src/test/ui/bad/bad-lint-cap2.stderr | 15 + .../{compile-fail => ui/bad}/bad-lint-cap3.rs | 0 src/test/ui/bad/bad-lint-cap3.stderr | 21 + src/test/{compile-fail => ui/bad}/bad-main.rs | 0 src/test/ui/bad/bad-main.stderr | 12 + .../bad}/bad-method-typaram-kind.rs | 0 .../ui/bad/bad-method-typaram-kind.stderr | 12 + .../bad}/bad-mid-path-type-params.rs | 8 +- .../ui/bad/bad-mid-path-type-params.stderr | 27 + .../{compile-fail => ui/bad}/bad-module.rs | 0 src/test/ui/bad/bad-module.stderr | 15 + .../{compile-fail => ui/bad}/bad-sized.rs | 0 src/test/ui/bad/bad-sized.stderr | 30 + .../bad}/bad-type-env-capture.rs | 0 src/test/ui/bad/bad-type-env-capture.stderr | 13 + src/test/ui/bastion-of-the-turbofish.rs | 46 + ...her-can-live-while-the-other-survives-2.rs | 0 ...can-live-while-the-other-survives-2.stderr | 11 + ...her-can-live-while-the-other-survives-3.rs | 0 ...can-live-while-the-other-survives-3.stderr | 11 + ...her-can-live-while-the-other-survives-4.rs | 0 ...can-live-while-the-other-survives-4.stderr | 11 + .../bind-by-move}/bind-by-move-no-guards.rs | 0 .../bind-by-move-no-guards.stderr | 9 + .../binop}/binop-bitxor-str.rs | 0 src/test/ui/binop/binop-bitxor-str.stderr | 11 + .../binop}/binop-consume-args.rs | 0 src/test/ui/binop/binop-consume-args.stderr | 213 + .../binop}/binop-logic-float.rs | 0 src/test/ui/binop/binop-logic-float.stderr | 15 + .../binop}/binop-logic-int.rs | 0 src/test/ui/binop/binop-logic-int.stderr | 21 + .../ui/binop/binop-move-semantics.nll.stderr | 68 + .../binop}/binop-move-semantics.rs | 0 src/test/ui/binop/binop-move-semantics.stderr | 80 + .../binop}/binop-mul-bool.rs | 0 src/test/ui/binop/binop-mul-bool.stderr | 11 + .../binop}/binop-typeck.rs | 0 src/test/ui/binop/binop-typeck.stderr | 11 + .../blind}/blind-item-block-item-shadow.rs | 0 .../blind/blind-item-block-item-shadow.stderr | 17 + .../blind}/blind-item-block-middle.rs | 0 .../ui/blind/blind-item-block-middle.stderr | 12 + .../ui/{ => blind}/blind-item-item-shadow.rs | 0 .../{ => blind}/blind-item-item-shadow.stderr | 0 .../borrowck/assign_mutable_fields.nll.stderr | 9 + src/test/ui/borrowck/assign_mutable_fields.rs | 32 + .../ui/borrowck/assign_mutable_fields.stderr | 21 + ...borrow-immutable-upvar-mutation.nll.stderr | 76 + .../borrow-immutable-upvar-mutation.rs | 0 .../borrow-immutable-upvar-mutation.stderr | 78 + .../borrowck/borrow-tuple-fields.nll.stderr | 65 + src/test/ui/borrowck/borrow-tuple-fields.rs | 53 + .../ui/borrowck/borrow-tuple-fields.stderr | 64 + ...borrowck-access-permissions.ast.nll.stderr | 53 + .../borrowck-access-permissions.ast.stderr | 46 + .../borrowck-access-permissions.mir.stderr | 53 + .../borrowck/borrowck-access-permissions.rs | 0 .../ui/borrowck/borrowck-and-init.nll.stderr | 9 + .../borrowck/borrowck-and-init.rs | 0 src/test/ui/borrowck/borrowck-and-init.stderr | 9 + .../borrowck-anon-fields-struct.nll.stderr | 40 + .../borrowck/borrowck-anon-fields-struct.rs | 0 .../borrowck-anon-fields-struct.stderr | 15 + .../borrowck-anon-fields-tuple.nll.stderr | 40 + .../borrowck/borrowck-anon-fields-tuple.rs | 0 .../borrowck-anon-fields-tuple.stderr | 15 + .../borrowck-anon-fields-variant.nll.stderr | 40 + .../borrowck/borrowck-anon-fields-variant.rs | 0 .../borrowck-anon-fields-variant.stderr | 15 + .../ui/borrowck/borrowck-argument.nll.stderr | 35 + .../borrowck/borrowck-argument.rs | 0 src/test/ui/borrowck/borrowck-argument.stderr | 35 + .../ui/borrowck/borrowck-asm.ast.nll.stderr | 79 + src/test/ui/borrowck/borrowck-asm.ast.stderr | 76 + src/test/ui/borrowck/borrowck-asm.mir.stderr | 79 + .../borrowck/borrowck-asm.rs | 0 .../borrowck-assign-comp-idx.nll.stderr | 27 + .../borrowck/borrowck-assign-comp-idx.rs | 0 .../borrowck/borrowck-assign-comp-idx.stderr | 26 + .../borrowck-assign-comp.ast.nll.stderr | 37 + .../borrowck/borrowck-assign-comp.ast.stderr | 28 + .../borrowck/borrowck-assign-comp.mir.stderr | 37 + .../borrowck/borrowck-assign-comp.rs | 0 ...sign-to-andmut-in-aliasable-loc.nll.stderr | 19 + ...rowck-assign-to-andmut-in-aliasable-loc.rs | 0 ...k-assign-to-andmut-in-aliasable-loc.stderr | 19 + ...ssign-to-andmut-in-borrowed-loc.nll.stderr | 24 + ...rrowck-assign-to-andmut-in-borrowed-loc.rs | 0 ...ck-assign-to-andmut-in-borrowed-loc.stderr | 11 + ...orrowck-assign-to-constants.ast.nll.stderr | 9 + .../borrowck-assign-to-constants.ast.stderr | 9 + .../borrowck-assign-to-constants.mir.stderr | 9 + .../borrowck/borrowck-assign-to-constants.rs | 0 ...rowck-auto-mut-ref-to-immut-var.nll.stderr | 11 + .../borrowck-auto-mut-ref-to-immut-var.rs | 0 .../borrowck-auto-mut-ref-to-immut-var.stderr | 11 + .../borrowck/borrowck-autoref-3261.nll.stderr | 22 + .../borrowck/borrowck-autoref-3261.rs | 0 .../ui/borrowck/borrowck-autoref-3261.stderr | 17 + .../borrowck-bad-nested-calls-free.nll.stderr | 25 + .../borrowck-bad-nested-calls-free.rs | 0 .../borrowck-bad-nested-calls-free.stderr | 23 + .../borrowck-bad-nested-calls-move.nll.stderr | 25 + .../borrowck-bad-nested-calls-move.rs | 0 .../borrowck-bad-nested-calls-move.stderr | 19 + .../borrowck/borrowck-block-unint.nll.stderr | 11 + .../borrowck/borrowck-block-unint.rs | 0 .../ui/borrowck/borrowck-block-unint.stderr | 9 + .../borrowck-borrow-from-owned-ptr.nll.stderr | 127 + .../borrowck-borrow-from-owned-ptr.rs | 0 .../borrowck-borrow-from-owned-ptr.stderr | 168 + ...owck-borrow-from-stack-variable.nll.stderr | 127 + .../borrowck-borrow-from-stack-variable.rs | 0 ...borrowck-borrow-from-stack-variable.stderr | 124 + .../borrowck-borrow-from-temporary.rs | 0 .../borrowck-borrow-from-temporary.stderr | 18 + ...orrow-immut-deref-of-box-as-mut.nll.stderr | 11 + ...rrowck-borrow-immut-deref-of-box-as-mut.rs | 0 ...ck-borrow-immut-deref-of-box-as-mut.stderr | 11 + ...w-mut-base-ptr-in-aliasable-loc.nll.stderr | 31 + ...ck-borrow-mut-base-ptr-in-aliasable-loc.rs | 0 ...orrow-mut-base-ptr-in-aliasable-loc.stderr | 29 + ...orrowck-borrow-mut-object-twice.nll.stderr | 13 + .../borrowck-borrow-mut-object-twice.rs | 8 +- .../borrowck-borrow-mut-object-twice.stderr | 14 + ...ck-borrow-overloaded-auto-deref.nll.stderr | 88 + .../borrowck-borrow-overloaded-auto-deref.rs | 0 ...rrowck-borrow-overloaded-auto-deref.stderr | 88 + ...orrowck-borrow-overloaded-deref.nll.stderr | 46 + .../borrowck-borrow-overloaded-deref.rs | 0 .../borrowck-borrow-overloaded-deref.stderr | 46 + ...borrowck-borrowed-uniq-rvalue-2.nll.stderr | 16 + .../borrowck-borrowed-uniq-rvalue-2.rs | 0 .../borrowck-borrowed-uniq-rvalue-2.stderr | 17 + .../borrowck-borrowed-uniq-rvalue.nll.stderr | 16 + .../borrowck/borrowck-borrowed-uniq-rvalue.rs | 0 .../borrowck-borrowed-uniq-rvalue.stderr | 16 + .../borrowck-box-insensitivity.nll.stderr | 35 +- .../ui/borrowck/borrowck-box-insensitivity.rs | 3 +- .../borrowck-break-uninit-2.nll.stderr | 9 + .../borrowck/borrowck-break-uninit-2.rs | 0 .../borrowck/borrowck-break-uninit-2.stderr | 9 + .../borrowck/borrowck-break-uninit.nll.stderr | 9 + .../borrowck/borrowck-break-uninit.rs | 0 .../ui/borrowck/borrowck-break-uninit.stderr | 9 + ...rrowck-closures-mut-and-imm.ast.nll.stderr | 116 + .../borrowck-closures-mut-and-imm.ast.stderr | 96 + .../borrowck-closures-mut-and-imm.mir.stderr | 116 + .../borrowck/borrowck-closures-mut-and-imm.rs | 0 .../borrowck-closures-mut-of-imm.nll.stderr | 15 + .../borrowck/borrowck-closures-mut-of-imm.rs | 0 .../borrowck-closures-mut-of-imm.stderr | 32 + .../borrowck-closures-two-mut-fail.nll.stderr | 75 + .../borrowck-closures-two-mut-fail.rs | 69 + .../borrowck-closures-two-mut-fail.stderr | 78 + .../borrowck/borrowck-closures-two-mut.stderr | 20 +- .../borrowck-closures-unique-imm.nll.stderr | 13 + .../borrowck/borrowck-closures-unique-imm.rs | 6 + .../borrowck-closures-unique-imm.stderr | 14 + .../borrowck-closures-unique.nll.stderr | 54 + .../ui/borrowck/borrowck-closures-unique.rs | 67 + .../borrowck/borrowck-closures-unique.stderr | 69 + ...orrowck-closures-use-after-free.nll.stderr | 17 + .../borrowck-closures-use-after-free.rs | 0 .../borrowck-closures-use-after-free.stderr | 16 + .../borrowck/borrowck-consume-unsize-vec.rs | 0 .../borrowck-consume-unsize-vec.stderr | 13 + .../borrowck-consume-upcast-box.nll.stderr | 13 + .../borrowck/borrowck-consume-upcast-box.rs | 0 .../borrowck-consume-upcast-box.stderr | 13 + .../borrowck-describe-lvalue.ast.nll.stderr | 540 ++ .../borrowck-describe-lvalue.ast.stderr | 246 + .../borrowck-describe-lvalue.mir.stderr | 540 ++ .../borrowck/borrowck-describe-lvalue.rs | 0 .../borrowck/borrowck-drop-from-guard.rs | 0 .../borrowck/borrowck-drop-from-guard.stderr | 14 + ...rrowck-escaping-closure-error-1.nll.stderr | 6 +- ...rrowck-escaping-closure-error-2.nll.stderr | 6 +- .../borrowck-feature-nll-overrides-migrate.rs | 2 +- .../borrowck-field-sensitivity.nll.stderr | 110 + .../borrowck/borrowck-field-sensitivity.rs | 0 .../borrowck-field-sensitivity.stderr | 129 + .../borrowck-fn-in-const-a.ast.stderr | 9 + .../borrowck-fn-in-const-a.mir.stderr | 9 + .../borrowck/borrowck-fn-in-const-a.rs | 0 .../borrowck-fn-in-const-c.nll.stderr | 13 + .../borrowck/borrowck-fn-in-const-c.rs | 0 .../ui/borrowck/borrowck-fn-in-const-c.stderr | 13 + ...or-loop-correct-cmt-for-pattern.nll.stderr | 48 + ...rrowck-for-loop-correct-cmt-for-pattern.rs | 0 ...ck-for-loop-correct-cmt-for-pattern.stderr | 30 + .../borrowck-for-loop-head-linkage.nll.stderr | 27 + .../borrowck-for-loop-head-linkage.rs | 0 .../borrowck-for-loop-head-linkage.stderr | 27 + .../borrowck/borrowck-if-no-else.rs | 0 .../ui/borrowck/borrowck-if-no-else.stderr | 9 + .../borrowck/borrowck-if-with-else.rs | 0 .../ui/borrowck/borrowck-if-with-else.stderr | 9 + ...-mut-rec-field-issue-3162-c.ast.nll.stderr | 15 + ...f-to-mut-rec-field-issue-3162-c.ast.stderr | 12 + ...f-to-mut-rec-field-issue-3162-c.mir.stderr | 15 + ...k-imm-ref-to-mut-rec-field-issue-3162-c.rs | 0 .../ui/borrowck/borrowck-in-static.nll.stderr | 2 + .../borrowck-init-in-called-fn-expr.rs | 0 .../borrowck-init-in-called-fn-expr.stderr | 9 + .../borrowck/borrowck-init-in-fn-expr.rs | 0 .../borrowck/borrowck-init-in-fn-expr.stderr | 9 + .../borrowck-init-in-fru.ast.nll.stderr | 9 + .../borrowck/borrowck-init-in-fru.ast.stderr | 9 + .../borrowck/borrowck-init-in-fru.mir.stderr | 9 + .../borrowck/borrowck-init-in-fru.rs | 0 .../borrowck/borrowck-init-op-equal.rs | 0 .../ui/borrowck/borrowck-init-op-equal.stderr | 9 + .../borrowck/borrowck-init-plus-equal.rs | 0 .../borrowck/borrowck-init-plus-equal.stderr | 9 + .../borrowck-insert-during-each.nll.stderr | 36 + .../borrowck/borrowck-insert-during-each.rs | 0 .../borrowck-insert-during-each.stderr | 15 + .../borrowck-issue-14498.ast.nll.stderr | 108 + .../borrowck/borrowck-issue-14498.ast.stderr | 82 + .../borrowck/borrowck-issue-14498.mir.stderr | 108 + .../borrowck/borrowck-issue-14498.rs | 0 .../borrowck/borrowck-issue-2657-1.nll.stderr | 13 + .../borrowck/borrowck-issue-2657-1.rs | 6 + .../ui/borrowck/borrowck-issue-2657-1.stderr | 11 + .../borrowck/borrowck-issue-2657-2.nll.stderr | 12 + .../borrowck/borrowck-issue-2657-2.rs | 0 .../ui/borrowck/borrowck-issue-2657-2.stderr | 12 + .../borrowck/borrowck-issue-48962.rs | 0 .../ui/borrowck/borrowck-issue-48962.stderr | 23 + .../borrowck/borrowck-lend-flow-if.rs | 2 + .../ui/borrowck/borrowck-lend-flow-if.stderr | 14 + .../borrowck-lend-flow-loop.nll.stderr | 26 + .../borrowck/borrowck-lend-flow-loop.rs | 0 .../borrowck/borrowck-lend-flow-loop.stderr | 93 + .../borrowck-lend-flow-match.ast.nll.stderr | 14 + .../borrowck-lend-flow-match.ast.stderr | 11 + .../borrowck-lend-flow-match.mir.stderr | 14 + .../borrowck/borrowck-lend-flow-match.rs | 0 .../borrowck/borrowck-lend-flow.rs | 2 + .../ui/borrowck/borrowck-lend-flow.stderr | 13 + .../borrowck-loan-blocks-move-cc.nll.stderr | 29 + .../borrowck/borrowck-loan-blocks-move-cc.rs | 11 +- .../borrowck-loan-blocks-move-cc.stderr | 21 + .../borrowck-loan-blocks-move.nll.stderr | 13 + .../borrowck/borrowck-loan-blocks-move.rs | 8 +- .../borrowck/borrowck-loan-blocks-move.stderr | 11 + .../borrowck-loan-blocks-mut-uniq.nll.stderr | 19 + .../borrowck/borrowck-loan-blocks-mut-uniq.rs | 0 .../borrowck-loan-blocks-mut-uniq.stderr | 16 + .../borrowck-loan-in-overloaded-op.nll.stderr | 13 + .../borrowck-loan-in-overloaded-op.rs | 0 .../borrowck-loan-in-overloaded-op.stderr | 13 + ...loan-of-static-data-issue-27616.nll.stderr | 14 + ...orrowck-loan-of-static-data-issue-27616.rs | 0 ...wck-loan-of-static-data-issue-27616.stderr | 12 + ...orrowck-loan-rcvr-overloaded-op.nll.stderr | 28 + .../borrowck-loan-rcvr-overloaded-op.rs | 0 .../borrowck-loan-rcvr-overloaded-op.stderr | 25 + .../ui/borrowck/borrowck-loan-rcvr.nll.stderr | 27 + .../borrowck/borrowck-loan-rcvr.rs | 0 .../ui/borrowck/borrowck-loan-rcvr.stderr | 26 + .../borrowck-loan-vec-content.nll.stderr | 16 + .../borrowck/borrowck-loan-vec-content.rs | 0 .../borrowck/borrowck-loan-vec-content.stderr | 15 + ...ck-local-borrow-outlives-fn.ast.nll.stderr | 14 + ...rrowck-local-borrow-outlives-fn.ast.stderr | 14 + ...rrowck-local-borrow-outlives-fn.mir.stderr | 14 + .../borrowck-local-borrow-outlives-fn.rs | 0 ...rrow-with-panic-outlives-fn.ast.nll.stderr | 14 + ...l-borrow-with-panic-outlives-fn.ast.stderr | 14 + ...l-borrow-with-panic-outlives-fn.mir.stderr | 14 + ...wck-local-borrow-with-panic-outlives-fn.rs | 0 ...owck-match-already-borrowed.ast.nll.stderr | 73 + ...borrowck-match-already-borrowed.ast.stderr | 30 + ...borrowck-match-already-borrowed.mir.stderr | 73 + .../borrowck-match-already-borrowed.rs | 0 ...match-binding-is-assignment.ast.nll.stderr | 58 + ...wck-match-binding-is-assignment.ast.stderr | 43 + ...wck-match-binding-is-assignment.mir.stderr | 58 + .../borrowck-match-binding-is-assignment.rs | 0 .../ui/borrowck/borrowck-migrate-to-nll.rs | 2 +- .../borrowck-move-by-capture.nll.stderr | 12 + .../borrowck/borrowck-move-by-capture.rs | 0 .../borrowck/borrowck-move-by-capture.stderr | 12 + .../borrowck-move-error-with-note.nll.stderr | 45 +- ...e-from-subpath-of-borrowed-path.nll.stderr | 14 + ...owck-move-from-subpath-of-borrowed-path.rs | 6 + ...-move-from-subpath-of-borrowed-path.stderr | 12 + .../borrowck-move-from-unsafe-ptr.nll.stderr | 12 + .../borrowck/borrowck-move-from-unsafe-ptr.rs | 0 .../borrowck-move-from-unsafe-ptr.stderr | 12 + ...orrowck-move-in-irrefut-pat.ast.nll.stderr | 50 + .../borrowck-move-in-irrefut-pat.ast.stderr | 30 + .../borrowck-move-in-irrefut-pat.mir.stderr | 50 + .../borrowck/borrowck-move-in-irrefut-pat.rs | 0 ...ve-moved-value-into-closure.ast.nll.stderr | 17 + ...k-move-moved-value-into-closure.ast.stderr | 13 + ...k-move-moved-value-into-closure.mir.stderr | 17 + .../borrowck-move-moved-value-into-closure.rs | 0 .../borrowck-move-mut-base-ptr.nll.stderr | 14 + .../borrowck/borrowck-move-mut-base-ptr.rs | 6 + .../borrowck-move-mut-base-ptr.stderr | 11 + ...orrowck-move-out-from-array.ast.nll.stderr | 19 + .../borrowck-move-out-from-array.ast.stderr | 23 + .../borrowck-move-out-from-array.mir.stderr | 19 + .../borrowck/borrowck-move-out-from-array.rs | 0 ...ve-out-of-overloaded-auto-deref.ast.stderr | 9 + ...ve-out-of-overloaded-auto-deref.mir.stderr | 9 + ...rowck-move-out-of-overloaded-auto-deref.rs | 0 ...ck-move-out-of-overloaded-deref.nll.stderr | 12 + .../borrowck-move-out-of-overloaded-deref.rs | 0 ...rrowck-move-out-of-overloaded-deref.stderr | 12 + ...orrowck-move-out-of-static-item.ast.stderr | 9 + ...orrowck-move-out-of-static-item.mir.stderr | 9 + .../borrowck-move-out-of-static-item.rs | 0 ...ove-out-of-struct-with-dtor.ast.nll.stderr | 47 + ...ck-move-out-of-struct-with-dtor.ast.stderr | 30 + ...ck-move-out-of-struct-with-dtor.mir.stderr | 47 + .../borrowck-move-out-of-struct-with-dtor.rs | 0 ...e-out-of-tuple-struct-with-dtor.nll.stderr | 46 + ...owck-move-out-of-tuple-struct-with-dtor.rs | 0 ...-move-out-of-tuple-struct-with-dtor.stderr | 30 + .../borrowck-move-out-of-vec-tail.nll.stderr | 26 +- .../borrowck-move-subcomponent.nll.stderr | 13 + .../borrowck/borrowck-move-subcomponent.rs | 0 .../borrowck-move-subcomponent.stderr | 11 + .../borrowck-multiple-captures.nll.stderr | 103 + .../borrowck/borrowck-multiple-captures.rs | 0 .../borrowck-multiple-captures.stderr | 84 + .../borrowck-mut-addr-of-imm-var.nll.stderr | 11 + .../borrowck/borrowck-mut-addr-of-imm-var.rs | 0 .../borrowck-mut-addr-of-imm-var.stderr | 11 + ...ck-mut-borrow-linear-errors.ast.nll.stderr | 32 + ...rrowck-mut-borrow-linear-errors.ast.stderr | 36 + ...rrowck-mut-borrow-linear-errors.mir.stderr | 32 + .../borrowck-mut-borrow-linear-errors.rs | 0 ...owck-mut-borrow-of-mut-base-ptr.nll.stderr | 26 + .../borrowck-mut-borrow-of-mut-base-ptr.rs | 7 + ...borrowck-mut-borrow-of-mut-base-ptr.stderr | 26 + .../borrowck-mut-slice-of-imm-vec.nll.stderr | 11 + .../borrowck/borrowck-mut-slice-of-imm-vec.rs | 0 .../borrowck-mut-slice-of-imm-vec.stderr | 11 + .../borrowck/borrowck-mutate-in-guard.rs | 0 .../borrowck/borrowck-mutate-in-guard.stderr | 22 + ...rowck-no-cycle-in-exchange-heap.nll.stderr | 13 + .../borrowck-no-cycle-in-exchange-heap.rs | 0 .../borrowck-no-cycle-in-exchange-heap.stderr | 11 + .../borrowck-object-lifetime.nll.stderr | 23 + .../ui/borrowck/borrowck-object-lifetime.rs | 50 + .../borrowck/borrowck-object-lifetime.stderr | 25 + .../ui/borrowck/borrowck-or-init.nll.stderr | 9 + .../borrowck/borrowck-or-init.rs | 0 src/test/ui/borrowck/borrowck-or-init.stderr | 9 + .../borrowck-overloaded-call.nll.stderr | 23 + .../borrowck/borrowck-overloaded-call.rs | 0 .../borrowck/borrowck-overloaded-call.stderr | 33 + ...-index-and-overloaded-deref.ast.nll.stderr | 14 + ...aded-index-and-overloaded-deref.ast.stderr | 11 + ...aded-index-and-overloaded-deref.mir.stderr | 14 + ...k-overloaded-index-and-overloaded-deref.rs | 0 ...owck-overloaded-index-autoderef.nll.stderr | 84 + .../borrowck-overloaded-index-autoderef.rs | 107 + ...borrowck-overloaded-index-autoderef.stderr | 80 + ...-overloaded-index-move-from-vec.nll.stderr | 12 + ...borrowck-overloaded-index-move-from-vec.rs | 0 ...owck-overloaded-index-move-from-vec.stderr | 12 + ...wck-overloaded-index-move-index.nll.stderr | 14 + .../borrowck-overloaded-index-move-index.rs | 0 ...orrowck-overloaded-index-move-index.stderr | 33 + ...-overloaded-index-ref-index.ast.nll.stderr | 33 + ...owck-overloaded-index-ref-index.ast.stderr | 35 + ...owck-overloaded-index-ref-index.mir.stderr | 33 + .../borrowck-overloaded-index-ref-index.rs | 0 .../borrowck-partial-reinit-1.nll.stderr | 23 + .../borrowck/borrowck-partial-reinit-1.rs | 0 .../borrowck/borrowck-partial-reinit-1.stderr | 15 + .../borrowck-partial-reinit-2.nll.stderr | 13 + .../borrowck/borrowck-partial-reinit-2.rs | 0 .../borrowck/borrowck-partial-reinit-2.stderr | 9 + .../borrowck-partial-reinit-3.nll.stderr | 13 + .../borrowck/borrowck-partial-reinit-3.rs | 0 .../borrowck/borrowck-partial-reinit-3.stderr | 9 + .../borrowck-partial-reinit-4.nll.stderr | 9 + .../borrowck/borrowck-partial-reinit-4.rs | 0 .../borrowck/borrowck-partial-reinit-4.stderr | 9 + ...rrowck-pat-reassign-binding.ast.nll.stderr | 15 + .../borrowck-pat-reassign-binding.ast.stderr | 12 + .../borrowck-pat-reassign-binding.mir.stderr | 15 + .../borrowck/borrowck-pat-reassign-binding.rs | 0 .../borrowck-reborrow-from-mut.nll.stderr | 11 + .../borrowck/borrowck-reborrow-from-mut.rs | 0 .../borrowck-reborrow-from-mut.stderr | 116 + ...orrow-from-shorter-lived-andmut.nll.stderr | 12 + ...owck-reborrow-from-shorter-lived-andmut.rs | 0 ...-reborrow-from-shorter-lived-andmut.stderr | 13 + .../borrowck-ref-mut-of-imm.nll.stderr | 12 + .../borrowck/borrowck-ref-mut-of-imm.rs | 0 .../borrowck/borrowck-ref-mut-of-imm.stderr | 12 + ...urn-variable-on-stack-via-clone.nll.stderr | 17 + ...owck-return-variable-on-stack-via-clone.rs | 0 ...-return-variable-on-stack-via-clone.stderr | 17 + .../borrowck/borrowck-return.rs | 0 src/test/ui/borrowck/borrowck-return.stderr | 9 + .../borrowck/borrowck-storage-dead.rs | 0 .../ui/borrowck/borrowck-storage-dead.stderr | 15 + ...wck-struct-update-with-dtor.ast.nll.stderr | 15 + ...orrowck-struct-update-with-dtor.ast.stderr | 15 + ...orrowck-struct-update-with-dtor.mir.stderr | 15 + .../borrowck-struct-update-with-dtor.rs | 0 .../borrowck-swap-mut-base-ptr.nll.stderr | 14 + .../borrowck/borrowck-swap-mut-base-ptr.rs | 6 + .../borrowck-swap-mut-base-ptr.stderr | 14 + ...l-static-borrow-outlives-fn.ast.nll.stderr | 12 + ...local-static-borrow-outlives-fn.ast.stderr | 13 + ...local-static-borrow-outlives-fn.mir.stderr | 12 + ...-thread-local-static-borrow-outlives-fn.rs | 2 +- .../borrowck-unary-move.ast.nll.stderr | 14 + .../borrowck/borrowck-unary-move.ast.stderr | 11 + .../borrowck/borrowck-unary-move.mir.stderr | 14 + .../borrowck/borrowck-unary-move.rs | 0 .../borrowck-unboxed-closures.nll.stderr | 22 + .../borrowck/borrowck-unboxed-closures.rs | 0 .../borrowck/borrowck-unboxed-closures.stderr | 32 + .../borrowck/borrowck-uninit-after-item.rs | 0 .../borrowck-uninit-after-item.stderr | 9 + ...orrowck-uninit-field-access.ast.nll.stderr | 30 + .../borrowck-uninit-field-access.ast.stderr | 30 + .../borrowck-uninit-field-access.mir.stderr | 30 + .../borrowck/borrowck-uninit-field-access.rs | 0 .../borrowck/borrowck-uninit-in-assignop.rs | 0 .../borrowck-uninit-in-assignop.stderr | 63 + .../borrowck-uninit-ref-chain.ast.nll.stderr | 33 + .../borrowck-uninit-ref-chain.ast.stderr | 45 + .../borrowck-uninit-ref-chain.mir.stderr | 33 + .../borrowck/borrowck-uninit-ref-chain.rs | 0 .../borrowck/borrowck-uninit.rs | 0 src/test/ui/borrowck/borrowck-uninit.stderr | 9 + .../borrowck-union-borrow-nested.nll.stderr | 13 + .../borrowck/borrowck-union-borrow-nested.rs | 7 + .../borrowck-union-borrow-nested.stderr | 11 + .../borrowck-union-borrow.ast.nll.stderr | 136 + .../borrowck/borrowck-union-borrow.ast.stderr | 118 + .../borrowck/borrowck-union-borrow.mir.stderr | 136 + .../borrowck/borrowck-union-borrow.rs | 0 .../borrowck-union-move-assign.nll.stderr | 35 + .../borrowck/borrowck-union-move-assign.rs | 0 .../borrowck-union-move-assign.stderr | 13 + .../borrowck/borrowck-union-move.nll.stderr | 63 + .../borrowck/borrowck-union-move.rs | 0 .../ui/borrowck/borrowck-union-move.stderr | 63 + .../borrowck-union-uninitialized.nll.stderr | 9 + .../borrowck/borrowck-union-uninitialized.rs | 0 .../borrowck-union-uninitialized.stderr | 15 + .../borrowck-uniq-via-lend.nll.stderr | 23 + .../borrowck/borrowck-uniq-via-lend.rs | 19 +- .../ui/borrowck/borrowck-uniq-via-lend.stderr | 25 + ...orrowck-use-in-index-lvalue.ast.nll.stderr | 15 + .../borrowck-use-in-index-lvalue.ast.stderr | 15 + .../borrowck-use-in-index-lvalue.mir.stderr | 15 + .../borrowck/borrowck-use-in-index-lvalue.rs | 0 .../borrowck-use-mut-borrow.nll.stderr | 95 + .../borrowck/borrowck-use-mut-borrow.rs | 0 .../borrowck/borrowck-use-mut-borrow.stderr | 75 + ...uninitialized-in-cast-trait.ast.nll.stderr | 9 + ...use-uninitialized-in-cast-trait.ast.stderr | 9 + ...use-uninitialized-in-cast-trait.mir.stderr | 9 + ...orrowck-use-uninitialized-in-cast-trait.rs | 0 ...k-use-uninitialized-in-cast.ast.nll.stderr | 9 + ...rowck-use-uninitialized-in-cast.ast.stderr | 9 + ...rowck-use-uninitialized-in-cast.mir.stderr | 9 + .../borrowck-use-uninitialized-in-cast.rs | 0 ...rrowck-vec-pattern-element-loan.nll.stderr | 48 + .../borrowck-vec-pattern-element-loan.rs | 0 .../borrowck-vec-pattern-element-loan.stderr | 48 + ...rowck-vec-pattern-loan-from-mut.nll.stderr | 14 + .../borrowck-vec-pattern-loan-from-mut.rs | 0 .../borrowck-vec-pattern-loan-from-mut.stderr | 15 + ...rowck-vec-pattern-move-tail.ast.nll.stderr | 15 + .../borrowck-vec-pattern-move-tail.ast.stderr | 12 + .../borrowck-vec-pattern-move-tail.cmp.stderr | 24 + .../borrowck-vec-pattern-move-tail.rs | 0 .../borrowck-vec-pattern-nesting.nll.stderr | 57 +- ...k-vec-pattern-tail-element-loan.nll.stderr | 18 + .../borrowck-vec-pattern-tail-element-loan.rs | 0 ...rowck-vec-pattern-tail-element-loan.stderr | 18 + .../borrowck/borrowck-while-break.nll.stderr | 9 + .../borrowck/borrowck-while-break.rs | 0 .../ui/borrowck/borrowck-while-break.stderr | 9 + .../borrowck/borrowck-while-cond.rs | 0 .../ui/borrowck/borrowck-while-cond.stderr | 9 + .../borrowck/borrowck-while.rs | 0 src/test/ui/borrowck/borrowck-while.stderr | 9 + src/test/ui/borrowck/immutable-arg.stderr | 2 +- .../index-mut-help-with-impl.nll.stderr | 11 + .../ui/borrowck/index-mut-help-with-impl.rs | 20 + .../borrowck/index-mut-help-with-impl.stderr | 9 + .../ui/borrowck/index-mut-help.nll.stderr | 26 + src/test/ui/borrowck/index-mut-help.rs | 24 + src/test/ui/borrowck/index-mut-help.stderr | 28 + src/test/ui/borrowck/issue-41962.stderr | 34 +- src/test/ui/borrowck/issue-45983.nll.stderr | 6 - src/test/ui/borrowck/issue-45983.rs | 5 +- src/test/ui/borrowck/issue-51415.nll.stderr | 8 +- src/test/ui/borrowck/issue-52713-bug.rs | 29 + src/test/ui/borrowck/issue-52713-bug.stderr | 14 + ...67-edition-2018-needs-two-phase-borrows.rs | 32 + src/test/ui/borrowck/issue-7573.nll.stderr | 6 - ...-static-initializer-issue-38520.ast.stderr | 15 + ...-static-initializer-issue-38520.mir.stderr | 15 + .../move-in-static-initializer-issue-38520.rs | 2 +- .../mut-borrow-outside-loop.nll.stderr | 2 +- src/test/ui/borrowck/mutability-errors.stderr | 6 +- ...mote-ref-mut-in-let-issue-46557.nll.stderr | 34 +- .../reassignment_immutable_fields.nll.stderr | 44 + .../borrowck/reassignment_immutable_fields.rs | 30 + .../reassignment_immutable_fields.stderr | 56 + ...nt_immutable_fields_overlapping.nll.stderr | 20 + ...assignment_immutable_fields_overlapping.rs | 26 + ...gnment_immutable_fields_overlapping.stderr | 20 + ...signment_immutable_fields_twice.nll.stderr | 38 + .../reassignment_immutable_fields_twice.rs | 27 + ...reassignment_immutable_fields_twice.stderr | 38 + .../regions-escape-bound-fn-2.nll.stderr | 6 - .../regions-escape-bound-fn.nll.stderr | 6 - .../regions-escape-unboxed-closure.nll.stderr | 6 - .../borrowck/two-phase-across-loop.rs | 0 .../ui/borrowck/two-phase-across-loop.stderr | 9 + ...ion-sharing-interference.nll_target.stderr | 47 + ...o-phase-activation-sharing-interference.rs | 0 ...ccess-during-reservation.nll_target.stderr | 27 + ...o-phase-allow-access-during-reservation.rs | 0 .../two-phase-cannot-nest-mut-self-calls.rs | 0 ...wo-phase-cannot-nest-mut-self-calls.stderr | 20 + .../ui/borrowck/two-phase-multi-mut.stderr | 16 +- .../two-phase-nonrecv-autoref.ast.nll.stderr | 82 + .../two-phase-nonrecv-autoref.ast.stderr | 113 + .../two-phase-nonrecv-autoref.nll.stderr | 82 + .../borrowck/two-phase-nonrecv-autoref.rs | 0 ...hase-reservation-sharing-interference-2.rs | 0 ...-reservation-sharing-interference-2.stderr | 14 + ...ion-sharing-interference.nll_target.stderr | 15 + ...-phase-reservation-sharing-interference.rs | 0 .../ui/borrowck/two-phase-sneaky.nll.stderr | 20 + .../borrowck/two-phase-sneaky.rs | 0 src/test/ui/borrowck/two-phase-sneaky.stderr | 15 + .../two-phase-surprise-no-conflict.ast.stderr | 133 + .../two-phase-surprise-no-conflict.nll.stderr | 165 + ...wo-phase-surprise-no-conflict.no2pb.stderr | 175 + .../two-phase-surprise-no-conflict.rs | 219 + ...upvar-from-non-once-ref-closure.nll.stderr | 3 + .../{compile-fail => ui}/bounds-lifetime.rs | 0 src/test/ui/bounds-lifetime.stderr | 32 + .../break-outside-loop.rs | 0 src/test/ui/break-outside-loop.stderr | 34 + .../auxiliary/trait_superkinds_in_metadata.rs | 0 .../builtin-superkinds-double-superkind.rs | 0 ...builtin-superkinds-double-superkind.stderr | 23 + .../builtin-superkinds-in-metadata.rs | 0 .../builtin-superkinds-in-metadata.stderr | 13 + .../builtin-superkinds-self-type.rs | 0 .../builtin-superkinds-self-type.stderr | 17 + .../builtin-superkinds-simple.rs | 0 .../builtin-superkinds-simple.stderr | 11 + .../builtin-superkinds-typaram-not-send.rs | 0 ...builtin-superkinds-typaram-not-send.stderr | 12 + .../ui/by-move-pattern-binding.nll.stderr | 21 + .../by-move-pattern-binding.rs | 0 src/test/ui/by-move-pattern-binding.stderr | 12 + .../call-fn-never-arg-wrong-type.rs | 0 .../ui/call-fn-never-arg-wrong-type.stderr | 12 + .../can-begin-expr-check.rs | 0 src/test/ui/can-begin-expr-check.stderr | 8 + ...mutate-captured-non-mut-var.ast.nll.stderr | 20 + ...not-mutate-captured-non-mut-var.ast.stderr | 16 + ...not-mutate-captured-non-mut-var.mir.stderr | 20 + .../cannot-mutate-captured-non-mut-var.rs | 0 src/test/{compile-fail => ui}/capture1.rs | 0 src/test/ui/capture1.stderr | 11 + src/test/ui/{ => cast}/cast-as-bool.rs | 0 src/test/ui/{ => cast}/cast-as-bool.stderr | 0 .../ui/{ => cast}/cast-errors-issue-43825.rs | 0 .../{ => cast}/cast-errors-issue-43825.stderr | 0 .../cast}/cast-from-nil.rs | 0 src/test/ui/cast/cast-from-nil.stderr | 11 + src/test/ui/cast/cast-ptr-to-int-const.rs | 17 + src/test/ui/cast/cast-ptr-to-int-const.stderr | 19 + src/test/ui/{ => cast}/cast-rfc0401-2.rs | 0 src/test/ui/{ => cast}/cast-rfc0401-2.stderr | 0 .../cast}/cast-to-bare-fn.rs | 0 src/test/ui/cast/cast-to-bare-fn.stderr | 19 + .../{compile-fail => ui/cast}/cast-to-nil.rs | 0 src/test/ui/cast/cast-to-nil.stderr | 11 + ...cast-to-unsized-trait-object-suggestion.rs | 0 ...-to-unsized-trait-object-suggestion.stderr | 0 src/test/ui/catch-block-type-error.rs | 26 - src/test/ui/catch-block-type-error.stderr | 21 - .../cdylib-deps-must-be-static.rs | 0 src/test/ui/cdylib-deps-must-be-static.stderr | 4 + src/test/ui/cfg-arg-invalid-1.rs | 10 - src/test/ui/cfg-arg-invalid-2.rs | 10 - src/test/ui/cfg-arg-invalid-3.rs | 10 - src/test/ui/cfg-arg-invalid-4.rs | 10 - src/test/ui/cfg-arg-invalid-5.rs | 10 - .../{compile-fail => ui}/cfg-attr-cfg-2.rs | 0 src/test/ui/cfg-attr-cfg-2.stderr | 7 + .../{compile-fail => ui}/cfg-attr-crate-2.rs | 0 src/test/ui/cfg-attr-crate-2.stderr | 11 + .../cfg-attr-invalid-predicate.rs | 0 src/test/ui/cfg-attr-invalid-predicate.stderr | 9 + src/test/ui/cfg-attr-syntax-validation.rs | 10 - src/test/ui/cfg-attr-syntax-validation.stderr | 18 +- ...-attr-unknown-attribute-macro-expansion.rs | 0 ...r-unknown-attribute-macro-expansion.stderr | 14 + .../{compile-fail => ui}/cfg-empty-codemap.rs | 4 +- .../{compile-fail => ui}/cfg-in-crate-1.rs | 0 src/test/ui/cfg-in-crate-1.stderr | 7 + .../{compile-fail => ui}/cfg-non-opt-expr.rs | 3 +- src/test/ui/cfg-non-opt-expr.stderr | 20 + .../{compile-fail => ui}/cfg_attr_path.rs | 0 src/test/ui/cfg_attr_path.stderr | 11 + src/test/ui/chalkify/lower_trait.rs | 6 +- .../ui/chalkify/lower_trait_higher_rank.rs | 2 +- .../ui/chalkify/lower_trait_where_clause.rs | 16 +- .../chalkify/lower_trait_where_clause.stderr | 3 +- .../check-static-immutable-mut-slices.rs | 0 .../check-static-immutable-mut-slices.stderr | 9 + ...check-static-values-constraints.nll.stderr | 70 + .../check-static-values-constraints.rs | 0 .../ui/check-static-values-constraints.stderr | 67 + .../class-cast-to-trait.rs | 0 src/test/ui/class-cast-to-trait.stderr | 9 + .../class-method-missing.rs | 0 src/test/ui/class-method-missing.stderr | 12 + .../class-missing-self.rs | 0 src/test/ui/class-missing-self.stderr | 19 + .../cleanup-rvalue-scopes-cf.rs | 2 + src/test/ui/cleanup-rvalue-scopes-cf.stderr | 93 + .../closure-expected-type/README.md | 0 .../expect-fn-supply-fn-multiple.rs | 0 .../expect-fn-supply-fn.nll.stderr | 54 + .../expect-fn-supply-fn.rs | 0 .../expect-fn-supply-fn.stderr | 93 + .../expect-infer-var-appearing-twice.rs | 0 .../expect-infer-var-appearing-twice.stderr | 20 + ...t-infer-var-supply-ty-with-bound-region.rs | 0 ...ct-infer-var-supply-ty-with-free-region.rs | 0 .../expect-region-supply-region.nll.stderr | 58 - ...-infer-vars-supply-ty-with-bound-region.rs | 0 ...er-vars-supply-ty-with-bound-region.stderr | 9 + src/test/ui/closure-expected.rs | 15 + src/test/ui/closure-expected.stderr | 12 + .../{compile-fail => ui}/closure_promotion.rs | 2 + src/test/ui/closure_promotion.stderr | 13 + .../closure-array-break-length.rs | 0 .../closure-array-break-length.stderr | 0 ...bounds-cant-promote-superkind-in-struct.rs | 0 ...ds-cant-promote-superkind-in-struct.stderr | 20 + ...ds-static-cant-capture-borrowed.nll.stderr | 29 + ...ure-bounds-static-cant-capture-borrowed.rs | 0 ...bounds-static-cant-capture-borrowed.stderr | 11 + .../closures}/closure-bounds-subtype.rs | 0 .../ui/closures/closure-bounds-subtype.stderr | 17 + .../expect-region-supply-region.nll.stderr | 34 + .../expect-region-supply-region.rs | 0 .../expect-region-supply-region.stderr | 0 .../closure-immutable-outer-variable.fixed | 0 ...losure-immutable-outer-variable.nll.stderr | 0 .../closure-immutable-outer-variable.rs | 0 .../closure-immutable-outer-variable.rs.fixed | 0 .../closure-immutable-outer-variable.stderr | 0 .../ui/{ => closures}/closure-move-sync.rs | 0 .../{ => closures}/closure-move-sync.stderr | 0 .../closures}/closure-no-fn-1.rs | 0 src/test/ui/closures/closure-no-fn-1.stderr | 12 + .../closures}/closure-no-fn-2.rs | 0 src/test/ui/closures/closure-no-fn-2.stderr | 12 + .../closures}/closure-no-fn-3.rs | 0 src/test/ui/closures/closure-no-fn-3.stderr | 11 + .../closure-referencing-itself-issue-25954.rs | 0 ...sure-referencing-itself-issue-25954.stderr | 9 + .../closures}/closure-reform-bad.rs | 0 .../ui/closures/closure-reform-bad.stderr | 12 + .../closures}/closure-wrong-kind.rs | 0 .../ui/closures/closure-wrong-kind.stderr | 14 + .../ui/codemap_tests/bad-format-args.stderr | 12 +- .../huge_multispan_highlight.stderr | 2 +- .../overlapping_spans.nll.stderr | 8 +- .../coerce-expect-unsized-ascribed.rs | 0 .../coerce-expect-unsized-ascribed.stderr | 129 + .../coercion}/coerce-mut.rs | 0 src/test/ui/coercion/coerce-mut.stderr | 12 + ...coerce-overloaded-autoderef.ast.nll.stderr | 47 + .../coerce-overloaded-autoderef.ast.stderr | 42 + ...coerce-overloaded-autoderef.mir.nll.stderr | 47 + .../coerce-overloaded-autoderef.mir.stderr | 47 + .../coercion}/coerce-overloaded-autoderef.rs | 0 .../coercion}/coerce-to-bang-cast.rs | 0 .../ui/coercion/coerce-to-bang-cast.stderr | 19 + .../coercion}/coerce-to-bang.rs | 0 src/test/ui/coercion/coerce-to-bang.stderr | 93 + .../coercion-missing-tail-expected-type.rs | 0 ...coercion-missing-tail-expected-type.stderr | 0 .../coercion}/coercion-slice.rs | 0 src/test/ui/coercion/coercion-slice.stderr | 15 + .../auxiliary/coherence_copy_like_lib.rs | 0 .../auxiliary/coherence_inherent_cc_lib.rs | 0 .../coherence}/auxiliary/coherence_lib.rs | 0 .../auxiliary/coherence_orphan_lib.rs | 0 .../coherence}/auxiliary/go_trait.rs | 0 .../auxiliary/trait_impl_conflict.rs | 0 .../coherence}/coherence-all-remote.rs | 0 .../ui/coherence/coherence-all-remote.stderr | 11 + .../coherence}/coherence-bigint-param.rs | 0 .../coherence/coherence-bigint-param.stderr | 11 + ...nket-conflicts-with-blanket-implemented.rs | 0 ...-conflicts-with-blanket-implemented.stderr | 12 + ...et-conflicts-with-blanket-unimplemented.rs | 0 ...onflicts-with-blanket-unimplemented.stderr | 12 + ...ket-conflicts-with-specific-cross-crate.rs | 0 ...conflicts-with-specific-cross-crate.stderr | 13 + ...t-conflicts-with-specific-multidispatch.rs | 0 ...nflicts-with-specific-multidispatch.stderr | 12 + ...e-blanket-conflicts-with-specific-trait.rs | 0 ...anket-conflicts-with-specific-trait.stderr | 12 + ...herence-blanket-conflicts-with-specific.rs | 0 ...nce-blanket-conflicts-with-specific.stderr | 12 + ...herence-conflicting-negative-trait-impl.rs | 0 ...nce-conflicting-negative-trait-impl.stderr | 21 + 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 + .../coherence}/coherence-cow.rs | 0 .../coherence-cross-crate-conflict.rs | 0 .../coherence-cross-crate-conflict.stderr | 21 + .../coherence-default-trait-impl.rs | 0 .../coherence-default-trait-impl.stderr | 16 + .../coherence-error-suppression.rs | 0 .../coherence-error-suppression.stderr | 0 ...erence-impl-trait-for-trait-object-safe.rs | 0 ...ce-impl-trait-for-trait-object-safe.stderr | 11 + .../coherence-impl-trait-for-trait.rs | 0 .../coherence-impl-trait-for-trait.stderr | 21 + .../{ => coherence}/coherence-impls-copy.rs | 0 .../coherence-impls-copy.stderr | 0 .../coherence}/coherence-impls-send.rs | 0 .../ui/coherence/coherence-impls-send.stderr | 37 + .../coherence}/coherence-impls-sized.rs | 0 .../ui/coherence/coherence-impls-sized.stderr | 67 + .../coherence-inherited-assoc-ty-cycle-err.rs | 0 ...erence-inherited-assoc-ty-cycle-err.stderr | 16 + .../coherence-lone-type-parameter.rs | 0 .../coherence-lone-type-parameter.stderr | 11 + .../coherence-negative-impls-safe.rs | 0 .../coherence-negative-impls-safe.stderr | 9 + .../coherence-no-direct-lifetime-dispatch.rs | 0 ...herence-no-direct-lifetime-dispatch.stderr | 11 + .../coherence}/coherence-orphan.rs | 0 src/test/ui/coherence/coherence-orphan.stderr | 21 + .../coherence-overlap-all-t-and-tuple.rs | 0 .../coherence-overlap-all-t-and-tuple.stderr | 12 + .../coherence-overlap-downstream-inherent.rs | 0 ...herence-overlap-downstream-inherent.stderr | 0 .../coherence-overlap-downstream.rs | 0 .../coherence-overlap-downstream.stderr | 0 .../coherence-overlap-issue-23516-inherent.rs | 0 ...erence-overlap-issue-23516-inherent.stderr | 0 .../coherence-overlap-issue-23516.rs | 0 .../coherence-overlap-issue-23516.stderr | 0 .../coherence}/coherence-overlap-messages.rs | 0 .../coherence-overlap-messages.stderr | 44 + .../coherence-overlap-upstream-inherent.rs | 0 ...coherence-overlap-upstream-inherent.stderr | 0 .../coherence-overlap-upstream.rs | 0 .../coherence-overlap-upstream.stderr | 0 .../coherence}/coherence-overlapping-pairs.rs | 0 .../coherence-overlapping-pairs.stderr | 11 + .../coherence-pair-covered-uncovered-1.rs | 0 .../coherence-pair-covered-uncovered-1.stderr | 11 + .../coherence-pair-covered-uncovered.rs | 0 .../coherence-pair-covered-uncovered.stderr | 11 + .../coherence-projection-conflict-orphan.rs | 0 ...oherence-projection-conflict-orphan.stderr | 14 + .../coherence-projection-conflict-ty-param.rs | 0 ...erence-projection-conflict-ty-param.stderr | 12 + .../coherence-projection-conflict.rs | 0 .../coherence-projection-conflict.stderr | 12 + .../coherence-projection-ok-orphan.rs | 0 .../coherence-projection-ok-orphan.stderr | 8 + .../coherence}/coherence-projection-ok.rs | 0 .../coherence/coherence-projection-ok.stderr | 8 + .../coherence}/coherence-tuple-conflict.rs | 0 .../coherence/coherence-tuple-conflict.stderr | 12 + .../coherence}/coherence-vec-local-2.rs | 0 .../ui/coherence/coherence-vec-local-2.stderr | 11 + .../coherence}/coherence-vec-local.rs | 0 .../ui/coherence/coherence-vec-local.stderr | 12 + ...erence_copy_like_err_fundamental_struct.rs | 0 ...ce_copy_like_err_fundamental_struct.stderr | 8 + ...ce_copy_like_err_fundamental_struct_ref.rs | 0 ...opy_like_err_fundamental_struct_ref.stderr | 8 + ..._copy_like_err_fundamental_struct_tuple.rs | 0 ...y_like_err_fundamental_struct_tuple.stderr | 14 + .../coherence_copy_like_err_struct.rs | 0 .../coherence_copy_like_err_struct.stderr | 14 + .../coherence_copy_like_err_tuple.rs | 0 .../coherence_copy_like_err_tuple.stderr | 14 + .../coherence}/coherence_inherent.rs | 0 .../ui/coherence/coherence_inherent.stderr | 13 + .../coherence}/coherence_inherent_cc.rs | 0 .../ui/coherence/coherence_inherent_cc.stderr | 13 + .../coherence}/coherence_local.rs | 0 src/test/ui/coherence/coherence_local.stderr | 8 + .../coherence}/coherence_local_err_struct.rs | 0 .../coherence_local_err_struct.stderr | 12 + .../coherence}/coherence_local_err_tuple.rs | 0 .../coherence_local_err_tuple.stderr | 12 + .../coherence}/coherence_local_ref.rs | 0 .../ui/coherence/coherence_local_ref.stderr | 8 + .../ui/command-line-diagnostics.nll.stderr | 2 +- .../compile_error_macro.rs | 0 src/test/ui/compile_error_macro.stderr | 8 + src/test/{compile-fail => ui}/concat.rs | 0 src/test/ui/concat.stderr | 30 + .../conflicting-repr-hints.rs | 0 src/test/ui/conflicting-repr-hints.stderr | 70 + .../conservative_impl_trait.rs | 0 src/test/ui/conservative_impl_trait.stderr | 12 + src/test/ui/const-deref-ptr.stderr | 9 - .../dont_promote_unstable_const_fn.nll.stderr | 22 - .../ui/const-eval/match-test-ptr-null.stderr | 30 - .../ui/const-eval/ref_to_float_transmute.rs | 28 - src/test/ui/const-eval/ub-enum-ptr.rs | 27 - src/test/ui/const-eval/ub-enum-ptr.stderr | 11 - src/test/ui/const-eval/ub-ptr-in-usize.rs | 22 - .../ui/const-eval/union-const-eval-field.rs | 45 - .../const-eval/union-const-eval-field.stderr | 11 - src/test/ui/const-eval/union-ice.stderr | 36 - .../constructor-lifetime-args.rs | 8 +- src/test/ui/constructor-lifetime-args.stderr | 27 + src/test/ui/consts/auxiliary/const_fn_lib.rs | 16 + .../consts}/const-array-oob-arith.rs | 0 .../ui/consts/const-array-oob-arith.stderr | 21 + .../consts}/const-array-oob.rs | 0 src/test/ui/consts/const-array-oob.stderr | 19 + .../const-block-non-item-statement-2.rs | 0 .../const-block-non-item-statement-2.stderr | 62 + .../const-block-non-item-statement-3.rs | 0 .../const-block-non-item-statement-3.stderr | 35 + .../consts}/const-block-non-item-statement.rs | 0 .../const-block-non-item-statement.stderr | 35 + .../{compile-fail => ui/consts}/const-call.rs | 0 src/test/ui/consts/const-call.stderr | 16 + .../consts}/const-cast-different-types.rs | 0 .../consts/const-cast-different-types.stderr | 15 + .../consts}/const-cast-wrong-type.rs | 0 .../ui/consts/const-cast-wrong-type.stderr | 9 + src/test/ui/{ => consts}/const-deref-ptr.rs | 3 +- src/test/ui/consts/const-deref-ptr.stderr | 11 + .../consts}/const-err-early.rs | 0 src/test/ui/consts/const-err-early.stderr | 48 + .../consts}/const-err-multi.rs | 0 src/test/ui/consts/const-err-multi.stderr | 67 + .../{compile-fail => ui/consts}/const-err.rs | 0 src/test/ui/consts/const-err.stderr | 26 + .../{compile-fail => ui/consts}/const-err2.rs | 0 src/test/ui/consts/const-err2.stderr | 38 + .../{compile-fail => ui/consts}/const-err4.rs | 2 +- src/test/ui/consts/const-err4.stderr | 9 + .../conditional_array_execution.nll.stderr | 0 .../const-eval/conditional_array_execution.rs | 0 .../conditional_array_execution.stderr | 0 .../const-eval}/const-eval-overflow-2.rs | 0 .../const-eval}/const-eval-overflow-2.stderr | 0 .../const-eval}/const-eval-overflow-3.rs | 0 .../const-eval/const-eval-overflow-3.stderr | 19 + .../const-eval}/const-eval-overflow-3b.rs | 0 .../const-eval/const-eval-overflow-3b.stderr | 18 + .../const-eval}/const-eval-overflow-4.rs | 0 .../const-eval}/const-eval-overflow-4.stderr | 0 .../const-eval}/const-eval-overflow-4b.rs | 0 .../const-eval/const-eval-overflow-4b.stderr | 24 + .../const-eval}/const-eval-overflow2.rs | 0 .../const-eval/const-eval-overflow2.stderr | 94 + .../const-eval}/const-eval-overflow2b.rs | 0 .../const-eval/const-eval-overflow2b.stderr | 94 + .../const-eval}/const-eval-overflow2c.rs | 0 .../const-eval/const-eval-overflow2c.stderr | 94 + .../const-eval}/const-eval-span.rs | 0 .../const-eval}/const-eval-span.stderr | 0 .../const-pointer-values-in-various-types.rs | 110 + ...nst-pointer-values-in-various-types.stderr | 233 + .../ui/{ => consts}/const-eval/const_let.rs | 0 .../{ => consts}/const-eval/const_let.stderr | 0 src/test/ui/consts/const-eval/const_panic.rs | 22 + .../ui/consts/const-eval/const_panic.stderr | 33 + .../consts/const-eval/const_panic_libcore.rs | 22 + .../const-eval/const_panic_libcore.stderr | 33 + .../const-eval/const_panic_libcore_main.rs | 36 + .../const_panic_libcore_main.stderr | 33 + .../const-eval/const_prop_errors.rs | 0 .../ui/consts/const-eval/const_raw_ptr_ops.rs | 27 + .../const-eval/const_raw_ptr_ops.stderr | 36 + .../const-eval/const_signed_pat.rs | 0 .../const-eval/const_transmute.rs | 2 + .../dont_promote_unstable_const_fn.rs | 0 .../dont_promote_unstable_const_fn.stderr | 0 ...e_unstable_const_fn_cross_crate.nll.stderr | 13 - .../{ => consts}/const-eval/double_check.rs | 0 .../{ => consts}/const-eval/double_check2.rs | 0 .../const-eval/double_check2.stderr | 2 +- .../const-eval/duration_conversion.rs | 0 .../ui/{ => consts}/const-eval/enum_discr.rs | 0 .../const-eval/extern_fat_pointer.rs | 0 .../const-eval/feature-gate-const_fn_union.rs | 22 + .../feature-gate-const_fn_union.stderr | 11 + .../const-eval/feature-gate-const_panic.rs | 20 + .../feature-gate-const_panic.stderr | 30 + .../const-eval/ice-generic-assoc-const.rs | 0 .../ui/{ => consts}/const-eval/ice-packed.rs | 0 .../const-eval/index_out_of_bounds.rs | 0 .../const-eval/index_out_of_bounds.stderr | 0 .../index_out_of_bounds_propagated.rs | 0 .../index_out_of_bounds_propagated.stderr | 0 .../{ => consts}/const-eval/infinite_loop.rs | 0 .../const-eval/infinite_loop.stderr | 0 .../const-eval/issue-43197.nll.stderr | 0 .../ui/{ => consts}/const-eval/issue-43197.rs | 2 +- .../const-eval/issue-43197.stderr | 0 .../const-eval/issue-44578.nll.stderr | 0 .../ui/{ => consts}/const-eval/issue-44578.rs | 0 .../const-eval/issue-44578.stderr | 0 .../ui/{ => consts}/const-eval/issue-47971.rs | 2 +- .../ui/{ => consts}/const-eval/issue-50706.rs | 0 .../{ => consts}/const-eval/issue-50814-2.rs | 0 .../const-eval/issue-50814-2.stderr | 0 .../ui/{ => consts}/const-eval/issue-50814.rs | 0 .../const-eval/issue-50814.stderr | 0 .../ui/{ => consts}/const-eval/issue-51300.rs | 0 .../ui/{ => consts}/const-eval/issue-52442.rs | 0 .../const-eval/issue-52442.stderr | 0 .../ui/{ => consts}/const-eval/issue-52443.rs | 0 .../const-eval/issue-52443.stderr | 0 src/test/ui/consts/const-eval/issue-52475.rs | 25 + .../ui/consts/const-eval/issue-52475.stderr | 42 + .../ui/{ => consts}/const-eval/issue-53157.rs | 0 .../const-eval/match-test-ptr-null.rs | 2 +- .../const-eval/match-test-ptr-null.stderr | 32 + .../const-eval/mod-static-with-const-fn.rs | 37 + .../mod-static-with-const-fn.stderr | 18 + .../no_lint_for_statically_known_error.rs | 0 .../promote_mutable_zst_mir_borrowck.rs | 0 .../const-eval/promoted_const_fn_fail.rs | 2 +- .../const-eval/promoted_errors.rs | 0 .../const-eval/promoted_errors.stderr | 0 .../consts/const-eval/promoted_raw_ptr_ops.rs | 18 + .../const-eval/promoted_raw_ptr_ops.stderr | 35 + .../{ => consts}/const-eval/pub_const_err.rs | 0 .../const-eval/pub_const_err.stderr | 0 .../const-eval/pub_const_err_bin.rs | 0 .../const-eval/pub_const_err_bin.stderr | 0 .../const-eval/ref_to_int_match.rs | 2 + .../const-eval/ref_to_int_match.stderr | 2 +- .../{ => consts}/const-eval/shift_overflow.rs | 0 .../const-eval/shift_overflow.stderr | 0 .../ui/consts/const-eval/simple_with_undef.rs | 16 + src/test/ui/{ => consts}/const-eval/strlen.rs | 0 .../const-eval/transmute-const-promotion.rs | 18 + .../transmute-const-promotion.stderr | 14 + .../ui/consts/const-eval/transmute-const.rs | 19 + .../consts/const-eval/transmute-const.stderr | 11 + src/test/ui/consts/const-eval/ub-enum.rs | 49 + src/test/ui/consts/const-eval/ub-enum.stderr | 27 + .../{ => consts}/const-eval/ub-uninhabit.rs | 0 .../const-eval/ub-uninhabit.stderr | 0 .../const-eval/ub-usize-in-ref.rs | 0 .../const-eval/union-const-eval-field.rs | 45 + .../const-eval/union-const-eval-field.stderr | 10 + .../ui/{ => consts}/const-eval/union-ice.rs | 4 +- .../ui/consts/const-eval/union-ice.stderr | 34 + .../ui/{ => consts}/const-eval/union-ub.rs | 0 .../{ => consts}/const-eval/union-ub.stderr | 0 .../const-eval/union_promotion.rs | 0 .../const-eval/union_promotion.stderr | 0 .../ui/consts/const-eval/zst_operand_eval.rs | 5 + .../{ => consts}/const-expr-addr-operator.rs | 0 .../consts}/const-fn-destructuring-arg.rs | 0 .../consts/const-fn-destructuring-arg.stderr | 35 + src/test/ui/{ => consts}/const-fn-error.rs | 0 .../ui/{ => consts}/const-fn-error.stderr | 0 src/test/ui/{ => consts}/const-fn-mismatch.rs | 0 .../ui/{ => consts}/const-fn-mismatch.stderr | 0 .../ui/{ => consts}/const-fn-not-in-trait.rs | 0 .../{ => consts}/const-fn-not-in-trait.stderr | 0 .../consts}/const-fn-not-safe-for-const.rs | 4 +- .../consts/const-fn-not-safe-for-const.stderr | 70 + .../consts}/const-fn-stability-calls-3.rs | 0 .../consts/const-fn-stability-calls-3.stderr | 10 + src/test/ui/consts/const-int-conversion.rs | 28 + .../ui/consts/const-int-conversion.stderr | 80 + src/test/ui/consts/const-int-overflowing.rs | 15 + .../ui/consts/const-int-overflowing.stderr | 35 + src/test/ui/consts/const-int-rotate.rs | 14 + src/test/ui/consts/const-int-rotate.stderr | 24 + src/test/ui/consts/const-int-sign.rs | 14 + src/test/ui/consts/const-int-sign.stderr | 24 + src/test/ui/consts/const-int-unchecked.rs | 21 + src/test/ui/consts/const-int-unchecked.stderr | 20 + src/test/ui/consts/const-int-wrapping.rs | 17 + src/test/ui/consts/const-int-wrapping.stderr | 57 + .../consts}/const-integer-bool-ops.rs | 0 .../ui/consts/const-integer-bool-ops.stderr | 135 + .../const-len-underflow-separate-spans.rs | 0 .../const-len-underflow-separate-spans.stderr | 0 .../consts}/const-len-underflow-subspans.rs | 0 .../const-len-underflow-subspans.stderr | 19 + .../ui/consts/const-match-check.eval1.stderr | 9 + .../ui/consts/const-match-check.eval2.stderr | 9 + .../consts/const-match-check.matchck.stderr | 27 + .../consts}/const-match-check.rs | 0 .../consts}/const-match-pattern-arm.rs | 0 .../ui/consts/const-match-pattern-arm.stderr | 15 + .../{ => consts}/const-pattern-irrefutable.rs | 0 .../const-pattern-irrefutable.stderr | 0 .../const-pattern-not-const-evaluable.rs | 2 +- .../consts}/const-size_of-cycle.rs | 4 +- src/test/ui/consts/const-size_of-cycle.stderr | 18 + .../consts}/const-slice-oob.rs | 0 src/test/ui/consts/const-slice-oob.stderr | 12 + .../consts}/const-tup-index-span.rs | 0 .../ui/consts/const-tup-index-span.stderr | 12 + .../ui/{ => consts}/const-type-mismatch.rs | 0 .../{ => consts}/const-type-mismatch.stderr | 0 .../consts}/const-typeid-of.rs | 0 src/test/ui/consts/const-typeid-of.stderr | 10 + src/test/ui/{ => consts}/const-unsized.rs | 0 src/test/ui/{ => consts}/const-unsized.stderr | 8 +- .../min_const_fn/min_const_fn.nll.stderr | 224 + .../ui/consts/min_const_fn/min_const_fn.rs | 156 + .../consts/min_const_fn/min_const_fn.stderr | 213 + .../min_const_fn/min_const_fn_dyn.nll.stderr | 25 + .../consts/min_const_fn/min_const_fn_dyn.rs | 27 + .../min_const_fn/min_const_fn_dyn.stderr | 14 + .../min_const_fn/min_const_fn_fn_ptr.rs | 29 + .../min_const_fn/min_const_fn_fn_ptr.stderr | 14 + .../min_const_fn/min_const_fn_libstd.rs | 38 + .../min_const_fn_libstd_stability.rs | 46 + .../min_const_fn_libstd_stability.stderr | 26 + .../min_const_fn/min_const_fn_unsafe.rs | 38 + .../min_const_fn/min_const_fn_unsafe.stderr | 59 + .../{compile-fail => ui}/copy-a-resource.rs | 0 src/test/ui/copy-a-resource.stderr | 16 + src/test/ui/crate-in-paths.rs | 22 + src/test/ui/crate-in-paths.stderr | 13 + .../crate-name-mismatch.rs | 0 src/test/ui/crate-name-mismatch.stderr | 8 + .../cross}/cross-borrow-trait.rs | 0 src/test/ui/cross/cross-borrow-trait.stderr | 15 + .../auxiliary/extern_macro_crate.rs | 0 .../cross-crate-macro-backtrace/main.rs | 0 .../cross-crate-macro-backtrace/main.stderr | 0 .../ui/{ => cross}/cross-file-errors/main.rs | 0 .../{ => cross}/cross-file-errors/main.stderr | 0 .../cross-file-errors/underscore.rs | 0 .../cross}/cross-fn-cache-hole.rs | 0 src/test/ui/cross/cross-fn-cache-hole.stderr | 18 + src/test/ui/custom-attribute-multisegment.rs | 18 + .../ui/custom-attribute-multisegment.stderr | 9 + src/test/ui/custom-test-frameworks-simple.rs | 32 + .../{compile-fail => ui}/custom_attribute.rs | 0 src/test/ui/custom_attribute.stderr | 27 + .../auxiliary/dynamic_runner.rs | 45 + .../auxiliary/example_runner.rs | 20 + src/test/ui/custom_test_frameworks/dynamic.rs | 45 + src/test/ui/custom_test_frameworks/full.rs | 38 + .../ui/custom_test_frameworks/mismatch.rs | 19 + .../ui/custom_test_frameworks/mismatch.stderr | 11 + .../cycle-projection-based-on-where-clause.rs | 0 ...le-projection-based-on-where-clause.stderr | 23 + .../cycle-trait-default-type-trait.rs | 0 .../cycle-trait-default-type-trait.stderr | 11 + .../cycle-trait-supertrait-direct.rs | 0 .../cycle-trait-supertrait-direct.stderr | 11 + .../cycle-trait-supertrait-indirect.rs | 0 .../cycle-trait-supertrait-indirect.stderr | 0 .../dead-code-closure-bang.rs | 0 .../{compile-fail => ui}/dead-code-ret.rs | 0 src/test/ui/dead-code-ret.stderr | 15 + .../defaulted-never-note.rs | 2 +- src/test/ui/defaulted-never-note.stderr | 16 + .../dep-graph-assoc-type-codegen.rs | 0 .../dep-graph-assoc-type-codegen.stderr | 8 + .../dep-graph}/dep-graph-caller-callee.rs | 0 .../dep-graph/dep-graph-caller-callee.stderr | 14 + .../dep-graph}/dep-graph-struct-signature.rs | 1 - .../dep-graph-struct-signature.stderr | 134 + ...graph-trait-impl-two-traits-same-method.rs | 0 ...h-trait-impl-two-traits-same-method.stderr | 14 + .../dep-graph-trait-impl-two-traits.rs | 0 .../dep-graph-trait-impl-two-traits.stderr | 14 + .../dep-graph}/dep-graph-trait-impl.rs | 0 .../ui/dep-graph/dep-graph-trait-impl.stderr | 32 + .../dep-graph}/dep-graph-type-alias.rs | 0 .../ui/dep-graph/dep-graph-type-alias.stderr | 74 + .../dep-graph}/dep-graph-variance-alias.rs | 0 .../dep-graph/dep-graph-variance-alias.stderr | 8 + .../auxiliary/deprecation-lint.rs | 0 .../deprecated-macro_escape-inner.rs | 0 .../deprecated-macro_escape-inner.stderr | 0 .../deprecated-macro_escape.rs | 0 .../deprecated-macro_escape.stderr | 0 .../deprecation}/deprecated_no_stack_check.rs | 0 .../deprecated_no_stack_check.stderr | 9 + .../deprecation}/deprecation-in-staged-api.rs | 2 +- .../deprecation-in-staged-api.stderr | 8 + .../deprecation}/deprecation-lint-2.rs | 0 .../ui/deprecation/deprecation-lint-2.stderr | 15 + .../deprecation}/deprecation-lint-3.rs | 0 .../ui/deprecation/deprecation-lint-3.stderr | 15 + .../deprecation}/deprecation-lint-nested.rs | 0 .../deprecation-lint-nested.stderr | 44 + .../deprecation}/deprecation-lint.rs | 0 .../ui/deprecation/deprecation-lint.stderr | 728 +++ .../{ => deprecation}/deprecation-sanity.rs | 0 .../deprecation-sanity.stderr | 0 .../{compile-fail => ui}/deref-non-pointer.rs | 0 src/test/ui/deref-non-pointer.stderr | 9 + src/test/ui/deref-suggestion.rs | 14 +- src/test/ui/deref-suggestion.stderr | 26 +- .../derived-errors/issue-30580.rs | 0 src/test/ui/derived-errors/issue-30580.stderr | 9 + .../derived-errors/issue-31997.rs | 0 src/test/ui/derived-errors/issue-31997.stderr | 9 + .../derives}/derive-assoc-type-not-impl.rs | 0 .../derives/derive-assoc-type-not-impl.stderr | 18 + .../derive-on-trait-item-or-impl-item.rs | 0 .../derive-on-trait-item-or-impl-item.stderr | 14 + .../derives-span-Clone-enum-struct-variant.rs | 0 ...ives-span-Clone-enum-struct-variant.stderr | 11 + .../derives}/derives-span-Clone-enum.rs | 0 .../ui/derives/derives-span-Clone-enum.stderr | 11 + .../derives}/derives-span-Clone-struct.rs | 0 .../derives/derives-span-Clone-struct.stderr | 11 + .../derives-span-Clone-tuple-struct.rs | 0 .../derives-span-Clone-tuple-struct.stderr | 11 + .../derives-span-Debug-enum-struct-variant.rs | 0 ...ives-span-Debug-enum-struct-variant.stderr | 14 + .../derives}/derives-span-Debug-enum.rs | 0 .../ui/derives/derives-span-Debug-enum.stderr | 14 + .../derives}/derives-span-Debug-struct.rs | 0 .../derives/derives-span-Debug-struct.stderr | 14 + .../derives-span-Debug-tuple-struct.rs | 0 .../derives-span-Debug-tuple-struct.stderr | 14 + .../derives}/derives-span-Default-struct.rs | 0 .../derives-span-Default-struct.stderr | 11 + .../derives-span-Default-tuple-struct.rs | 0 .../derives-span-Default-tuple-struct.stderr | 11 + .../derives-span-Eq-enum-struct-variant.rs | 0 ...derives-span-Eq-enum-struct-variant.stderr | 11 + .../derives}/derives-span-Eq-enum.rs | 0 .../ui/derives/derives-span-Eq-enum.stderr | 11 + .../derives}/derives-span-Eq-struct.rs | 0 .../ui/derives/derives-span-Eq-struct.stderr | 11 + .../derives}/derives-span-Eq-tuple-struct.rs | 0 .../derives-span-Eq-tuple-struct.stderr | 11 + .../derives-span-Hash-enum-struct-variant.rs | 0 ...rives-span-Hash-enum-struct-variant.stderr | 11 + .../derives}/derives-span-Hash-enum.rs | 0 .../ui/derives/derives-span-Hash-enum.stderr | 11 + .../derives}/derives-span-Hash-struct.rs | 0 .../derives/derives-span-Hash-struct.stderr | 11 + .../derives-span-Hash-tuple-struct.rs | 0 .../derives-span-Hash-tuple-struct.stderr | 11 + .../derives-span-Ord-enum-struct-variant.rs | 0 ...erives-span-Ord-enum-struct-variant.stderr | 11 + .../derives}/derives-span-Ord-enum.rs | 0 .../ui/derives/derives-span-Ord-enum.stderr | 11 + .../derives}/derives-span-Ord-struct.rs | 0 .../ui/derives/derives-span-Ord-struct.stderr | 11 + .../derives}/derives-span-Ord-tuple-struct.rs | 0 .../derives-span-Ord-tuple-struct.stderr | 11 + ...ives-span-PartialEq-enum-struct-variant.rs | 0 ...-span-PartialEq-enum-struct-variant.stderr | 19 + .../derives}/derives-span-PartialEq-enum.rs | 0 .../derives-span-PartialEq-enum.stderr | 19 + .../derives}/derives-span-PartialEq-struct.rs | 0 .../derives-span-PartialEq-struct.stderr | 19 + .../derives-span-PartialEq-tuple-struct.rs | 0 ...derives-span-PartialEq-tuple-struct.stderr | 19 + ...ves-span-PartialOrd-enum-struct-variant.rs | 0 ...span-PartialOrd-enum-struct-variant.stderr | 12 + .../derives}/derives-span-PartialOrd-enum.rs | 0 .../derives-span-PartialOrd-enum.stderr | 12 + .../derives-span-PartialOrd-struct.rs | 0 .../derives-span-PartialOrd-struct.stderr | 12 + .../derives-span-PartialOrd-tuple-struct.rs | 0 ...erives-span-PartialOrd-tuple-struct.stderr | 12 + .../derives}/deriving-bounds.rs | 0 src/test/ui/derives/deriving-bounds.stderr | 14 + .../derives}/deriving-copyclone.rs | 0 src/test/ui/derives/deriving-copyclone.stderr | 42 + .../deriving-meta-empty-trait-list.rs | 0 .../deriving-meta-empty-trait-list.stderr | 0 .../derives}/deriving-meta-unknown-trait.rs | 0 .../deriving-meta-unknown-trait.stderr | 8 + .../deriving-no-inner-impl-error-message.rs | 0 ...eriving-no-inner-impl-error-message.stderr | 28 + .../derives}/deriving-non-type.rs | 0 src/test/ui/derives/deriving-non-type.stderr | 56 + .../derives}/deriving-primitive.rs | 0 src/test/ui/derives/deriving-primitive.stderr | 8 + .../deriving-with-repr-packed.rs | 0 .../deriving-with-repr-packed.stderr | 0 .../destructure-trait-ref.rs | 0 src/test/ui/destructure-trait-ref.stderr | 51 + ...e-21659-show-relevant-trait-impls-2.stderr | 2 +- .../ui/did_you_mean/issue-35937.nll.stderr | 19 +- src/test/ui/did_you_mean/issue-35937.stderr | 6 +- .../ui/did_you_mean/issue-39544.nll.stderr | 6 +- src/test/ui/did_you_mean/issue-39544.stderr | 4 +- .../issue-39802-show-5-trait-impls.stderr | 8 +- ...80-expected-float-found-integer-literal.rs | 29 + ...xpected-float-found-integer-literal.stderr | 57 + .../issue-54109-and_instead_of_ampersands.rs | 66 + ...sue-54109-and_instead_of_ampersands.stderr | 54 + .../foo/compiletest-ignore-dir | 0 .../foo/mod_file_not_owning/aux2.rs | 0 .../foo/mod_file_not_owning_aux2.rs | 0 .../directory_ownership/macro-expanded-mod.rs | 0 .../macro-expanded-mod.stderr | 8 + .../macro_expanded_mod_helper/foo/bar.rs | 0 .../macro_expanded_mod_helper/foo/mod.rs | 0 .../mod_file_not_owning_aux1.rs | 0 .../compiletest-ignore-dir | 0 .../mod_file_not_owning_aux2.rs | 0 .../mod_file_not_owning_aux2.rs | 0 .../mod_file_not_owning_aux3.rs | 0 .../non-inline-mod-restriction.rs | 0 .../non-inline-mod-restriction.stderr | 8 + ...tructing-destructing-struct-let.nll.stderr | 17 + ...d-deconstructing-destructing-struct-let.rs | 0 ...constructing-destructing-struct-let.stderr | 12 + ...ucting-destructing-struct-match.nll.stderr | 17 + ...deconstructing-destructing-struct-match.rs | 0 ...nstructing-destructing-struct-match.stderr | 12 + .../discrim}/discrim-ill-typed.rs | 0 src/test/ui/discrim/discrim-ill-typed.stderr | 51 + .../ui/{ => discrim}/discrim-overflow-2.rs | 0 .../{ => discrim}/discrim-overflow-2.stderr | 0 src/test/ui/{ => discrim}/discrim-overflow.rs | 0 .../ui/{ => discrim}/discrim-overflow.stderr | 0 .../diverging-fn-tail-35849.rs | 0 src/test/ui/diverging-fn-tail-35849.stderr | 15 + .../diverging-tuple-parts-39485.rs | 0 .../ui/diverging-tuple-parts-39485.stderr | 25 + src/test/{compile-fail => ui}/does-nothing.rs | 0 src/test/ui/does-nothing.stderr | 9 + .../dollar-crate-is-keyword-2.rs | 0 .../dollar-crate-is-keyword-2.stderr | 31 + .../dollar-crate/dollar-crate-is-keyword.rs | 28 + .../dollar-crate-is-keyword.stderr | 42 + .../double-type-import.rs | 0 src/test/ui/double-type-import.stderr | 17 + .../dropck}/drop-on-non-struct.rs | 0 src/test/ui/dropck/drop-on-non-struct.stderr | 19 + .../drop-with-active-borrows-1.nll.stderr | 13 + .../dropck}/drop-with-active-borrows-1.rs | 0 .../dropck/drop-with-active-borrows-1.stderr | 11 + .../drop-with-active-borrows-2.nll.stderr | 18 + .../dropck}/drop-with-active-borrows-2.rs | 0 .../dropck/drop-with-active-borrows-2.stderr | 18 + src/test/ui/dropck/dropck-union.nll.stderr | 16 + src/test/ui/dropck/dropck-union.rs | 50 + src/test/ui/dropck/dropck-union.stderr | 13 + .../dropck_no_diverge_on_nonregular_1.rs | 0 .../dropck_no_diverge_on_nonregular_1.stderr | 19 + .../dropck_no_diverge_on_nonregular_2.rs | 0 .../dropck_no_diverge_on_nonregular_2.stderr | 19 + .../dropck_no_diverge_on_nonregular_3.rs | 0 .../dropck_no_diverge_on_nonregular_3.stderr | 27 + .../dropck_trait_cycle_checked.nll.stderr | 68 + .../dropck}/dropck_trait_cycle_checked.rs | 0 .../dropck/dropck_trait_cycle_checked.stderr | 68 + .../dst}/dst-bad-assign-2.rs | 0 src/test/ui/dst/dst-bad-assign-2.stderr | 13 + .../dst}/dst-bad-assign-3.rs | 0 src/test/ui/dst/dst-bad-assign-3.stderr | 23 + .../dst}/dst-bad-assign.rs | 0 src/test/ui/dst/dst-bad-assign.stderr | 23 + .../dst}/dst-bad-coerce1.rs | 0 src/test/ui/dst/dst-bad-coerce1.stderr | 38 + .../dst}/dst-bad-coerce2.rs | 0 src/test/ui/dst/dst-bad-coerce2.stderr | 39 + src/test/ui/dst/dst-bad-coerce3.nll.stderr | 63 + .../dst}/dst-bad-coerce3.rs | 0 src/test/ui/dst/dst-bad-coerce3.stderr | 63 + .../dst}/dst-bad-coerce4.rs | 0 src/test/ui/dst/dst-bad-coerce4.stderr | 21 + .../dst}/dst-bad-coercions.rs | 0 src/test/ui/dst/dst-bad-coercions.stderr | 72 + .../dst}/dst-bad-deep-2.rs | 0 src/test/ui/dst/dst-bad-deep-2.stderr | 15 + .../{compile-fail => ui/dst}/dst-bad-deep.rs | 0 src/test/ui/dst/dst-bad-deep.stderr | 15 + src/test/ui/dst/dst-index.nll.stderr | 28 + .../{compile-fail => ui/dst}/dst-index.rs | 0 src/test/ui/dst/dst-index.stderr | 28 + .../dst}/dst-object-from-unsized-type.rs | 0 .../dst/dst-object-from-unsized-type.stderr | 45 + src/test/ui/dst/dst-rvalue.nll.stderr | 28 + .../{compile-fail => ui/dst}/dst-rvalue.rs | 0 src/test/ui/dst/dst-rvalue.stderr | 28 + .../dst}/dst-sized-trait-param.rs | 0 src/test/ui/dst/dst-sized-trait-param.stderr | 21 + .../ui/duplicate-check-macro-exports.stderr | 14 - .../duplicate}/dupe-symbols-1.rs | 0 src/test/ui/duplicate/dupe-symbols-1.stderr | 10 + .../duplicate}/dupe-symbols-2.rs | 0 src/test/ui/duplicate/dupe-symbols-2.stderr | 10 + .../duplicate}/dupe-symbols-3.rs | 0 src/test/ui/duplicate/dupe-symbols-3.stderr | 10 + .../duplicate}/dupe-symbols-4.rs | 0 src/test/ui/duplicate/dupe-symbols-4.stderr | 8 + .../duplicate}/dupe-symbols-5.rs | 0 src/test/ui/duplicate/dupe-symbols-5.stderr | 10 + .../duplicate}/dupe-symbols-6.rs | 0 src/test/ui/duplicate/dupe-symbols-6.stderr | 8 + .../duplicate}/dupe-symbols-7.rs | 0 src/test/ui/duplicate/dupe-symbols-7.stderr | 10 + .../duplicate-check-macro-exports.rs | 4 +- .../duplicate-check-macro-exports.stderr | 18 + .../duplicate}/duplicate-parameter.rs | 0 .../ui/duplicate/duplicate-parameter.stderr | 9 + .../duplicate}/duplicate-type-parameter.rs | 0 .../duplicate/duplicate-type-parameter.stderr | 66 + .../duplicate_entry_error.rs | 0 src/test/ui/duplicate_entry_error.stderr | 14 + .../dyn-trait-compatibility.rs | 0 src/test/ui/dyn-trait-compatibility.stderr | 52 + .../auxiliary/edition-extern-crate-allowed.rs | 0 .../auxiliary/edition-kw-macro-2015.rs | 3 +- .../auxiliary/edition-kw-macro-2018.rs | 3 +- .../editions}/edition-extern-crate-allowed.rs | 2 +- .../edition-extern-crate-allowed.stderr | 13 + .../editions}/edition-feature-ok.rs | 1 - .../ui/editions/edition-feature-redundant.rs | 17 + .../editions/edition-feature-redundant.stderr | 6 + .../edition-keywords-2015-2015-expansion.rs | 3 +- .../edition-keywords-2015-2015-parsing.rs | 2 - .../edition-keywords-2015-2015-parsing.stderr | 4 +- .../edition-keywords-2015-2018-expansion.rs | 2 - ...dition-keywords-2015-2018-expansion.stderr | 2 +- .../edition-keywords-2015-2018-parsing.rs | 2 - .../edition-keywords-2015-2018-parsing.stderr | 4 +- .../edition-keywords-2018-2015-expansion.rs | 3 +- .../edition-keywords-2018-2015-parsing.rs | 2 - .../edition-keywords-2018-2015-parsing.stderr | 8 +- .../edition-keywords-2018-2018-expansion.rs | 2 - ...dition-keywords-2018-2018-expansion.stderr | 2 +- .../edition-keywords-2018-2018-parsing.rs | 2 - .../edition-keywords-2018-2018-parsing.stderr | 8 +- .../edition-raw-pointer-method-2015.rs | 0 .../edition-raw-pointer-method-2015.stderr | 17 + .../edition-raw-pointer-method-2018.rs | 0 .../edition-raw-pointer-method-2018.stderr | 9 + .../ui/elide-errors-on-mismatched-tuple.rs | 28 + .../elide-errors-on-mismatched-tuple.stderr | 12 + src/test/{compile-fail => ui}/elided-test.rs | 0 src/test/ui/elided-test.stderr | 7 + .../empty}/auxiliary/empty-struct.rs | 0 .../empty}/auxiliary/two_macros.rs | 0 .../empty}/empty-comment.rs | 0 src/test/ui/empty/empty-comment.stderr | 8 + .../empty}/empty-linkname.rs | 0 src/test/ui/empty/empty-linkname.stderr | 9 + .../empty}/empty-macro-use.rs | 0 src/test/ui/empty/empty-macro-use.stderr | 8 + .../empty}/empty-never-array.rs | 0 src/test/ui/empty/empty-never-array.stderr | 9 + .../empty}/empty-struct-braces-expr.rs | 0 .../ui/empty/empty-struct-braces-expr.stderr | 68 + .../empty}/empty-struct-braces-pat-1.rs | 0 .../ui/empty/empty-struct-braces-pat-1.stderr | 18 + .../empty}/empty-struct-braces-pat-2.rs | 0 .../ui/empty/empty-struct-braces-pat-2.stderr | 39 + .../empty}/empty-struct-braces-pat-3.rs | 0 .../ui/empty/empty-struct-braces-pat-3.stderr | 33 + .../empty}/empty-struct-tuple-pat.rs | 0 .../ui/empty/empty-struct-tuple-pat.stderr | 36 + .../ui/{ => empty}/empty-struct-unit-expr.rs | 0 .../{ => empty}/empty-struct-unit-expr.stderr | 0 .../empty}/empty-struct-unit-pat.rs | 0 .../ui/empty/empty-struct-unit-pat.stderr | 55 + .../enable-unstable-lib-feature.rs | 2 +- .../ui/enable-unstable-lib-feature.stderr | 14 + .../enum-and-module-in-same-scope.rs | 0 .../enum-and-module-in-same-scope.stderr | 0 src/test/ui/enum/enum-discrim-autosizing.rs | 21 + .../ui/enum/enum-discrim-autosizing.stderr | 11 + .../enum}/enum-discrim-too-small.rs | 0 .../ui/enum/enum-discrim-too-small.stderr | 35 + .../enum}/enum-discrim-too-small2.rs | 0 .../ui/enum/enum-discrim-too-small2.stderr | 32 + .../enum}/enum-in-scope.rs | 0 src/test/ui/enum/enum-in-scope.stderr | 12 + src/test/ui/{ => enum}/enum-size-variance.rs | 0 .../ui/{ => enum}/enum-size-variance.stderr | 0 .../enum}/enum-to-float-cast-2.rs | 0 src/test/ui/enum/enum-to-float-cast-2.stderr | 19 + .../enum}/enum-to-float-cast.rs | 0 src/test/ui/enum/enum-to-float-cast.stderr | 19 + .../enum}/enum-variant-type-2.rs | 0 src/test/ui/enum/enum-variant-type-2.stderr | 12 + .../enums-pats-not-idents.rs | 0 src/test/ui/enums-pats-not-idents.stderr | 9 + src/test/ui/error-codes/E0087.rs | 18 - src/test/ui/error-codes/E0087.stderr | 15 - src/test/ui/error-codes/E0088.rs | 17 - src/test/ui/error-codes/E0088.stderr | 15 - src/test/ui/error-codes/E0089.rs | 15 - src/test/ui/error-codes/E0089.stderr | 9 - src/test/ui/error-codes/E0090.rs | 15 - src/test/ui/error-codes/E0090.stderr | 9 - src/test/ui/error-codes/E0107.rs | 9 +- src/test/ui/error-codes/E0107.stderr | 14 +- src/test/ui/error-codes/E0161.ast.stderr | 9 + src/test/ui/error-codes/E0161.astul.stderr | 9 + src/test/ui/error-codes/E0161.edition.stderr | 9 + .../ui/error-codes/E0161.editionul.stderr | 9 + src/test/ui/error-codes/E0161.nll.stderr | 9 + src/test/ui/error-codes/E0161.nllul.stderr | 9 + src/test/ui/error-codes/E0161.rs | 25 +- src/test/ui/error-codes/E0161.zflags.stderr | 9 + src/test/ui/error-codes/E0161.zflagsul.stderr | 9 + src/test/ui/error-codes/E0232.stderr | 2 +- src/test/ui/error-codes/E0243.rs | 16 - src/test/ui/error-codes/E0243.stderr | 9 - src/test/ui/error-codes/E0244.rs | 17 - src/test/ui/error-codes/E0244.stderr | 9 - src/test/ui/error-codes/E0277.stderr | 3 +- src/test/ui/error-codes/E0308.stderr | 4 +- src/test/ui/error-codes/E0395.rs | 4 +- src/test/ui/error-codes/E0395.stderr | 12 +- src/test/ui/error-codes/E0396-fixed.rs | 19 + src/test/ui/error-codes/E0396-fixed.stderr | 12 + src/test/ui/error-codes/E0396.rs | 5 +- src/test/ui/error-codes/E0396.stderr | 12 +- src/test/ui/error-codes/E0401.stderr | 9 +- src/test/ui/error-codes/E0504.nll.stderr | 17 +- src/test/ui/error-codes/E0509.nll.stderr | 12 + src/test/ui/error-codes/E0565-1.rs | 2 - src/test/ui/error-codes/E0565-1.stderr | 2 +- src/test/ui/error-codes/E0565.rs | 2 - src/test/ui/error-codes/E0565.stderr | 2 +- ...1-does-not-trigger-for-closures.nll.stderr | 17 +- src/test/ui/error-codes/E0659.stderr | 4 +- .../error-should-say-copy-not-pod.rs | 0 .../ui/error-should-say-copy-not-pod.stderr | 15 + .../{compile-fail => ui}/estr-subtyping.rs | 0 src/test/ui/estr-subtyping.stderr | 15 + src/test/{compile-fail => ui}/eval-enum.rs | 0 src/test/ui/eval-enum.stderr | 41 + .../exclusive-drop-and-copy.rs | 0 src/test/ui/exclusive-drop-and-copy.stderr | 15 + ...xclusive_range_pattern_syntax_collision.rs | 0 ...sive_range_pattern_syntax_collision.stderr | 8 + ...clusive_range_pattern_syntax_collision2.rs | 0 ...ive_range_pattern_syntax_collision2.stderr | 8 + ...clusive_range_pattern_syntax_collision3.rs | 0 ...ive_range_pattern_syntax_collision3.stderr | 8 + src/test/ui/exhaustive_integer_patterns.rs | 173 + .../ui/exhaustive_integer_patterns.stderr | 87 + ..._type_does_not_live_long_enough.nll.stderr | 8 +- ...eric_type_does_not_live_long_enough.stderr | 2 +- .../nested_existential_types.rs | 31 + .../never_reveal_concrete_type.stderr | 2 +- .../no_inferrable_concrete_type.rs | 23 + .../no_inferrable_concrete_type.stderr | 16 + ...o_revealing_outside_defining_module.stderr | 4 +- src/test/{compile-fail => ui}/expanded-cfg.rs | 0 src/test/ui/expanded-cfg.stderr | 8 + .../explicit}/explicit-call-to-dtor.rs | 0 .../ui/explicit/explicit-call-to-dtor.stderr | 9 + .../explicit-call-to-supertrait-dtor.rs | 0 .../explicit-call-to-supertrait-dtor.stderr | 9 + .../explicit-self-lifetime-mismatch.rs | 0 .../explicit-self-lifetime-mismatch.stderr | 41 + .../export-fully-qualified.rs | 0 src/test/ui/export-fully-qualified.stderr | 9 + .../{compile-fail => ui}/export-import.rs | 0 src/test/ui/export-import.stderr | 9 + .../export-tag-variant.rs | 0 src/test/ui/export-tag-variant.stderr | 9 + src/test/{compile-fail => ui}/export.rs | 0 src/test/ui/export.stderr | 34 + src/test/{compile-fail => ui}/export2.rs | 0 src/test/ui/export2.stderr | 9 + .../expr_attr_paren_order.rs | 0 src/test/ui/expr_attr_paren_order.stderr | 14 + .../{compile-fail => ui}/ext-nonexistent.rs | 0 src/test/ui/ext-nonexistent.stderr | 8 + .../extenv-arg-2-not-string-literal.rs | 0 .../extenv-arg-2-not-string-literal.stderr | 8 + .../extenv}/extenv-no-args.rs | 0 src/test/ui/extenv/extenv-no-args.stderr | 8 + .../extenv}/extenv-not-defined-custom.rs | 0 .../extenv/extenv-not-defined-custom.stderr | 8 + .../extenv}/extenv-not-defined-default.rs | 0 .../extenv/extenv-not-defined-default.stderr | 8 + .../extenv}/extenv-not-string-literal.rs | 0 .../extenv/extenv-not-string-literal.stderr | 8 + .../extenv}/extenv-too-many-args.rs | 0 .../ui/extenv/extenv-too-many-args.stderr | 8 + src/test/ui/{ => extern}/auxiliary/m1.rs | 0 src/test/ui/{ => extern}/auxiliary/m2.rs | 0 src/test/ui/{ => extern}/extern-const.fixed | 0 src/test/ui/{ => extern}/extern-const.rs | 0 src/test/ui/{ => extern}/extern-const.stderr | 0 .../ui/{ => extern}/extern-crate-rename.rs | 0 .../{ => extern}/extern-crate-rename.stderr | 0 .../extern}/extern-crate-visibility.rs | 0 .../ui/extern/extern-crate-visibility.stderr | 15 + .../extern}/extern-macro.rs | 2 - src/test/ui/extern/extern-macro.stderr | 8 + .../extern}/extern-main-fn.rs | 0 src/test/ui/extern/extern-main-fn.stderr | 12 + .../extern}/extern-types-distinct-types.rs | 0 .../extern/extern-types-distinct-types.stderr | 12 + .../extern}/extern-types-not-sync-send.rs | 0 .../extern/extern-types-not-sync-send.stderr | 29 + .../extern}/extern-types-unsized.rs | 0 .../ui/extern/extern-types-unsized.stderr | 63 + .../extern}/extern-with-type-bounds.rs | 0 .../ui/extern/extern-with-type-bounds.stderr | 9 + .../extern}/extern-wrong-value-type.rs | 2 +- .../ui/extern/extern-wrong-value-type.stderr | 17 + .../extern}/external-doc-error.rs | 3 + src/test/ui/extern/external-doc-error.stderr | 8 + .../extoption_env-no-args.rs | 0 src/test/ui/extoption_env-no-args.stderr | 8 + .../extoption_env-not-string-literal.rs | 0 .../extoption_env-not-string-literal.stderr | 8 + .../extoption_env-too-many-args.rs | 0 .../ui/extoption_env-too-many-args.stderr | 8 + .../fail-no-dead-code-core.rs | 0 src/test/ui/fail-no-dead-code-core.stderr | 14 + .../{compile-fail => ui}/fail-no-dead-code.rs | 0 src/test/ui/fail-no-dead-code.stderr | 14 + src/test/{compile-fail => ui}/fail-simple.rs | 0 src/test/ui/fail-simple.stderr | 8 + src/test/ui/feature-gate-catch_expr.rs | 17 - src/test/ui/feature-gate-catch_expr.stderr | 15 - src/test/ui/feature-gate-const_fn.stderr | 62 - src/test/ui/feature-gate-crate_in_paths.rs | 15 - .../ui/feature-gate-crate_in_paths.stderr | 11 - .../ui/feature-gate-custom_test_frameworks.rs | 13 + ...feature-gate-custom_test_frameworks.stderr | 11 + .../ui/feature-gate-doc_cfg-cfg-rustdoc.rs | 14 + .../feature-gate-doc_cfg-cfg-rustdoc.stderr | 11 + ...eature-gate-exhaustive_integer_patterns.rs | 16 + ...re-gate-exhaustive_integer_patterns.stderr | 9 + ...feature-gate-in_band_lifetimes-impl.stderr | 15 - ...eature-gate-infer_outlives_requirements.rs | 18 - ...re-gate-infer_outlives_requirements.stderr | 17 - src/test/ui/feature-gate-linker-flavor.stderr | 11 - src/test/ui/feature-gate-macro-vis-matcher.rs | 19 - .../ui/feature-gate-macro-vis-matcher.stderr | 11 - src/test/ui/feature-gate-raw-identifiers.rs | 14 - .../ui/feature-gate-raw-identifiers.stderr | 11 - src/test/ui/feature-gate-rustc-attrs.stderr | 27 - src/test/ui/feature-gate-tool_attributes.rs | 15 - .../ui/feature-gate-tool_attributes.stderr | 11 - src/test/ui/feature-gate-unsized_locals.rs | 15 + .../ui/feature-gate-unsized_locals.stderr | 14 + src/test/ui/feature-gate-used.rs | 15 - src/test/ui/feature-gate-used.stderr | 11 - .../ui/feature-gate/duplicate-features.rs | 19 + .../ui/feature-gate/duplicate-features.stderr | 15 + .../issue-43106-gating-of-bench.rs | 2 + .../issue-43106-gating-of-builtin-attrs.rs | 3 +- ...issue-43106-gating-of-builtin-attrs.stderr | 428 +- .../stability-attribute-consistency.rs | 26 + .../stability-attribute-consistency.stderr | 15 + src/test/ui/feature-gate/unknown-feature.rs | 13 + .../ui/feature-gate/unknown-feature.stderr | 9 + .../feature-gated-feature-in-macro-arg.rs | 0 .../feature-gated-feature-in-macro-arg.stderr | 13 + .../auxiliary/cfg-target-thread-local.rs | 0 .../feature-gate-abi-msp430-interrupt.rs | 0 .../feature-gate-abi-msp430-interrupt.stderr | 0 .../{ => feature-gates}/feature-gate-abi.rs | 0 .../feature-gate-abi.stderr | 0 .../feature-gate-abi_unadjusted.rs | 0 .../feature-gate-abi_unadjusted.stderr | 0 .../feature-gate-alloc-error-handler.rs | 0 .../feature-gate-alloc-error-handler.stderr | 11 + .../feature-gate-allocator_internals.rs | 0 .../feature-gate-allocator_internals.stderr | 0 ...gate-allow-internal-unsafe-nested-macro.rs | 0 ...-allow-internal-unsafe-nested-macro.stderr | 0 ...te-allow-internal-unstable-nested-macro.rs | 0 ...llow-internal-unstable-nested-macro.stderr | 0 ...ure-gate-allow-internal-unstable-struct.rs | 0 ...gate-allow-internal-unstable-struct.stderr | 0 .../feature-gate-allow-internal-unstable.rs | 0 ...eature-gate-allow-internal-unstable.stderr | 0 .../feature-gate-allow_fail.rs | 0 .../feature-gate-allow_fail.stderr | 0 .../feature-gate-arbitrary-self-types.rs | 0 .../feature-gate-arbitrary-self-types.stderr | 0 ...e-gate-arbitrary_self_types-raw-pointer.rs | 0 ...te-arbitrary_self_types-raw-pointer.stderr | 0 .../{ => feature-gates}/feature-gate-asm.rs | 0 .../feature-gate-asm.stderr | 0 .../{ => feature-gates}/feature-gate-asm2.rs | 0 .../feature-gate-asm2.stderr | 0 .../feature-gate-assoc-type-defaults.rs | 0 .../feature-gate-assoc-type-defaults.stderr | 0 .../feature-gate-async-await-2015-edition.rs | 0 ...ature-gate-async-await-2015-edition.stderr | 0 .../feature-gate-async-await.rs | 0 .../feature-gate-async-await.stderr | 0 .../feature-gate-box-expr.rs | 0 .../feature-gate-box-expr.stderr | 0 .../feature-gate-box_patterns.rs | 0 .../feature-gate-box_patterns.stderr | 0 .../feature-gate-box_syntax.rs | 0 .../feature-gate-box_syntax.stderr | 0 .../feature-gate-cfg-target-has-atomic.rs | 0 .../feature-gate-cfg-target-has-atomic.stderr | 0 .../feature-gate-cfg-target-thread-local.rs | 0 ...eature-gate-cfg-target-thread-local.stderr | 0 .../feature-gate-cfg-target-vendor.rs | 0 .../feature-gate-cfg-target-vendor.stderr | 0 .../feature-gate-compiler-builtins.rs | 0 .../feature-gate-compiler-builtins.stderr | 0 .../feature-gate-concat_idents.rs | 0 .../feature-gate-concat_idents.stderr | 0 .../feature-gate-concat_idents2.rs | 0 .../feature-gate-concat_idents2.stderr | 0 .../feature-gate-concat_idents3.rs | 0 .../feature-gate-concat_idents3.stderr | 0 .../feature-gate-const-indexing.rs | 0 .../feature-gate-const_fn.rs | 11 +- .../feature-gate-const_fn.stderr | 38 + .../feature-gate-const_let.rs | 0 .../feature-gate-const_let.stderr | 0 .../feature-gate-const_transmute.rs | 19 + .../feature-gate-const_transmute.stderr | 11 + .../feature-gate-crate_visibility_modifier.rs | 0 ...ture-gate-crate_visibility_modifier.stderr | 0 .../feature-gate-custom_attribute.rs | 2 +- .../feature-gate-custom_attribute.stderr | 52 +- .../feature-gate-custom_attribute2.rs | 0 .../feature-gate-custom_attribute2.stderr | 0 .../feature-gate-custom_derive.rs | 0 .../feature-gate-custom_derive.stderr | 4 +- .../feature-gate-decl_macro.rs | 0 .../feature-gate-decl_macro.stderr | 0 ...re-gate-default_type_parameter_fallback.rs | 0 ...ate-default_type_parameter_fallback.stderr | 0 .../feature-gate-doc_alias.rs | 0 .../feature-gate-doc_alias.stderr | 0 .../feature-gate-doc_cfg.rs | 0 .../feature-gate-doc_cfg.stderr | 0 .../feature-gate-doc_keyword.rs | 0 .../feature-gate-doc_keyword.stderr | 0 .../feature-gate-doc_masked.rs | 0 .../feature-gate-doc_masked.stderr | 0 .../feature-gate-doc_spotlight.rs | 0 .../feature-gate-doc_spotlight.stderr | 0 .../feature-gate-dropck-ugeh-2.rs | 0 .../feature-gate-dropck-ugeh-2.stderr | 0 .../feature-gate-dropck-ugeh.rs | 0 .../feature-gate-dropck-ugeh.stderr | 0 .../feature-gate-exclusive-range-pattern.rs | 0 ...eature-gate-exclusive-range-pattern.stderr | 0 .../feature-gate-exhaustive-patterns.rs | 0 .../feature-gate-exhaustive-patterns.stderr | 0 .../feature-gate-existential-type.rs | 0 .../feature-gate-existential-type.stderr | 0 .../feature-gate-extern_absolute_paths.rs | 0 .../feature-gate-extern_absolute_paths.stderr | 0 .../feature-gate-extern_in_paths.rs | 0 .../feature-gate-extern_in_paths.stderr | 0 .../feature-gate-extern_prelude.rs | 0 .../feature-gate-extern_prelude.stderr | 0 .../feature-gate-extern_types.rs | 0 .../feature-gate-extern_types.stderr | 0 .../feature-gate-external_doc.rs | 0 .../feature-gate-external_doc.stderr | 0 .../feature-gate-feature-gate.rs | 0 .../feature-gate-feature-gate.stderr | 0 .../feature-gate-format_args_nl.rs | 0 .../feature-gate-format_args_nl.stderr | 0 .../feature-gate-fundamental.rs | 0 .../feature-gate-fundamental.stderr | 0 .../feature-gate-generators.rs | 0 .../feature-gate-generators.stderr | 0 .../feature-gate-generic_associated_types.rs | 0 ...ature-gate-generic_associated_types.stderr | 0 .../feature-gate-global_asm.rs | 0 .../feature-gate-global_asm.stderr | 0 .../feature-gate-if_while_or_patterns.rs | 0 .../feature-gate-if_while_or_patterns.stderr | 0 ...pl_header_lifetime_elision-with-in_band.rs | 27 + ...eader_lifetime_elision-with-in_band.stderr | 15 + ...ture-gate-impl_header_lifetime_elision.rs} | 0 ...e-gate-impl_header_lifetime_elision.stderr | 15 + .../feature-gate-in_band_lifetimes.rs | 3 + .../feature-gate-in_band_lifetimes.stderr | 34 +- ...gate-infer_static_outlives_requirements.rs | 0 ...-infer_static_outlives_requirements.stderr | 0 .../feature-gate-intrinsics.rs | 0 .../feature-gate-intrinsics.stderr | 0 .../feature-gate-label_break_value.rs | 0 .../feature-gate-label_break_value.stderr | 0 .../feature-gate-lang-items.rs | 0 .../feature-gate-lang-items.stderr | 0 .../feature-gate-link_args.rs | 0 .../feature-gate-link_args.stderr | 0 .../feature-gate-link_cfg.rs | 0 .../feature-gate-link_cfg.stderr | 0 .../feature-gate-link_llvm_intrinsics.rs | 0 .../feature-gate-link_llvm_intrinsics.stderr | 0 .../feature-gate-linkage.rs | 0 .../feature-gate-linkage.stderr | 0 .../feature-gate-linker-flavor.rs | 3 +- .../feature-gate-linker-flavor.stderr | 8 + .../feature-gate-log_syntax.rs | 0 .../feature-gate-log_syntax.stderr | 0 .../feature-gate-log_syntax2.rs | 0 .../feature-gate-log_syntax2.stderr | 0 .../feature-gate-macro-literal-matcher.rs | 0 .../feature-gate-macro-literal-matcher.stderr | 0 .../feature-gate-macros_in_extern.rs | 6 +- .../feature-gate-macros_in_extern.stderr | 6 +- .../{ => feature-gates}/feature-gate-main.rs | 0 .../feature-gate-main.stderr | 0 .../feature-gate-may-dangle.rs | 0 .../feature-gate-may-dangle.stderr | 0 .../feature-gate-min_const_fn.rs | 46 + .../feature-gate-min_const_fn.stderr | 62 + .../feature-gate-naked_functions.rs | 0 .../feature-gate-naked_functions.stderr | 0 .../feature-gate-needs-allocator.rs | 0 .../feature-gate-needs-allocator.stderr | 0 .../feature-gate-negate-unsigned.rs | 0 .../feature-gate-negate-unsigned.stderr | 0 .../feature-gate-never_type.rs | 0 .../feature-gate-never_type.stderr | 0 .../feature-gate-nll.nll.stderr | 0 .../{ => feature-gates}/feature-gate-nll.rs | 0 .../feature-gate-nll.stderr | 0 .../feature-gate-no-debug-2.rs | 0 .../feature-gate-no-debug-2.stderr | 0 .../feature-gate-no-debug.rs | 0 .../feature-gate-no-debug.stderr | 0 .../feature-gate-no_core.rs | 0 .../feature-gate-no_core.stderr | 0 .../feature-gate-non_ascii_idents.rs | 0 .../feature-gate-non_ascii_idents.stderr | 0 .../feature-gate-non_exhaustive.rs | 0 .../feature-gate-non_exhaustive.stderr | 0 ...re-gate-omit-gdb-pretty-printer-section.rs | 0 ...ate-omit-gdb-pretty-printer-section.stderr | 0 .../feature-gate-on-unimplemented.rs | 0 .../feature-gate-on-unimplemented.stderr | 0 .../feature-gate-optin-builtin-traits.rs | 0 .../feature-gate-optin-builtin-traits.stderr | 0 .../feature-gate-overlapping_marker_traits.rs | 0 ...ture-gate-overlapping_marker_traits.stderr | 0 .../feature-gate-panic-implementation.rs | 2 +- .../feature-gate-panic-implementation.stderr | 11 + .../feature-gate-pattern_parentheses.rs | 0 .../feature-gate-pattern_parentheses.stderr | 0 .../feature-gate-plugin.rs | 0 .../feature-gate-plugin.stderr | 0 .../feature-gate-plugin_registrar.rs | 0 .../feature-gate-plugin_registrar.stderr | 0 .../feature-gate-prelude_import.rs | 0 .../feature-gate-prelude_import.stderr | 0 .../feature-gate-profiler-runtime.rs | 0 .../feature-gate-profiler-runtime.stderr | 0 .../feature-gate-repr-simd.rs | 0 .../feature-gate-repr-simd.stderr | 0 .../feature-gate-repr128.rs | 0 .../feature-gate-repr128.stderr | 0 .../feature-gate-repr_packed.rs | 0 .../feature-gate-repr_packed.stderr | 0 .../feature-gate-rustc-attrs-1.rs | 18 + .../feature-gate-rustc-attrs-1.stderr | 19 + .../feature-gate-rustc-attrs.rs | 2 - .../feature-gate-rustc-attrs.stderr | 11 + .../feature-gate-rustc-diagnostic-macros.rs | 0 ...eature-gate-rustc-diagnostic-macros.stderr | 0 .../feature-gate-rustc_const_unstable.rs | 0 .../feature-gate-rustc_const_unstable.stderr | 0 .../feature-gate-sanitizer-runtime.rs | 0 .../feature-gate-sanitizer-runtime.stderr | 0 .../feature-gate-self-in-typedefs.rs | 18 + .../feature-gate-self-in-typedefs.stderr | 9 + .../feature-gate-self-struct-ctor.rs | 22 + .../feature-gate-self-struct-ctor.stderr | 19 + .../feature-gate-simd-ffi.rs | 0 .../feature-gate-simd-ffi.stderr | 0 .../{ => feature-gates}/feature-gate-simd.rs | 0 .../feature-gate-simd.stderr | 0 .../feature-gate-slice-patterns.rs | 0 .../feature-gate-slice-patterns.stderr | 0 .../feature-gate-staged_api.rs | 0 .../feature-gate-staged_api.stderr | 0 .../{ => feature-gates}/feature-gate-start.rs | 0 .../feature-gate-start.stderr | 0 .../feature-gate-static-nobundle.rs | 0 .../feature-gate-static-nobundle.stderr | 0 .../feature-gate-stmt_expr_attributes.rs | 0 .../feature-gate-stmt_expr_attributes.stderr | 0 .../feature-gate-thread_local.rs | 0 .../feature-gate-thread_local.stderr | 0 .../feature-gate-tool_lints-fail.rs} | 0 .../feature-gate-tool_lints-fail.stderr | 11 + .../feature-gate-tool_lints.rs | 0 .../feature-gate-tool_lints.stderr | 0 .../feature-gate-trace_macros.rs | 0 .../feature-gate-trace_macros.stderr | 0 .../feature-gate-trivial_bounds-lint.rs | 0 .../feature-gate-trivial_bounds.rs | 0 .../feature-gate-trivial_bounds.stderr | 6 +- .../feature-gates/feature-gate-try_blocks.rs | 19 + .../feature-gate-try_blocks.stderr | 15 + .../feature-gate-try_reserve.rs | 0 .../feature-gate-try_reserve.stderr | 0 .../feature-gate-type_ascription.rs | 0 .../feature-gate-type_ascription.stderr | 0 ...ture-gate-unboxed-closures-manual-impls.rs | 0 ...-gate-unboxed-closures-manual-impls.stderr | 0 ...ture-gate-unboxed-closures-method-calls.rs | 0 ...-gate-unboxed-closures-method-calls.stderr | 0 ...eature-gate-unboxed-closures-ufcs-calls.rs | 0 ...re-gate-unboxed-closures-ufcs-calls.stderr | 0 .../feature-gate-unboxed-closures.rs | 0 .../feature-gate-unboxed-closures.stderr | 0 .../feature-gate-underscore-imports.rs | 0 .../feature-gate-underscore-imports.stderr | 0 .../feature-gate-uniform-paths.rs | 22 + .../feature-gate-uniform-paths.stderr | 9 + ...ture-gate-unrestricted-attribute-tokens.rs | 17 + ...-gate-unrestricted-attribute-tokens.stderr | 20 + .../feature-gate-unsized_tuple_coercion.rs | 0 ...feature-gate-unsized_tuple_coercion.stderr | 0 .../feature-gate-untagged_unions.rs | 0 .../feature-gate-untagged_unions.stderr | 0 .../feature-gate-unwind-attributes.rs | 2 +- .../feature-gate-unwind-attributes.stderr | 0 ...e-gate-without_gate_irrefutable_pattern.rs | 0 ...te-without_gate_irrefutable_pattern.stderr | 9 + .../float-literal-inference-restrictions.rs | 0 ...loat-literal-inference-restrictions.stderr | 21 + .../fn}/fn-bad-block-type.rs | 0 src/test/ui/fn/fn-bad-block-type.stderr | 11 + .../fn-closure-mutable-capture.nll.stderr | 0 .../ui/{ => fn}/fn-closure-mutable-capture.rs | 0 .../fn-closure-mutable-capture.stderr | 0 .../fn}/fn-compare-mismatch.rs | 0 src/test/ui/fn/fn-compare-mismatch.stderr | 21 + .../{compile-fail => ui/fn}/fn-item-type.rs | 0 src/test/ui/fn/fn-item-type.stderr | 39 + .../fn}/fn-trait-formatting.rs | 2 +- src/test/ui/fn/fn-trait-formatting.stderr | 44 + src/test/ui/{ => for}/for-c-in-str.rs | 0 src/test/ui/{ => for}/for-c-in-str.stderr | 0 src/test/{compile-fail => ui/for}/for-expn.rs | 0 src/test/ui/for/for-expn.stderr | 9 + .../for}/for-loop-bogosity.rs | 0 src/test/ui/for/for-loop-bogosity.stderr | 12 + ...or-loop-refutable-pattern-error-message.rs | 0 ...oop-refutable-pattern-error-message.stderr | 9 + .../for}/for-loop-type-error.rs | 0 src/test/ui/for/for-loop-type-error.stderr | 11 + .../for-loop-unconstrained-element-type.rs | 0 ...for-loop-unconstrained-element-type.stderr | 12 + .../foreign-fn-return-lifetime.rs | 0 src/test/ui/foreign-fn-return-lifetime.stderr | 12 + .../foreign-unsafe-fn-called.rs | 0 src/test/ui/foreign-unsafe-fn-called.stderr | 11 + .../fully-qualified-type-name1.rs | 0 .../fully-qualified-type-name1.stderr | 15 + .../fully-qualified-type-name2.rs | 0 .../fully-qualified-type-name2.stderr | 12 + .../fully-qualified-type-name3.rs | 0 .../fully-qualified-type-name4.rs | 0 .../fully-qualified-type-name4.stderr | 12 + ...ional-struct-update-noncopyable.nll.stderr | 9 + .../functional-struct-update-noncopyable.rs | 0 ...unctional-struct-update-noncopyable.stderr | 9 + ...nctional-struct-update-respects-privacy.rs | 0 ...onal-struct-update-respects-privacy.stderr | 9 + .../future-incompatible-lint-group.rs | 0 .../ui/future-incompatible-lint-group.stderr | 17 + .../{compile-fail => ui}/gated-bad-feature.rs | 2 + src/test/ui/gated-bad-feature.stderr | 34 + .../generator-yielding-or-returning-itself.rs | 0 ...erator-yielding-or-returning-itself.stderr | 39 + src/test/ui/generator/dropck.nll.stderr | 2 - src/test/ui/generator/sized-yield.stderr | 4 +- ...eric-type-less-params-with-defaults.stderr | 9 - ...eric-type-more-params-with-defaults.stderr | 9 - .../generic/generic-arg-mismatch-recover.rs | 21 + .../generic-arg-mismatch-recover.stderr | 31 + .../generic}/generic-extern-lifetime.rs | 0 .../ui/generic/generic-extern-lifetime.stderr | 21 + .../generic}/generic-extern.rs | 0 src/test/ui/generic/generic-extern.stderr | 11 + .../generic-impl-less-params-with-defaults.rs | 0 ...eric-impl-less-params-with-defaults.stderr | 9 + .../generic-impl-more-params-with-defaults.rs | 0 ...eric-impl-more-params-with-defaults.stderr | 9 + .../generic}/generic-lifetime-trait-impl.rs | 0 .../generic-lifetime-trait-impl.stderr | 12 + .../generic}/generic-no-mangle.rs | 0 src/test/ui/generic/generic-no-mangle.stderr | 24 + .../generic}/generic-non-trailing-defaults.rs | 0 .../generic-non-trailing-defaults.stderr | 21 + .../ui/{ => generic}/generic-param-attrs.rs | 0 .../generic-type-less-params-with-defaults.rs | 2 +- ...eric-type-less-params-with-defaults.stderr | 9 + .../generic-type-more-params-with-defaults.rs | 2 +- ...eric-type-more-params-with-defaults.stderr | 9 + .../generic-type-params-forward-mention.rs | 0 ...generic-type-params-forward-mention.stderr | 9 + .../generic}/generic-type-params-name-repr.rs | 0 .../generic-type-params-name-repr.stderr | 57 + src/test/{compile-fail => ui}/glob-cycles.rs | 0 src/test/ui/glob-cycles.stderr | 8 + .../{compile-fail => ui}/glob-resolve1.rs | 0 src/test/ui/glob-resolve1.stderr | 79 + .../ui/hashmap-iter-value-lifetime.nll.stderr | 15 + .../hashmap-iter-value-lifetime.rs | 0 .../ui/hashmap-iter-value-lifetime.stderr | 15 + src/test/ui/hashmap-lifetimes.nll.stderr | 13 + .../{compile-fail => ui}/hashmap-lifetimes.rs | 3 + src/test/ui/hashmap-lifetimes.stderr | 14 + .../hidden-rt-injection.rs | 0 src/test/ui/hidden-rt-injection.stderr | 9 + .../hidden-rt-injection2.rs | 0 src/test/ui/hidden-rt-injection2.stderr | 9 + ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 16 + .../hr-subtype.bound_a_b_vs_bound_a.stderr | 16 + .../hr-subtype.bound_a_vs_bound_a.stderr | 14 + .../hr-subtype.bound_a_vs_bound_b.stderr | 14 + .../hr-subtype.bound_a_vs_free_x.stderr | 16 + ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 16 + ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 16 + ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 14 + ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 16 + ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 16 + ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 14 + ...ubtype.free_inv_x_vs_free_inv_y.nll.stderr | 30 + ...hr-subtype.free_inv_x_vs_free_inv_y.stderr | 65 + .../hr-subtype.free_x_vs_free_x.stderr | 14 + .../hr-subtype.free_x_vs_free_y.nll.stderr | 16 + .../hr-subtype.free_x_vs_free_y.stderr | 34 + .../hr-subtype}/hr-subtype.rs | 0 .../hrtb}/hrtb-conflate-regions.rs | 0 src/test/ui/hrtb/hrtb-conflate-regions.stderr | 20 + .../hrtb/hrtb-debruijn-in-receiver.nll.stderr | 14 + .../hrtb}/hrtb-debruijn-in-receiver.rs | 0 .../ui/hrtb/hrtb-debruijn-in-receiver.stderr | 13 + ...tb-higher-ranker-supertraits-transitive.rs | 0 ...igher-ranker-supertraits-transitive.stderr | 19 + .../hrtb}/hrtb-higher-ranker-supertraits.rs | 0 .../hrtb-higher-ranker-supertraits.stderr | 40 + .../hrtb-identity-fn-borrows.ast.nll.stderr | 14 + .../hrtb/hrtb-identity-fn-borrows.ast.stderr | 11 + .../hrtb/hrtb-identity-fn-borrows.mir.stderr | 14 + .../hrtb}/hrtb-identity-fn-borrows.rs | 0 .../hrtb}/hrtb-just-for-static.rs | 0 src/test/ui/hrtb/hrtb-just-for-static.stderr | 20 + .../hrtb}/hrtb-perfect-forwarding.rs | 0 .../ui/hrtb/hrtb-perfect-forwarding.stderr | 23 + .../{compile-fail => ui}/huge-array-simple.rs | 0 src/test/{compile-fail => ui}/huge-array.rs | 0 src/test/ui/huge-array.stderr | 4 + src/test/{compile-fail => ui}/huge-enum.rs | 1 + src/test/ui/huge-enum.stderr | 4 + src/test/{compile-fail => ui}/huge-struct.rs | 2 + src/test/ui/huge-struct.stderr | 4 + .../ui/hygiene/dollar-crate-modern.stderr | 8 + src/test/ui/hygiene/fields-move.nll.stderr | 24 +- src/test/ui/hygiene/generate-mod.rs | 2 + src/test/ui/hygiene/generate-mod.stderr | 9 +- .../hygiene}/hygienic-label-1.rs | 0 src/test/ui/hygiene/hygienic-label-1.stderr | 12 + .../hygiene}/hygienic-label-2.rs | 0 src/test/ui/hygiene/hygienic-label-2.stderr | 9 + .../hygiene}/hygienic-label-3.rs | 0 src/test/ui/hygiene/hygienic-label-3.stderr | 12 + .../hygiene}/hygienic-label-4.rs | 0 src/test/ui/hygiene/hygienic-label-4.stderr | 9 + src/test/ui/hygiene/local_inner_macros.rs | 2 - .../ui/hygiene/local_inner_macros_disabled.rs | 20 - .../local_inner_macros_disabled.stderr | 10 - src/test/ui/hygiene/no_implicit_prelude.rs | 2 + .../ui/hygiene/no_implicit_prelude.stderr | 8 +- .../if}/if-branch-types.rs | 0 src/test/ui/if/if-branch-types.stderr | 12 + src/test/ui/{ => if}/if-let-arm-types.rs | 0 src/test/ui/{ => if}/if-let-arm-types.stderr | 0 src/test/{compile-fail => ui/if}/if-let.rs | 0 src/test/ui/if/if-let.stderr | 39 + src/test/{compile-fail => ui/if}/if-loop.rs | 0 src/test/ui/if/if-loop.stderr | 8 + src/test/{compile-fail => ui/if}/if-typeck.rs | 0 src/test/ui/if/if-typeck.stderr | 12 + src/test/ui/{ => if}/if-without-block.rs | 0 src/test/ui/{ => if}/if-without-block.stderr | 0 .../if}/if-without-else-result.rs | 0 src/test/ui/if/if-without-else-result.stderr | 12 + src/test/ui/{ => if}/ifmt-bad-arg.rs | 0 src/test/ui/{ => if}/ifmt-bad-arg.stderr | 0 .../if}/ifmt-bad-format-args.rs | 0 src/test/ui/if/ifmt-bad-format-args.stderr | 18 + .../{compile-fail => ui/if}/ifmt-unimpl.rs | 0 src/test/ui/if/ifmt-unimpl.stderr | 12 + .../if}/ifmt-unknown-trait.rs | 0 src/test/ui/if/ifmt-unknown-trait.stderr | 8 + .../{compile-fail => ui}/illegal-ufcs-drop.rs | 0 src/test/ui/illegal-ufcs-drop.stderr | 9 + .../immut-function-arguments.ast.nll.stderr | 19 + .../ui/immut-function-arguments.ast.stderr | 19 + .../ui/immut-function-arguments.mir.stderr | 19 + .../immut-function-arguments.rs | 0 .../impl-bounds-checking.rs | 0 src/test/ui/impl-bounds-checking.stderr | 9 + .../assoc-type.rs | 4 +- .../assoc-type.stderr | 0 .../dyn-trait.nll.stderr | 10 + .../impl-header-lifetime-elision/dyn-trait.rs | 43 + .../dyn-trait.stderr | 0 .../path-elided.rs | 2 +- .../path-elided.stderr | 0 .../path-underscore.rs | 2 +- .../ref-underscore.rs | 2 +- .../trait-elided.rs | 2 +- .../trait-elided.stderr | 0 .../trait-underscore.rs | 2 +- src/test/ui/impl-trait/equality2.rs | 2 +- src/test/ui/impl-trait/equality2.stderr | 2 +- .../impl-trait/impl-generic-mismatch-ab.rs | 0 .../impl-generic-mismatch-ab.stderr | 15 + .../ui/impl-trait/impl-generic-mismatch.rs | 3 + .../impl-trait/impl-generic-mismatch.stderr | 8 +- .../impl_trait_projections.rs | 0 .../impl_trait_projections.stderr | 0 .../infinite-impl-trait-issue-38064.rs | 0 .../infinite-impl-trait-issue-38064.stderr | 7 + ...t_outlive_least_region_or_bound.nll.stderr | 43 + .../must_outlive_least_region_or_bound.rs | 0 .../must_outlive_least_region_or_bound.stderr | 71 + .../impl-trait/needs_least_region_or_bound.rs | 0 .../needs_least_region_or_bound.stderr | 8 + .../impl-trait/no-trait.rs | 0 src/test/ui/impl-trait/no-trait.stderr | 8 + .../static-return-lifetime-infered.nll.stderr | 18 +- .../type_parameters_captured.nll.stderr | 11 + .../impl-trait/type_parameters_captured.rs | 0 .../type_parameters_captured.stderr | 17 + .../impl-trait/where-allowed.rs | 2 +- src/test/ui/impl-trait/where-allowed.stderr | 244 + .../impl-unused-tps-inherent.rs | 0 src/test/ui/impl-unused-tps-inherent.stderr | 15 + .../{compile-fail => ui}/impl-unused-tps.rs | 0 src/test/ui/impl-unused-tps.stderr | 33 + .../implicit-method-bind.rs | 0 src/test/ui/implicit-method-bind.stderr | 11 + src/test/{compile-fail => ui}/import.rs | 0 src/test/ui/import.stderr | 22 + src/test/{compile-fail => ui}/import2.rs | 0 src/test/ui/import2.stderr | 9 + src/test/{compile-fail => ui}/import3.rs | 0 src/test/ui/import3.stderr | 9 + src/test/{compile-fail => ui}/import4.rs | 0 src/test/ui/import4.stderr | 9 + .../imports}/auxiliary/import_crate_var.rs | 0 src/test/ui/imports/duplicate.stderr | 14 +- src/test/ui/imports/glob-shadowing.stderr | 6 +- .../imports}/import-crate-var.rs | 7 +- src/test/ui/imports/import-crate-var.stderr | 21 + .../imports}/import-from-missing.rs | 0 .../ui/imports/import-from-missing.stderr | 9 + .../imports}/import-glob-0.rs | 0 src/test/ui/imports/import-glob-0.stderr | 9 + .../imports}/import-glob-circular.rs | 2 + .../ui/imports/import-glob-circular.stderr | 9 + .../imports}/import-loop-2.rs | 2 + src/test/ui/imports/import-loop-2.stderr | 9 + .../imports}/import-loop.rs | 0 src/test/ui/imports/import-loop.stderr | 9 + .../imports}/import-prefix-macro-1.rs | 0 .../ui/imports/import-prefix-macro-1.stderr | 11 + .../imports}/import-prefix-macro-2.rs | 0 .../ui/imports/import-prefix-macro-2.stderr | 11 + .../imports}/import-trait-method.rs | 0 .../ui/imports/import-trait-method.stderr | 9 + src/test/ui/imports/issue-53269.rs | 21 + src/test/ui/imports/issue-53269.stderr | 27 + src/test/ui/imports/issue-53512.rs | 17 + src/test/ui/imports/issue-53512.stderr | 9 + .../local-modularized-tricky-fail-1.rs | 56 + .../local-modularized-tricky-fail-1.stderr | 83 + .../local-modularized-tricky-fail-2.rs | 58 + .../local-modularized-tricky-fail-2.stderr | 36 + .../local-modularized-tricky-fail-3.rs | 32 + .../local-modularized-tricky-fail-3.stderr | 41 + .../imports/local-modularized-tricky-pass.rs | 29 + src/test/ui/imports/local-modularized.rs | 45 + src/test/ui/imports/macro-paths.rs | 2 - src/test/ui/imports/macro-paths.stderr | 16 +- src/test/ui/imports/macros.rs | 2 - src/test/ui/imports/macros.stderr | 30 +- .../{compile-fail => ui}/imports/reexports.rs | 0 src/test/ui/imports/reexports.stderr | 34 + .../ui/imports/rfc-1560-warning-cycle.stderr | 2 +- src/test/ui/imports/shadow_builtin_macros.rs | 6 +- .../ui/imports/shadow_builtin_macros.stderr | 36 +- .../imports/unused-macro-use.rs | 0 src/test/ui/imports/unused-macro-use.stderr | 21 + .../{compile-fail => ui}/imports/unused.rs | 0 src/test/ui/imports/unused.stderr | 15 + .../in-band-lifetimes/elided-lifetimes.fixed | 2 +- .../ui/in-band-lifetimes/elided-lifetimes.rs | 2 +- .../impl/dyn-trait.nll.stderr | 16 - .../ui/in-band-lifetimes/impl/dyn-trait.rs | 43 - .../in-band-lifetimes/mismatched.nll.stderr | 30 +- .../ui/in-band-lifetimes/mismatched.stderr | 6 +- .../mismatched_trait.nll.stderr | 17 - .../in-band-lifetimes/mismatched_trait.stderr | 2 +- .../inaccessible-test-modules.rs | 0 src/test/ui/inaccessible-test-modules.stderr | 15 + src/test/{compile-fail => ui}/index-bot.rs | 0 src/test/ui/index-bot.stderr | 9 + .../{compile-fail => ui}/index_message.rs | 0 src/test/ui/index_message.stderr | 9 + .../indexing-requires-a-uint.rs | 0 src/test/ui/indexing-requires-a-uint.stderr | 19 + .../auxiliary/inference_unstable_iterator.rs | 0 .../auxiliary/inference_unstable_itertools.rs | 0 .../inference-variable-behind-raw-pointer.rs | 0 ...ference-variable-behind-raw-pointer.stderr | 0 .../ui/{ => inference}/inference_unstable.rs | 0 .../{ => inference}/inference_unstable.stderr | 0 .../inference_unstable_featured.rs | 0 .../inference_unstable_featured.stderr | 0 .../inference_unstable_forced.rs | 0 .../inference_unstable_forced.stderr | 0 .../infinite}/infinite-autoderef.rs | 0 .../ui/infinite/infinite-autoderef.stderr | 52 + .../infinite}/infinite-instantiation.rs | 0 .../ui/infinite/infinite-instantiation.stderr | 14 + .../infinite}/infinite-macro-expansion.rs | 0 .../infinite/infinite-macro-expansion.stderr | 13 + .../infinite-recursion-const-fn.rs | 2 +- .../infinite-recursion-const-fn.stderr | 0 .../infinite}/infinite-tag-type-recursion.rs | 0 .../infinite-tag-type-recursion.stderr | 13 + .../infinite}/infinite-vec-type-recursion.rs | 0 .../infinite-vec-type-recursion.stderr | 11 + .../inhabitedness-infinite-loop.rs | 0 .../ui/inhabitedness-infinite-loop.stderr | 4 + src/test/{compile-fail => ui}/init-unsafe.rs | 0 src/test/ui/init-unsafe.stderr | 11 + .../inner-static-type-parameter.rs | 0 .../ui/inner-static-type-parameter.stderr | 22 + .../integer-literal-suffix-inference.rs | 0 .../integer-literal-suffix-inference.stderr | 291 ++ .../{compile-fail => ui}/integral-indexing.rs | 0 src/test/ui/integral-indexing.stderr | 75 + .../integral-variable-unification-error.rs | 0 ...integral-variable-unification-error.stderr | 12 + .../internal}/auxiliary/internal_unstable.rs | 0 .../internal}/internal-unstable-noallow.rs | 0 .../internal/internal-unstable-noallow.stderr | 39 + .../internal-unstable-thread-local.rs | 0 .../internal-unstable-thread-local.stderr | 11 + .../internal}/internal-unstable.rs | 0 src/test/ui/internal/internal-unstable.stderr | 46 + .../intrinsic-invalid-number-of-arguments.rs | 0 ...trinsic-invalid-number-of-arguments.stderr | 9 + .../invalid-module-declaration.rs | 3 - src/test/ui/invalid/invalid-crate-type.rs | 58 + src/test/ui/invalid/invalid-crate-type.stderr | 58 + .../invalid}/invalid-inline.rs | 0 src/test/ui/invalid/invalid-inline.stderr | 22 + .../invalid}/invalid-macro-matcher.rs | 0 .../ui/invalid/invalid-macro-matcher.stderr | 8 + .../ui/{ => invalid}/invalid-path-in-const.rs | 0 .../invalid-path-in-const.stderr | 0 .../invalid}/invalid-plugin-attr.rs | 0 .../ui/invalid/invalid-plugin-attr.stderr | 20 + .../invalid-variadic-function.rs | 0 .../invalid-variadic-function.stderr | 0 .../invalid_crate_type_syntax.rs | 2 + src/test/ui/invalid_crate_type_syntax.stderr | 10 + src/test/ui/issue-10291.nll.stderr | 14 - src/test/{parse-fail => ui}/issue-10636-1.rs | 9 +- src/test/ui/issue-10636-1.stderr | 11 + src/test/ui/issue-11692-1.stderr | 12 - src/test/ui/issue-11692-2.stderr | 8 - src/test/ui/issue-12567.nll.stderr | 31 - src/test/ui/issue-12796.stderr | 11 - src/test/ui/issue-13058.nll.stderr | 27 - src/test/ui/issue-14092.stderr | 9 - src/test/ui/issue-14285.nll.stderr | 17 - src/test/ui/issue-15034.nll.stderr | 17 - src/test/ui/issue-16683.nll.stderr | 22 - src/test/ui/issue-16922.nll.stderr | 17 - src/test/ui/issue-17458.stderr | 9 - .../ui/issue-17718-const-bad-values.stderr | 28 - src/test/ui/issue-17758.nll.stderr | 22 - src/test/ui/issue-17954.ast.nll.stderr | 14 - src/test/ui/issue-17954.ast.stderr | 14 - src/test/ui/issue-17954.mir.stderr | 14 - src/test/ui/issue-17954.rs | 33 - src/test/ui/issue-18294.stderr | 9 - src/test/ui/issue-18423.stderr | 9 - src/test/ui/issue-22034.stderr | 11 - src/test/{parse-fail => ui}/issue-2354.rs | 4 +- src/test/ui/issue-2354.stderr | 16 + src/test/ui/issue-23966.stderr | 9 - src/test/ui/issue-25826.stderr | 9 - src/test/ui/issue-26217.nll.stderr | 15 - ...e-27282-move-match-input-into-guard.stderr | 25 - src/test/ui/issue-3154.nll.stderr | 23 - src/test/ui/issue-3214.stderr | 21 - src/test/ui/issue-32829.stderr | 11 - src/test/ui/issue-37323.stderr | 20 - src/test/ui/issue-38715.rs | 16 - src/test/ui/issue-38715.stderr | 22 - src/test/ui/issue-40288-2.nll.stderr | 57 - src/test/ui/issue-40288-2.stderr | 21 - .../issue-40402-2.nll.stderr | 14 - src/test/ui/issue-40510-1.nll.stderr | 17 - src/test/ui/issue-40510-3.nll.stderr | 20 - src/test/ui/issue-41726.nll.stderr | 9 - src/test/ui/issue-41726.stderr | 9 - src/test/ui/issue-42755.stderr | 13 - src/test/ui/issue-4335.nll.stderr | 25 - .../ui/issue-43784-associated-type.stderr | 16 - src/test/ui/issue-43784-supertrait.stderr | 16 - src/test/ui/issue-45199.ast.nll.stderr | 36 - src/test/ui/issue-45199.mir.stderr | 36 - src/test/ui/issue-46471-1.stderr | 28 - src/test/ui/issue-49074.stderr | 19 - src/test/ui/issue-51602.rs | 15 + src/test/ui/issue-51602.stderr | 10 + ...issue-52023-array-size-pointer-cast.stderr | 9 - src/test/ui/issue-52213.nll.stderr | 14 - src/test/ui/issue-5239-1.stderr | 13 - src/test/ui/issue-52533-1.nll.stderr | 17 - src/test/ui/issue-52533.nll.stderr | 17 - src/test/ui/issue-52992.rs | 37 + src/test/ui/issue-53251.rs | 30 + src/test/ui/issue-53251.stderr | 12 + src/test/ui/issue-53300.rs | 22 + src/test/ui/issue-53300.stderr | 9 + src/test/ui/issue-53419.rs | 19 + src/test/ui/issue-53565.rs | 14 + src/test/ui/issue-53565.stderr | 20 + src/test/ui/issue-53568.rs | 61 + src/test/ui/issue-53692.rs | 24 + src/test/ui/issue-53692.stderr | 27 + src/test/ui/issues/auxiliary/empty-struct.rs | 19 + .../issues}/auxiliary/issue-19163.rs | 0 .../issues}/auxiliary/issue-21146-inc.rs | 0 .../issues}/auxiliary/issue-29181.rs | 0 .../issues}/auxiliary/issue-30535.rs | 0 .../ui/{ => issues}/auxiliary/issue-36708.rs | 0 .../issues}/auxiliary/issue-36881-aux.rs | 0 src/test/ui/issues/auxiliary/issue-52489.rs | 13 + .../issues}/auxiliary/issue_11680.rs | 0 .../issues}/auxiliary/issue_16725.rs | 0 .../auxiliary/issue_17718_const_privacy.rs | 0 .../issues}/auxiliary/issue_1920.rs | 0 .../issues}/auxiliary/issue_21202.rs | 0 .../issues}/auxiliary/issue_30123_aux.rs | 0 .../issues}/auxiliary/issue_41549.rs | 0 .../issues}/auxiliary/issue_5844_aux.rs | 0 .../ui/issues/auxiliary/lint_stability.rs | 198 + .../issues}/auxiliary/private_trait_xc.rs | 0 .../auxiliary/xcrate_issue_43189_a.rs | 0 .../auxiliary/xcrate_issue_43189_b.rs | 0 .../xcrate_issue_46112_rexport_core.rs | 0 src/test/ui/{ => issues}/issue-10176.rs | 0 src/test/ui/{ => issues}/issue-10176.stderr | 0 src/test/ui/{ => issues}/issue-10200.rs | 0 src/test/ui/{ => issues}/issue-10200.stderr | 0 src/test/ui/issues/issue-10291.nll.stderr | 10 + src/test/ui/{ => issues}/issue-10291.rs | 0 src/test/ui/{ => issues}/issue-10291.stderr | 0 .../ui/{ => issues}/issue-10398.nll.stderr | 0 src/test/ui/{ => issues}/issue-10398.rs | 0 src/test/ui/{ => issues}/issue-10398.stderr | 0 src/test/ui/{ => issues}/issue-10401.rs | 0 src/test/ui/{ => issues}/issue-10401.stderr | 0 src/test/ui/{ => issues}/issue-10412.rs | 0 src/test/ui/{ => issues}/issue-10412.stderr | 0 src/test/ui/{ => issues}/issue-10465.rs | 0 src/test/ui/{ => issues}/issue-10465.stderr | 0 src/test/ui/{ => issues}/issue-10536.rs | 0 src/test/ui/{ => issues}/issue-10536.stderr | 0 src/test/ui/{ => issues}/issue-10545.rs | 0 src/test/ui/{ => issues}/issue-10545.stderr | 0 src/test/ui/{ => issues}/issue-10656.rs | 0 src/test/ui/{ => issues}/issue-10656.stderr | 0 src/test/ui/{ => issues}/issue-10764.rs | 0 src/test/ui/{ => issues}/issue-10764.stderr | 0 src/test/ui/{ => issues}/issue-10877.rs | 0 src/test/ui/{ => issues}/issue-10877.stderr | 0 src/test/ui/{ => issues}/issue-10969.rs | 0 src/test/ui/{ => issues}/issue-10969.stderr | 0 src/test/ui/{ => issues}/issue-10991.rs | 0 src/test/ui/{ => issues}/issue-10991.stderr | 0 src/test/ui/{ => issues}/issue-11004.rs | 0 src/test/ui/{ => issues}/issue-11004.stderr | 0 src/test/ui/{ => issues}/issue-11154.rs | 0 src/test/ui/{ => issues}/issue-11154.stderr | 0 .../ui/{ => issues}/issue-11192.nll.stderr | 2 +- src/test/ui/{ => issues}/issue-11192.rs | 0 src/test/ui/{ => issues}/issue-11192.stderr | 0 src/test/ui/{ => issues}/issue-11319.rs | 0 src/test/ui/{ => issues}/issue-11319.stderr | 0 src/test/ui/{ => issues}/issue-11374.rs | 0 src/test/ui/{ => issues}/issue-11374.stderr | 0 .../ui/{ => issues}/issue-11493.ast.stderr | 0 .../ui/{ => issues}/issue-11493.mir.stderr | 0 src/test/ui/{ => issues}/issue-11493.rs | 0 src/test/ui/{ => issues}/issue-11515.rs | 0 src/test/ui/{ => issues}/issue-11515.stderr | 0 .../issues}/issue-11593.rs | 0 src/test/ui/issues/issue-11593.stderr | 9 + .../issues}/issue-11680.rs | 0 src/test/ui/issues/issue-11680.stderr | 15 + src/test/ui/{ => issues}/issue-11681.rs | 0 src/test/ui/{ => issues}/issue-11681.stderr | 0 src/test/ui/{ => issues}/issue-11692-1.rs | 2 +- src/test/ui/issues/issue-11692-1.stderr | 12 + src/test/ui/{ => issues}/issue-11692-2.rs | 3 +- src/test/ui/issues/issue-11692-2.stderr | 8 + src/test/ui/{ => issues}/issue-11740.rs | 0 src/test/ui/{ => issues}/issue-11740.stderr | 0 src/test/ui/{ => issues}/issue-11771.rs | 0 src/test/ui/{ => issues}/issue-11771.stderr | 0 src/test/ui/{ => issues}/issue-11844.rs | 0 src/test/ui/{ => issues}/issue-11844.stderr | 0 .../ui/{ => issues}/issue-11873.nll.stderr | 4 +- src/test/ui/{ => issues}/issue-11873.rs | 0 src/test/ui/{ => issues}/issue-11873.stderr | 0 src/test/ui/{ => issues}/issue-12028.rs | 0 src/test/ui/{ => issues}/issue-12028.stderr | 0 .../ui/{ => issues}/issue-12041.nll.stderr | 0 src/test/ui/{ => issues}/issue-12041.rs | 0 src/test/ui/{ => issues}/issue-12041.stderr | 0 src/test/ui/{ => issues}/issue-12116.rs | 0 src/test/ui/{ => issues}/issue-12116.stderr | 0 src/test/ui/{ => issues}/issue-12127.rs | 0 src/test/ui/{ => issues}/issue-12127.stderr | 0 src/test/ui/{ => issues}/issue-12187-1.rs | 0 src/test/ui/{ => issues}/issue-12187-1.stderr | 0 src/test/ui/{ => issues}/issue-12187-2.rs | 0 src/test/ui/{ => issues}/issue-12187-2.stderr | 0 src/test/ui/{ => issues}/issue-12369.rs | 0 src/test/ui/{ => issues}/issue-12369.stderr | 0 .../ui/{ => issues}/issue-12470.nll.stderr | 0 src/test/ui/{ => issues}/issue-12470.rs | 0 src/test/ui/{ => issues}/issue-12470.stderr | 0 src/test/ui/{ => issues}/issue-12511.rs | 0 src/test/ui/{ => issues}/issue-12511.stderr | 0 src/test/ui/{ => issues}/issue-12552.rs | 0 src/test/ui/{ => issues}/issue-12552.stderr | 0 src/test/ui/issues/issue-12567.nll.stderr | 45 + src/test/ui/{ => issues}/issue-12567.rs | 0 src/test/ui/{ => issues}/issue-12567.stderr | 0 src/test/ui/{ => issues}/issue-12796.rs | 0 src/test/ui/issues/issue-12796.stderr | 12 + src/test/ui/{ => issues}/issue-12863.rs | 0 src/test/ui/{ => issues}/issue-12863.stderr | 0 src/test/ui/{ => issues}/issue-12997-1.rs | 0 src/test/ui/{ => issues}/issue-12997-1.stderr | 0 src/test/ui/{ => issues}/issue-12997-2.rs | 0 src/test/ui/{ => issues}/issue-12997-2.stderr | 2 +- src/test/ui/{ => issues}/issue-13033.rs | 0 src/test/ui/{ => issues}/issue-13033.stderr | 0 src/test/ui/issues/issue-13058.nll.stderr | 15 + src/test/ui/{ => issues}/issue-13058.rs | 0 src/test/ui/{ => issues}/issue-13058.stderr | 2 +- src/test/ui/{ => issues}/issue-13352.rs | 0 src/test/ui/{ => issues}/issue-13352.stderr | 0 src/test/ui/{ => issues}/issue-13359.rs | 0 src/test/ui/{ => issues}/issue-13359.stderr | 0 src/test/ui/{ => issues}/issue-13404.rs | 0 src/test/ui/{ => issues}/issue-13404.stderr | 0 src/test/ui/{ => issues}/issue-13407.rs | 0 src/test/ui/{ => issues}/issue-13407.stderr | 0 src/test/ui/{ => issues}/issue-13446.rs | 0 src/test/ui/{ => issues}/issue-13446.stderr | 0 src/test/ui/{ => issues}/issue-13466.rs | 0 src/test/ui/{ => issues}/issue-13466.stderr | 0 src/test/ui/{ => issues}/issue-13482-2.rs | 0 src/test/ui/{ => issues}/issue-13482-2.stderr | 0 src/test/ui/{ => issues}/issue-13482.rs | 0 src/test/ui/{ => issues}/issue-13482.stderr | 0 src/test/ui/{ => issues}/issue-13483.rs | 0 src/test/ui/{ => issues}/issue-13483.stderr | 0 .../ui/{ => issues}/issue-13497-2.nll.stderr | 0 src/test/ui/{ => issues}/issue-13497-2.rs | 0 src/test/ui/{ => issues}/issue-13497-2.stderr | 0 src/test/ui/{ => issues}/issue-13497.rs | 0 src/test/ui/{ => issues}/issue-13497.stderr | 0 src/test/ui/{ => issues}/issue-1362.rs | 0 src/test/ui/{ => issues}/issue-1362.stderr | 0 src/test/ui/{ => issues}/issue-13641.rs | 0 src/test/ui/{ => issues}/issue-13641.stderr | 0 src/test/ui/{ => issues}/issue-13727.rs | 0 src/test/ui/{ => issues}/issue-13727.stderr | 0 src/test/ui/{ => issues}/issue-13847.rs | 0 src/test/ui/{ => issues}/issue-13847.stderr | 0 src/test/ui/{ => issues}/issue-13853-2.rs | 0 src/test/ui/{ => issues}/issue-13853-2.stderr | 0 src/test/ui/{ => issues}/issue-13853-5.rs | 0 src/test/ui/{ => issues}/issue-13853-5.stderr | 0 src/test/ui/{ => issues}/issue-13853.rs | 0 src/test/ui/{ => issues}/issue-13853.stderr | 0 src/test/ui/{ => issues}/issue-14091-2.rs | 0 src/test/ui/{ => issues}/issue-14091-2.stderr | 0 src/test/ui/{ => issues}/issue-14091.rs | 0 src/test/ui/{ => issues}/issue-14091.stderr | 0 src/test/ui/{ => issues}/issue-14092.rs | 2 +- src/test/ui/issues/issue-14092.stderr | 9 + src/test/ui/{ => issues}/issue-14221.rs | 0 src/test/ui/{ => issues}/issue-14221.stderr | 0 src/test/ui/{ => issues}/issue-14227.rs | 0 src/test/ui/{ => issues}/issue-14227.stderr | 0 src/test/ui/{ => issues}/issue-14285.rs | 0 src/test/ui/{ => issues}/issue-14285.stderr | 2 +- src/test/ui/{ => issues}/issue-14309.rs | 0 src/test/ui/{ => issues}/issue-14309.stderr | 0 src/test/ui/{ => issues}/issue-14366.rs | 0 src/test/ui/{ => issues}/issue-14366.stderr | 2 +- src/test/ui/{ => issues}/issue-1448-2.rs | 0 src/test/ui/{ => issues}/issue-1448-2.stderr | 0 src/test/ui/{ => issues}/issue-14541.rs | 0 src/test/ui/{ => issues}/issue-14541.stderr | 0 src/test/ui/{ => issues}/issue-14721.rs | 0 src/test/ui/{ => issues}/issue-14721.stderr | 0 src/test/ui/{ => issues}/issue-1476.rs | 0 src/test/ui/{ => issues}/issue-1476.stderr | 0 src/test/ui/{ => issues}/issue-14772.rs | 0 src/test/ui/{ => issues}/issue-14772.stderr | 0 src/test/ui/{ => issues}/issue-14845.rs | 0 src/test/ui/{ => issues}/issue-14845.stderr | 0 src/test/ui/{ => issues}/issue-14853.rs | 0 src/test/ui/{ => issues}/issue-14853.stderr | 0 src/test/ui/{ => issues}/issue-14915.rs | 0 src/test/ui/{ => issues}/issue-14915.stderr | 0 src/test/ui/issues/issue-15034.nll.stderr | 11 + src/test/ui/{ => issues}/issue-15034.rs | 0 src/test/ui/{ => issues}/issue-15034.stderr | 2 +- src/test/ui/{ => issues}/issue-15094.rs | 0 src/test/ui/{ => issues}/issue-15094.stderr | 0 src/test/ui/{ => issues}/issue-15129.rs | 0 src/test/ui/{ => issues}/issue-15129.stderr | 0 src/test/ui/{ => issues}/issue-15167.rs | 0 src/test/ui/{ => issues}/issue-15167.stderr | 0 src/test/ui/{ => issues}/issue-15207.rs | 0 src/test/ui/{ => issues}/issue-15207.stderr | 0 src/test/ui/{ => issues}/issue-15260.rs | 0 src/test/ui/{ => issues}/issue-15260.stderr | 0 src/test/ui/{ => issues}/issue-15381.rs | 0 src/test/ui/{ => issues}/issue-15381.stderr | 0 src/test/ui/{ => issues}/issue-15524.rs | 0 src/test/ui/{ => issues}/issue-15524.stderr | 0 src/test/ui/{ => issues}/issue-15756.rs | 0 src/test/ui/{ => issues}/issue-15756.stderr | 3 +- src/test/ui/{ => issues}/issue-15783.rs | 0 src/test/ui/{ => issues}/issue-15783.stderr | 0 src/test/ui/{ => issues}/issue-15896.rs | 0 src/test/ui/{ => issues}/issue-15896.stderr | 0 .../issues}/issue-15919.rs | 1 + src/test/ui/issues/issue-15919.stderr | 4 + src/test/ui/{ => issues}/issue-15965.rs | 0 src/test/ui/{ => issues}/issue-15965.stderr | 0 src/test/ui/{ => issues}/issue-16048.rs | 0 src/test/ui/{ => issues}/issue-16048.stderr | 0 src/test/ui/{ => issues}/issue-16098.rs | 0 src/test/ui/{ => issues}/issue-16098.stderr | 0 src/test/ui/{ => issues}/issue-16149.rs | 0 src/test/ui/{ => issues}/issue-16149.stderr | 0 src/test/ui/{ => issues}/issue-16250.rs | 0 src/test/ui/{ => issues}/issue-16250.stderr | 0 src/test/ui/{ => issues}/issue-16338.rs | 0 src/test/ui/{ => issues}/issue-16338.stderr | 0 src/test/ui/{ => issues}/issue-16401.rs | 0 src/test/ui/{ => issues}/issue-16401.stderr | 0 src/test/ui/{ => issues}/issue-16538.rs | 0 src/test/ui/{ => issues}/issue-16538.stderr | 0 src/test/ui/{ => issues}/issue-16562.rs | 0 src/test/ui/{ => issues}/issue-16562.stderr | 0 src/test/ui/issues/issue-16683.nll.stderr | 10 + src/test/ui/{ => issues}/issue-16683.rs | 0 src/test/ui/{ => issues}/issue-16683.stderr | 0 .../issues}/issue-16725.rs | 0 src/test/ui/issues/issue-16725.stderr | 9 + src/test/ui/issues/issue-16922.nll.stderr | 11 + src/test/ui/{ => issues}/issue-16922.rs | 0 src/test/ui/{ => issues}/issue-16922.stderr | 2 +- src/test/ui/{ => issues}/issue-16939.rs | 0 src/test/ui/{ => issues}/issue-16939.stderr | 0 src/test/ui/{ => issues}/issue-16966.rs | 0 src/test/ui/{ => issues}/issue-16966.stderr | 0 src/test/ui/{ => issues}/issue-1697.rs | 0 src/test/ui/{ => issues}/issue-1697.stderr | 0 src/test/ui/{ => issues}/issue-16994.rs | 0 src/test/ui/{ => issues}/issue-16994.stderr | 0 src/test/ui/{ => issues}/issue-17001.rs | 0 src/test/ui/{ => issues}/issue-17001.stderr | 0 src/test/ui/{ => issues}/issue-17025.rs | 0 src/test/ui/{ => issues}/issue-17033.rs | 0 src/test/ui/{ => issues}/issue-17033.stderr | 0 src/test/ui/{ => issues}/issue-17252.rs | 0 src/test/ui/{ => issues}/issue-17252.stderr | 0 .../ui/{ => issues}/issue-17263.nll.stderr | 0 src/test/ui/{ => issues}/issue-17263.rs | 0 src/test/ui/{ => issues}/issue-17263.stderr | 0 src/test/ui/{ => issues}/issue-17337.rs | 4 +- src/test/ui/{ => issues}/issue-17337.stderr | 0 src/test/ui/{ => issues}/issue-17373.rs | 0 src/test/ui/{ => issues}/issue-17373.stderr | 0 .../ui/{ => issues}/issue-17385.nll.stderr | 0 src/test/ui/{ => issues}/issue-17385.rs | 0 src/test/ui/{ => issues}/issue-17385.stderr | 0 src/test/ui/{ => issues}/issue-17405.rs | 0 src/test/ui/{ => issues}/issue-17405.stderr | 0 src/test/ui/{ => issues}/issue-17431-1.rs | 0 src/test/ui/{ => issues}/issue-17431-1.stderr | 0 src/test/ui/{ => issues}/issue-17431-2.rs | 0 src/test/ui/{ => issues}/issue-17431-2.stderr | 0 src/test/ui/{ => issues}/issue-17431-3.rs | 0 src/test/ui/{ => issues}/issue-17431-3.stderr | 0 src/test/ui/{ => issues}/issue-17431-4.rs | 0 src/test/ui/{ => issues}/issue-17431-4.stderr | 0 src/test/ui/{ => issues}/issue-17431-5.rs | 0 src/test/ui/{ => issues}/issue-17431-5.stderr | 0 src/test/ui/{ => issues}/issue-17431-6.rs | 0 src/test/ui/{ => issues}/issue-17431-6.stderr | 0 src/test/ui/{ => issues}/issue-17431-7.rs | 0 src/test/ui/{ => issues}/issue-17431-7.stderr | 0 src/test/ui/{ => issues}/issue-17441.rs | 0 src/test/ui/{ => issues}/issue-17441.stderr | 0 src/test/ui/{ => issues}/issue-17444.rs | 0 src/test/ui/{ => issues}/issue-17444.stderr | 0 src/test/ui/{ => issues}/issue-17458.rs | 2 +- src/test/ui/issues/issue-17458.stderr | 11 + .../ui/{ => issues}/issue-17545.nll.stderr | 0 src/test/ui/{ => issues}/issue-17545.rs | 0 src/test/ui/{ => issues}/issue-17545.stderr | 0 src/test/ui/{ => issues}/issue-17546.rs | 0 src/test/ui/{ => issues}/issue-17546.stderr | 0 src/test/ui/{ => issues}/issue-17551.rs | 0 src/test/ui/{ => issues}/issue-17551.stderr | 0 src/test/ui/{ => issues}/issue-17651.rs | 0 src/test/ui/{ => issues}/issue-17651.stderr | 2 +- .../issue-17718-const-bad-values.rs | 1 - .../issue-17718-const-bad-values.stderr | 22 + .../{ => issues}/issue-17718-const-borrow.rs | 0 .../issue-17718-const-borrow.stderr | 0 .../{ => issues}/issue-17718-const-naming.rs | 0 .../issue-17718-const-naming.stderr | 0 .../issues}/issue-17718-const-privacy.rs | 0 .../issues/issue-17718-const-privacy.stderr | 15 + .../issue-17718-constants-not-static.rs | 0 .../issue-17718-constants-not-static.stderr | 0 .../ui/{ => issues}/issue-17718-patterns.rs | 0 .../{ => issues}/issue-17718-patterns.stderr | 0 .../ui/{ => issues}/issue-17718-references.rs | 0 .../issue-17718-references.stderr | 0 .../issues/issue-17718-static-move.nll.stderr | 12 + .../{ => issues}/issue-17718-static-move.rs | 0 .../issue-17718-static-move.stderr | 0 .../{ => issues}/issue-17718-static-sync.rs | 0 .../issue-17718-static-sync.stderr | 0 .../ui/{ => issues}/issue-17728.nll.stderr | 6 - src/test/ui/{ => issues}/issue-17728.rs | 0 src/test/ui/{ => issues}/issue-17728.stderr | 0 src/test/ui/{ => issues}/issue-17740.rs | 0 src/test/ui/{ => issues}/issue-17740.stderr | 0 src/test/ui/issues/issue-17758.nll.stderr | 10 + src/test/ui/{ => issues}/issue-17758.rs | 0 src/test/ui/{ => issues}/issue-17758.stderr | 0 src/test/ui/{ => issues}/issue-17800.rs | 0 src/test/ui/{ => issues}/issue-17800.stderr | 0 src/test/ui/{ => issues}/issue-17904-2.rs | 0 src/test/ui/{ => issues}/issue-17904-2.stderr | 0 src/test/ui/{ => issues}/issue-17905.rs | 0 src/test/ui/{ => issues}/issue-17905.stderr | 0 .../issues}/issue-17913.rs | 2 +- src/test/ui/issues/issue-17913.stderr | 4 + src/test/ui/{ => issues}/issue-17933.rs | 0 src/test/ui/{ => issues}/issue-17933.stderr | 0 src/test/ui/issues/issue-17954.nll.stderr | 12 + src/test/ui/issues/issue-17954.rs | 26 + src/test/ui/issues/issue-17954.stderr | 14 + src/test/ui/{ => issues}/issue-17959.rs | 0 src/test/ui/{ => issues}/issue-17959.stderr | 0 src/test/ui/{ => issues}/issue-17994.rs | 0 src/test/ui/{ => issues}/issue-17994.stderr | 0 src/test/ui/{ => issues}/issue-17999.rs | 0 src/test/ui/{ => issues}/issue-17999.stderr | 0 src/test/ui/{ => issues}/issue-18058.rs | 0 src/test/ui/{ => issues}/issue-18058.stderr | 0 src/test/ui/{ => issues}/issue-18107.rs | 0 src/test/ui/{ => issues}/issue-18107.stderr | 2 +- src/test/ui/{ => issues}/issue-18118-2.rs | 0 src/test/ui/{ => issues}/issue-18118-2.stderr | 0 .../ui/{ => issues}/issue-18118.nll.stderr | 0 src/test/ui/{ => issues}/issue-18118.rs | 0 src/test/ui/{ => issues}/issue-18118.stderr | 0 src/test/ui/{ => issues}/issue-18119.rs | 0 src/test/ui/{ => issues}/issue-18119.stderr | 0 src/test/ui/{ => issues}/issue-18159.rs | 0 src/test/ui/{ => issues}/issue-18159.stderr | 0 src/test/ui/{ => issues}/issue-18183.rs | 0 src/test/ui/{ => issues}/issue-18183.stderr | 0 src/test/ui/{ => issues}/issue-18294.rs | 2 +- src/test/ui/issues/issue-18294.stderr | 11 + src/test/ui/{ => issues}/issue-18389.rs | 0 src/test/ui/{ => issues}/issue-18389.stderr | 0 src/test/ui/{ => issues}/issue-18400.rs | 0 src/test/ui/{ => issues}/issue-18400.stderr | 0 src/test/ui/{ => issues}/issue-18423.rs | 4 +- src/test/ui/issues/issue-18423.stderr | 9 + src/test/ui/{ => issues}/issue-18446.rs | 0 src/test/ui/{ => issues}/issue-18446.stderr | 0 src/test/ui/{ => issues}/issue-18532.rs | 0 src/test/ui/{ => issues}/issue-18532.stderr | 0 .../ui/{ => issues}/issue-18566.nll.stderr | 0 src/test/ui/{ => issues}/issue-18566.rs | 0 src/test/ui/{ => issues}/issue-18566.stderr | 0 src/test/ui/{ => issues}/issue-18611.rs | 0 src/test/ui/{ => issues}/issue-18611.stderr | 0 src/test/ui/{ => issues}/issue-1871.rs | 0 src/test/ui/{ => issues}/issue-1871.stderr | 0 .../ui/{ => issues}/issue-18783.nll.stderr | 8 +- src/test/ui/{ => issues}/issue-18783.rs | 0 src/test/ui/{ => issues}/issue-18783.stderr | 0 src/test/ui/{ => issues}/issue-18819.rs | 0 src/test/ui/{ => issues}/issue-18819.stderr | 0 src/test/ui/{ => issues}/issue-18919.rs | 0 src/test/ui/{ => issues}/issue-18919.stderr | 2 +- src/test/ui/{ => issues}/issue-18937.rs | 0 src/test/ui/{ => issues}/issue-18937.stderr | 0 src/test/ui/{ => issues}/issue-18959.rs | 0 src/test/ui/{ => issues}/issue-18959.stderr | 0 src/test/ui/{ => issues}/issue-1900.rs | 0 src/test/ui/{ => issues}/issue-1900.stderr | 0 src/test/ui/{ => issues}/issue-19086.rs | 0 src/test/ui/{ => issues}/issue-19086.stderr | 0 src/test/ui/{ => issues}/issue-19100.fixed | 0 src/test/ui/{ => issues}/issue-19100.rs | 0 src/test/ui/{ => issues}/issue-19100.stderr | 0 src/test/ui/issues/issue-19163.nll.stderr | 9 + .../issues}/issue-19163.rs | 0 src/test/ui/issues/issue-19163.stderr | 9 + .../issues}/issue-1920-1.rs | 0 src/test/ui/issues/issue-1920-1.stderr | 15 + .../issues}/issue-1920-2.rs | 0 src/test/ui/issues/issue-1920-2.stderr | 15 + .../issues}/issue-1920-3.rs | 0 src/test/ui/issues/issue-1920-3.stderr | 15 + src/test/ui/{ => issues}/issue-19244-1.rs | 0 src/test/ui/{ => issues}/issue-19244-1.stderr | 0 src/test/ui/{ => issues}/issue-19244-2.rs | 0 src/test/ui/{ => issues}/issue-19244-2.stderr | 0 src/test/ui/{ => issues}/issue-19380.rs | 0 src/test/ui/{ => issues}/issue-19380.stderr | 0 src/test/ui/{ => issues}/issue-19482.rs | 0 src/test/ui/{ => issues}/issue-19482.stderr | 0 src/test/ui/{ => issues}/issue-19498.rs | 0 src/test/ui/{ => issues}/issue-19498.stderr | 0 src/test/ui/{ => issues}/issue-19521.rs | 0 src/test/ui/{ => issues}/issue-19521.stderr | 0 src/test/ui/{ => issues}/issue-19538.rs | 0 src/test/ui/{ => issues}/issue-19538.stderr | 0 src/test/ui/{ => issues}/issue-19601.rs | 0 src/test/ui/{ => issues}/issue-19601.stderr | 0 src/test/ui/{ => issues}/issue-1962.rs | 0 src/test/ui/{ => issues}/issue-1962.stderr | 0 src/test/ui/{ => issues}/issue-19660.rs | 0 src/test/ui/{ => issues}/issue-19660.stderr | 0 src/test/ui/{ => issues}/issue-19692.rs | 0 src/test/ui/{ => issues}/issue-19692.stderr | 0 src/test/ui/{ => issues}/issue-19707.rs | 0 src/test/ui/{ => issues}/issue-19707.stderr | 0 src/test/ui/{ => issues}/issue-19734.rs | 0 src/test/ui/{ => issues}/issue-19734.stderr | 0 src/test/ui/{ => issues}/issue-19883.rs | 0 src/test/ui/{ => issues}/issue-19883.stderr | 0 src/test/ui/{ => issues}/issue-19922.rs | 0 src/test/ui/{ => issues}/issue-19922.stderr | 0 src/test/ui/{ => issues}/issue-19982.rs | 0 src/test/ui/{ => issues}/issue-19982.stderr | 0 src/test/ui/{ => issues}/issue-19991.rs | 0 src/test/ui/{ => issues}/issue-19991.stderr | 0 src/test/ui/{ => issues}/issue-20005.rs | 0 src/test/ui/{ => issues}/issue-20005.stderr | 2 +- src/test/ui/{ => issues}/issue-20162.rs | 0 src/test/ui/{ => issues}/issue-20162.stderr | 0 src/test/ui/{ => issues}/issue-20225.rs | 0 src/test/ui/{ => issues}/issue-20225.stderr | 0 src/test/ui/{ => issues}/issue-20261.rs | 0 src/test/ui/{ => issues}/issue-20261.stderr | 0 src/test/ui/{ => issues}/issue-20313.rs | 0 src/test/ui/{ => issues}/issue-20313.stderr | 0 src/test/ui/{ => issues}/issue-20413.rs | 0 src/test/ui/{ => issues}/issue-20413.stderr | 0 src/test/ui/{ => issues}/issue-20433.rs | 0 src/test/ui/{ => issues}/issue-20433.stderr | 2 +- src/test/ui/{ => issues}/issue-20605.rs | 0 src/test/ui/{ => issues}/issue-20605.stderr | 2 +- src/test/ui/{ => issues}/issue-20616-1.rs | 0 src/test/ui/{ => issues}/issue-20616-1.stderr | 0 src/test/ui/{ => issues}/issue-20616-2.rs | 0 src/test/ui/{ => issues}/issue-20616-2.stderr | 0 src/test/ui/{ => issues}/issue-20616-3.rs | 0 src/test/ui/{ => issues}/issue-20616-3.stderr | 0 src/test/ui/{ => issues}/issue-20616-4.rs | 0 src/test/ui/{ => issues}/issue-20616-4.stderr | 0 src/test/ui/{ => issues}/issue-20616-5.rs | 0 src/test/ui/{ => issues}/issue-20616-5.stderr | 0 src/test/ui/{ => issues}/issue-20616-6.rs | 0 src/test/ui/{ => issues}/issue-20616-6.stderr | 0 src/test/ui/{ => issues}/issue-20616-7.rs | 0 src/test/ui/{ => issues}/issue-20616-7.stderr | 0 src/test/ui/{ => issues}/issue-20616-8.rs | 0 src/test/ui/{ => issues}/issue-20616-8.stderr | 0 src/test/ui/{ => issues}/issue-20616-9.rs | 0 src/test/ui/{ => issues}/issue-20616-9.stderr | 0 src/test/ui/{ => issues}/issue-20692.rs | 0 src/test/ui/{ => issues}/issue-20692.stderr | 0 src/test/ui/{ => issues}/issue-20714.rs | 0 src/test/ui/{ => issues}/issue-20714.stderr | 0 src/test/ui/{ => issues}/issue-20772.rs | 0 src/test/ui/{ => issues}/issue-20772.stderr | 0 .../ui/{ => issues}/issue-20801.nll.stderr | 8 +- src/test/ui/{ => issues}/issue-20801.rs | 0 src/test/ui/{ => issues}/issue-20801.stderr | 0 src/test/ui/{ => issues}/issue-20825.rs | 0 src/test/ui/{ => issues}/issue-20825.stderr | 0 .../ui/{ => issues}/issue-20831-debruijn.rs | 0 .../{ => issues}/issue-20831-debruijn.stderr | 0 src/test/ui/{ => issues}/issue-20939.rs | 0 src/test/ui/{ => issues}/issue-20939.stderr | 0 src/test/ui/{ => issues}/issue-2111.rs | 0 src/test/ui/{ => issues}/issue-2111.stderr | 0 .../issues}/issue-21146.rs | 0 src/test/ui/issues/issue-21146.stderr | 8 + src/test/ui/{ => issues}/issue-21160.rs | 0 src/test/ui/{ => issues}/issue-21160.stderr | 0 src/test/ui/{ => issues}/issue-21174.rs | 0 src/test/ui/{ => issues}/issue-21174.stderr | 0 src/test/ui/{ => issues}/issue-21177.rs | 0 src/test/ui/{ => issues}/issue-21177.stderr | 0 .../issues}/issue-21202.rs | 0 src/test/ui/issues/issue-21202.stderr | 9 + src/test/ui/{ => issues}/issue-21332.rs | 0 src/test/ui/{ => issues}/issue-21332.stderr | 0 src/test/ui/{ => issues}/issue-21356.rs | 0 src/test/ui/{ => issues}/issue-21356.stderr | 0 src/test/ui/{ => issues}/issue-21449.rs | 0 src/test/ui/{ => issues}/issue-21449.stderr | 0 src/test/ui/{ => issues}/issue-2149.rs | 0 src/test/ui/{ => issues}/issue-2149.stderr | 0 src/test/ui/{ => issues}/issue-2150.rs | 0 src/test/ui/{ => issues}/issue-2150.stderr | 0 src/test/ui/{ => issues}/issue-2151.rs | 0 src/test/ui/{ => issues}/issue-2151.stderr | 0 src/test/ui/{ => issues}/issue-21546.rs | 0 src/test/ui/{ => issues}/issue-21546.stderr | 0 src/test/ui/{ => issues}/issue-21554.rs | 0 src/test/ui/{ => issues}/issue-21554.stderr | 0 .../ui/{ => issues}/issue-21600.nll.stderr | 0 src/test/ui/{ => issues}/issue-21600.rs | 0 src/test/ui/{ => issues}/issue-21600.stderr | 0 src/test/ui/{ => issues}/issue-21701.rs | 0 src/test/ui/{ => issues}/issue-21701.stderr | 0 src/test/ui/{ => issues}/issue-21763.rs | 0 src/test/ui/{ => issues}/issue-21763.stderr | 0 src/test/ui/{ => issues}/issue-21837.rs | 0 src/test/ui/{ => issues}/issue-21837.stderr | 0 src/test/ui/{ => issues}/issue-21946.rs | 0 src/test/ui/{ => issues}/issue-21946.stderr | 0 src/test/ui/{ => issues}/issue-21950.rs | 0 src/test/ui/{ => issues}/issue-21950.stderr | 0 src/test/ui/{ => issues}/issue-21974.rs | 0 src/test/ui/{ => issues}/issue-21974.stderr | 0 src/test/ui/{ => issues}/issue-22034.rs | 2 +- src/test/ui/issues/issue-22034.stderr | 13 + src/test/ui/{ => issues}/issue-22037.rs | 0 src/test/ui/{ => issues}/issue-22037.stderr | 0 src/test/ui/{ => issues}/issue-22289.rs | 0 src/test/ui/{ => issues}/issue-22289.stderr | 0 src/test/ui/{ => issues}/issue-22312.rs | 0 src/test/ui/{ => issues}/issue-22312.stderr | 0 src/test/ui/{ => issues}/issue-22370.rs | 0 src/test/ui/{ => issues}/issue-22370.stderr | 0 src/test/ui/{ => issues}/issue-22384.rs | 0 src/test/ui/{ => issues}/issue-22384.stderr | 0 src/test/ui/{ => issues}/issue-22434.rs | 0 src/test/ui/{ => issues}/issue-22434.stderr | 0 src/test/ui/{ => issues}/issue-22468.rs | 0 src/test/ui/{ => issues}/issue-22468.stderr | 0 src/test/ui/{ => issues}/issue-22560.rs | 0 src/test/ui/{ => issues}/issue-22560.stderr | 0 src/test/ui/{ => issues}/issue-22599.rs | 0 src/test/ui/{ => issues}/issue-22599.stderr | 0 src/test/ui/{ => issues}/issue-22603.rs | 0 src/test/ui/{ => issues}/issue-22603.stderr | 0 .../issues}/issue-22638.rs | 2 + src/test/ui/issues/issue-22638.stderr | 14 + src/test/ui/{ => issues}/issue-22644.rs | 0 src/test/ui/{ => issues}/issue-22644.stderr | 0 src/test/ui/{ => issues}/issue-22673.rs | 0 src/test/ui/{ => issues}/issue-22673.stderr | 0 src/test/ui/{ => issues}/issue-22684.rs | 0 src/test/ui/{ => issues}/issue-22684.stderr | 0 src/test/ui/{ => issues}/issue-22706.rs | 0 src/test/ui/{ => issues}/issue-22706.stderr | 0 src/test/ui/{ => issues}/issue-22789.rs | 0 src/test/ui/{ => issues}/issue-22789.stderr | 0 src/test/ui/{ => issues}/issue-2281-part1.rs | 0 .../ui/{ => issues}/issue-2281-part1.stderr | 0 src/test/ui/{ => issues}/issue-22874.rs | 0 src/test/ui/{ => issues}/issue-22874.stderr | 2 +- src/test/ui/{ => issues}/issue-22886.rs | 0 src/test/ui/{ => issues}/issue-22886.stderr | 0 src/test/ui/{ => issues}/issue-22933-1.rs | 0 src/test/ui/{ => issues}/issue-22933-1.stderr | 0 src/test/ui/{ => issues}/issue-22933-2.rs | 0 src/test/ui/{ => issues}/issue-22933-2.stderr | 0 src/test/ui/{ => issues}/issue-22933-3.rs | 0 src/test/ui/{ => issues}/issue-22933-3.stderr | 0 src/test/ui/{ => issues}/issue-23024.rs | 2 +- src/test/ui/{ => issues}/issue-23024.stderr | 6 +- src/test/ui/{ => issues}/issue-23041.rs | 0 src/test/ui/{ => issues}/issue-23041.stderr | 0 src/test/ui/{ => issues}/issue-23046.rs | 0 src/test/ui/{ => issues}/issue-23046.stderr | 0 src/test/ui/{ => issues}/issue-23073.rs | 0 src/test/ui/{ => issues}/issue-23073.stderr | 0 src/test/ui/{ => issues}/issue-23080-2.rs | 0 src/test/ui/{ => issues}/issue-23080-2.stderr | 0 src/test/ui/{ => issues}/issue-23080.rs | 0 src/test/ui/{ => issues}/issue-23080.stderr | 0 src/test/ui/{ => issues}/issue-23122-1.rs | 0 src/test/ui/{ => issues}/issue-23122-1.stderr | 0 src/test/ui/{ => issues}/issue-23122-2.rs | 0 src/test/ui/{ => issues}/issue-23122-2.stderr | 0 src/test/ui/{ => issues}/issue-23173.rs | 0 src/test/ui/{ => issues}/issue-23173.stderr | 0 src/test/ui/{ => issues}/issue-23217.rs | 0 src/test/ui/{ => issues}/issue-23217.stderr | 0 src/test/ui/{ => issues}/issue-23253.rs | 0 src/test/ui/{ => issues}/issue-23253.stderr | 0 src/test/ui/{ => issues}/issue-23281.rs | 0 src/test/ui/{ => issues}/issue-23281.stderr | 2 +- src/test/ui/{ => issues}/issue-2330.rs | 0 src/test/ui/{ => issues}/issue-2330.stderr | 0 src/test/ui/{ => issues}/issue-23302-1.rs | 0 src/test/ui/{ => issues}/issue-23302-1.stderr | 0 src/test/ui/{ => issues}/issue-23302-2.rs | 0 src/test/ui/{ => issues}/issue-23302-2.stderr | 0 src/test/ui/{ => issues}/issue-23302-3.rs | 0 src/test/ui/{ => issues}/issue-23302-3.stderr | 0 src/test/ui/{ => issues}/issue-23543.rs | 0 src/test/ui/{ => issues}/issue-23543.stderr | 0 src/test/ui/{ => issues}/issue-23544.rs | 0 src/test/ui/{ => issues}/issue-23544.stderr | 0 src/test/ui/{ => issues}/issue-23589.rs | 0 src/test/ui/{ => issues}/issue-23589.stderr | 0 src/test/ui/{ => issues}/issue-23595-2.rs | 0 src/test/ui/{ => issues}/issue-23595-2.stderr | 0 src/test/ui/{ => issues}/issue-23716.rs | 0 src/test/ui/{ => issues}/issue-23716.stderr | 0 src/test/ui/{ => issues}/issue-23966.rs | 0 src/test/ui/issues/issue-23966.stderr | 11 + src/test/ui/{ => issues}/issue-24013.rs | 0 src/test/ui/{ => issues}/issue-24013.stderr | 0 src/test/ui/{ => issues}/issue-24036.rs | 0 src/test/ui/{ => issues}/issue-24036.stderr | 0 src/test/ui/{ => issues}/issue-24081.rs | 0 src/test/ui/{ => issues}/issue-24081.stderr | 0 src/test/ui/{ => issues}/issue-24204.rs | 0 src/test/ui/{ => issues}/issue-24204.stderr | 0 .../issue-24267-flow-exit.nll.stderr | 0 .../ui/{ => issues}/issue-24267-flow-exit.rs | 0 .../{ => issues}/issue-24267-flow-exit.stderr | 0 src/test/ui/{ => issues}/issue-24322.rs | 0 src/test/ui/{ => issues}/issue-24322.stderr | 0 src/test/ui/{ => issues}/issue-24352.rs | 0 src/test/ui/{ => issues}/issue-24352.stderr | 0 .../ui/{ => issues}/issue-24357.nll.stderr | 4 +- src/test/ui/{ => issues}/issue-24357.rs | 0 src/test/ui/{ => issues}/issue-24357.stderr | 0 src/test/ui/{ => issues}/issue-24363.rs | 0 src/test/ui/{ => issues}/issue-24363.stderr | 0 src/test/ui/{ => issues}/issue-24365.rs | 0 src/test/ui/{ => issues}/issue-24365.stderr | 0 src/test/ui/{ => issues}/issue-24424.rs | 0 src/test/ui/{ => issues}/issue-24424.stderr | 0 src/test/ui/{ => issues}/issue-24446.rs | 0 src/test/ui/{ => issues}/issue-24446.stderr | 2 +- src/test/ui/{ => issues}/issue-24682.rs | 0 src/test/ui/{ => issues}/issue-24682.stderr | 0 src/test/ui/{ => issues}/issue-24819.rs | 0 src/test/ui/{ => issues}/issue-24819.stderr | 0 src/test/ui/{ => issues}/issue-24883.rs | 0 src/test/ui/{ => issues}/issue-24883.stderr | 0 src/test/ui/{ => issues}/issue-25076.rs | 0 src/test/ui/{ => issues}/issue-25076.stderr | 0 src/test/ui/{ => issues}/issue-25368.rs | 0 src/test/ui/{ => issues}/issue-25368.stderr | 0 src/test/ui/{ => issues}/issue-25385.rs | 0 src/test/ui/{ => issues}/issue-25385.stderr | 0 src/test/ui/{ => issues}/issue-25386.rs | 0 src/test/ui/{ => issues}/issue-25386.stderr | 0 src/test/ui/{ => issues}/issue-25396.rs | 0 src/test/ui/{ => issues}/issue-25396.stderr | 0 src/test/ui/{ => issues}/issue-25439.rs | 0 src/test/ui/{ => issues}/issue-25439.stderr | 0 .../{ => issues}/issue-25579.ast.nll.stderr | 0 .../ui/{ => issues}/issue-25579.ast.stderr | 0 .../ui/{ => issues}/issue-25579.mir.stderr | 0 src/test/ui/{ => issues}/issue-25579.rs | 0 src/test/ui/{ => issues}/issue-25700.rs | 0 src/test/ui/{ => issues}/issue-25700.stderr | 0 .../ui/{ => issues}/issue-25793.nll.stderr | 0 src/test/ui/{ => issues}/issue-25793.rs | 0 src/test/ui/{ => issues}/issue-25793.stderr | 0 src/test/ui/{ => issues}/issue-25826.rs | 2 +- src/test/ui/issues/issue-25826.stderr | 11 + .../ui/{ => issues}/issue-2590.nll.stderr | 0 src/test/ui/{ => issues}/issue-2590.rs | 0 src/test/ui/{ => issues}/issue-2590.stderr | 0 src/test/ui/{ => issues}/issue-25901.rs | 0 src/test/ui/{ => issues}/issue-25901.stderr | 0 src/test/ui/{ => issues}/issue-26056.rs | 0 src/test/ui/{ => issues}/issue-26056.stderr | 0 src/test/ui/{ => issues}/issue-26093.rs | 0 src/test/ui/{ => issues}/issue-26093.stderr | 0 src/test/ui/{ => issues}/issue-26094.rs | 0 src/test/ui/{ => issues}/issue-26094.stderr | 0 src/test/ui/{ => issues}/issue-26158.rs | 0 src/test/ui/{ => issues}/issue-26158.stderr | 0 src/test/ui/issues/issue-26217.nll.stderr | 9 + src/test/ui/{ => issues}/issue-26217.rs | 0 src/test/ui/{ => issues}/issue-26217.stderr | 0 src/test/ui/{ => issues}/issue-26237.rs | 0 src/test/ui/{ => issues}/issue-26237.stderr | 0 src/test/ui/{ => issues}/issue-26262.rs | 0 src/test/ui/{ => issues}/issue-26262.stderr | 0 src/test/ui/{ => issues}/issue-26459.rs | 0 src/test/ui/{ => issues}/issue-26459.stderr | 0 src/test/ui/{ => issues}/issue-26472.rs | 0 src/test/ui/{ => issues}/issue-26472.stderr | 0 .../issues}/issue-26548.rs | 0 src/test/ui/issues/issue-26548.stderr | 13 + src/test/ui/{ => issues}/issue-26614.rs | 0 src/test/ui/{ => issues}/issue-26614.stderr | 0 src/test/ui/{ => issues}/issue-26638.rs | 0 src/test/ui/{ => issues}/issue-26638.stderr | 0 src/test/ui/{ => issues}/issue-26812.rs | 0 src/test/ui/{ => issues}/issue-26812.stderr | 0 src/test/ui/{ => issues}/issue-26886.rs | 0 src/test/ui/{ => issues}/issue-26886.stderr | 0 src/test/ui/{ => issues}/issue-26905.rs | 0 src/test/ui/{ => issues}/issue-26905.stderr | 0 src/test/ui/{ => issues}/issue-26930.rs | 0 src/test/ui/{ => issues}/issue-26930.stderr | 0 src/test/ui/{ => issues}/issue-26948.rs | 0 src/test/ui/{ => issues}/issue-26948.stderr | 0 src/test/ui/{ => issues}/issue-27008.rs | 0 src/test/ui/{ => issues}/issue-27008.stderr | 0 src/test/ui/{ => issues}/issue-27033.rs | 0 src/test/ui/{ => issues}/issue-27033.stderr | 0 src/test/ui/{ => issues}/issue-27042.rs | 0 src/test/ui/{ => issues}/issue-27042.stderr | 0 src/test/ui/{ => issues}/issue-27060-2.rs | 0 src/test/ui/{ => issues}/issue-27060-2.stderr | 4 +- src/test/ui/{ => issues}/issue-27060.rs | 0 src/test/ui/{ => issues}/issue-27060.stderr | 0 src/test/ui/{ => issues}/issue-27078.rs | 0 src/test/ui/{ => issues}/issue-27078.stderr | 3 +- src/test/ui/{ => issues}/issue-2718-a.rs | 0 src/test/ui/{ => issues}/issue-2718-a.stderr | 0 ...issue-27282-move-match-input-into-guard.rs | 0 ...e-27282-move-match-input-into-guard.stderr | 29 + .../issue-27282-move-ref-mut-into-guard.rs | 0 ...issue-27282-move-ref-mut-into-guard.stderr | 0 ...sue-27282-mutate-before-diverging-arm-1.rs | 0 ...27282-mutate-before-diverging-arm-1.stderr | 2 +- ...sue-27282-mutate-before-diverging-arm-2.rs | 0 ...27282-mutate-before-diverging-arm-2.stderr | 2 +- .../issue-27282-reborrow-ref-mut-in-guard.rs | 0 ...sue-27282-reborrow-ref-mut-in-guard.stderr | 0 src/test/ui/{ => issues}/issue-27340.rs | 0 src/test/ui/{ => issues}/issue-27340.stderr | 0 src/test/ui/{ => issues}/issue-27433.rs | 0 src/test/ui/{ => issues}/issue-27433.stderr | 0 .../ui/{ => issues}/issue-27592.nll.stderr | 16 +- src/test/ui/{ => issues}/issue-27592.rs | 0 src/test/ui/{ => issues}/issue-27592.stderr | 0 src/test/ui/{ => issues}/issue-27815.rs | 0 src/test/ui/{ => issues}/issue-27815.stderr | 0 src/test/ui/{ => issues}/issue-27842.rs | 0 src/test/ui/{ => issues}/issue-27842.stderr | 0 src/test/ui/{ => issues}/issue-27895.rs | 0 src/test/ui/{ => issues}/issue-27895.stderr | 0 src/test/ui/{ => issues}/issue-27942.rs | 0 src/test/ui/{ => issues}/issue-27942.stderr | 0 .../issues}/issue-28075.rs | 3 +- src/test/ui/issues/issue-28075.stderr | 11 + src/test/ui/{ => issues}/issue-28098.rs | 0 src/test/ui/{ => issues}/issue-28098.stderr | 0 src/test/ui/{ => issues}/issue-28105.rs | 0 src/test/ui/{ => issues}/issue-28105.stderr | 0 src/test/ui/{ => issues}/issue-28109.rs | 0 src/test/ui/{ => issues}/issue-28109.stderr | 0 src/test/ui/{ => issues}/issue-28113.rs | 0 src/test/ui/{ => issues}/issue-28113.stderr | 0 src/test/ui/{ => issues}/issue-2823.rs | 0 src/test/ui/{ => issues}/issue-2823.stderr | 0 src/test/ui/{ => issues}/issue-28324.rs | 0 src/test/ui/{ => issues}/issue-28324.stderr | 0 src/test/ui/{ => issues}/issue-28344.rs | 0 src/test/ui/{ => issues}/issue-28344.stderr | 0 .../issues}/issue-28388-1.rs | 0 src/test/ui/issues/issue-28388-1.stderr | 9 + .../issues}/issue-28388-2.rs | 0 src/test/ui/issues/issue-28388-2.stderr | 9 + .../issues}/issue-28388-3.rs | 3 +- src/test/ui/issues/issue-28388-3.stderr | 11 + src/test/ui/{ => issues}/issue-28433.rs | 0 src/test/ui/{ => issues}/issue-28433.stderr | 0 src/test/ui/{ => issues}/issue-28472.rs | 0 src/test/ui/{ => issues}/issue-28472.stderr | 0 src/test/ui/{ => issues}/issue-2848.rs | 0 src/test/ui/{ => issues}/issue-2848.stderr | 0 src/test/ui/{ => issues}/issue-2849.rs | 0 src/test/ui/{ => issues}/issue-2849.stderr | 0 src/test/ui/{ => issues}/issue-28568.rs | 0 src/test/ui/{ => issues}/issue-28568.stderr | 0 src/test/ui/{ => issues}/issue-28576.rs | 0 src/test/ui/{ => issues}/issue-28576.stderr | 0 src/test/ui/{ => issues}/issue-28586.rs | 0 src/test/ui/{ => issues}/issue-28586.stderr | 0 .../issues}/issue-28625.rs | 2 + src/test/ui/issues/issue-28625.stderr | 12 + src/test/ui/{ => issues}/issue-28776.rs | 0 src/test/ui/{ => issues}/issue-28776.stderr | 0 src/test/ui/{ => issues}/issue-28837.rs | 0 src/test/ui/{ => issues}/issue-28837.stderr | 0 .../issues}/issue-28848.rs | 2 + src/test/ui/issues/issue-28848.stderr | 20 + src/test/ui/{ => issues}/issue-28971.rs | 0 src/test/ui/{ => issues}/issue-28971.stderr | 0 src/test/ui/{ => issues}/issue-28992-empty.rs | 0 .../ui/{ => issues}/issue-28992-empty.stderr | 0 src/test/ui/{ => issues}/issue-29084.rs | 0 src/test/ui/{ => issues}/issue-29084.stderr | 0 src/test/ui/{ => issues}/issue-29124.rs | 0 src/test/ui/{ => issues}/issue-29124.stderr | 0 src/test/ui/{ => issues}/issue-29147.rs | 0 src/test/ui/{ => issues}/issue-29147.stderr | 0 src/test/ui/{ => issues}/issue-29161.rs | 0 src/test/ui/{ => issues}/issue-29161.stderr | 0 .../issues}/issue-29181.rs | 0 src/test/ui/issues/issue-29181.stderr | 9 + src/test/ui/{ => issues}/issue-29184.rs | 0 src/test/ui/{ => issues}/issue-29184.stderr | 0 src/test/ui/{ => issues}/issue-2937.rs | 0 src/test/ui/{ => issues}/issue-2937.stderr | 0 src/test/ui/{ => issues}/issue-2951.rs | 0 src/test/ui/{ => issues}/issue-2951.stderr | 0 src/test/ui/{ => issues}/issue-29723.rs | 0 src/test/ui/{ => issues}/issue-29723.stderr | 0 src/test/ui/{ => issues}/issue-29857.rs | 0 src/test/ui/{ => issues}/issue-29857.stderr | 0 src/test/ui/{ => issues}/issue-29861.rs | 0 src/test/ui/{ => issues}/issue-29861.stderr | 0 src/test/ui/{ => issues}/issue-2995.rs | 0 src/test/ui/{ => issues}/issue-2995.stderr | 0 src/test/ui/{ => issues}/issue-30007.rs | 0 src/test/ui/{ => issues}/issue-30007.stderr | 0 src/test/ui/{ => issues}/issue-30079.rs | 0 src/test/ui/{ => issues}/issue-30079.stderr | 0 src/test/ui/{ => issues}/issue-3008-1.rs | 0 src/test/ui/{ => issues}/issue-3008-1.stderr | 0 src/test/ui/{ => issues}/issue-3008-2.rs | 0 src/test/ui/{ => issues}/issue-3008-2.stderr | 0 src/test/ui/{ => issues}/issue-3008-3.rs | 0 src/test/ui/{ => issues}/issue-3008-3.stderr | 0 .../issues}/issue-30123.rs | 0 src/test/ui/issues/issue-30123.stderr | 9 + src/test/ui/{ => issues}/issue-3021-b.rs | 0 src/test/ui/{ => issues}/issue-3021-b.stderr | 0 src/test/ui/{ => issues}/issue-3021-c.rs | 0 src/test/ui/{ => issues}/issue-3021-c.stderr | 0 src/test/ui/{ => issues}/issue-3021-d.rs | 0 src/test/ui/{ => issues}/issue-3021-d.stderr | 0 src/test/ui/{ => issues}/issue-3021.rs | 0 src/test/ui/{ => issues}/issue-3021.stderr | 0 src/test/ui/{ => issues}/issue-30225.rs | 0 src/test/ui/{ => issues}/issue-30225.stderr | 0 src/test/ui/{ => issues}/issue-30236.rs | 0 src/test/ui/{ => issues}/issue-30236.stderr | 0 src/test/ui/{ => issues}/issue-30240-b.rs | 0 src/test/ui/{ => issues}/issue-30240-b.stderr | 0 src/test/ui/{ => issues}/issue-30240.rs | 0 src/test/ui/{ => issues}/issue-30240.stderr | 0 src/test/ui/{ => issues}/issue-30255.rs | 0 src/test/ui/{ => issues}/issue-30255.stderr | 0 src/test/ui/{ => issues}/issue-30302.rs | 0 src/test/ui/{ => issues}/issue-30302.stderr | 0 .../ui/{ => issues}/issue-30355.nll.stderr | 0 src/test/ui/{ => issues}/issue-30355.rs | 0 src/test/ui/{ => issues}/issue-30355.stderr | 0 src/test/ui/{ => issues}/issue-3038.rs | 0 src/test/ui/{ => issues}/issue-3038.stderr | 0 .../ui/{ => issues}/issue-30438-a.nll.stderr | 0 src/test/ui/{ => issues}/issue-30438-a.rs | 0 src/test/ui/{ => issues}/issue-30438-a.stderr | 0 src/test/ui/{ => issues}/issue-30438-b.rs | 0 src/test/ui/{ => issues}/issue-30438-b.stderr | 0 .../ui/{ => issues}/issue-30438-c.nll.stderr | 0 src/test/ui/{ => issues}/issue-30438-c.rs | 0 src/test/ui/{ => issues}/issue-30438-c.stderr | 0 src/test/ui/{ => issues}/issue-3044.rs | 0 src/test/ui/{ => issues}/issue-3044.stderr | 0 .../issues}/issue-30535.rs | 0 src/test/ui/issues/issue-30535.stderr | 11 + src/test/ui/{ => issues}/issue-30560.rs | 0 src/test/ui/{ => issues}/issue-30560.stderr | 0 src/test/ui/{ => issues}/issue-30589.rs | 0 src/test/ui/{ => issues}/issue-30589.stderr | 0 src/test/ui/{ => issues}/issue-30730.rs | 0 src/test/ui/{ => issues}/issue-30730.stderr | 0 src/test/ui/{ => issues}/issue-3080.rs | 0 src/test/ui/{ => issues}/issue-3080.stderr | 0 src/test/ui/{ => issues}/issue-3096-1.rs | 0 src/test/ui/{ => issues}/issue-3096-1.stderr | 0 src/test/ui/{ => issues}/issue-3096-2.rs | 0 src/test/ui/{ => issues}/issue-3096-2.stderr | 0 src/test/ui/{ => issues}/issue-3099-a.rs | 0 src/test/ui/{ => issues}/issue-3099-a.stderr | 0 src/test/ui/{ => issues}/issue-3099-b.rs | 0 src/test/ui/{ => issues}/issue-3099-b.stderr | 0 src/test/ui/{ => issues}/issue-3099.rs | 0 src/test/ui/{ => issues}/issue-3099.stderr | 0 src/test/ui/{ => issues}/issue-31011.rs | 0 src/test/ui/{ => issues}/issue-31011.stderr | 0 src/test/ui/{ => issues}/issue-31109.rs | 0 src/test/ui/{ => issues}/issue-31109.stderr | 0 src/test/ui/{ => issues}/issue-31173.rs | 0 src/test/ui/{ => issues}/issue-31173.stderr | 0 src/test/ui/{ => issues}/issue-31212.rs | 0 src/test/ui/{ => issues}/issue-31212.stderr | 0 src/test/ui/{ => issues}/issue-31221.rs | 0 src/test/ui/{ => issues}/issue-31221.stderr | 0 src/test/ui/{ => issues}/issue-31511.rs | 0 src/test/ui/{ => issues}/issue-31511.stderr | 0 src/test/ui/{ => issues}/issue-3154.rs | 0 src/test/ui/{ => issues}/issue-3154.stderr | 2 +- src/test/ui/{ => issues}/issue-31561.rs | 0 src/test/ui/{ => issues}/issue-31561.stderr | 0 src/test/ui/{ => issues}/issue-31769.rs | 0 src/test/ui/{ => issues}/issue-31769.stderr | 0 src/test/ui/{ => issues}/issue-31804.rs | 0 src/test/ui/{ => issues}/issue-31804.stderr | 0 src/test/ui/{ => issues}/issue-31845.rs | 2 +- src/test/ui/{ => issues}/issue-31845.stderr | 0 src/test/ui/{ => issues}/issue-31910.rs | 0 src/test/ui/{ => issues}/issue-31910.stderr | 0 .../{ => issues}/issue-31924-non-snake-ffi.rs | 0 .../issue-31924-non-snake-ffi.stderr | 0 src/test/ui/{ => issues}/issue-32004.rs | 0 src/test/ui/{ => issues}/issue-32004.stderr | 0 src/test/ui/{ => issues}/issue-32086.rs | 0 src/test/ui/{ => issues}/issue-32086.stderr | 0 src/test/ui/{ => issues}/issue-32119.rs | 0 src/test/ui/{ => issues}/issue-32119.stderr | 0 src/test/ui/{ => issues}/issue-3214.rs | 0 src/test/ui/issues/issue-3214.stderr | 21 + src/test/ui/{ => issues}/issue-32201.rs | 0 src/test/ui/{ => issues}/issue-32201.stderr | 0 src/test/ui/{ => issues}/issue-32222.rs | 0 src/test/ui/{ => issues}/issue-32222.stderr | 0 src/test/ui/{ => issues}/issue-32323.rs | 0 src/test/ui/{ => issues}/issue-32323.stderr | 0 src/test/ui/{ => issues}/issue-32326.rs | 0 src/test/ui/{ => issues}/issue-32326.stderr | 0 .../issue-32354-suggest-import-rename.fixed | 0 .../issue-32354-suggest-import-rename.rs | 0 .../issue-32354-suggest-import-rename.stderr | 0 .../issues}/issue-32377.rs | 2 + src/test/ui/issues/issue-32377.stderr | 12 + src/test/ui/{ => issues}/issue-32655.rs | 0 src/test/ui/{ => issues}/issue-32655.stderr | 8 +- src/test/ui/{ => issues}/issue-32709.rs | 0 src/test/ui/{ => issues}/issue-32709.stderr | 0 src/test/ui/{ => issues}/issue-32782.rs | 0 src/test/ui/{ => issues}/issue-32782.stderr | 0 src/test/ui/{ => issues}/issue-32797.rs | 0 src/test/ui/{ => issues}/issue-32797.stderr | 0 src/test/ui/{ => issues}/issue-32829.rs | 2 +- src/test/ui/issues/issue-32829.stderr | 12 + src/test/ui/{ => issues}/issue-32833.rs | 0 src/test/ui/{ => issues}/issue-32833.stderr | 0 src/test/ui/{ => issues}/issue-32922.rs | 0 src/test/ui/{ => issues}/issue-32922.stderr | 0 src/test/ui/{ => issues}/issue-32950.rs | 0 src/test/ui/{ => issues}/issue-32950.stderr | 0 src/test/ui/{ => issues}/issue-32963.rs | 0 src/test/ui/{ => issues}/issue-32963.stderr | 0 src/test/ui/{ => issues}/issue-32995-2.rs | 0 src/test/ui/{ => issues}/issue-32995-2.stderr | 0 src/test/ui/{ => issues}/issue-32995.rs | 0 src/test/ui/{ => issues}/issue-32995.stderr | 0 src/test/ui/{ => issues}/issue-33241.rs | 0 src/test/ui/{ => issues}/issue-33241.stderr | 0 src/test/ui/{ => issues}/issue-33293.rs | 0 src/test/ui/{ => issues}/issue-33293.stderr | 0 src/test/ui/{ => issues}/issue-3344.rs | 0 src/test/ui/{ => issues}/issue-3344.stderr | 0 src/test/ui/{ => issues}/issue-33464.rs | 0 src/test/ui/{ => issues}/issue-33464.stderr | 0 src/test/ui/{ => issues}/issue-33504.rs | 0 src/test/ui/{ => issues}/issue-33504.stderr | 0 src/test/ui/{ => issues}/issue-33525.rs | 0 src/test/ui/{ => issues}/issue-33525.stderr | 0 src/test/ui/{ => issues}/issue-33571.rs | 0 src/test/ui/{ => issues}/issue-33571.stderr | 0 .../ui/{ => issues}/issue-33819.nll.stderr | 0 src/test/ui/{ => issues}/issue-33819.rs | 0 src/test/ui/{ => issues}/issue-33819.stderr | 0 src/test/ui/{ => issues}/issue-33941.rs | 0 src/test/ui/{ => issues}/issue-33941.stderr | 0 src/test/ui/{ => issues}/issue-34028.rs | 0 src/test/ui/{ => issues}/issue-34028.stderr | 0 src/test/ui/{ => issues}/issue-34047.rs | 0 src/test/ui/{ => issues}/issue-34047.stderr | 0 src/test/ui/{ => issues}/issue-34171.rs | 0 src/test/ui/{ => issues}/issue-34171.stderr | 0 src/test/ui/{ => issues}/issue-34209.rs | 0 src/test/ui/{ => issues}/issue-34209.stderr | 0 src/test/ui/{ => issues}/issue-34222-1.rs | 0 src/test/ui/{ => issues}/issue-34222-1.stderr | 0 src/test/ui/{ => issues}/issue-34334.rs | 0 src/test/ui/{ => issues}/issue-34334.stderr | 0 src/test/ui/{ => issues}/issue-34349.rs | 0 src/test/ui/{ => issues}/issue-34349.stderr | 0 src/test/ui/{ => issues}/issue-34373.rs | 0 src/test/ui/{ => issues}/issue-34373.stderr | 0 src/test/ui/{ => issues}/issue-34418.rs | 0 src/test/ui/{ => issues}/issue-34418.stderr | 0 src/test/ui/{ => issues}/issue-3477.rs | 0 src/test/ui/{ => issues}/issue-3477.stderr | 0 src/test/ui/{ => issues}/issue-34839.rs | 0 src/test/ui/{ => issues}/issue-34839.stderr | 0 src/test/ui/{ => issues}/issue-35075.rs | 0 src/test/ui/{ => issues}/issue-35075.stderr | 0 src/test/ui/{ => issues}/issue-35139.rs | 0 src/test/ui/{ => issues}/issue-35139.stderr | 0 src/test/ui/{ => issues}/issue-3521-2.rs | 0 src/test/ui/{ => issues}/issue-3521-2.stderr | 0 src/test/ui/{ => issues}/issue-3521.rs | 0 src/test/ui/{ => issues}/issue-3521.stderr | 0 src/test/ui/{ => issues}/issue-35241.rs | 0 src/test/ui/{ => issues}/issue-35241.stderr | 0 src/test/ui/{ => issues}/issue-35450.rs | 0 src/test/ui/{ => issues}/issue-35450.stderr | 0 src/test/ui/{ => issues}/issue-35570.rs | 0 src/test/ui/{ => issues}/issue-35570.stderr | 0 src/test/ui/{ => issues}/issue-35668.rs | 0 src/test/ui/{ => issues}/issue-35668.stderr | 0 src/test/ui/{ => issues}/issue-35675.rs | 0 src/test/ui/{ => issues}/issue-35675.stderr | 0 src/test/ui/{ => issues}/issue-35869.rs | 0 src/test/ui/{ => issues}/issue-35869.stderr | 0 src/test/ui/{ => issues}/issue-35976.rs | 0 src/test/ui/{ => issues}/issue-35976.stderr | 0 src/test/ui/{ => issues}/issue-35988.rs | 0 src/test/ui/{ => issues}/issue-35988.stderr | 2 +- src/test/ui/{ => issues}/issue-3601.rs | 0 src/test/ui/{ => issues}/issue-3601.stderr | 0 .../{ => issues}/issue-36082.ast.nll.stderr | 2 + .../ui/{ => issues}/issue-36082.ast.stderr | 0 .../ui/{ => issues}/issue-36082.mir.stderr | 2 + src/test/ui/{ => issues}/issue-36082.rs | 1 + src/test/ui/{ => issues}/issue-36116.rs | 0 src/test/ui/{ => issues}/issue-36116.stderr | 0 src/test/ui/{ => issues}/issue-36163.rs | 0 src/test/ui/{ => issues}/issue-36163.stderr | 0 src/test/ui/{ => issues}/issue-36299.rs | 0 src/test/ui/{ => issues}/issue-36299.stderr | 0 src/test/ui/{ => issues}/issue-36379.rs | 0 src/test/ui/{ => issues}/issue-36379.stderr | 0 .../ui/{ => issues}/issue-36400.nll.stderr | 0 src/test/ui/{ => issues}/issue-36400.rs | 0 src/test/ui/{ => issues}/issue-36400.stderr | 2 +- src/test/ui/{ => issues}/issue-36617.rs | 0 src/test/ui/{ => issues}/issue-36617.stderr | 0 src/test/ui/{ => issues}/issue-36638.rs | 0 src/test/ui/{ => issues}/issue-36638.stderr | 0 src/test/ui/{ => issues}/issue-3668-2.rs | 0 src/test/ui/{ => issues}/issue-3668-2.stderr | 0 src/test/ui/{ => issues}/issue-3668.rs | 0 src/test/ui/{ => issues}/issue-3668.stderr | 0 src/test/ui/{ => issues}/issue-36708.rs | 0 src/test/ui/{ => issues}/issue-36708.stderr | 0 src/test/ui/{ => issues}/issue-3680.rs | 0 src/test/ui/{ => issues}/issue-3680.stderr | 0 src/test/ui/{ => issues}/issue-36839.rs | 0 src/test/ui/{ => issues}/issue-36839.stderr | 0 .../issues}/issue-36881.rs | 0 src/test/ui/issues/issue-36881.stderr | 9 + src/test/ui/{ => issues}/issue-3702-2.rs | 0 src/test/ui/{ => issues}/issue-3702-2.stderr | 0 src/test/ui/{ => issues}/issue-37026.rs | 0 src/test/ui/{ => issues}/issue-37026.stderr | 0 src/test/ui/{ => issues}/issue-37051.rs | 0 src/test/ui/{ => issues}/issue-37051.stderr | 0 src/test/ui/{ => issues}/issue-3707.rs | 0 src/test/ui/{ => issues}/issue-3707.stderr | 0 .../issues}/issue-37131.rs | 0 src/test/ui/issues/issue-37131.stderr | 7 + .../issue-37311.rs | 0 .../issue-37311.stderr | 0 src/test/ui/{ => issues}/issue-37323.rs | 3 +- src/test/ui/{ => issues}/issue-37366.rs | 0 src/test/ui/{ => issues}/issue-37366.stderr | 0 src/test/ui/{ => issues}/issue-37510.rs | 0 src/test/ui/{ => issues}/issue-37510.stderr | 0 src/test/ui/{ => issues}/issue-37515.rs | 0 src/test/ui/{ => issues}/issue-37515.stderr | 0 src/test/ui/{ => issues}/issue-37534.rs | 0 src/test/ui/{ => issues}/issue-37534.stderr | 0 src/test/ui/{ => issues}/issue-37550.rs | 0 src/test/ui/{ => issues}/issue-37550.stderr | 0 src/test/ui/{ => issues}/issue-37576.rs | 0 src/test/ui/{ => issues}/issue-37576.stderr | 0 src/test/ui/{ => issues}/issue-3763.rs | 0 src/test/ui/{ => issues}/issue-3763.stderr | 0 src/test/ui/{ => issues}/issue-37665.rs | 0 src/test/ui/{ => issues}/issue-37665.stderr | 0 src/test/ui/{ => issues}/issue-3779.rs | 0 src/test/ui/{ => issues}/issue-3779.stderr | 0 src/test/ui/{ => issues}/issue-37884.rs | 0 src/test/ui/{ => issues}/issue-37884.stderr | 0 src/test/ui/{ => issues}/issue-37887.rs | 0 src/test/ui/{ => issues}/issue-37887.stderr | 0 src/test/ui/{ => issues}/issue-38160.rs | 0 src/test/ui/{ => issues}/issue-38160.stderr | 0 src/test/ui/{ => issues}/issue-3820.rs | 0 src/test/ui/{ => issues}/issue-3820.stderr | 0 src/test/ui/{ => issues}/issue-38293.rs | 0 src/test/ui/{ => issues}/issue-38293.stderr | 0 src/test/ui/{ => issues}/issue-38381.rs | 0 src/test/ui/{ => issues}/issue-38381.stderr | 0 src/test/ui/{ => issues}/issue-38404.rs | 0 src/test/ui/{ => issues}/issue-38404.stderr | 0 src/test/ui/{ => issues}/issue-38412.rs | 0 src/test/ui/{ => issues}/issue-38412.stderr | 0 src/test/ui/{ => issues}/issue-38458.rs | 0 src/test/ui/{ => issues}/issue-38458.stderr | 0 src/test/ui/{ => issues}/issue-38604.rs | 0 src/test/ui/{ => issues}/issue-38604.stderr | 0 src/test/ui/issues/issue-38715.rs | 18 + src/test/ui/issues/issue-38715.stderr | 17 + .../issues/issue-38821.rs} | 0 src/test/ui/issues/issue-38821.stderr | 12 + src/test/ui/{ => issues}/issue-38857.rs | 0 src/test/ui/{ => issues}/issue-38857.stderr | 0 src/test/ui/{ => issues}/issue-38868.rs | 0 src/test/ui/{ => issues}/issue-38868.stderr | 0 .../issue-38875/auxiliary/issue_38875_b.rs | 0 .../{ => issues}/issue-38875/issue_38875.rs | 0 src/test/ui/{ => issues}/issue-38919.rs | 0 src/test/ui/{ => issues}/issue-38919.stderr | 0 src/test/ui/{ => issues}/issue-38954.rs | 0 src/test/ui/{ => issues}/issue-38954.stderr | 4 +- src/test/ui/{ => issues}/issue-39211.rs | 0 src/test/ui/{ => issues}/issue-39211.stderr | 0 src/test/ui/{ => issues}/issue-39362.rs | 0 src/test/ui/{ => issues}/issue-39362.stderr | 0 src/test/ui/{ => issues}/issue-39388.rs | 0 src/test/ui/{ => issues}/issue-39388.stderr | 0 src/test/ui/{ => issues}/issue-39404.rs | 0 src/test/ui/{ => issues}/issue-39404.stderr | 0 src/test/ui/{ => issues}/issue-39559-2.rs | 0 src/test/ui/{ => issues}/issue-39559-2.stderr | 0 src/test/ui/{ => issues}/issue-39559.rs | 0 src/test/ui/{ => issues}/issue-39559.stderr | 0 src/test/ui/{ => issues}/issue-39616.rs | 0 src/test/ui/{ => issues}/issue-39616.stderr | 0 src/test/ui/{ => issues}/issue-39687.rs | 0 src/test/ui/{ => issues}/issue-39687.stderr | 0 src/test/ui/{ => issues}/issue-3973.rs | 0 src/test/ui/{ => issues}/issue-3973.stderr | 0 src/test/ui/{ => issues}/issue-39848.rs | 0 src/test/ui/{ => issues}/issue-39848.stderr | 0 src/test/ui/{ => issues}/issue-3993.rs | 0 src/test/ui/{ => issues}/issue-3993.stderr | 0 src/test/ui/{ => issues}/issue-39970.rs | 0 src/test/ui/{ => issues}/issue-39970.stderr | 0 src/test/ui/{ => issues}/issue-39974.rs | 0 src/test/ui/{ => issues}/issue-39974.stderr | 0 src/test/ui/{ => issues}/issue-40000.rs | 0 src/test/ui/{ => issues}/issue-40000.stderr | 0 src/test/ui/issues/issue-40288-2.nll.stderr | 21 + src/test/ui/{ => issues}/issue-40288-2.rs | 0 src/test/ui/issues/issue-40288-2.stderr | 21 + .../ui/{ => issues}/issue-40288.nll.stderr | 0 src/test/ui/{ => issues}/issue-40288.rs | 0 src/test/ui/{ => issues}/issue-40288.stderr | 0 src/test/ui/{ => issues}/issue-40350.rs | 0 src/test/ui/{ => issues}/issue-40350.stderr | 0 .../issue-40402-1.nll.stderr | 2 +- .../issue-40402-ref-hints/issue-40402-1.rs | 0 .../issue-40402-1.stderr | 0 .../issue-40402-2.nll.stderr | 20 + .../issue-40402-ref-hints/issue-40402-2.rs | 0 .../issue-40402-2.stderr | 0 src/test/ui/issues/issue-40510-1.nll.stderr | 15 + src/test/ui/{ => issues}/issue-40510-1.rs | 0 src/test/ui/{ => issues}/issue-40510-1.stderr | 0 src/test/ui/{ => issues}/issue-40510-2.rs | 0 src/test/ui/{ => issues}/issue-40510-2.stderr | 0 src/test/ui/issues/issue-40510-3.nll.stderr | 17 + src/test/ui/{ => issues}/issue-40510-3.rs | 0 src/test/ui/{ => issues}/issue-40510-3.stderr | 0 src/test/ui/{ => issues}/issue-40510-4.rs | 0 src/test/ui/{ => issues}/issue-40510-4.stderr | 0 src/test/ui/{ => issues}/issue-40610.rs | 0 src/test/ui/{ => issues}/issue-40610.stderr | 0 src/test/ui/{ => issues}/issue-40749.rs | 0 src/test/ui/{ => issues}/issue-40749.stderr | 0 src/test/ui/{ => issues}/issue-40782.rs | 0 src/test/ui/{ => issues}/issue-40782.stderr | 0 src/test/ui/{ => issues}/issue-40845.rs | 0 src/test/ui/{ => issues}/issue-40845.stderr | 0 src/test/ui/{ => issues}/issue-40861.rs | 0 src/test/ui/{ => issues}/issue-40861.stderr | 0 .../ui/{ => issues}/issue-41139.nll.stderr | 0 src/test/ui/{ => issues}/issue-41139.rs | 0 src/test/ui/{ => issues}/issue-41139.stderr | 0 .../ui/{ => issues}/issue-41229-ref-str.rs | 0 .../{ => issues}/issue-41229-ref-str.stderr | 4 +- src/test/ui/{ => issues}/issue-41255.rs | 0 src/test/ui/{ => issues}/issue-41255.stderr | 0 src/test/ui/{ => issues}/issue-41394.rs | 0 src/test/ui/{ => issues}/issue-41394.stderr | 0 .../issues}/issue-41549.rs | 0 src/test/ui/issues/issue-41549.stderr | 12 + .../issue-41652/auxiliary/issue_41652_b.rs | 0 .../{ => issues}/issue-41652/issue_41652.rs | 0 .../issue-41652/issue_41652.stderr | 0 src/test/ui/issues/issue-41726.nll.stderr | 11 + src/test/ui/{ => issues}/issue-41726.rs | 0 src/test/ui/issues/issue-41726.stderr | 11 + src/test/ui/{ => issues}/issue-41742.rs | 0 src/test/ui/{ => issues}/issue-41742.stderr | 0 src/test/ui/{ => issues}/issue-41776.rs | 0 src/test/ui/{ => issues}/issue-41776.stderr | 0 src/test/ui/{ => issues}/issue-41880.rs | 0 src/test/ui/{ => issues}/issue-41880.stderr | 0 src/test/ui/{ => issues}/issue-41974.rs | 0 src/test/ui/{ => issues}/issue-41974.stderr | 0 src/test/ui/{ => issues}/issue-41998.rs | 0 src/test/ui/{ => issues}/issue-41998.stderr | 0 src/test/ui/{ => issues}/issue-4201.rs | 0 src/test/ui/{ => issues}/issue-4201.stderr | 0 src/test/ui/{ => issues}/issue-42060.rs | 0 src/test/ui/{ => issues}/issue-42060.stderr | 0 .../ui/{ => issues}/issue-42106.nll.stderr | 0 src/test/ui/{ => issues}/issue-42106.rs | 0 src/test/ui/{ => issues}/issue-42106.stderr | 0 src/test/ui/{ => issues}/issue-42312.rs | 0 src/test/ui/{ => issues}/issue-42312.stderr | 8 +- .../ui/{ => issues}/issue-42344.nll.stderr | 0 src/test/ui/{ => issues}/issue-42344.rs | 0 src/test/ui/{ => issues}/issue-42344.stderr | 0 src/test/ui/{ => issues}/issue-4265.rs | 0 src/test/ui/{ => issues}/issue-4265.stderr | 0 src/test/ui/{ => issues}/issue-42755.rs | 4 +- src/test/ui/issues/issue-42755.stderr | 8 + .../ui/{ => issues}/issue-42796.nll.stderr | 0 src/test/ui/{ => issues}/issue-42796.rs | 0 src/test/ui/{ => issues}/issue-42796.stderr | 0 src/test/ui/{ => issues}/issue-42880.rs | 0 src/test/ui/{ => issues}/issue-42880.stderr | 0 src/test/ui/{ => issues}/issue-42954.fixed | 0 src/test/ui/{ => issues}/issue-42954.rs | 0 src/test/ui/{ => issues}/issue-42954.stderr | 0 src/test/ui/{ => issues}/issue-43023.rs | 0 src/test/ui/{ => issues}/issue-43023.stderr | 0 src/test/ui/{ => issues}/issue-43105.rs | 0 src/test/ui/{ => issues}/issue-43105.stderr | 0 src/test/ui/{ => issues}/issue-43162.rs | 0 src/test/ui/{ => issues}/issue-43162.stderr | 0 src/test/ui/{ => issues}/issue-43189.rs | 0 src/test/ui/{ => issues}/issue-43189.stderr | 0 src/test/ui/{ => issues}/issue-43196.rs | 0 src/test/ui/{ => issues}/issue-43196.stderr | 0 src/test/ui/{ => issues}/issue-4321.rs | 0 src/test/ui/{ => issues}/issue-4321.stderr | 0 src/test/ui/{ => issues}/issue-43250.rs | 0 src/test/ui/{ => issues}/issue-43250.stderr | 0 src/test/ui/issues/issue-4335.nll.stderr | 29 + src/test/ui/{ => issues}/issue-4335.rs | 0 src/test/ui/{ => issues}/issue-4335.stderr | 0 src/test/ui/{ => issues}/issue-43355.rs | 0 src/test/ui/{ => issues}/issue-43355.stderr | 0 .../issue-43420-no-over-suggest.rs | 0 .../issue-43420-no-over-suggest.stderr | 0 src/test/ui/{ => issues}/issue-43424.rs | 0 src/test/ui/{ => issues}/issue-43424.stderr | 0 src/test/ui/{ => issues}/issue-43431.rs | 0 src/test/ui/{ => issues}/issue-43431.stderr | 0 src/test/ui/{ => issues}/issue-4366-2.rs | 0 src/test/ui/{ => issues}/issue-4366-2.stderr | 0 src/test/ui/{ => issues}/issue-4366.rs | 0 src/test/ui/{ => issues}/issue-4366.stderr | 0 src/test/ui/{ => issues}/issue-43733.rs | 0 src/test/ui/{ => issues}/issue-43733.stderr | 0 .../issue-43784-associated-type.rs | 2 + .../issues/issue-43784-associated-type.stderr | 11 + .../ui/{ => issues}/issue-43784-supertrait.rs | 2 + .../ui/issues/issue-43784-supertrait.stderr | 11 + src/test/ui/{ => issues}/issue-43806.rs | 0 src/test/ui/{ => issues}/issue-43925.rs | 2 - src/test/ui/{ => issues}/issue-43925.stderr | 2 +- src/test/ui/{ => issues}/issue-43926.rs | 0 src/test/ui/{ => issues}/issue-43926.stderr | 0 src/test/ui/{ => issues}/issue-43988.rs | 0 src/test/ui/{ => issues}/issue-43988.stderr | 0 src/test/ui/{ => issues}/issue-44021.rs | 0 src/test/ui/{ => issues}/issue-44021.stderr | 0 src/test/ui/{ => issues}/issue-44023.rs | 0 src/test/ui/{ => issues}/issue-44023.stderr | 0 src/test/ui/{ => issues}/issue-44078.rs | 0 src/test/ui/{ => issues}/issue-44078.stderr | 0 src/test/ui/{ => issues}/issue-44239.rs | 0 src/test/ui/{ => issues}/issue-44239.stderr | 0 src/test/ui/{ => issues}/issue-44373.rs | 0 src/test/ui/{ => issues}/issue-44373.stderr | 0 src/test/ui/{ => issues}/issue-44406.rs | 0 src/test/ui/{ => issues}/issue-44406.stderr | 0 src/test/ui/{ => issues}/issue-44415.rs | 2 +- src/test/ui/{ => issues}/issue-44415.stderr | 0 .../issue-45087-unreachable-unsafe.rs | 0 .../issue-45087-unreachable-unsafe.stderr | 0 ...sue-45107-unnecessary-unsafe-in-closure.rs | 0 ...45107-unnecessary-unsafe-in-closure.stderr | 0 src/test/ui/{ => issues}/issue-45157.rs | 0 src/test/ui/{ => issues}/issue-45157.stderr | 0 src/test/ui/{ => issues}/issue-4517.rs | 0 src/test/ui/{ => issues}/issue-4517.stderr | 0 src/test/ui/issues/issue-45199.ast.nll.stderr | 36 + .../ui/{ => issues}/issue-45199.ast.stderr | 8 +- src/test/ui/issues/issue-45199.mir.stderr | 36 + src/test/ui/{ => issues}/issue-45199.rs | 9 +- src/test/ui/{ => issues}/issue-45296.rs | 0 src/test/ui/{ => issues}/issue-45296.stderr | 0 src/test/ui/{ => issues}/issue-45562.fixed | 0 src/test/ui/{ => issues}/issue-45562.rs | 0 src/test/ui/{ => issues}/issue-45562.stderr | 0 .../issue-45696-long-live-borrows-in-boxes.rs | 133 + .../issue-45696-no-variant-box-recur.rs | 66 + ...-45696-scribble-on-boxed-borrow.ast.stderr | 14 + ...96-scribble-on-boxed-borrow.migrate.stderr | 69 + ...-45696-scribble-on-boxed-borrow.nll.stderr | 48 + .../issue-45696-scribble-on-boxed-borrow.rs | 110 + src/test/ui/{ => issues}/issue-45697-1.rs | 0 src/test/ui/{ => issues}/issue-45697-1.stderr | 0 src/test/ui/{ => issues}/issue-45697.rs | 0 src/test/ui/{ => issues}/issue-45697.stderr | 0 .../issue-45729-unsafe-in-generator.rs | 0 .../issue-45729-unsafe-in-generator.stderr | 0 src/test/ui/{ => issues}/issue-45730.rs | 0 src/test/ui/{ => issues}/issue-45730.stderr | 0 ...n-crate-rename-suggestion-formatting.fixed | 0 ...tern-crate-rename-suggestion-formatting.rs | 0 ...-crate-rename-suggestion-formatting.stderr | 0 src/test/ui/{ => issues}/issue-45801.rs | 0 src/test/ui/{ => issues}/issue-45801.stderr | 0 src/test/ui/{ => issues}/issue-45965.rs | 0 src/test/ui/{ => issues}/issue-45965.stderr | 0 .../{ => issues}/issue-46023.ast.nll.stderr | 0 .../ui/{ => issues}/issue-46023.ast.stderr | 0 .../ui/{ => issues}/issue-46023.mir.stderr | 0 src/test/ui/{ => issues}/issue-46023.rs | 0 src/test/ui/{ => issues}/issue-46036.rs | 0 src/test/ui/{ => issues}/issue-46036.stderr | 0 src/test/ui/{ => issues}/issue-46112.rs | 0 src/test/ui/{ => issues}/issue-46112.stderr | 0 src/test/ui/{ => issues}/issue-46186.rs | 0 src/test/ui/{ => issues}/issue-46186.stderr | 0 src/test/ui/{ => issues}/issue-46302.rs | 0 src/test/ui/{ => issues}/issue-46302.stderr | 0 src/test/ui/{ => issues}/issue-46311.rs | 0 src/test/ui/{ => issues}/issue-46311.stderr | 0 src/test/ui/{ => issues}/issue-46332.rs | 0 src/test/ui/{ => issues}/issue-46332.stderr | 0 src/test/ui/{ => issues}/issue-46438.rs | 0 src/test/ui/{ => issues}/issue-46438.stderr | 0 src/test/ui/{ => issues}/issue-46471-1.rs | 0 src/test/ui/issues/issue-46471-1.stderr | 25 + src/test/ui/{ => issues}/issue-46471.rs | 0 src/test/ui/{ => issues}/issue-46471.stderr | 0 src/test/ui/{ => issues}/issue-46472.rs | 0 src/test/ui/{ => issues}/issue-46472.stderr | 0 src/test/ui/{ => issues}/issue-46576.rs | 0 src/test/ui/{ => issues}/issue-46576.stderr | 0 .../{ => issues}/issue-46604.ast.nll.stderr | 0 .../ui/{ => issues}/issue-46604.ast.stderr | 0 .../ui/{ => issues}/issue-46604.mir.stderr | 0 src/test/ui/{ => issues}/issue-46604.rs | 0 ...6-consider-borrowing-cast-or-binexpr.fixed | 0 ...6756-consider-borrowing-cast-or-binexpr.rs | 0 ...-consider-borrowing-cast-or-binexpr.stderr | 0 src/test/ui/{ => issues}/issue-46771.rs | 0 src/test/ui/{ => issues}/issue-46771.stderr | 0 src/test/ui/{ => issues}/issue-46843.rs | 0 src/test/ui/{ => issues}/issue-46843.stderr | 0 src/test/ui/{ => issues}/issue-46983.rs | 0 src/test/ui/{ => issues}/issue-46983.stderr | 2 +- ...-47073-zero-padded-tuple-struct-indices.rs | 0 ...73-zero-padded-tuple-struct-indices.stderr | 0 src/test/ui/{ => issues}/issue-47094.rs | 0 src/test/ui/{ => issues}/issue-47094.stderr | 0 src/test/ui/{ => issues}/issue-47184.rs | 0 src/test/ui/{ => issues}/issue-47184.stderr | 0 src/test/ui/{ => issues}/issue-47309.rs | 0 src/test/ui/{ => issues}/issue-4736.rs | 0 src/test/ui/{ => issues}/issue-4736.stderr | 0 src/test/ui/{ => issues}/issue-47377.rs | 0 src/test/ui/{ => issues}/issue-47377.stderr | 0 src/test/ui/{ => issues}/issue-47380.rs | 0 src/test/ui/{ => issues}/issue-47380.stderr | 0 src/test/ui/{ => issues}/issue-47412.rs | 0 src/test/ui/{ => issues}/issue-47412.stderr | 0 src/test/ui/{ => issues}/issue-47511.rs | 0 src/test/ui/{ => issues}/issue-47511.stderr | 0 src/test/ui/{ => issues}/issue-47623.rs | 0 src/test/ui/{ => issues}/issue-47623.stderr | 0 src/test/ui/{ => issues}/issue-47646.rs | 0 src/test/ui/{ => issues}/issue-47646.stderr | 0 src/test/ui/{ => issues}/issue-47706-trait.rs | 0 .../ui/{ => issues}/issue-47706-trait.stderr | 0 src/test/ui/{ => issues}/issue-47706.rs | 0 src/test/ui/{ => issues}/issue-47706.stderr | 0 src/test/ui/{ => issues}/issue-47715.rs | 0 src/test/ui/{ => issues}/issue-47715.stderr | 0 src/test/ui/{ => issues}/issue-48131.rs | 0 src/test/ui/{ => issues}/issue-48131.stderr | 0 src/test/ui/{ => issues}/issue-48132.rs | 0 src/test/ui/{ => issues}/issue-48179.rs | 0 src/test/ui/{ => issues}/issue-48276.rs | 0 src/test/ui/{ => issues}/issue-48276.stderr | 0 src/test/ui/{ => issues}/issue-48364.rs | 0 src/test/ui/{ => issues}/issue-48364.stderr | 0 src/test/ui/{ => issues}/issue-48636.fixed | 0 src/test/ui/{ => issues}/issue-48636.rs | 0 src/test/ui/{ => issues}/issue-48636.stderr | 0 src/test/ui/{ => issues}/issue-48728.rs | 0 src/test/ui/{ => issues}/issue-48728.stderr | 0 src/test/ui/{ => issues}/issue-48803.rs | 0 src/test/ui/{ => issues}/issue-48803.stderr | 0 src/test/ui/{ => issues}/issue-48838.rs | 0 src/test/ui/{ => issues}/issue-48838.stderr | 0 src/test/ui/{ => issues}/issue-49040.rs | 0 src/test/ui/{ => issues}/issue-49040.stderr | 0 src/test/ui/{ => issues}/issue-49074.rs | 1 - src/test/ui/issues/issue-49074.stderr | 11 + src/test/ui/{ => issues}/issue-49257.rs | 0 src/test/ui/{ => issues}/issue-49257.stderr | 0 src/test/ui/{ => issues}/issue-4935.rs | 0 src/test/ui/{ => issues}/issue-4935.stderr | 0 src/test/ui/issues/issue-49579.rs | 27 + src/test/ui/{ => issues}/issue-4968.rs | 0 src/test/ui/{ => issues}/issue-4968.stderr | 0 src/test/ui/{ => issues}/issue-4972.rs | 0 src/test/ui/{ => issues}/issue-4972.stderr | 0 src/test/ui/issues/issue-49824.nll.stderr | 17 + src/test/ui/issues/issue-49824.rs | 26 + src/test/ui/issues/issue-49824.stderr | 14 + .../issue-49851/compiler-builtins-error.rs | 0 .../compiler-builtins-error.stderr | 0 src/test/ui/{ => issues}/issue-49934.rs | 0 src/test/ui/{ => issues}/issue-49934.stderr | 0 src/test/ui/{ => issues}/issue-50187.rs | 2 +- .../option_deref.rs | 16 + .../option_deref.stderr | 12 + .../result_deref.rs | 16 + .../result_deref.stderr | 12 + .../result_deref_err.rs | 16 + .../result_deref_err.stderr | 13 + .../result_deref_ok.rs | 16 + .../result_deref_ok.stderr | 12 + src/test/ui/{ => issues}/issue-50403.rs | 0 src/test/ui/{ => issues}/issue-50403.stderr | 0 src/test/ui/{ => issues}/issue-50471.rs | 0 src/test/ui/{ => issues}/issue-50480.rs | 0 src/test/ui/{ => issues}/issue-50480.stderr | 0 src/test/ui/{ => issues}/issue-50576.rs | 0 src/test/ui/{ => issues}/issue-50576.stderr | 0 src/test/ui/{ => issues}/issue-50577.rs | 0 src/test/ui/{ => issues}/issue-50577.stderr | 0 src/test/ui/{ => issues}/issue-50581.rs | 0 src/test/ui/{ => issues}/issue-50581.stderr | 0 src/test/ui/{ => issues}/issue-50585.rs | 0 src/test/ui/{ => issues}/issue-50585.stderr | 0 src/test/ui/{ => issues}/issue-50599.rs | 0 src/test/ui/{ => issues}/issue-50599.stderr | 0 src/test/ui/{ => issues}/issue-50600.rs | 0 src/test/ui/{ => issues}/issue-50600.stderr | 0 src/test/ui/{ => issues}/issue-50618.rs | 0 src/test/ui/{ => issues}/issue-50618.stderr | 0 src/test/ui/{ => issues}/issue-5062.rs | 0 src/test/ui/{ => issues}/issue-5062.stderr | 0 src/test/ui/{ => issues}/issue-5067.rs | 0 src/test/ui/{ => issues}/issue-5067.stderr | 0 src/test/ui/{ => issues}/issue-50688.rs | 0 src/test/ui/{ => issues}/issue-50688.stderr | 0 src/test/ui/{ => issues}/issue-50714-1.rs | 0 src/test/ui/{ => issues}/issue-50714-1.stderr | 0 src/test/ui/{ => issues}/issue-50714.rs | 0 src/test/ui/{ => issues}/issue-50714.stderr | 0 src/test/ui/{ => issues}/issue-50761.rs | 2 +- src/test/ui/{ => issues}/issue-50781.rs | 0 src/test/ui/{ => issues}/issue-50781.stderr | 0 src/test/ui/{ => issues}/issue-50802.rs | 0 src/test/ui/{ => issues}/issue-50802.stderr | 0 src/test/ui/{ => issues}/issue-50825-1.rs | 0 src/test/ui/{ => issues}/issue-50825.rs | 0 src/test/ui/{ => issues}/issue-5099.rs | 0 src/test/ui/{ => issues}/issue-5099.stderr | 0 src/test/ui/{ => issues}/issue-50993.rs | 0 src/test/ui/{ => issues}/issue-50993.stderr | 0 src/test/ui/{ => issues}/issue-5100.rs | 0 src/test/ui/{ => issues}/issue-5100.stderr | 0 src/test/ui/{ => issues}/issue-51022.rs | 0 src/test/ui/{ => issues}/issue-51022.stderr | 0 src/test/ui/{ => issues}/issue-51044.rs | 0 src/test/ui/{ => issues}/issue-51102.rs | 0 src/test/ui/{ => issues}/issue-51102.stderr | 0 src/test/ui/{ => issues}/issue-51116.rs | 0 src/test/ui/{ => issues}/issue-51116.stderr | 0 .../ui/{ => issues}/issue-51244.nll.stderr | 0 src/test/ui/{ => issues}/issue-51244.rs | 0 src/test/ui/{ => issues}/issue-51244.stderr | 0 src/test/ui/{ => issues}/issue-51279.rs | 0 src/test/ui/{ => issues}/issue-51279.stderr | 0 src/test/ui/{ => issues}/issue-51515.rs | 0 src/test/ui/{ => issues}/issue-51515.stderr | 0 src/test/ui/{ => issues}/issue-5153.rs | 0 src/test/ui/{ => issues}/issue-5153.stderr | 0 ...51632-try-desugar-incompatible-types.fixed | 0 ...ue-51632-try-desugar-incompatible-types.rs | 0 ...1632-try-desugar-incompatible-types.stderr | 0 src/test/ui/{ => issues}/issue-51714.rs | 0 src/test/ui/{ => issues}/issue-51714.stderr | 0 src/test/ui/{ => issues}/issue-51848.rs | 0 src/test/ui/{ => issues}/issue-51848.stderr | 0 src/test/ui/{ => issues}/issue-51874.rs | 0 src/test/ui/{ => issues}/issue-51874.stderr | 0 .../issue-52023-array-size-pointer-cast.rs | 2 +- ...issue-52023-array-size-pointer-cast.stderr | 11 + .../ui/{ => issues}/issue-52049.nll.stderr | 0 src/test/ui/{ => issues}/issue-52049.rs | 0 src/test/ui/{ => issues}/issue-52049.stderr | 0 src/test/ui/{ => issues}/issue-52057.rs | 0 src/test/ui/issues/issue-52060.rs | 8 + src/test/ui/issues/issue-52060.stderr | 17 + ...ssue-52126-assign-op-invariance.nll.stderr | 2 +- .../issue-52126-assign-op-invariance.rs | 0 .../issue-52126-assign-op-invariance.stderr | 0 src/test/ui/{ => issues}/issue-5216.rs | 0 src/test/ui/{ => issues}/issue-5216.stderr | 0 src/test/ui/issues/issue-52213.nll.stderr | 13 + src/test/ui/{ => issues}/issue-52213.rs | 0 src/test/ui/{ => issues}/issue-52213.stderr | 0 src/test/ui/{ => issues}/issue-5239-1.rs | 0 src/test/ui/issues/issue-5239-1.stderr | 15 + src/test/ui/issues/issue-52489.rs | 18 + src/test/ui/issues/issue-52489.stderr | 11 + src/test/ui/issues/issue-52533-1.nll.stderr | 11 + src/test/ui/{ => issues}/issue-52533-1.rs | 0 src/test/ui/{ => issues}/issue-52533-1.stderr | 0 src/test/ui/issues/issue-52533.nll.stderr | 11 + src/test/ui/{ => issues}/issue-52533.rs | 0 src/test/ui/{ => issues}/issue-52533.stderr | 0 src/test/ui/issues/issue-53348.rs | 26 + src/test/ui/issues/issue-53348.stderr | 12 + src/test/ui/{ => issues}/issue-5358-1.rs | 0 src/test/ui/{ => issues}/issue-5358-1.stderr | 0 src/test/ui/{ => issues}/issue-5439.rs | 0 src/test/ui/{ => issues}/issue-5439.stderr | 0 src/test/ui/issues/issue-5500-1.ast.stderr | 15 + src/test/ui/issues/issue-5500-1.mir.stderr | 15 + .../issues}/issue-5500-1.rs | 1 + .../{compile-fail => ui/issues}/issue-5844.rs | 0 src/test/ui/issues/issue-5844.stderr | 11 + src/test/ui/{ => issues}/issue-5883.rs | 0 src/test/ui/{ => issues}/issue-5883.stderr | 5 +- src/test/ui/{ => issues}/issue-5927.rs | 0 src/test/ui/{ => issues}/issue-5927.stderr | 0 src/test/ui/{ => issues}/issue-5997-enum.rs | 0 .../ui/{ => issues}/issue-5997-enum.stderr | 0 src/test/ui/{ => issues}/issue-5997-struct.rs | 0 .../ui/{ => issues}/issue-5997-struct.stderr | 0 src/test/ui/{ => issues}/issue-6458-2.rs | 0 src/test/ui/{ => issues}/issue-6458-2.stderr | 0 src/test/ui/{ => issues}/issue-6458-3.rs | 0 src/test/ui/{ => issues}/issue-6458-3.stderr | 0 src/test/ui/{ => issues}/issue-6458-4.rs | 0 src/test/ui/{ => issues}/issue-6458-4.stderr | 0 src/test/ui/{ => issues}/issue-6458.rs | 0 src/test/ui/{ => issues}/issue-6458.stderr | 0 src/test/ui/{ => issues}/issue-6596-1.rs | 0 src/test/ui/{ => issues}/issue-6596-1.stderr | 0 src/test/ui/{ => issues}/issue-6596-2.rs | 0 src/test/ui/{ => issues}/issue-6596-2.stderr | 0 src/test/ui/{ => issues}/issue-6642.rs | 0 src/test/ui/{ => issues}/issue-6642.stderr | 0 src/test/ui/{ => issues}/issue-6738.rs | 0 src/test/ui/{ => issues}/issue-6738.stderr | 0 .../ui/{ => issues}/issue-6801.nll.stderr | 4 +- src/test/ui/{ => issues}/issue-6801.rs | 0 src/test/ui/{ => issues}/issue-6801.stderr | 0 src/test/ui/{ => issues}/issue-6804.rs | 0 src/test/ui/{ => issues}/issue-6804.stderr | 0 src/test/ui/{ => issues}/issue-6936.rs | 0 src/test/ui/{ => issues}/issue-6936.stderr | 0 src/test/ui/{ => issues}/issue-7013.rs | 0 src/test/ui/{ => issues}/issue-7013.stderr | 0 src/test/ui/{ => issues}/issue-7044.rs | 0 src/test/ui/{ => issues}/issue-7044.stderr | 0 src/test/ui/{ => issues}/issue-7061.rs | 0 src/test/ui/{ => issues}/issue-7061.stderr | 0 src/test/ui/{ => issues}/issue-7092.rs | 0 src/test/ui/{ => issues}/issue-7092.stderr | 0 src/test/ui/{ => issues}/issue-7246.rs | 0 src/test/ui/{ => issues}/issue-7246.stderr | 0 src/test/ui/{ => issues}/issue-7364.rs | 0 src/test/ui/{ => issues}/issue-7364.stderr | 0 src/test/ui/{ => issues}/issue-7607-1.rs | 0 src/test/ui/{ => issues}/issue-7607-1.stderr | 0 src/test/ui/{ => issues}/issue-7813.rs | 0 src/test/ui/{ => issues}/issue-7813.stderr | 0 src/test/ui/{ => issues}/issue-7867.rs | 0 src/test/ui/{ => issues}/issue-7867.stderr | 0 src/test/ui/{ => issues}/issue-7950.rs | 0 src/test/ui/{ => issues}/issue-7950.stderr | 0 src/test/ui/{ => issues}/issue-7970a.rs | 0 src/test/ui/{ => issues}/issue-7970a.stderr | 0 src/test/ui/{ => issues}/issue-7970b.rs | 0 src/test/ui/{ => issues}/issue-7970b.stderr | 0 src/test/ui/{ => issues}/issue-8153.rs | 0 src/test/ui/{ => issues}/issue-8153.stderr | 0 src/test/ui/{ => issues}/issue-8208.rs | 0 src/test/ui/{ => issues}/issue-8208.stderr | 0 src/test/ui/{ => issues}/issue-8460-const.rs | 0 .../ui/{ => issues}/issue-8460-const.stderr | 0 src/test/ui/{ => issues}/issue-8640.rs | 0 src/test/ui/{ => issues}/issue-8640.stderr | 0 src/test/ui/{ => issues}/issue-8727.rs | 2 +- src/test/ui/{ => issues}/issue-8727.stderr | 4 +- src/test/ui/{ => issues}/issue-8761.rs | 0 src/test/ui/{ => issues}/issue-8761.stderr | 0 src/test/ui/{ => issues}/issue-8767.rs | 0 src/test/ui/{ => issues}/issue-8767.stderr | 0 src/test/ui/{ => issues}/issue-9575.rs | 0 src/test/ui/{ => issues}/issue-9575.stderr | 0 src/test/ui/{ => issues}/issue-9725.rs | 0 src/test/ui/{ => issues}/issue-9725.stderr | 0 src/test/ui/{ => issues}/issue-9814.rs | 0 src/test/ui/{ => issues}/issue-9814.stderr | 0 src/test/ui/{ => issues}/issue-pr29383.rs | 0 src/test/ui/{ => issues}/issue-pr29383.stderr | 0 .../{compile-fail => ui/issues}/issue32829.rs | 0 src/test/ui/issues/issue32829.stderr | 94 + .../keyword}/keyword-extern-as-identifier.rs | 2 +- .../keyword-extern-as-identifier.stderr | 9 + .../keyword}/keyword-false-as-identifier.rs | 0 .../keyword-false-as-identifier.stderr | 12 + .../keyword}/keyword-self-as-identifier.rs | 1 + .../keyword/keyword-self-as-identifier.stderr | 18 + .../keyword}/keyword-super-as-identifier.rs | 0 .../keyword-super-as-identifier.stderr | 9 + .../keyword}/keyword-super.rs | 0 src/test/ui/keyword/keyword-super.stderr | 9 + .../keyword}/keyword-true-as-identifier.rs | 0 .../keyword/keyword-true-as-identifier.stderr | 12 + .../kindck}/kindck-copy.rs | 0 src/test/ui/kindck/kindck-copy.stderr | 139 + .../kindck}/kindck-impl-type-params-2.rs | 0 .../kindck/kindck-impl-type-params-2.stderr | 16 + .../kindck/kindck-impl-type-params.nll.stderr | 63 + .../kindck}/kindck-impl-type-params.rs | 0 .../ui/kindck/kindck-impl-type-params.stderr | 72 + .../kindck}/kindck-inherited-copy-bound.rs | 0 .../kindck/kindck-inherited-copy-bound.stderr | 34 + .../kindck}/kindck-nonsendable-1.rs | 0 .../ui/kindck/kindck-nonsendable-1.stderr | 17 + .../kindck}/kindck-send-object.rs | 0 src/test/ui/kindck/kindck-send-object.stderr | 32 + .../ui/kindck/kindck-send-object1.nll.stderr | 32 + .../kindck}/kindck-send-object1.rs | 0 src/test/ui/kindck/kindck-send-object1.stderr | 41 + .../kindck}/kindck-send-object2.rs | 0 src/test/ui/kindck/kindck-send-object2.stderr | 32 + .../kindck}/kindck-send-owned.rs | 0 src/test/ui/kindck/kindck-send-owned.stderr | 18 + .../kindck}/kindck-send-unsafe.rs | 0 .../kindck-send-unsafe.rs~rust-lang_master | 0 src/test/ui/kindck/kindck-send-unsafe.stderr | 16 + .../label}/label-static.rs | 0 src/test/ui/label/label-static.stderr | 14 + .../label}/label-underscore.rs | 0 src/test/ui/label/label-underscore.stderr | 14 + .../{ => label}/label_break_value_continue.rs | 0 .../label_break_value_continue.stderr | 0 .../label_break_value_illegal_uses.rs | 2 +- .../label_break_value_illegal_uses.stderr | 0 .../label_break_value_unlabeled_break.rs | 0 .../label_break_value_unlabeled_break.stderr | 0 .../{compile-fail => ui}/lang-item-missing.rs | 0 src/test/ui/lang-item-missing.stderr | 4 + .../{compile-fail => ui}/lexical-scopes.rs | 0 src/test/ui/lexical-scopes.stderr | 20 + ...701_one_named_and_one_anonymous.nll.stderr | 22 - ...ting-name-early-bound-in-struct.nll.stderr | 17 - ...urn-one-existing-name-if-else-2.nll.stderr | 17 - ...urn-one-existing-name-if-else-3.nll.stderr | 18 - ...sting-name-if-else-using-impl-2.nll.stderr | 17 - ...sting-name-if-else-using-impl-3.nll.stderr | 18 - ...xisting-name-if-else-using-impl.nll.stderr | 20 - ...eturn-one-existing-name-if-else.nll.stderr | 17 - ...isting-name-return-type-is-anon.nll.stderr | 20 - ...-one-existing-name-self-is-anon.nll.stderr | 20 - .../ex2a-push-one-existing-name-2.nll.stderr | 17 - ...h-one-existing-name-early-bound.nll.stderr | 17 - .../ex2a-push-one-existing-name.nll.stderr | 17 - .../ex2a-push-one-existing-name.stderr | 11 - .../ex2b-push-no-existing-names.nll.stderr | 17 - .../ex2c-push-inference-variable.nll.stderr | 18 - .../ex2d-push-inference-variable-2.nll.stderr | 18 - .../ex2e-push-inference-variable-3.nll.stderr | 18 - .../ex3-both-anon-regions-2.nll.stderr | 17 - .../ex3-both-anon-regions-3.nll.stderr | 31 - ...anon-regions-both-are-structs-2.nll.stderr | 17 - ...anon-regions-both-are-structs-3.nll.stderr | 19 - ...anon-regions-both-are-structs-4.nll.stderr | 19 - ...-are-structs-earlybound-regions.nll.stderr | 18 - ...h-are-structs-latebound-regions.nll.stderr | 17 - ...h-anon-regions-both-are-structs.nll.stderr | 17 - ...-anon-regions-latebound-regions.nll.stderr | 17 - ...th-anon-regions-one-is-struct-2.nll.stderr | 28 - ...th-anon-regions-one-is-struct-3.nll.stderr | 17 - ...th-anon-regions-one-is-struct-4.nll.stderr | 17 - ...both-anon-regions-one-is-struct.nll.stderr | 17 - ...non-regions-return-type-is-anon.nll.stderr | 19 - ...-both-anon-regions-self-is-anon.nll.stderr | 19 - ...oth-anon-regions-using-fn-items.nll.stderr | 26 - ...h-anon-regions-using-impl-items.nll.stderr | 17 - ...non-regions-using-trait-objects.nll.stderr | 26 - .../ex3-both-anon-regions.nll.stderr | 17 - .../lifetime_bound_will_change_warning_lib.rs | 0 .../borrowck-let-suggestion.nll.stderr | 1 + ...etime-bound-will-change-warning.nll.stderr | 20 + .../lifetime-bound-will-change-warning.rs | 0 .../lifetime-bound-will-change-warning.stderr | 33 + .../lifetime-doesnt-live-long-enough.rs | 2 +- .../lifetime-doesnt-live-long-enough.stderr | 16 +- ...-return-type-requires-explicit-lifetime.rs | 0 ...urn-type-requires-explicit-lifetime.stderr | 0 .../42701_one_named_and_one_anonymous.rs | 0 .../42701_one_named_and_one_anonymous.stderr | 2 +- ...one-existing-name-early-bound-in-struct.rs | 0 ...existing-name-early-bound-in-struct.stderr | 2 +- .../ex1-return-one-existing-name-if-else-2.rs | 0 ...-return-one-existing-name-if-else-2.stderr | 2 +- .../ex1-return-one-existing-name-if-else-3.rs | 0 ...-return-one-existing-name-if-else-3.stderr | 2 +- ...-one-existing-name-if-else-using-impl-2.rs | 0 ...-existing-name-if-else-using-impl-2.stderr | 2 +- ...-one-existing-name-if-else-using-impl-3.rs | 0 ...-existing-name-if-else-using-impl-3.stderr | 2 +- ...xisting-name-if-else-using-impl.nll.stderr | 13 + ...rn-one-existing-name-if-else-using-impl.rs | 0 ...ne-existing-name-if-else-using-impl.stderr | 0 .../ex1-return-one-existing-name-if-else.rs | 0 ...x1-return-one-existing-name-if-else.stderr | 2 +- ...isting-name-return-type-is-anon.nll.stderr | 13 + ...n-one-existing-name-return-type-is-anon.rs | 0 ...e-existing-name-return-type-is-anon.stderr | 0 ...-one-existing-name-self-is-anon.nll.stderr | 13 + ...1-return-one-existing-name-self-is-anon.rs | 0 ...turn-one-existing-name-self-is-anon.stderr | 0 .../ex1b-return-no-names-if-else.rs | 0 .../ex1b-return-no-names-if-else.stderr | 0 .../ex2a-push-one-existing-name-2.nll.stderr | 11 + .../ex2a-push-one-existing-name-2.rs | 0 .../ex2a-push-one-existing-name-2.stderr | 2 +- ...h-one-existing-name-early-bound.nll.stderr | 12 + ...ex2a-push-one-existing-name-early-bound.rs | 1 - ...-push-one-existing-name-early-bound.stderr | 2 +- .../ex2a-push-one-existing-name.nll.stderr | 11 + .../ex2a-push-one-existing-name.rs | 0 .../ex2a-push-one-existing-name.stderr | 11 + .../ex2b-push-no-existing-names.nll.stderr | 12 + .../ex2b-push-no-existing-names.rs | 0 .../ex2b-push-no-existing-names.stderr | 0 .../ex2c-push-inference-variable.nll.stderr | 13 + .../ex2c-push-inference-variable.rs | 0 .../ex2c-push-inference-variable.stderr | 0 .../ex2d-push-inference-variable-2.nll.stderr | 13 + .../ex2d-push-inference-variable-2.rs | 0 .../ex2d-push-inference-variable-2.stderr | 0 .../ex2e-push-inference-variable-3.nll.stderr | 13 + .../ex2e-push-inference-variable-3.rs | 0 .../ex2e-push-inference-variable-3.stderr | 0 .../ex3-both-anon-regions-2.nll.stderr | 12 + .../ex3-both-anon-regions-2.rs | 0 .../ex3-both-anon-regions-2.stderr | 0 .../ex3-both-anon-regions-3.nll.stderr | 22 + .../ex3-both-anon-regions-3.rs | 0 .../ex3-both-anon-regions-3.stderr | 0 ...anon-regions-both-are-structs-2.nll.stderr | 12 + ...x3-both-anon-regions-both-are-structs-2.rs | 0 ...oth-anon-regions-both-are-structs-2.stderr | 0 ...anon-regions-both-are-structs-3.nll.stderr | 13 + ...x3-both-anon-regions-both-are-structs-3.rs | 0 ...oth-anon-regions-both-are-structs-3.stderr | 0 ...anon-regions-both-are-structs-4.nll.stderr | 13 + ...x3-both-anon-regions-both-are-structs-4.rs | 0 ...oth-anon-regions-both-are-structs-4.stderr | 0 ...-are-structs-earlybound-regions.nll.stderr | 13 + ...ons-both-are-structs-earlybound-regions.rs | 0 ...both-are-structs-earlybound-regions.stderr | 0 ...h-are-structs-latebound-regions.nll.stderr | 12 + ...ions-both-are-structs-latebound-regions.rs | 0 ...-both-are-structs-latebound-regions.stderr | 0 ...h-anon-regions-both-are-structs.nll.stderr | 12 + .../ex3-both-anon-regions-both-are-structs.rs | 0 ...-both-anon-regions-both-are-structs.stderr | 0 ...-anon-regions-latebound-regions.nll.stderr | 12 + ...ex3-both-anon-regions-latebound-regions.rs | 0 ...both-anon-regions-latebound-regions.stderr | 0 ...th-anon-regions-one-is-struct-2.nll.stderr | 21 + .../ex3-both-anon-regions-one-is-struct-2.rs | 0 ...3-both-anon-regions-one-is-struct-2.stderr | 0 ...th-anon-regions-one-is-struct-3.nll.stderr | 12 + .../ex3-both-anon-regions-one-is-struct-3.rs | 0 ...3-both-anon-regions-one-is-struct-3.stderr | 0 ...th-anon-regions-one-is-struct-4.nll.stderr | 12 + .../ex3-both-anon-regions-one-is-struct-4.rs | 0 ...3-both-anon-regions-one-is-struct-4.stderr | 0 ...both-anon-regions-one-is-struct.nll.stderr | 12 + .../ex3-both-anon-regions-one-is-struct.rs | 0 ...ex3-both-anon-regions-one-is-struct.stderr | 0 ...non-regions-return-type-is-anon.nll.stderr | 12 + ...3-both-anon-regions-return-type-is-anon.rs | 0 ...th-anon-regions-return-type-is-anon.stderr | 0 ...-both-anon-regions-self-is-anon.nll.stderr | 12 + .../ex3-both-anon-regions-self-is-anon.rs | 0 .../ex3-both-anon-regions-self-is-anon.stderr | 0 ...oth-anon-regions-using-fn-items.nll.stderr | 21 + .../ex3-both-anon-regions-using-fn-items.rs | 0 ...x3-both-anon-regions-using-fn-items.stderr | 0 ...h-anon-regions-using-impl-items.nll.stderr | 12 + .../ex3-both-anon-regions-using-impl-items.rs | 0 ...-both-anon-regions-using-impl-items.stderr | 0 ...non-regions-using-trait-objects.nll.stderr | 21 + ...3-both-anon-regions-using-trait-objects.rs | 0 ...th-anon-regions-using-trait-objects.stderr | 0 .../ex3-both-anon-regions.nll.stderr | 12 + .../lifetime-errors/ex3-both-anon-regions.rs | 0 .../ex3-both-anon-regions.stderr | 0 .../liveness-assign-imm-local-notes.rs | 4 +- .../liveness-assign-imm-local-notes.stderr | 8 +- .../lifetimes}/lifetime-no-keyword.rs | 0 .../ui/lifetimes/lifetime-no-keyword.stderr | 26 + src/test/{compile-fail => ui}/linkage2.rs | 0 src/test/ui/linkage2.stderr | 8 + src/test/{compile-fail => ui}/linkage3.rs | 0 src/test/ui/linkage3.stderr | 8 + src/test/{compile-fail => ui}/linkage4.rs | 0 src/test/ui/linkage4.stderr | 11 + src/test/ui/lint-anon-param-edition.fixed | 23 - src/test/ui/lint-anon-param-edition.rs | 23 - src/test/ui/lint-anon-param-edition.stderr | 10 - .../ui/lint-unconditional-recursion.stderr | 157 - .../lint}/auxiliary/inherited_stability.rs | 10 +- .../ui/lint/auxiliary/lint_output_format.rs | 30 + src/test/ui/lint/auxiliary/lint_stability.rs | 198 + .../lint/auxiliary/lint_stability_fields.rs | 61 + .../auxiliary/lint_unused_extern_crate.rs | 0 .../auxiliary/lint_unused_extern_crate2.rs | 0 .../auxiliary/lint_unused_extern_crate3.rs | 0 .../auxiliary/lint_unused_extern_crate4.rs | 0 .../auxiliary/lint_unused_extern_crate5.rs | 0 .../lint}/auxiliary/stability_cfg1.rs | 0 src/test/ui/lint/auxiliary/stability_cfg2.rs | 15 + .../lint}/lint-attr-non-item-node.rs | 0 .../ui/lint/lint-attr-non-item-node.stderr | 14 + .../lint}/lint-change-warnings.rs | 0 src/test/ui/lint/lint-change-warnings.stderr | 36 + .../lint}/lint-ctypes-enum.rs | 0 src/test/ui/lint/lint-ctypes-enum.stderr | 46 + src/test/ui/{ => lint}/lint-ctypes.rs | 9 + src/test/ui/{ => lint}/lint-ctypes.stderr | 46 +- .../lint}/lint-dead-code-1.rs | 4 +- src/test/ui/lint/lint-dead-code-1.stderr | 62 + .../lint}/lint-dead-code-2.rs | 0 src/test/ui/lint/lint-dead-code-2.stderr | 26 + .../lint}/lint-dead-code-3.rs | 2 +- src/test/ui/lint/lint-dead-code-3.stderr | 38 + .../lint}/lint-dead-code-4.rs | 0 src/test/ui/lint/lint-dead-code-4.stderr | 72 + .../lint}/lint-dead-code-5.rs | 0 src/test/ui/lint/lint-dead-code-5.stderr | 32 + .../lint}/lint-dead-code-type-alias.rs | 0 .../ui/lint/lint-dead-code-type-alias.stderr | 14 + .../lint}/lint-dead-code-variant.rs | 0 .../ui/lint/lint-dead-code-variant.stderr | 14 + ...int-directives-on-use-items-issue-10534.rs | 0 ...directives-on-use-items-issue-10534.stderr | 26 + .../lint}/lint-exceeding-bitshifts.rs | 0 .../ui/lint/lint-exceeding-bitshifts.stderr | 116 + .../lint}/lint-exceeding-bitshifts2.rs | 0 .../ui/lint/lint-exceeding-bitshifts2.stderr | 26 + src/test/ui/{ => lint}/lint-forbid-attr.rs | 0 .../ui/{ => lint}/lint-forbid-attr.stderr | 0 .../lint}/lint-forbid-cmdline.rs | 0 src/test/ui/lint/lint-forbid-cmdline.stderr | 11 + src/test/ui/lint/lint-group-style.rs | 8 +- src/test/ui/lint/lint-group-style.stderr | 30 +- .../{compile-fail => ui/lint}/lint-impl-fn.rs | 0 src/test/ui/lint/lint-impl-fn.stderr | 38 + .../lint}/lint-malformed.rs | 0 src/test/ui/lint/lint-malformed.stderr | 15 + .../lint}/lint-misplaced-attr.rs | 0 src/test/ui/lint/lint-misplaced-attr.stderr | 32 + .../lint-missing-copy-implementations.rs | 0 .../lint-missing-copy-implementations.stderr | 16 + .../lint}/lint-missing-doc.rs | 0 src/test/ui/lint/lint-missing-doc.stderr | 122 + .../lint}/lint-non-camel-case-types.rs | 0 .../ui/lint/lint-non-camel-case-types.stderr | 88 + .../lint}/lint-non-snake-case-crate-2.rs | 0 .../lint/lint-non-snake-case-crate-2.stderr | 10 + .../lint}/lint-non-snake-case-crate.rs | 0 .../ui/lint/lint-non-snake-case-crate.stderr | 14 + .../lint}/lint-non-snake-case-functions.rs | 0 .../lint/lint-non-snake-case-functions.stderr | 62 + .../lint}/lint-non-snake-case-lifetimes.rs | 0 .../lint/lint-non-snake-case-lifetimes.stderr | 14 + .../lint}/lint-non-snake-case-modules.rs | 0 .../lint/lint-non-snake-case-modules.stderr | 16 + .../lint}/lint-non-uppercase-statics.rs | 0 .../ui/lint/lint-non-uppercase-statics.stderr | 20 + .../lint}/lint-obsolete-attr.rs | 0 src/test/ui/lint/lint-obsolete-attr.stderr | 20 + .../ui/{ => lint}/lint-output-format-2.rs | 5 +- .../ui/{ => lint}/lint-output-format-2.stderr | 6 +- .../lint}/lint-output-format.rs | 0 src/test/ui/lint/lint-output-format.stderr | 27 + .../lint}/lint-owned-heap-memory.rs | 0 .../ui/lint/lint-owned-heap-memory.stderr | 20 + .../lint}/lint-qualification.rs | 0 src/test/ui/lint/lint-qualification.stderr | 14 + .../lint}/lint-removed-allow.rs | 0 src/test/ui/lint/lint-removed-allow.stderr | 14 + .../lint}/lint-removed-cmdline.rs | 0 src/test/ui/lint/lint-removed-cmdline.stderr | 19 + .../{compile-fail => ui/lint}/lint-removed.rs | 0 src/test/ui/lint/lint-removed.stderr | 22 + .../lint}/lint-renamed-allow.rs | 2 +- src/test/ui/lint/lint-renamed-allow.stderr | 15 + src/test/ui/lint/lint-renamed-cmdline.rs | 18 + src/test/ui/lint/lint-renamed-cmdline.stderr | 19 + .../{compile-fail => ui/lint}/lint-renamed.rs | 3 +- src/test/ui/lint/lint-renamed.stderr | 23 + .../lint}/lint-shorthand-field.rs | 2 +- src/test/ui/lint/lint-shorthand-field.stderr | 24 + .../lint}/lint-stability-2.rs | 68 +- src/test/ui/lint/lint-stability-2.stderr | 259 + .../lint}/lint-stability-deprecated.rs | 54 +- .../ui/lint/lint-stability-deprecated.stderr | 644 +++ .../lint}/lint-stability-fields-deprecated.rs | 25 +- .../lint-stability-fields-deprecated.stderr | 380 ++ .../lint}/lint-stability-fields.rs | 22 +- src/test/ui/lint/lint-stability-fields.stderr | 347 ++ .../lint}/lint-stability.rs | 62 +- src/test/ui/lint/lint-stability.stderr | 331 ++ .../lint}/lint-stability2.rs | 0 src/test/ui/lint/lint-stability2.stderr | 15 + .../lint}/lint-stability3.rs | 0 src/test/ui/lint/lint-stability3.stderr | 15 + .../lint}/lint-type-limits.rs | 0 src/test/ui/lint/lint-type-limits.stderr | 58 + .../lint}/lint-type-limits2.rs | 0 src/test/ui/lint/lint-type-limits2.stderr | 18 + .../lint}/lint-type-limits3.rs | 0 src/test/ui/lint/lint-type-limits3.stderr | 18 + .../lint}/lint-type-overflow.rs | 0 src/test/ui/lint/lint-type-overflow.stderr | 116 + .../lint}/lint-type-overflow2.rs | 0 src/test/ui/lint/lint-type-overflow2.stderr | 50 + .../lint-unconditional-recursion.rs | 28 +- .../lint/lint-unconditional-recursion.stderr | 157 + .../lint}/lint-unexported-no-mangle.rs | 0 .../ui/lint/lint-unexported-no-mangle.stderr | 43 + .../lint}/lint-unknown-attr.rs | 0 src/test/ui/lint/lint-unknown-attr.stderr | 26 + .../lint}/lint-unknown-feature-default.rs | 3 +- .../lint/lint-unknown-feature-default.stderr | 8 + .../lint}/lint-unknown-feature.rs | 3 +- src/test/ui/lint/lint-unknown-feature.stderr | 8 + .../lint}/lint-unknown-lint-cmdline.rs | 0 .../ui/lint/lint-unknown-lint-cmdline.stderr | 7 + .../lint}/lint-unknown-lint.rs | 0 src/test/ui/lint/lint-unknown-lint.stderr | 23 + .../lint}/lint-unnecessary-import-braces.rs | 0 .../lint-unnecessary-import-braces.stderr | 14 + .../lint}/lint-unnecessary-parens.rs | 0 .../ui/lint/lint-unnecessary-parens.stderr | 80 + .../lint}/lint-unsafe-code.rs | 0 src/test/ui/lint/lint-unsafe-code.stderr | 95 + .../lint}/lint-unused-extern-crate.rs | 2 +- .../ui/lint/lint-unused-extern-crate.stderr | 20 + .../lint}/lint-unused-imports.rs | 0 src/test/ui/lint/lint-unused-imports.stderr | 56 + .../lint}/lint-unused-mut-self.rs | 0 src/test/ui/lint/lint-unused-mut-self.stderr | 24 + .../lint-unused-mut-variables.lexical.stderr | 150 + .../lint/lint-unused-mut-variables.nll.stderr | 150 + .../lint}/lint-unused-mut-variables.rs | 0 .../lint}/lint-uppercase-variables.rs | 0 .../ui/lint/lint-uppercase-variables.stderr | 52 + src/test/ui/lint/outer-forbid.rs | 4 +- src/test/ui/lint/outer-forbid.stderr | 6 +- src/test/ui/lint/test-inner-fn.rs | 6 +- src/test/ui/lint/test-inner-fn.stderr | 10 +- src/test/ui/lint/unreachable_pub-pub_crate.rs | 2 +- src/test/ui/lint/unreachable_pub.rs | 2 +- .../lint/unused_parens_json_suggestion.stderr | 2 +- ...ss-assign-imm-local-in-loop.ast.nll.stderr | 12 + ...veness-assign-imm-local-in-loop.ast.stderr | 9 + ...veness-assign-imm-local-in-loop.mir.stderr | 12 + .../liveness-assign-imm-local-in-loop.rs | 3 +- ...s-assign-imm-local-in-op-eq.ast.nll.stderr | 15 + ...eness-assign-imm-local-in-op-eq.ast.stderr | 12 + ...eness-assign-imm-local-in-op-eq.mir.stderr | 15 + .../liveness-assign-imm-local-in-op-eq.rs | 3 +- ...-assign-imm-local-with-drop.ast.nll.stderr | 15 + ...ness-assign-imm-local-with-drop.ast.stderr | 12 + ...ness-assign-imm-local-with-drop.mir.stderr | 15 + .../liveness-assign-imm-local-with-drop.rs | 3 +- ...-assign-imm-local-with-init.ast.nll.stderr | 15 + ...ness-assign-imm-local-with-init.ast.stderr | 12 + ...ness-assign-imm-local-with-init.mir.stderr | 15 + .../liveness-assign-imm-local-with-init.rs | 3 +- .../liveness}/liveness-closure-require-ret.rs | 0 .../liveness-closure-require-ret.stderr | 12 + .../liveness}/liveness-dead.rs | 0 src/test/ui/liveness/liveness-dead.stderr | 32 + .../liveness}/liveness-forgot-ret.rs | 0 .../ui/liveness/liveness-forgot-ret.stderr | 12 + .../liveness}/liveness-issue-2163.rs | 0 .../ui/liveness/liveness-issue-2163.stderr | 15 + .../liveness}/liveness-missing-ret2.rs | 0 .../ui/liveness/liveness-missing-ret2.stderr | 17 + .../liveness}/liveness-move-call-arg.rs | 0 .../ui/liveness/liveness-move-call-arg.stderr | 11 + .../liveness}/liveness-move-in-loop.rs | 0 .../ui/liveness/liveness-move-in-loop.stderr | 11 + .../liveness-move-in-while.nll.stderr | 21 + .../liveness}/liveness-move-in-while.rs | 0 .../ui/liveness/liveness-move-in-while.stderr | 21 + .../liveness-return-last-stmt-semi.rs | 0 .../liveness-return-last-stmt-semi.stderr | 0 .../liveness}/liveness-unused.rs | 0 src/test/ui/liveness/liveness-unused.stderr | 111 + .../liveness-use-after-move.nll.stderr | 11 + .../liveness}/liveness-use-after-move.rs | 0 .../liveness/liveness-use-after-move.stderr | 13 + .../liveness-use-after-send.nll.stderr | 13 + .../liveness}/liveness-use-after-send.rs | 0 .../liveness/liveness-use-after-send.stderr | 13 + .../{ => loops}/loop-break-value-no-repeat.rs | 0 .../loop-break-value-no-repeat.stderr | 0 .../loops}/loop-break-value.rs | 0 src/test/ui/loops/loop-break-value.stderr | 156 + .../loops}/loop-labeled-break-value.rs | 0 .../ui/loops/loop-labeled-break-value.stderr | 30 + .../ui/loops/loop-proper-liveness.nll.stderr | 9 + .../loops}/loop-proper-liveness.rs | 0 src/test/ui/loops/loop-proper-liveness.stderr | 9 + .../loops}/loop-properly-diverging-2.rs | 0 .../ui/loops/loop-properly-diverging-2.stderr | 12 + .../loops-reject-duplicate-labels-2.rs | 0 .../loops-reject-duplicate-labels-2.stderr | 0 .../loops-reject-duplicate-labels.rs | 0 .../loops-reject-duplicate-labels.stderr | 0 ...loops-reject-labels-shadowing-lifetimes.rs | 0 ...s-reject-labels-shadowing-lifetimes.stderr | 0 .../loops-reject-lifetime-shadowing-label.rs | 0 ...ops-reject-lifetime-shadowing-label.stderr | 0 src/test/ui/lto-duplicate-symbols.rs | 20 + src/test/ui/lto-duplicate-symbols.stderr | 6 + src/test/ui/lub-if.nll.stderr | 20 + src/test/{compile-fail => ui}/lub-if.rs | 0 src/test/ui/lub-if.stderr | 29 + src/test/ui/lub-match.nll.stderr | 20 + src/test/{compile-fail => ui}/lub-match.rs | 0 src/test/ui/lub-match.stderr | 29 + src/test/ui/macro-shadowing.stderr | 24 - .../macros/auxiliary/macro-in-other-crate.rs | 24 + .../auxiliary/macro_crate_nonterminal.rs | 0 .../ui/{ => macros}/auxiliary/two_macros.rs | 0 .../ui/macros/auxiliary/unstable-macros.rs | 16 + src/test/ui/macros/format-foreign.rs | 2 + src/test/ui/macros/format-foreign.stderr | 21 +- .../ui/macros/format-unused-lables.stderr | 6 +- src/test/ui/macros/issue-30143.rs | 21 + src/test/ui/macros/issue-30143.stderr | 32 + ...ost-once-rep-2015-ques-rep-feature-flag.rs | 2 +- .../macro-at-most-once-rep-2015-ques-rep.rs | 2 +- .../macro-at-most-once-rep-2015-ques-sep.rs | 2 +- ...acro-at-most-once-rep-2018-feature-gate.rs | 2 +- .../ui/macros/macro-at-most-once-rep-2018.rs | 2 +- .../macros}/macro-attribute.rs | 4 +- src/test/ui/macros/macro-attribute.stderr | 8 + .../macros/macro-comma-behavior.core.stderr | 44 + .../macros}/macro-comma-behavior.rs | 0 .../ui/macros/macro-comma-behavior.std.stderr | 62 + .../macros}/macro-comma-support.rs | 0 src/test/ui/macros/macro-comma-support.stderr | 14 + src/test/ui/{ => macros}/macro-context.rs | 0 src/test/ui/{ => macros}/macro-context.stderr | 0 .../macro-crate-nonterminal-non-root.rs | 0 .../macro-crate-nonterminal-non-root.stderr | 9 + .../macros}/macro-error.rs | 0 src/test/ui/macros/macro-error.stderr | 14 + .../macros}/macro-expanded-include/file.txt | 0 .../macros}/macro-expanded-include/foo/mod.rs | 0 .../macros}/macro-expanded-include/test.rs | 0 .../macros/macro-expanded-include/test.stderr | 8 + .../macros}/macro-expansion-tests.rs | 0 .../ui/macros/macro-expansion-tests.stderr | 18 + .../macros}/macro-follow.rs | 0 src/test/ui/macros/macro-follow.stderr | 512 ++ .../macros}/macro-followed-by-seq-bad.rs | 0 .../macros/macro-followed-by-seq-bad.stderr | 14 + .../macros}/macro-inner-attributes.rs | 0 .../ui/macros/macro-inner-attributes.stderr | 9 + .../macros}/macro-input-future-proofing.rs | 0 .../macros/macro-input-future-proofing.stderr | 56 + .../macro-invalid-fragment-spec.rs | 0 .../macro-invalid-fragment-spec.stderr | 0 .../macros}/macro-local-data-key-priv.rs | 0 .../macros/macro-local-data-key-priv.stderr | 9 + .../macros}/macro-match-nonterminal.rs | 0 .../ui/macros/macro-match-nonterminal.stderr | 8 + .../macros}/macro-missing-delimiters.rs | 0 .../ui/macros/macro-missing-delimiters.stderr | 8 + .../macros}/macro-missing-fragment.rs | 0 .../ui/macros/macro-missing-fragment.stderr | 8 + .../macros}/macro-non-lifetime.rs | 0 src/test/ui/macros/macro-non-lifetime.stderr | 8 + .../macros}/macro-outer-attributes.rs | 0 .../ui/macros/macro-outer-attributes.stderr | 13 + .../macros}/macro-parameter-span.rs | 0 .../ui/macros/macro-parameter-span.stderr | 9 + .../ui/macros/macro-path-prelude-fail-1.rs | 20 + .../macros/macro-path-prelude-fail-1.stderr | 15 + .../ui/macros/macro-path-prelude-fail-2.rs | 17 + .../macros/macro-path-prelude-fail-2.stderr | 8 + .../ui/macros/macro-path-prelude-fail-3.rs | 3 + .../macros/macro-path-prelude-fail-3.stderr | 8 + .../ui/macros/macro-path-prelude-fail-4.rs | 4 + .../macros/macro-path-prelude-fail-4.stderr | 8 + src/test/ui/macros/macro-path-prelude-pass.rs | 21 + .../ui/macros/macro-path-prelude-pass.stderr | 8 + .../ui/macros/macro-path-prelude-shadowing.rs | 43 + .../macro-path-prelude-shadowing.stderr | 21 + .../ui/{ => macros}/macro-reexport-removed.rs | 0 .../macro-reexport-removed.stderr | 6 +- src/test/ui/macros/macro-shadowing-relaxed.rs | 35 + src/test/ui/{ => macros}/macro-shadowing.rs | 4 +- src/test/ui/macros/macro-shadowing.stderr | 35 + .../macros}/macro-stability.rs | 0 src/test/ui/macros/macro-stability.stderr | 11 + .../macros}/macro-stmt-matchers.rs | 0 src/test/ui/macros/macro-stmt-matchers.stderr | 11 + .../macros}/macro-tt-matchers.rs | 0 src/test/ui/macros/macro-tt-matchers.stderr | 8 + .../macros}/macro-use-bad-args-1.rs | 2 + .../ui/macros/macro-use-bad-args-1.stderr | 9 + .../macros}/macro-use-bad-args-2.rs | 2 + .../ui/macros/macro-use-bad-args-2.stderr | 9 + .../macros}/macro-use-scope.rs | 0 src/test/ui/macros/macro-use-scope.stderr | 8 + .../macros}/macro-use-undef.rs | 0 src/test/ui/macros/macro-use-undef.stderr | 9 + .../macros}/macro-use-wrong-name.rs | 0 .../ui/macros/macro-use-wrong-name.stderr | 8 + src/test/ui/macros/macro_undefined.rs | 2 +- src/test/ui/macros/macro_undefined.stderr | 10 +- src/test/ui/macros/macros-in-extern.rs | 42 + src/test/ui/macros/macros-in-extern.stderr | 27 + .../macros}/macros-nonfatal-errors.rs | 5 +- .../ui/macros/macros-nonfatal-errors.stderr | 91 + src/test/ui/macros/missing-comma.rs | 30 + src/test/ui/macros/missing-comma.stderr | 38 + .../ui/macros/restricted-shadowing-legacy.rs | 289 ++ .../macros/restricted-shadowing-legacy.stderr | 195 + .../ui/macros/restricted-shadowing-modern.rs | 243 + .../macros/restricted-shadowing-modern.stderr | 147 + .../ui/macros/span-covering-argument-1.stderr | 2 +- src/test/ui/macros/trace-macro.stderr | 5 +- .../{compile-fail => ui}/main-wrong-type.rs | 0 src/test/ui/main-wrong-type.stderr | 12 + .../malformed}/malformed-derive-entry.rs | 0 .../malformed/malformed-derive-entry.stderr | 26 + .../malformed}/malformed-plugin-1.rs | 0 .../ui/malformed/malformed-plugin-1.stderr | 9 + .../malformed}/malformed-plugin-2.rs | 0 .../ui/malformed/malformed-plugin-2.stderr | 9 + .../malformed}/malformed-plugin-3.rs | 0 .../ui/malformed/malformed-plugin-3.stderr | 9 + .../malformed_macro_lhs.rs | 0 src/test/ui/malformed_macro_lhs.stderr | 8 + .../manual}/manual-link-bad-form.rs | 0 .../ui/manual/manual-link-bad-form.stderr | 4 + .../manual}/manual-link-bad-kind.rs | 0 .../ui/manual/manual-link-bad-kind.stderr | 2 + .../manual}/manual-link-bad-search-path.rs | 0 .../manual/manual-link-bad-search-path.stderr | 2 + .../manual}/manual-link-framework.rs | 0 .../ui/manual/manual-link-framework.stderr | 4 + src/test/{compile-fail => ui}/map-types.rs | 0 src/test/ui/map-types.stderr | 11 + .../match}/match-argm-statics-2.rs | 0 src/test/ui/match/match-argm-statics-2.stderr | 21 + .../match}/match-arm-statics.rs | 0 src/test/ui/match/match-arm-statics.stderr | 26 + .../match}/match-byte-array-patterns-2.rs | 0 .../match/match-byte-array-patterns-2.stderr | 15 + .../match}/match-byte-array-patterns.rs | 0 .../ui/match/match-byte-array-patterns.stderr | 56 + .../match}/match-ill-type2.rs | 0 src/test/ui/match/match-ill-type2.stderr | 9 + .../{compile-fail => ui/match}/match-join.rs | 0 src/test/ui/match/match-join.stderr | 9 + .../match}/match-no-arms-unreachable-after.rs | 0 .../match-no-arms-unreachable-after.stderr | 14 + .../match}/match-non-exhaustive.rs | 0 src/test/ui/match/match-non-exhaustive.stderr | 15 + .../match}/match-pattern-field-mismatch-2.rs | 0 .../match-pattern-field-mismatch-2.stderr | 9 + .../match}/match-pattern-field-mismatch.rs | 0 .../match/match-pattern-field-mismatch.stderr | 9 + .../match}/match-privately-empty.rs | 0 .../ui/match/match-privately-empty.stderr | 9 + .../match}/match-range-fail-2.rs | 0 src/test/ui/match/match-range-fail-2.stderr | 22 + .../match}/match-range-fail-dominate.rs | 0 .../ui/match/match-range-fail-dominate.stderr | 66 + .../match}/match-range-fail.rs | 0 src/test/ui/match/match-range-fail.stderr | 31 + .../match}/match-ref-ice.rs | 0 src/test/ui/match/match-ref-ice.stderr | 14 + .../match/match-ref-mut-invariance.nll.stderr | 12 + .../match}/match-ref-mut-invariance.rs | 0 .../ui/match/match-ref-mut-invariance.stderr | 22 + .../match-ref-mut-let-invariance.nll.stderr | 13 + .../match}/match-ref-mut-let-invariance.rs | 0 .../match/match-ref-mut-let-invariance.stderr | 22 + .../match}/match-slice-patterns.rs | 0 src/test/ui/match/match-slice-patterns.stderr | 9 + .../match}/match-static-const-lc.rs | 0 .../ui/match/match-static-const-lc.stderr | 26 + .../match}/match-struct.rs | 0 src/test/ui/match/match-struct.stderr | 12 + .../match}/match-tag-nullary.rs | 0 src/test/ui/match/match-tag-nullary.stderr | 12 + .../match}/match-tag-unary.rs | 0 src/test/ui/match/match-tag-unary.stderr | 12 + ...eachable-warning-with-diverging-discrim.rs | 0 ...able-warning-with-diverging-discrim.stderr | 14 + .../match}/match-unresolved-one-arm.rs | 0 .../ui/match/match-unresolved-one-arm.stderr | 12 + .../match}/match-vec-fixed.rs | 0 src/test/ui/match/match-vec-fixed.stderr | 20 + .../match}/match-vec-mismatch-2.rs | 0 src/test/ui/match/match-vec-mismatch-2.stderr | 9 + .../match}/match-vec-mismatch.rs | 0 src/test/ui/match/match-vec-mismatch.stderr | 36 + .../match}/match-vec-unreachable.rs | 0 .../ui/match/match-vec-unreachable.stderr | 26 + .../maybe-bounds-where-cpass.rs | 0 src/test/ui/maybe-bounds-where-cpass.stderr | 11 + .../maybe-bounds-where.rs | 0 src/test/ui/maybe-bounds-where.stderr | 45 + .../meta-expected-error-correct-rev.a.stderr | 9 + .../meta-expected-error-correct-rev.rs | 0 .../methods}/auxiliary/ambig_impl_2_lib.rs | 0 .../methods/auxiliary/macro-in-other-crate.rs | 19 + ...method-ambig-one-trait-unknown-int-type.rs | 0 ...od-ambig-one-trait-unknown-int-type.stderr | 18 + .../method-ambig-two-traits-cross-crate.rs | 0 ...method-ambig-two-traits-cross-crate.stderr | 16 + .../method-ambig-two-traits-from-bounds.rs | 0 ...method-ambig-two-traits-from-bounds.stderr | 22 + ...od-ambig-two-traits-with-default-method.rs | 0 ...mbig-two-traits-with-default-method.stderr | 20 + .../ui/{ => methods}/method-call-err-msg.rs | 0 .../{ => methods}/method-call-err-msg.stderr | 0 .../methods/method-call-lifetime-args-fail.rs | 82 + .../method-call-lifetime-args-fail.stderr | 195 + .../method-call-lifetime-args-lint-fail.rs} | 0 ...method-call-lifetime-args-lint-fail.stderr | 187 + .../method-call-lifetime-args-lint.rs | 0 .../method-call-lifetime-args-lint.stderr | 0 .../method-call-lifetime-args-subst-index.rs | 0 ...thod-call-lifetime-args-subst-index.stderr | 8 + .../method-call-lifetime-args-unresolved.rs | 0 ...ethod-call-lifetime-args-unresolved.stderr | 9 + .../method-call-lifetime-args.rs | 0 .../method-call-lifetime-args.stderr | 0 .../methods}/method-call-type-binding.rs | 0 .../methods/method-call-type-binding.stderr | 9 + .../methods}/method-macro-backtrace.rs | 0 .../ui/methods/method-macro-backtrace.stderr | 11 + .../ui/{ => methods}/method-missing-call.rs | 0 .../{ => methods}/method-missing-call.stderr | 0 .../method-on-ambiguous-numeric-type.rs | 0 .../method-on-ambiguous-numeric-type.stderr | 0 .../methods}/method-path-in-pattern.rs | 0 .../ui/methods/method-path-in-pattern.stderr | 21 + .../method-resolvable-path-in-pattern.rs | 0 .../method-resolvable-path-in-pattern.stderr | 9 + .../methods}/method-self-arg-1.rs | 0 src/test/ui/methods/method-self-arg-1.stderr | 24 + .../ui/methods/method-self-arg-2.nll.stderr | 24 + .../methods}/method-self-arg-2.rs | 7 + src/test/ui/methods/method-self-arg-2.stderr | 26 + src/test/{compile-fail => ui}/minus-string.rs | 0 src/test/ui/minus-string.stderr | 11 + .../mir-dataflow/README.md | 0 .../mir-dataflow/def-inits-1.rs | 0 src/test/ui/mir-dataflow/def-inits-1.stderr | 28 + .../mir-dataflow/inits-1.rs | 0 src/test/ui/mir-dataflow/inits-1.stderr | 22 + .../mir-dataflow/uninits-1.rs | 0 src/test/ui/mir-dataflow/uninits-1.stderr | 34 + .../mir-dataflow/uninits-2.rs | 0 src/test/ui/mir-dataflow/uninits-2.stderr | 10 + src/test/{compile-fail => ui}/mir-unpretty.rs | 0 src/test/ui/mir-unpretty.stderr | 12 + .../ui/mismatched_types/cast-rfc0401.stderr | 4 +- src/test/ui/missing/auxiliary/two_macros.rs | 15 + .../missing-alloc_error_handler.rs | 4 +- .../missing-alloc_error_handler.stderr | 0 .../ui/{ => missing}/missing-allocator.rs | 4 +- .../ui/{ => missing}/missing-allocator.stderr | 0 .../ui/{ => missing}/missing-block-hint.rs | 0 .../{ => missing}/missing-block-hint.stderr | 0 .../missing-comma-in-match.fixed | 0 .../{ => missing}/missing-comma-in-match.rs | 0 .../missing-comma-in-match.stderr | 0 .../missing}/missing-derivable-attr.rs | 0 .../ui/missing/missing-derivable-attr.stderr | 12 + .../missing-fields-in-struct-pattern.rs | 0 .../missing-fields-in-struct-pattern.stderr | 0 .../missing-items/auxiliary/m1.rs | 0 .../missing-items/issue-40221.rs | 0 .../missing-items/issue-40221.stderr | 0 src/test/ui/{ => missing}/missing-items/m2.rs | 0 .../ui/{ => missing}/missing-items/m2.stderr | 0 .../missing-items/missing-type-parameter.rs | 0 .../missing-type-parameter.stderr | 0 .../missing}/missing-macro-use.rs | 0 src/test/ui/missing/missing-macro-use.stderr | 8 + .../missing}/missing-main.rs | 0 src/test/ui/missing/missing-main.stderr | 7 + .../missing}/missing-return.rs | 0 src/test/ui/missing/missing-return.stderr | 12 + .../missing}/missing-semicolon-warning.rs | 0 .../missing/missing-semicolon-warning.stderr | 30 + .../missing}/missing-stability.rs | 6 +- src/test/ui/missing/missing-stability.stderr | 17 + .../missing_debug_impls.rs | 0 src/test/ui/missing_debug_impls.stderr | 20 + .../{compile-fail => ui/mod}/mod_file_aux.rs | 0 .../mod}/mod_file_correct_spans.rs | 2 +- src/test/ui/mod/mod_file_correct_spans.stderr | 9 + .../mod}/mod_file_disambig.rs | 0 src/test/ui/mod/mod_file_disambig.stderr | 11 + .../mod}/mod_file_disambig_aux.rs | 0 .../mod}/mod_file_disambig_aux/mod.rs | 0 .../module-macro_use-arguments.rs | 0 src/test/ui/module-macro_use-arguments.stderr | 8 + .../moves-based-on-type-block-bad.nll.stderr | 15 - .../moves}/move-guard-same-consts.rs | 0 .../ui/moves/move-guard-same-consts.stderr | 13 + .../moves}/move-in-guard-1.rs | 0 src/test/ui/moves/move-in-guard-1.stderr | 13 + .../moves}/move-in-guard-2.rs | 0 src/test/ui/moves/move-in-guard-2.stderr | 11 + .../moves/move-into-dead-array-1.nll.stderr | 9 + .../moves}/move-into-dead-array-1.rs | 0 .../ui/moves/move-into-dead-array-1.stderr | 9 + .../moves/move-into-dead-array-2.nll.stderr | 13 + .../moves}/move-into-dead-array-2.rs | 0 .../ui/moves/move-into-dead-array-2.stderr | 13 + .../moves}/move-out-of-array-1.rs | 0 src/test/ui/moves/move-out-of-array-1.stderr | 9 + .../ui/moves/move-out-of-slice-1.nll.stderr | 17 + .../moves}/move-out-of-slice-1.rs | 0 src/test/ui/moves/move-out-of-slice-1.stderr | 12 + .../moves/move-out-of-tuple-field.nll.stderr | 23 + .../moves}/move-out-of-tuple-field.rs | 0 .../ui/moves/move-out-of-tuple-field.stderr | 23 + ...s-based-on-type-access-to-field.nll.stderr | 13 + .../moves-based-on-type-access-to-field.rs | 0 ...moves-based-on-type-access-to-field.stderr | 13 + .../moves-based-on-type-block-bad.nll.stderr | 21 + .../moves-based-on-type-block-bad.rs | 0 .../moves-based-on-type-block-bad.stderr | 0 ...ased-on-type-capture-clause-bad.nll.stderr | 16 + .../moves-based-on-type-capture-clause-bad.rs | 0 ...es-based-on-type-capture-clause-bad.stderr | 14 + ...on-type-cyclic-types-issue-4821.nll.stderr | 14 + ...s-based-on-type-cyclic-types-issue-4821.rs | 0 ...sed-on-type-cyclic-types-issue-4821.stderr | 14 + ...type-distribute-copy-over-paren.nll.stderr | 25 + ...ased-on-type-distribute-copy-over-paren.rs | 0 ...-on-type-distribute-copy-over-paren.stderr | 25 + .../moves-based-on-type-exprs.nll.stderr | 118 + .../moves}/moves-based-on-type-exprs.rs | 0 .../ui/moves/moves-based-on-type-exprs.stderr | 118 + ...es-based-on-type-match-bindings.nll.stderr | 0 .../moves-based-on-type-match-bindings.rs | 0 .../moves-based-on-type-match-bindings.stderr | 0 ...e-out-of-closure-env-issue-1965.nll.stderr | 11 + ...type-move-out-of-closure-env-issue-1965.rs | 0 ...-move-out-of-closure-env-issue-1965.stderr | 11 + ...type-no-recursive-stack-closure.nll.stderr | 24 + ...ased-on-type-no-recursive-stack-closure.rs | 0 ...-on-type-no-recursive-stack-closure.stderr | 23 + .../{ => moves}/moves-based-on-type-tuple.rs | 0 .../moves-based-on-type-tuple.stderr | 0 .../ui/moves/moves-sru-moved-field.nll.stderr | 13 + .../moves}/moves-sru-moved-field.rs | 0 .../ui/moves/moves-sru-moved-field.stderr | 13 + .../{compile-fail => ui}/multiple-main-2.rs | 0 src/test/ui/multiple-main-2.stderr | 14 + .../{compile-fail => ui}/multiple-main-3.rs | 0 src/test/ui/multiple-main-3.stderr | 14 + .../multiple-plugin-registrars.rs | 0 src/test/ui/multiple-plugin-registrars.stderr | 15 + src/test/ui/mut/mut-cant-alias.nll.stderr | 13 + .../mut}/mut-cant-alias.rs | 6 + src/test/ui/mut/mut-cant-alias.stderr | 14 + .../mut}/mut-cross-borrowing.rs | 0 src/test/ui/mut/mut-cross-borrowing.stderr | 15 + ...pattern-internal-mutability.ast.nll.stderr | 26 + ...mut-pattern-internal-mutability.ast.stderr | 20 + ...mut-pattern-internal-mutability.mir.stderr | 26 + .../mut}/mut-pattern-internal-mutability.rs | 0 .../mut}/mut-pattern-mismatched.rs | 0 src/test/ui/mut/mut-pattern-mismatched.stderr | 21 + src/test/ui/{ => mut}/mut-ref.rs | 0 src/test/ui/{ => mut}/mut-ref.stderr | 0 src/test/ui/mut/mut-suggestion.nll.stderr | 21 + .../mut}/mut-suggestion.rs | 6 +- src/test/ui/mut/mut-suggestion.stderr | 21 + .../ui/mut/mutable-class-fields-2.nll.stderr | 11 + .../mut}/mutable-class-fields-2.rs | 0 src/test/ui/mut/mutable-class-fields-2.stderr | 11 + .../mut/mutable-class-fields.ast.nll.stderr | 11 + .../ui/mut/mutable-class-fields.ast.stderr | 11 + .../ui/mut/mutable-class-fields.mir.stderr | 11 + .../mut}/mutable-class-fields.rs | 0 .../mut}/mutable-enum-indirect.rs | 0 src/test/ui/mut/mutable-enum-indirect.stderr | 18 + .../{compile-fail => ui}/mutexguard-sync.rs | 0 src/test/ui/mutexguard-sync.stderr | 17 + .../namespace}/auxiliary/namespace-mix.rs | 0 .../namespace}/auxiliary/namespaced_enums.rs | 0 .../namespace}/namespace-mix.rs | 0 src/test/ui/namespace/namespace-mix.stderr | 594 +++ ...spaced-enum-glob-import-no-impls-xcrate.rs | 0 ...ed-enum-glob-import-no-impls-xcrate.stderr | 27 + .../namespaced-enum-glob-import-no-impls.rs | 0 ...amespaced-enum-glob-import-no-impls.stderr | 27 + .../{compile-fail => ui}/nested-cfg-attrs.rs | 0 src/test/ui/nested-cfg-attrs.stderr | 9 + .../{compile-fail => ui}/nested-ty-params.rs | 2 + src/test/ui/nested-ty-params.stderr | 23 + .../never-assign-dead-code.rs | 0 src/test/ui/never-assign-dead-code.stderr | 44 + .../never-assign-wrong-type.rs | 0 src/test/ui/never-assign-wrong-type.stderr | 12 + .../never_transmute_never.rs | 0 .../ui/nll/borrowed-temporary-error.stderr | 2 + .../ui/nll/cannot-move-block-spans.nll.stderr | 18 +- src/test/ui/nll/closure-access-spans.rs | 68 + src/test/ui/nll/closure-access-spans.stderr | 110 + src/test/ui/nll/closure-borrow-spans.rs | 112 + src/test/ui/nll/closure-borrow-spans.stderr | 172 + src/test/ui/nll/closure-captures.rs | 2 +- src/test/ui/nll/closure-move-spans.rs | 33 + src/test/ui/nll/closure-move-spans.stderr | 39 + .../escape-argument-callee.rs | 1 - .../escape-argument-callee.stderr | 22 +- .../escape-upvar-nested.rs | 4 +- .../escape-upvar-nested.stderr | 26 +- .../escape-upvar-ref.stderr | 6 +- .../propagate-approximated-fail-no-postdom.rs | 1 - ...pagate-approximated-fail-no-postdom.stderr | 32 +- .../propagate-approximated-ref.rs | 4 +- .../propagate-approximated-ref.stderr | 45 +- ...horter-to-static-comparing-against-free.rs | 1 - ...er-to-static-comparing-against-free.stderr | 34 +- ...approximated-shorter-to-static-no-bound.rs | 5 +- ...oximated-shorter-to-static-no-bound.stderr | 54 +- ...roximated-shorter-to-static-wrong-bound.rs | 4 +- ...mated-shorter-to-static-wrong-bound.stderr | 52 +- .../propagate-approximated-val.rs | 4 +- .../propagate-approximated-val.stderr | 45 +- .../propagate-despite-same-free-region.stderr | 7 +- ...te-fail-to-approximate-longer-no-bounds.rs | 3 +- ...ail-to-approximate-longer-no-bounds.stderr | 35 +- ...fail-to-approximate-longer-wrong-bounds.rs | 3 +- ...-to-approximate-longer-wrong-bounds.stderr | 35 +- .../propagate-from-trait-match.rs | 1 - .../propagate-from-trait-match.stderr | 40 +- ...region-lbr-anon-does-not-outlive-static.rs | 3 +- ...on-lbr-anon-does-not-outlive-static.stderr | 8 +- ...egion-lbr-named-does-not-outlive-static.rs | 3 +- ...n-lbr-named-does-not-outlive-static.stderr | 10 +- .../region-lbr1-does-not-outlive-ebr2.rs | 3 +- .../region-lbr1-does-not-outlive-ebr2.stderr | 17 +- .../return-wrong-bound-region.rs | 3 +- .../return-wrong-bound-region.stderr | 27 +- src/test/ui/nll/closure-use-spans.rs | 33 + src/test/ui/nll/closure-use-spans.stderr | 33 + src/test/ui/nll/closures-in-loops.rs | 36 + src/test/ui/nll/closures-in-loops.stderr | 30 + .../nll/constant-thread-locals-issue-47053.rs | 0 .../constant-thread-locals-issue-47053.stderr | 9 + .../do-not-ignore-lifetime-bounds-in-copy.rs | 0 ...-not-ignore-lifetime-bounds-in-copy.stderr | 14 + src/test/ui/nll/extra-unused-mut.rs | 9 + src/test/ui/nll/get_default.nll.stderr | 15 +- src/test/ui/nll/get_default.stderr | 15 +- src/test/ui/nll/guarantor-issue-46974.stderr | 2 +- src/test/ui/nll/issue-27868.rs | 40 + src/test/ui/nll/issue-27868.stderr | 18 + src/test/ui/nll/issue-30104.rs | 52 + src/test/ui/nll/issue-48238.stderr | 11 +- src/test/ui/nll/issue-48697.rs | 24 + src/test/ui/nll/issue-51268.stderr | 2 +- src/test/ui/nll/issue-52113.rs | 50 + src/test/ui/nll/issue-52113.stderr | 12 + src/test/ui/nll/issue-52133.rs | 50 - src/test/ui/nll/issue-52133.stderr | 11 - ...issue-52663-span-decl-captured-variable.rs | 23 + ...e-52663-span-decl-captured-variable.stderr | 11 + src/test/ui/nll/issue-52742.rs | 31 + src/test/ui/nll/issue-52742.stderr | 12 + src/test/ui/nll/issue-53119.rs | 35 + src/test/ui/nll/issue-53570.rs | 46 + .../nll/loan_ends_mid_block_pair.rs | 0 .../ui/nll/loan_ends_mid_block_pair.stderr | 93 + .../nll/loan_ends_mid_block_vec.rs | 0 .../ui/nll/loan_ends_mid_block_vec.stderr | 111 + .../match-guards-always-borrow.ast.nll.stderr | 9 + .../nll/match-guards-always-borrow.ast.stderr | 12 + .../nll/match-guards-always-borrow.mir.stderr | 9 + .../nll/match-guards-always-borrow.rs | 0 ...initialized-drop-implicit-fragment-drop.rs | 4 +- ...ialized-drop-implicit-fragment-drop.stderr | 2 +- src/test/ui/nll/mir_check_cast_closure.rs | 3 +- src/test/ui/nll/mir_check_cast_closure.stderr | 15 +- src/test/ui/nll/mir_check_cast_reify.rs | 3 +- src/test/ui/nll/mir_check_cast_reify.stderr | 14 +- src/test/ui/nll/mir_check_cast_unsafe_fn.rs | 3 +- .../ui/nll/mir_check_cast_unsafe_fn.stderr | 14 +- src/test/ui/nll/mir_check_cast_unsize.rs | 3 +- src/test/ui/nll/mir_check_cast_unsize.stderr | 19 +- src/test/ui/nll/move-errors.stderr | 91 +- .../promotable-mutable-zst-doesnt-conflict.rs | 23 + ...arried-through-struct-field.ast.nll.stderr | 14 + ...ce-carried-through-struct-field.ast.stderr | 11 + ...ce-carried-through-struct-field.mir.stderr | 14 + .../reference-carried-through-struct-field.rs | 0 .../region-ends-after-if-condition.nll.stderr | 39 + .../nll/region-ends-after-if-condition.rs | 0 .../nll/region-ends-after-if-condition.stderr | 39 + .../ui/nll/relate_tys/hr-fn-aaa-as-aba.rs | 11 +- .../ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr | 8 +- .../ui/nll/relate_tys/hr-fn-aau-eq-abu.rs | 5 +- .../ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr | 8 - .../ui/nll/relate_tys/universe-violation.rs | 17 + .../nll/relate_tys/universe-violation.stderr | 8 + .../ui/nll/relate_tys/var-appears-twice.rs | 38 + .../nll/relate_tys/var-appears-twice.stderr | 14 + .../ui/nll/return-ref-mut-issue-46557.stderr | 17 +- .../nll/return_from_loop.rs | 0 src/test/ui/nll/return_from_loop.stderr | 39 + .../ui/nll/ty-outlives/impl-trait-captures.rs | 3 +- .../ty-outlives/impl-trait-captures.stderr | 12 +- .../ui/nll/ty-outlives/impl-trait-outlives.rs | 2 - .../ty-outlives/impl-trait-outlives.stderr | 16 +- .../ty-outlives/projection-implied-bounds.rs | 3 +- .../projection-implied-bounds.stderr | 6 - .../projection-no-regions-closure.rs | 6 +- .../projection-no-regions-closure.stderr | 72 +- .../ty-outlives/projection-no-regions-fn.rs | 6 +- .../projection-no-regions-fn.stderr | 14 +- .../projection-one-region-closure.rs | 9 +- .../projection-one-region-closure.stderr | 138 +- ...ojection-one-region-trait-bound-closure.rs | 9 +- ...tion-one-region-trait-bound-closure.stderr | 104 +- ...e-region-trait-bound-static-closure.stderr | 1 + ...ojection-two-region-trait-bound-closure.rs | 12 +- ...tion-two-region-trait-bound-closure.stderr | 147 +- ...y-param-closure-approximate-lower-bound.rs | 7 +- ...ram-closure-approximate-lower-bound.stderr | 50 +- ...param-closure-outlives-from-return-type.rs | 6 +- ...m-closure-outlives-from-return-type.stderr | 34 +- ...aram-closure-outlives-from-where-clause.rs | 2 - ...-closure-outlives-from-where-clause.stderr | 94 +- .../ui/nll/ty-outlives/ty-param-fn-body.rs | 3 +- .../nll/ty-outlives/ty-param-fn-body.stderr | 6 - src/test/ui/nll/ty-outlives/ty-param-fn.rs | 6 +- .../ui/nll/ty-outlives/ty-param-fn.stderr | 14 +- .../nll/unused-mut-issue-50343.rs | 0 src/test/ui/nll/unused-mut-issue-50343.stderr | 16 + .../nll/user-annotations/adt-brace-enums.rs | 62 + .../user-annotations/adt-brace-enums.stderr | 41 + .../nll/user-annotations/adt-brace-structs.rs | 60 + .../user-annotations/adt-brace-structs.stderr | 41 + .../nll/user-annotations/adt-nullary-enums.rs | 80 + .../user-annotations/adt-nullary-enums.stderr | 44 + .../nll/user-annotations/adt-tuple-enums.rs | 64 + .../user-annotations/adt-tuple-enums.stderr | 41 + .../nll/user-annotations/adt-tuple-struct.rs | 60 + .../user-annotations/adt-tuple-struct.stderr | 41 + .../user-annotations/dump-adt-brace-struct.rs | 29 + .../dump-adt-brace-struct.stderr | 8 + .../ui/nll/user-annotations/dump-fn-method.rs | 59 + .../user-annotations/dump-fn-method.stderr | 26 + src/test/ui/nll/user-annotations/fns.rs | 60 + src/test/ui/nll/user-annotations/fns.stderr | 41 + .../ui/nll/user-annotations/method-call.rs | 81 + .../nll/user-annotations/method-call.stderr | 41 + .../ui/nll/user-annotations/method-ufcs-1.rs | 75 + .../nll/user-annotations/method-ufcs-1.stderr | 45 + .../ui/nll/user-annotations/method-ufcs-2.rs | 75 + .../nll/user-annotations/method-ufcs-2.stderr | 45 + .../ui/nll/user-annotations/method-ufcs-3.rs | 81 + .../nll/user-annotations/method-ufcs-3.stderr | 41 + src/test/ui/nll/user-annotations/patterns.rs | 121 + .../ui/nll/user-annotations/patterns.stderr | 143 + .../nll/where_clauses_in_functions.rs | 3 +- .../ui/nll/where_clauses_in_functions.stderr | 12 + .../nll/where_clauses_in_structs.rs | 3 +- .../ui/nll/where_clauses_in_structs.stderr | 12 + src/test/ui/no-capture-arc.nll.stderr | 29 + .../{compile-fail => ui}/no-capture-arc.rs | 0 src/test/ui/no-capture-arc.stderr | 25 + .../no-implicit-prelude-nested.rs | 0 src/test/ui/no-implicit-prelude-nested.stderr | 196 + .../no-implicit-prelude.rs | 0 src/test/ui/no-implicit-prelude.stderr | 68 + src/test/{compile-fail => ui}/no-link.rs | 1 - src/test/ui/no-link.stderr | 9 + .../no-patterns-in-args-2.rs | 0 src/test/ui/no-patterns-in-args-2.stderr | 23 + .../no-patterns-in-args-macro.rs | 0 src/test/ui/no-patterns-in-args-macro.stderr | 22 + src/test/ui/no-reuse-move-arc.nll.stderr | 29 + .../{compile-fail => ui}/no-reuse-move-arc.rs | 0 src/test/ui/no-reuse-move-arc.stderr | 25 + .../{compile-fail => ui}/no-send-res-ports.rs | 0 src/test/ui/no-send-res-ports.stderr | 15 + .../{compile-fail => ui}/no-std-inject.rs | 0 src/test/ui/no-std-inject.stderr | 15 + .../no-type-for-node-ice.rs | 0 src/test/ui/no-type-for-node-ice.stderr | 9 + .../no-warn-on-field-replace-issue-34101.rs | 0 ...o-warn-on-field-replace-issue-34101.stderr | 11 + .../{compile-fail => ui}/no_crate_type.rs | 0 src/test/ui/no_crate_type.stderr | 10 + .../no_owned_box_lang_item.rs | 4 +- src/test/ui/no_owned_box_lang_item.stderr | 4 + src/test/{compile-fail => ui}/no_send-enum.rs | 0 src/test/ui/no_send-enum.stderr | 17 + src/test/{compile-fail => ui}/no_send-rc.rs | 0 src/test/ui/no_send-rc.stderr | 16 + .../{compile-fail => ui}/no_send-struct.rs | 0 src/test/ui/no_send-struct.stderr | 16 + .../{compile-fail => ui}/no_share-enum.rs | 0 src/test/ui/no_share-enum.stderr | 17 + .../{compile-fail => ui}/no_share-struct.rs | 0 src/test/ui/no_share-struct.stderr | 16 + .../{compile-fail => ui}/noexporttypeexe.rs | 0 src/test/ui/noexporttypeexe.stderr | 12 + .../non-constant-in-const-path.rs | 0 src/test/ui/non-constant-in-const-path.stderr | 9 + .../{compile-fail => ui}/non-copyable-void.rs | 0 src/test/ui/non-copyable-void.stderr | 9 + .../non-exhaustive-match-nested.rs | 0 .../non-exhaustive-match-nested.stderr | 15 + .../non-exhaustive}/non-exhaustive-match.rs | 0 .../non-exhaustive-match.stderr | 51 + .../non-exhaustive-pattern-witness.rs | 0 .../non-exhaustive-pattern-witness.stderr | 0 .../non-interger-atomic.rs | 0 src/test/ui/non-interger-atomic.stderr | 99 + src/test/ui/non_modrs_mods/non_modrs_mods.rs | 28 - .../ui/non_modrs_mods/non_modrs_mods.stderr | 39 - .../{compile-fail => ui}/noncopyable-class.rs | 0 src/test/ui/noncopyable-class.stderr | 16 + .../{compile-fail => ui}/nonscalar-cast.rs | 0 src/test/ui/nonscalar-cast.stderr | 11 + .../{compile-fail => ui}/not-clone-closure.rs | 0 src/test/ui/not-clone-closure.stderr | 11 + src/test/ui/not-copy-closure.nll.stderr | 11 + .../{compile-fail => ui}/not-copy-closure.rs | 0 src/test/ui/not-copy-closure.stderr | 17 + .../not-panic}/not-panic-safe-2.rs | 0 src/test/ui/not-panic/not-panic-safe-2.stderr | 34 + .../not-panic}/not-panic-safe-3.rs | 0 src/test/ui/not-panic/not-panic-safe-3.stderr | 34 + .../not-panic}/not-panic-safe-4.rs | 0 src/test/ui/not-panic/not-panic-safe-4.stderr | 34 + .../not-panic}/not-panic-safe-5.rs | 0 src/test/ui/not-panic/not-panic-safe-5.stderr | 17 + .../not-panic}/not-panic-safe-6.rs | 0 src/test/ui/not-panic/not-panic-safe-6.stderr | 34 + .../not-panic}/not-panic-safe.rs | 0 src/test/ui/not-panic/not-panic-safe.stderr | 16 + src/test/{compile-fail => ui}/not-sync.rs | 0 src/test/ui/not-sync.stderr | 81 + src/test/ui/{ => numeric}/numeric-cast-2.rs | 0 .../ui/{ => numeric}/numeric-cast-2.stderr | 0 src/test/ui/{ => numeric}/numeric-cast.rs | 0 src/test/ui/{ => numeric}/numeric-cast.stderr | 0 src/test/ui/{ => numeric}/numeric-fields.rs | 0 .../ui/{ => numeric}/numeric-fields.stderr | 0 .../object-does-not-impl-trait.rs | 0 src/test/ui/object-does-not-impl-trait.stderr | 15 + .../object-lifetime-default-ambiguous.rs | 0 .../object-lifetime-default-ambiguous.stderr | 21 + ...object-lifetime-default-elision.nll.stderr | 13 + .../object-lifetime-default-elision.rs | 0 .../object-lifetime-default-elision.stderr | 53 + ...lifetime-default-from-box-error.nll.stderr | 28 + .../object-lifetime-default-from-box-error.rs | 0 ...ect-lifetime-default-from-box-error.stderr | 21 + ...ime-default-from-rptr-box-error.nll.stderr | 10 + ...ct-lifetime-default-from-rptr-box-error.rs | 0 ...ifetime-default-from-rptr-box-error.stderr | 18 + ...-default-from-rptr-struct-error.nll.stderr | 10 + ...lifetime-default-from-rptr-struct-error.rs | 0 ...time-default-from-rptr-struct-error.stderr | 18 + .../object-lifetime-default-mybox.nll.stderr | 21 + .../object-lifetime-default-mybox.rs | 0 .../object-lifetime-default-mybox.stderr | 31 + .../object-lifetime-default.rs | 2 + .../object-lifetime-default.stderr | 44 + .../object-pointer-types.rs | 0 src/test/ui/object-pointer-types.stderr | 29 + .../object-safety-associated-consts.rs | 0 .../object-safety-associated-consts.stderr | 0 ...object-safety-by-value-self-use.nll.stderr | 9 + .../object-safety-by-value-self-use.rs | 0 .../object-safety-by-value-self-use.stderr | 9 + .../object-safety-by-value-self.rs | 0 .../object-safety-by-value-self.stderr | 9 + .../object-safety-generics.rs | 0 .../object-safety-generics.stderr | 0 .../object-safety-issue-22040.rs | 0 .../object-safety-issue-22040.stderr | 11 + .../object-safety-mentions-Self.rs | 0 .../object-safety-mentions-Self.stderr | 0 .../object-safety}/object-safety-no-static.rs | 0 .../object-safety-no-static.stderr | 11 + .../object-safety-phantom-fn.rs | 0 .../object-safety-phantom-fn.stderr | 9 + .../object-safety}/object-safety-sized-2.rs | 0 .../object-safety-sized-2.stderr | 11 + .../object-safety-sized.rs | 0 .../object-safety-sized.stderr | 0 .../object-safety-supertrait-mentions-Self.rs | 0 ...ect-safety-supertrait-mentions-Self.stderr | 0 .../{compile-fail => ui}/occurs-check-2.rs | 0 src/test/ui/occurs-check-2.stderr | 12 + .../{compile-fail => ui}/occurs-check-3.rs | 0 src/test/ui/occurs-check-3.stderr | 9 + src/test/{compile-fail => ui}/occurs-check.rs | 0 src/test/ui/occurs-check.stderr | 12 + .../old-suffixes-are-really-forbidden.rs | 0 .../old-suffixes-are-really-forbidden.stderr | 18 + .../ui/on-unimplemented/bad-annotation.rs | 2 +- .../ui/on-unimplemented/bad-annotation.stderr | 16 +- .../once-cant-call-twice-on-heap.rs | 0 .../ui/once-cant-call-twice-on-heap.stderr | 13 + src/test/{compile-fail => ui}/opt-in-copy.rs | 0 src/test/ui/opt-in-copy.stderr | 21 + .../or-patter-mismatch.rs | 0 src/test/ui/or-patter-mismatch.stderr | 12 + .../orphan-check-diagnostics.rs | 0 src/test/ui/orphan-check-diagnostics.stderr | 11 + .../{compile-fail => ui}/osx-frameworks.rs | 0 src/test/ui/osx-frameworks.stderr | 9 + .../out-of-order-shadowing.rs | 3 +- src/test/ui/out-of-order-shadowing.stderr | 22 + .../output-type-mismatch.rs | 0 src/test/ui/output-type-mismatch.stderr | 12 + .../overlap-marker-trait.rs | 0 src/test/ui/overlap-marker-trait.stderr | 15 + .../overloaded-calls-nontuple.rs | 0 src/test/ui/overloaded-calls-nontuple.stderr | 9 + .../packed-struct-generic-transmute.rs | 0 .../packed-struct-generic-transmute.stderr | 12 + .../packed-struct}/packed-struct-transmute.rs | 1 + .../packed-struct-transmute.stderr | 12 + .../auxiliary/some-panic-impl.rs | 21 + .../panic-handler-bad-signature-1.rs | 23 + .../panic-handler-bad-signature-1.stderr | 14 + .../panic-handler-bad-signature-2.rs | 24 + .../panic-handler-bad-signature-2.stderr | 8 + .../panic-handler-bad-signature-3.rs | 21 + .../panic-handler-bad-signature-3.stderr | 8 + .../panic-handler-bad-signature-4.rs | 22 + .../panic-handler-bad-signature-4.stderr | 11 + .../panic-handler/panic-handler-duplicate.rs | 27 + .../panic-handler-duplicate.stderr | 19 + .../panic-handler-requires-panic-info.rs | 25 + .../panic-handler-requires-panic-info.stderr | 4 + .../ui/panic-handler/panic-handler-std.rs | 21 + .../ui/panic-handler/panic-handler-std.stderr | 19 + .../panic-implementation-deprecated.rs | 24 + .../panic-implementation-deprecated.stderr | 14 + .../abort-link-to-unwind-dylib.rs | 0 .../abort-link-to-unwind-dylib.stderr | 4 + .../panic-runtime/auxiliary/depends.rs | 0 .../auxiliary/needs-panic-runtime.rs | 0 .../auxiliary/panic-runtime-abort.rs | 0 .../auxiliary/panic-runtime-lang-items.rs | 25 + .../auxiliary/panic-runtime-unwind.rs | 27 + .../auxiliary/panic-runtime-unwind2.rs | 27 + .../auxiliary/wants-panic-runtime-abort.rs | 0 .../auxiliary/wants-panic-runtime-unwind.rs | 16 + .../panic-runtime/bad-panic-flag1.rs | 0 .../ui/panic-runtime/bad-panic-flag1.stderr | 2 + .../panic-runtime/bad-panic-flag2.rs | 0 .../ui/panic-runtime/bad-panic-flag2.stderr | 2 + .../panic-runtime/libtest-unwinds.rs | 0 .../ui/panic-runtime/libtest-unwinds.stderr | 4 + .../panic-runtime/needs-gate.rs | 0 src/test/ui/panic-runtime/needs-gate.stderr | 19 + .../runtime-depend-on-needs-runtime.rs | 0 .../runtime-depend-on-needs-runtime.stderr | 9 + .../panic-runtime/transitive-link-a-bunch.rs | 0 .../transitive-link-a-bunch.stderr | 10 + .../panic-runtime/want-unwind-got-abort.rs | 0 .../want-unwind-got-abort.stderr | 6 + .../panic-runtime/want-unwind-got-abort2.rs | 0 .../want-unwind-got-abort2.stderr | 8 + .../panic_implementation-closures.rs | 3 +- src/test/{compile-fail => ui}/paren-span.rs | 0 src/test/ui/paren-span.stderr | 9 + .../parse-error-correct.rs | 0 src/test/ui/parse-error-correct.stderr | 31 + .../{compile-fail => ui}/parser-recovery-1.rs | 9 +- src/test/ui/parser-recovery-1.stderr | 40 + .../{compile-fail => ui}/parser-recovery-2.rs | 0 src/test/ui/parser-recovery-2.stderr | 30 + .../ui/parser/expected-comma-found-token.rs | 2 + src/test/ui/parser/unclosed-braces.rs | 32 + src/test/ui/parser/unclosed-braces.stderr | 17 + .../pattern}/pat-shadow-in-nested-binding.rs | 0 .../pat-shadow-in-nested-binding.stderr | 12 + .../pattern}/pat-tuple-bad-type.rs | 0 src/test/ui/pattern/pat-tuple-bad-type.stderr | 24 + .../pattern}/pat-tuple-overfield.rs | 0 .../ui/pattern/pat-tuple-overfield.stderr | 34 + .../pattern}/patkind-litrange-no-expr.rs | 0 .../pattern/patkind-litrange-no-expr.stderr | 18 + .../pattern-binding-disambiguation.rs | 0 .../pattern-binding-disambiguation.stderr | 75 + .../pattern}/pattern-bindings-after-at.rs | 0 .../pattern/pattern-bindings-after-at.stderr | 9 + .../pattern}/pattern-error-continue.rs | 0 .../ui/pattern/pattern-error-continue.stderr | 39 + .../pattern}/pattern-ident-path-generics.rs | 0 .../pattern-ident-path-generics.stderr | 12 + .../pattern}/pattern-tyvar-2.rs | 0 src/test/ui/pattern/pattern-tyvar-2.stderr | 11 + .../pattern}/pattern-tyvar.rs | 0 src/test/ui/pattern/pattern-tyvar.stderr | 12 + .../{compile-fail => ui}/phantom-oibit.rs | 0 src/test/ui/phantom-oibit.stderr | 38 + .../platform-intrinsic-params.rs | 0 src/test/ui/platform-intrinsic-params.stderr | 9 + src/test/{compile-fail => ui}/pptypedef.rs | 0 src/test/ui/pptypedef.stderr | 15 + .../{compile-fail => ui}/prim-with-args.rs | 0 src/test/ui/prim-with-args.stderr | 136 + .../priv-in-bad-locations.rs | 0 src/test/ui/priv-in-bad-locations.stderr | 31 + .../associated-item-privacy-inherent.rs | 0 .../associated-item-privacy-inherent.stderr | 191 + .../privacy/associated-item-privacy-trait.rs | 0 .../associated-item-privacy-trait.stderr | 317 ++ .../associated-item-privacy-type-binding.rs | 0 ...ssociated-item-privacy-type-binding.stderr | 146 + .../privacy}/auxiliary/cci_class.rs | 0 .../privacy}/auxiliary/cci_class_5.rs | 0 .../auxiliary/privacy_tuple_struct.rs | 0 .../auxiliary/private-inferred-type.rs | 0 .../privacy/legacy-ctor-visibility.rs | 0 .../ui/privacy/legacy-ctor-visibility.stderr | 12 + .../privacy}/privacy-in-paths.rs | 0 src/test/ui/privacy/privacy-in-paths.stderr | 21 + .../privacy}/privacy-ns1.rs | 0 src/test/ui/privacy/privacy-ns1.stderr | 60 + .../privacy}/privacy-ns2.rs | 0 src/test/ui/privacy/privacy-ns2.stderr | 78 + .../privacy}/privacy-sanity.rs | 0 src/test/ui/privacy/privacy-sanity.stderr | 123 + .../privacy}/privacy-ufcs.rs | 0 src/test/ui/privacy/privacy-ufcs.stderr | 9 + .../{compile-fail => ui/privacy}/privacy1.rs | 0 src/test/ui/privacy/privacy1.stderr | 112 + .../{compile-fail => ui/privacy}/privacy2.rs | 0 src/test/ui/privacy/privacy2.stderr | 18 + .../{compile-fail => ui/privacy}/privacy3.rs | 0 src/test/ui/privacy/privacy3.stderr | 11 + .../{compile-fail => ui/privacy}/privacy4.rs | 0 src/test/ui/privacy/privacy4.stderr | 9 + .../{compile-fail => ui/privacy}/privacy5.rs | 0 src/test/ui/privacy/privacy5.stderr | 291 ++ .../privacy}/private-impl-method.rs | 0 .../ui/privacy/private-impl-method.stderr | 9 + .../privacy}/private-in-public-assoc-ty.rs | 0 .../privacy/private-in-public-assoc-ty.stderr | 52 + .../privacy}/private-in-public-ill-formed.rs | 0 .../private-in-public-ill-formed.stderr | 19 + .../privacy}/private-in-public-lint.rs | 0 .../ui/privacy/private-in-public-lint.stderr | 21 + .../privacy}/private-in-public-warn.rs | 0 .../ui/privacy/private-in-public-warn.stderr | 329 ++ .../privacy}/private-in-public.rs | 0 src/test/ui/privacy/private-in-public.stderr | 268 + .../privacy}/private-inferred-type-1.rs | 0 .../ui/privacy/private-inferred-type-1.stderr | 14 + .../privacy}/private-inferred-type-2.rs | 0 .../ui/privacy/private-inferred-type-2.stderr | 20 + .../privacy}/private-inferred-type-3.rs | 0 .../ui/privacy/private-inferred-type-3.stderr | 58 + .../privacy}/private-inferred-type.rs | 0 .../ui/privacy/private-inferred-type.stderr | 225 + .../privacy}/private-item-simple.rs | 0 .../ui/privacy/private-item-simple.stderr | 9 + .../privacy}/private-method-cross-crate.rs | 0 .../privacy/private-method-cross-crate.stderr | 9 + .../privacy}/private-method-inherited.rs | 0 .../privacy/private-method-inherited.stderr | 9 + .../privacy}/private-method.rs | 0 src/test/ui/privacy/private-method.stderr | 9 + .../private-struct-field-cross-crate.rs | 0 .../private-struct-field-cross-crate.stderr | 9 + .../privacy}/private-struct-field-ctor.rs | 0 .../privacy/private-struct-field-ctor.stderr | 9 + .../privacy}/private-struct-field-pattern.rs | 0 .../private-struct-field-pattern.stderr | 9 + .../privacy}/private-struct-field.rs | 0 .../ui/privacy/private-struct-field.stderr | 9 + .../privacy}/private-type-in-interface.rs | 0 .../privacy/private-type-in-interface.stderr | 68 + .../privacy}/private-variant-reexport.rs | 0 .../privacy/private-variant-reexport.stderr | 29 + .../restricted/auxiliary/pub_restricted.rs | 0 .../restricted/lookup-ignores-private.rs | 0 .../restricted/lookup-ignores-private.stderr | 12 + .../privacy/restricted/private-in-public.rs | 0 .../restricted/private-in-public.stderr | 21 + .../restricted/struct-literal-field.rs | 0 .../restricted/struct-literal-field.stderr | 9 + .../privacy/restricted/test.rs | 0 src/test/ui/privacy/restricted/test.stderr | 82 + .../privacy/union-field-privacy-1.rs | 0 .../ui/privacy/union-field-privacy-1.stderr | 15 + .../privacy/union-field-privacy-2.rs | 0 .../ui/privacy/union-field-privacy-2.stderr | 9 + src/test/{compile-fail => ui}/ptr-coercion.rs | 0 src/test/ui/ptr-coercion.stderr | 30 + src/test/ui/{ => pub}/pub-ident-fn-2.rs | 0 src/test/ui/{ => pub}/pub-ident-fn-2.stderr | 0 .../ui/{ => pub}/pub-ident-fn-or-struct-2.rs | 0 .../{ => pub}/pub-ident-fn-or-struct-2.stderr | 0 .../ui/{ => pub}/pub-ident-fn-or-struct.rs | 0 .../{ => pub}/pub-ident-fn-or-struct.stderr | 0 src/test/ui/{ => pub}/pub-ident-fn.fixed | 0 src/test/ui/{ => pub}/pub-ident-fn.rs | 0 src/test/ui/{ => pub}/pub-ident-fn.stderr | 0 src/test/ui/{ => pub}/pub-ident-struct.rs | 0 src/test/ui/{ => pub}/pub-ident-struct.stderr | 0 .../pub}/pub-reexport-priv-extern-crate.rs | 0 .../pub/pub-reexport-priv-extern-crate.stderr | 30 + .../qualified-path-params-2.rs | 0 .../qualified-path-params-2.stderr | 0 .../qualified}/qualified-path-params.rs | 0 .../ui/qualified/qualified-path-params.stderr | 19 + .../question-mark-type-infer.rs | 0 src/test/ui/question-mark-type-infer.stderr | 9 + .../quote-with-interpolated.rs | 0 src/test/ui/quote-with-interpolated.stderr | 11 + .../{compile-fail => ui/range}/range-1.rs | 0 src/test/ui/range/range-1.stderr | 28 + .../range-inclusive-pattern-precedence.rs | 0 .../range-inclusive-pattern-precedence.stderr | 0 .../range}/range_traits-1.rs | 0 src/test/ui/range/range_traits-1.stderr | 105 + .../range}/range_traits-2.rs | 0 src/test/ui/range/range_traits-2.stderr | 11 + .../range}/range_traits-3.rs | 0 src/test/ui/range/range_traits-3.stderr | 11 + .../range}/range_traits-4.rs | 0 src/test/ui/range/range_traits-4.stderr | 8 + .../range}/range_traits-5.rs | 0 src/test/ui/range/range_traits-5.stderr | 8 + .../range}/range_traits-6.rs | 0 src/test/ui/range/range_traits-6.stderr | 11 + .../range}/range_traits-7.rs | 0 src/test/ui/range/range_traits-7.stderr | 8 + src/test/ui/{ => raw}/raw-literal-keywords.rs | 2 - .../ui/{ => raw}/raw-literal-keywords.stderr | 6 +- src/test/ui/{ => raw}/raw-literal-self.rs | 2 - src/test/ui/{ => raw}/raw-literal-self.stderr | 2 +- .../ui/{ => raw}/raw-literal-underscore.rs | 0 .../{ => raw}/raw-literal-underscore.stderr | 0 src/test/ui/{ => raw}/raw_string.rs | 0 src/test/ui/{ => raw}/raw_string.stderr | 0 .../auxiliary/recursive_reexports.rs | 0 .../recursion}/recursion.rs | 0 src/test/ui/recursion/recursion.stderr | 14 + .../recursion}/recursive-enum.rs | 0 src/test/ui/recursion/recursive-enum.stderr | 13 + .../recursion}/recursive-reexports.rs | 0 .../ui/recursion/recursive-reexports.stderr | 9 + .../{ => recursion}/recursive-requirements.rs | 0 .../recursive-requirements.stderr | 0 .../recursion}/recursive-static-definition.rs | 0 .../recursive-static-definition.stderr | 11 + .../recursive-types-are-not-uninhabited.rs | 0 ...recursive-types-are-not-uninhabited.stderr | 9 + src/test/ui/ref-suggestion.nll.stderr | 34 + .../{compile-fail => ui}/ref-suggestion.rs | 0 src/test/ui/ref-suggestion.stderr | 34 + .../refutable-pattern-errors.rs | 0 src/test/ui/refutable-pattern-errors.stderr | 15 + .../refutable-pattern-in-fn-arg.rs | 0 .../ui/refutable-pattern-in-fn-arg.stderr | 9 + ...borrow-params-issue-29793-small.nll.stderr | 279 -- ...egions-fn-subtyping-return-static-fail.rs} | 0 ...ons-fn-subtyping-return-static-fail.stderr | 21 + src/test/ui/regions-nested-fns-2.nll.stderr | 16 - .../auxiliary/rbmtp_cross_crate_lib.rs | 0 ...rrow-params-issue-29793-big.ast.nll.stderr | 25 + ...n-borrow-params-issue-29793-big.ast.stderr | 29 + ...n-borrow-params-issue-29793-big.mir.stderr | 25 + .../region-borrow-params-issue-29793-big.rs | 0 ...borrow-params-issue-29793-small.nll.stderr | 319 ++ .../region-borrow-params-issue-29793-small.rs | 0 ...ion-borrow-params-issue-29793-small.stderr | 0 ...gion-bound-extra-bound-in-inherent-impl.rs | 0 ...-bound-extra-bound-in-inherent-impl.stderr | 8 + ...-bound-on-closure-outlives-call.nll.stderr | 14 + .../region-bound-on-closure-outlives-call.rs | 0 ...gion-bound-on-closure-outlives-call.stderr | 11 + ...ion-bound-same-bounds-in-trait-and-impl.rs | 0 ...bound-same-bounds-in-trait-and-impl.stderr | 8 + ...n-bounds-on-objects-and-type-parameters.rs | 0 ...unds-on-objects-and-type-parameters.stderr | 35 + ...nvariant-static-error-reporting.nll.stderr | 11 + ...region-invariant-static-error-reporting.rs | 0 ...on-invariant-static-error-reporting.stderr | 23 + ...time-bounds-on-fns-where-clause.nll.stderr | 12 + ...ion-lifetime-bounds-on-fns-where-clause.rs | 0 ...lifetime-bounds-on-fns-where-clause.stderr | 31 + ...time-bounds-on-fns-where-clause.nll.stderr | 12 + ...ple-lifetime-bounds-on-fns-where-clause.rs | 0 ...lifetime-bounds-on-fns-where-clause.stderr | 42 + .../regions}/region-object-lifetime-1.rs | 0 .../regions/region-object-lifetime-1.stderr | 8 + .../region-object-lifetime-2.nll.stderr | 12 + .../regions}/region-object-lifetime-2.rs | 0 .../regions/region-object-lifetime-2.stderr | 30 + .../regions}/region-object-lifetime-3.rs | 0 .../regions/region-object-lifetime-3.stderr | 8 + .../region-object-lifetime-4.nll.stderr | 12 + .../regions}/region-object-lifetime-4.rs | 0 .../regions/region-object-lifetime-4.stderr | 30 + .../region-object-lifetime-5.nll.stderr | 13 + .../regions}/region-object-lifetime-5.rs | 0 .../regions/region-object-lifetime-5.stderr | 13 + ...ion-object-lifetime-in-coercion.nll.stderr | 38 + .../region-object-lifetime-in-coercion.rs | 0 .../region-object-lifetime-in-coercion.stderr | 52 + .../ui/regions/regions-addr-of-arg.nll.stderr | 27 + .../regions}/regions-addr-of-arg.rs | 0 .../ui/regions/regions-addr-of-arg.stderr | 27 + .../regions/regions-addr-of-self.nll.stderr | 10 + .../regions}/regions-addr-of-self.rs | 0 .../ui/regions/regions-addr-of-self.stderr | 29 + .../regions-addr-of-upvar-self.nll.stderr | 46 + .../regions}/regions-addr-of-upvar-self.rs | 0 .../regions/regions-addr-of-upvar-self.stderr | 26 + .../regions-adjusted-lvalue-op.nll.stderr | 23 + .../regions}/regions-adjusted-lvalue-op.rs | 0 .../regions/regions-adjusted-lvalue-op.stderr | 21 + ...c-type-in-supertrait-outlives-container.rs | 2 + ...pe-in-supertrait-outlives-container.stderr | 20 + ...ssoc-type-region-bound-in-trait-not-met.rs | 0 ...-type-region-bound-in-trait-not-met.stderr | 49 + ...ssoc-type-static-bound-in-trait-not-met.rs | 0 ...-type-static-bound-in-trait-not-met.stderr | 24 + ...gions-bounded-by-trait-requiring-static.rs | 2 + ...s-bounded-by-trait-requiring-static.stderr | 51 + ...hod-type-parameters-cross-crate.nll.stderr | 13 + ...nded-method-type-parameters-cross-crate.rs | 0 ...-method-type-parameters-cross-crate.stderr | 12 + ...hod-type-parameters-trait-bound.nll.stderr | 13 + ...nded-method-type-parameters-trait-bound.rs | 0 ...-method-type-parameters-trait-bound.stderr | 12 + .../regions-bounded-method-type-parameters.rs | 2 + ...ions-bounded-method-type-parameters.stderr | 11 + src/test/ui/regions/regions-bounds.nll.stderr | 22 + .../regions}/regions-bounds.rs | 0 src/test/ui/regions/regions-bounds.stderr | 41 + ...ose-associated-type-into-object.nll.stderr | 36 + ...gions-close-associated-type-into-object.rs | 0 ...s-close-associated-type-into-object.stderr | 56 + ...ions-close-object-into-object-1.nll.stderr | 13 + .../regions-close-object-into-object-1.rs | 0 .../regions-close-object-into-object-1.stderr | 13 + ...ions-close-object-into-object-2.nll.stderr | 21 + .../regions-close-object-into-object-2.rs | 0 .../regions-close-object-into-object-2.stderr | 24 + ...ions-close-object-into-object-3.nll.stderr | 13 + .../regions-close-object-into-object-3.rs | 0 .../regions-close-object-into-object-3.stderr | 13 + ...ions-close-object-into-object-4.nll.stderr | 38 + .../regions-close-object-into-object-4.rs | 0 .../regions-close-object-into-object-4.stderr | 24 + ...ions-close-object-into-object-5.nll.stderr | 31 + .../regions-close-object-into-object-5.rs | 0 .../regions-close-object-into-object-5.stderr | 93 + ...ons-close-over-type-parameter-1.nll.stderr | 20 + .../regions-close-over-type-parameter-1.rs | 0 ...regions-close-over-type-parameter-1.stderr | 60 + ...se-over-type-parameter-multiple.nll.stderr | 11 + ...ions-close-over-type-parameter-multiple.rs | 0 ...-close-over-type-parameter-multiple.stderr | 28 + ...regions-close-param-into-object.nll.stderr | 36 + .../regions-close-param-into-object.rs | 0 .../regions-close-param-into-object.stderr | 64 + .../regions/regions-creating-enums.nll.stderr | 31 + .../regions}/regions-creating-enums.rs | 0 .../ui/regions/regions-creating-enums.stderr | 33 + .../regions-creating-enums3.nll.stderr | 12 + .../regions}/regions-creating-enums3.rs | 0 .../ui/regions/regions-creating-enums3.stderr | 13 + .../regions-creating-enums4.nll.stderr | 12 + .../regions}/regions-creating-enums4.rs | 0 .../ui/regions/regions-creating-enums4.stderr | 26 + ...egions-early-bound-error-method.nll.stderr | 12 + .../regions-early-bound-error-method.rs | 0 .../regions-early-bound-error-method.stderr | 20 + .../regions-early-bound-error.nll.stderr | 12 + .../regions}/regions-early-bound-error.rs | 0 .../regions/regions-early-bound-error.stderr | 20 + src/test/ui/regions/regions-enum-not-wf.rs | 50 + .../ui/regions/regions-enum-not-wf.stderr | 67 + .../regions/regions-escape-method.nll.stderr | 11 + .../regions}/regions-escape-method.rs | 0 .../ui/regions/regions-escape-method.stderr | 28 + ...regions-escape-via-trait-or-not.nll.stderr | 11 + .../regions-escape-via-trait-or-not.rs | 0 .../regions-escape-via-trait-or-not.stderr | 28 + .../regions-fn-subtyping-return-static.rs | 0 .../regions-fn-subtyping-return-static.stderr | 0 .../regions-free-region-ordering-callee-4.rs | 0 ...gions-free-region-ordering-callee-4.stderr | 24 + ...ons-free-region-ordering-callee.nll.stderr | 24 + .../regions-free-region-ordering-callee.rs | 0 ...regions-free-region-ordering-callee.stderr | 25 + .../regions-free-region-ordering-caller.rs | 2 + ...regions-free-region-ordering-caller.stderr | 32 + ...ns-free-region-ordering-caller1.nll.stderr | 18 + .../regions-free-region-ordering-caller1.rs | 0 ...egions-free-region-ordering-caller1.stderr | 33 + ...-free-region-ordering-incorrect.nll.stderr | 15 + .../regions-free-region-ordering-incorrect.rs | 0 ...ions-free-region-ordering-incorrect.stderr | 33 + .../regions}/regions-glb-free-free.rs | 0 .../ui/regions/regions-glb-free-free.stderr | 16 + ...regions-implied-bounds-projection-gap-1.rs | 2 + ...ons-implied-bounds-projection-gap-1.stderr | 18 + ...regions-implied-bounds-projection-gap-2.rs | 0 ...ons-implied-bounds-projection-gap-2.stderr | 8 + ...regions-implied-bounds-projection-gap-3.rs | 0 ...ons-implied-bounds-projection-gap-3.stderr | 8 + ...regions-implied-bounds-projection-gap-4.rs | 0 ...ons-implied-bounds-projection-gap-4.stderr | 8 + ...ions-implied-bounds-projection-gap-hr-1.rs | 0 ...-implied-bounds-projection-gap-hr-1.stderr | 23 + .../regions}/regions-in-enums-anon.rs | 0 .../ui/regions/regions-in-enums-anon.stderr | 9 + .../regions}/regions-in-enums.rs | 0 src/test/ui/regions/regions-in-enums.stderr | 15 + .../regions}/regions-in-structs-anon.rs | 0 .../ui/regions/regions-in-structs-anon.stderr | 9 + .../regions}/regions-in-structs.rs | 0 src/test/ui/regions/regions-in-structs.stderr | 15 + .../regions}/regions-infer-at-fn-not-param.rs | 0 .../regions-infer-at-fn-not-param.stderr | 11 + ...ions-infer-borrow-scope-too-big.nll.stderr | 18 + .../regions-infer-borrow-scope-too-big.rs | 0 .../regions-infer-borrow-scope-too-big.stderr | 18 + ...ons-infer-bound-from-trait-self.nll.stderr | 11 + .../regions-infer-bound-from-trait-self.rs | 0 ...regions-infer-bound-from-trait-self.stderr | 16 + .../regions-infer-bound-from-trait.nll.stderr | 19 + .../regions-infer-bound-from-trait.rs | 0 .../regions-infer-bound-from-trait.stderr | 31 + .../regions/regions-infer-call-3.nll.stderr | 11 + .../regions}/regions-infer-call-3.rs | 0 .../ui/regions/regions-infer-call-3.stderr | 30 + ...egions-infer-contravariance-due-to-decl.rs | 2 + ...ns-infer-contravariance-due-to-decl.stderr | 15 + .../regions-infer-covariance-due-to-decl.rs | 2 + ...egions-infer-covariance-due-to-decl.stderr | 14 + ...ns-infer-invariance-due-to-decl.nll.stderr | 10 + .../regions-infer-invariance-due-to-decl.rs | 0 ...egions-infer-invariance-due-to-decl.stderr | 18 + ...-invariance-due-to-mutability-3.nll.stderr | 10 + ...ns-infer-invariance-due-to-mutability-3.rs | 0 ...nfer-invariance-due-to-mutability-3.stderr | 18 + ...-invariance-due-to-mutability-4.nll.stderr | 10 + ...ns-infer-invariance-due-to-mutability-4.rs | 0 ...nfer-invariance-due-to-mutability-4.stderr | 18 + .../regions-infer-not-param.nll.stderr | 26 + .../regions}/regions-infer-not-param.rs | 0 .../ui/regions/regions-infer-not-param.stderr | 60 + .../regions-infer-paramd-indirect.nll.stderr | 12 + .../regions}/regions-infer-paramd-indirect.rs | 0 .../regions-infer-paramd-indirect.stderr | 28 + ...regions-infer-proc-static-upvar.nll.stderr | 14 + .../regions-infer-proc-static-upvar.rs | 0 .../regions-infer-proc-static-upvar.stderr | 14 + .../regions-lifetime-bounds-on-fns.nll.stderr | 12 + .../regions-lifetime-bounds-on-fns.rs | 0 .../regions-lifetime-bounds-on-fns.stderr | 31 + ...ions-lifetime-of-struct-or-enum-variant.rs | 0 ...-lifetime-of-struct-or-enum-variant.stderr | 33 + .../regions}/regions-name-duplicated.rs | 0 .../ui/regions/regions-name-duplicated.stderr | 11 + .../regions}/regions-name-static.rs | 0 .../ui/regions/regions-name-static.stderr | 9 + .../regions}/regions-name-undeclared.rs | 0 .../ui/regions/regions-name-undeclared.stderr | 69 + .../regions/regions-nested-fns-2.nll.stderr | 17 + .../ui/{ => regions}/regions-nested-fns-2.rs | 0 .../{ => regions}/regions-nested-fns-2.stderr | 0 .../ui/regions/regions-nested-fns.nll.stderr | 48 + .../regions}/regions-nested-fns.rs | 0 src/test/ui/regions/regions-nested-fns.stderr | 61 + .../regions-normalize-in-where-clause-list.rs | 0 ...ions-normalize-in-where-clause-list.stderr | 26 + ...s-outlives-nominal-type-enum-region-rev.rs | 5 +- ...gions-outlives-nominal-type-enum-region.rs | 5 +- ...ons-outlives-nominal-type-enum-type-rev.rs | 7 +- ...regions-outlives-nominal-type-enum-type.rs | 5 +- ...outlives-nominal-type-struct-region-rev.rs | 5 +- ...ons-outlives-nominal-type-struct-region.rs | 3 +- ...s-outlives-nominal-type-struct-type-rev.rs | 3 +- ...gions-outlives-nominal-type-struct-type.rs | 3 +- ...lives-projection-container-hrtb.nll.stderr | 9 + ...ions-outlives-projection-container-hrtb.rs | 0 ...-outlives-projection-container-hrtb.stderr | 37 + ...egions-outlives-projection-container-wc.rs | 2 + ...ns-outlives-projection-container-wc.stderr | 20 + .../regions-outlives-projection-container.rs | 4 + ...gions-outlives-projection-container.stderr | 71 + .../regions-outlives-projection-hrtype.rs | 0 .../regions-outlives-projection-hrtype.stderr | 8 + .../regions-outlives-projection-trait-def.rs | 0 ...gions-outlives-projection-trait-def.stderr | 8 + .../regions}/regions-outlives-scalar.rs | 0 .../ui/regions/regions-outlives-scalar.stderr | 8 + ...ions-pattern-typing-issue-19552.nll.stderr | 14 + .../regions-pattern-typing-issue-19552.rs | 0 .../regions-pattern-typing-issue-19552.stderr | 14 + ...-pattern-typing-issue-19997.ast.nll.stderr | 15 + ...ions-pattern-typing-issue-19997.ast.stderr | 12 + ...ions-pattern-typing-issue-19997.mir.stderr | 15 + .../regions-pattern-typing-issue-19997.rs | 0 .../regions}/regions-proc-bound-capture.rs | 0 .../regions/regions-proc-bound-capture.stderr | 12 + ...ow-from-shorter-mut-ref-mut-ref.nll.stderr | 12 + ...s-reborrow-from-shorter-mut-ref-mut-ref.rs | 0 ...borrow-from-shorter-mut-ref-mut-ref.stderr | 13 + ...s-reborrow-from-shorter-mut-ref.nll.stderr | 12 + .../regions-reborrow-from-shorter-mut-ref.rs | 0 ...gions-reborrow-from-shorter-mut-ref.stderr | 13 + .../regions/regions-ref-in-fn-arg.nll.stderr | 22 + .../regions}/regions-ref-in-fn-arg.rs | 0 .../ui/regions/regions-ref-in-fn-arg.stderr | 24 + .../regions/regions-ret-borrowed-1.nll.stderr | 11 + .../regions}/regions-ret-borrowed-1.rs | 0 .../ui/regions/regions-ret-borrowed-1.stderr | 28 + .../regions/regions-ret-borrowed.nll.stderr | 11 + .../regions}/regions-ret-borrowed.rs | 0 .../ui/regions/regions-ret-borrowed.stderr | 28 + src/test/ui/regions/regions-ret.nll.stderr | 19 + .../regions}/regions-ret.rs | 0 src/test/ui/regions/regions-ret.stderr | 20 + ...return-ref-to-upvar-issue-17403.nll.stderr | 13 + ...regions-return-ref-to-upvar-issue-17403.rs | 0 ...ons-return-ref-to-upvar-issue-17403.stderr | 30 + .../regions-return-stack-allocated-vec.rs | 0 .../regions-return-stack-allocated-vec.stderr | 13 + .../regions-static-bound.ll.nll.stderr | 49 + .../ui/regions/regions-static-bound.ll.stderr | 34 + .../regions/regions-static-bound.nll.stderr | 49 + src/test/ui/regions/regions-static-bound.rs | 32 + .../regions/regions-steal-closure.nll.stderr | 15 + .../regions}/regions-steal-closure.rs | 0 .../ui/regions/regions-steal-closure.stderr | 16 + src/test/ui/regions/regions-struct-not-wf.rs | 38 + .../ui/regions/regions-struct-not-wf.stderr | 49 + .../regions}/regions-trait-1.rs | 0 src/test/ui/regions/regions-trait-1.stderr | 24 + .../regions-trait-object-subtyping.nll.stderr | 24 + .../regions-trait-object-subtyping.rs | 0 .../regions-trait-object-subtyping.stderr | 65 + .../regions/regions-trait-variance.nll.stderr | 18 + .../regions}/regions-trait-variance.rs | 0 .../ui/regions/regions-trait-variance.stderr | 18 + .../regions}/regions-undeclared.rs | 0 src/test/ui/regions/regions-undeclared.stderr | 33 + .../regions-var-type-out-of-scope.nll.stderr | 16 + .../regions}/regions-var-type-out-of-scope.rs | 0 .../regions-var-type-out-of-scope.stderr | 16 + ...ariant-use-covariant-in-second-position.rs | 2 + ...nt-use-covariant-in-second-position.stderr | 14 + ...ns-variance-contravariant-use-covariant.rs | 2 + ...ariance-contravariant-use-covariant.stderr | 15 + ...ns-variance-covariant-use-contravariant.rs | 2 + ...ariance-covariant-use-contravariant.stderr | 14 + ...ns-variance-invariant-use-contravariant.rs | 2 + ...ariance-invariant-use-contravariant.stderr | 14 + ...egions-variance-invariant-use-covariant.rs | 2 + ...ns-variance-invariant-use-covariant.stderr | 18 + .../regions}/regions-wf-trait-object.rs | 0 .../ui/regions/regions-wf-trait-object.stderr | 20 + .../reject-specialized-drops-8142.rs | 0 .../ui/reject-specialized-drops-8142.stderr | 115 + src/test/ui/removing-extern-crate.fixed | 2 +- src/test/ui/removing-extern-crate.rs | 8 +- src/test/ui/removing-extern-crate.stderr | 12 +- .../repeat-to-run-dtor-twice.rs | 0 src/test/ui/repeat-to-run-dtor-twice.stderr | 11 + src/test/{compile-fail => ui}/repeat_count.rs | 0 src/test/ui/repeat_count.stderr | 64 + .../ui/{ => repr}/repr-align-assign.fixed | 0 src/test/ui/{ => repr}/repr-align-assign.rs | 0 .../ui/{ => repr}/repr-align-assign.stderr | 0 .../{compile-fail => ui/repr}/repr-align.rs | 0 src/test/ui/repr/repr-align.stderr | 21 + .../repr}/repr-packed-contains-align.rs | 0 .../ui/repr/repr-packed-contains-align.stderr | 59 + .../repr}/repr-transparent-other-items.rs | 2 + .../repr/repr-transparent-other-items.stderr | 69 + .../repr}/repr-transparent-other-reprs.rs | 4 +- .../repr/repr-transparent-other-reprs.stderr | 29 + .../repr}/repr-transparent.rs | 4 +- src/test/ui/repr/repr-transparent.stderr | 72 + .../required-lang-item.rs | 0 src/test/ui/required-lang-item.stderr | 4 + .../reserved}/reserved-attr-on-macro.rs | 0 .../ui/reserved/reserved-attr-on-macro.stderr | 11 + .../reserved}/reserved-become.rs | 0 src/test/ui/reserved/reserved-become.stderr | 8 + src/test/ui/resolve/issue-5035-2.stderr | 3 +- .../resolve}/resolve-bad-import-prefix.rs | 0 .../resolve/resolve-bad-import-prefix.stderr | 24 + .../resolve}/resolve-bad-visibility.rs | 0 .../ui/resolve/resolve-bad-visibility.stderr | 34 + ...e-conflict-extern-crate-vs-extern-crate.rs | 0 ...nflict-extern-crate-vs-extern-crate.stderr | 15 + ...resolve-conflict-import-vs-extern-crate.rs | 0 ...lve-conflict-import-vs-extern-crate.stderr | 15 + .../resolve-conflict-import-vs-import.rs | 0 .../resolve-conflict-import-vs-import.stderr | 17 + .../resolve-conflict-item-vs-extern-crate.rs | 0 ...solve-conflict-item-vs-extern-crate.stderr | 15 + .../resolve-conflict-item-vs-import.rs | 0 .../resolve-conflict-item-vs-import.stderr | 0 .../resolve-conflict-type-vs-import.rs | 0 .../resolve-conflict-type-vs-import.stderr | 18 + .../resolve-inconsistent-binding-mode.rs | 0 .../resolve-inconsistent-binding-mode.stderr | 53 + .../resolve-inconsistent-names.rs | 0 .../resolve-inconsistent-names.stderr | 0 .../resolve}/resolve-label.rs | 0 src/test/ui/resolve/resolve-label.stderr | 9 + .../resolve}/resolve-primitive-fallback.rs | 0 .../resolve/resolve-primitive-fallback.stderr | 22 + .../resolve}/resolve-self-in-impl-2.rs | 0 .../ui/resolve/resolve-self-in-impl-2.stderr | 16 + .../resolve}/resolve-self-in-impl.rs | 0 .../ui/resolve/resolve-self-in-impl.stderr | 43 + .../resolve-type-param-in-item-in-trait.rs | 0 ...resolve-type-param-in-item-in-trait.stderr | 45 + .../resolve}/resolve-unknown-trait.rs | 2 + .../ui/resolve/resolve-unknown-trait.stderr | 21 + .../resolve}/resolve-variant-assoc-item.rs | 0 .../resolve/resolve-variant-assoc-item.stderr | 15 + .../ui/resolve/token-error-correct-2.stderr | 11 +- .../ui/resolve/token-error-correct-3.stderr | 13 +- src/test/ui/resolve/token-error-correct.rs | 1 - .../ui/resolve/token-error-correct.stderr | 25 +- src/test/ui/resolve/tuple-struct-alias.rs | 9 - src/test/ui/resolve/tuple-struct-alias.stderr | 22 +- .../resolve_self_super_hint.rs | 2 + src/test/ui/resolve_self_super_hint.stderr | 27 + src/test/{compile-fail => ui}/ret-non-nil.rs | 0 src/test/ui/ret-non-nil.stderr | 9 + src/test/{compile-fail => ui}/retslot-cast.rs | 0 src/test/ui/retslot-cast.stderr | 12 + .../return}/return-from-diverging.rs | 0 .../ui/return/return-from-diverging.stderr | 12 + .../{ => return}/return-match-array-const.rs | 0 .../return-match-array-const.stderr | 0 src/test/ui/{ => return}/return-type.rs | 0 src/test/ui/{ => return}/return-type.stderr | 0 .../return}/return-unit-from-diverging.rs | 0 .../return/return-unit-from-diverging.stderr | 9 + .../termination-trait-main-i32.rs | 0 .../termination-trait-main-i32.stderr | 11 + .../termination-trait-not-satisfied.rs | 0 .../termination-trait-not-satisfied.stderr | 11 + .../termination-trait-test-wrong-type.stderr | 2 +- .../borrowck-issue-49631.nll.stderr | 2 +- .../auxiliary/enums.rs | 0 .../auxiliary/structs.rs | 0 .../auxiliary/variants.rs | 0 .../rfc-2008-non-exhaustive/enum.rs | 0 .../ui/rfc-2008-non-exhaustive/enum.stderr | 9 + .../invalid-attribute.rs | 0 .../invalid-attribute.stderr | 34 + .../rfc-2008-non-exhaustive/structs.rs | 0 .../ui/rfc-2008-non-exhaustive/structs.stderr | 64 + .../rfc-2008-non-exhaustive/variants.rs | 0 .../variants_create.rs | 0 .../variants_create.stderr | 20 + .../ui/rfc-2093-infer-outlives/cross-crate.rs | 3 +- .../cross-crate.stderr | 4 +- .../dont-infer-static.rs | 4 +- .../dont-infer-static.stderr | 8 +- src/test/ui/rfc-2093-infer-outlives/enum.rs | 18 +- .../ui/rfc-2093-infer-outlives/enum.stderr | 47 +- .../rfc-2093-infer-outlives/explicit-dyn.rs | 3 +- .../explicit-dyn.stderr | 4 +- .../rfc-2093-infer-outlives/explicit-enum.rs | 3 +- .../explicit-enum.stderr | 4 +- .../explicit-projection.rs | 1 - .../explicit-projection.stderr | 2 +- .../explicit-struct.rs | 3 +- .../explicit-struct.stderr | 4 +- .../rfc-2093-infer-outlives/explicit-union.rs | 4 +- .../explicit-union.stderr | 4 +- .../rfc-2093-infer-outlives/infer-static.rs | 3 +- .../infer-static.stderr | 4 +- .../ui/rfc-2093-infer-outlives/nested-enum.rs | 4 +- .../nested-enum.stderr | 4 +- .../rfc-2093-infer-outlives/nested-regions.rs | 3 +- .../nested-regions.stderr | 4 +- .../rfc-2093-infer-outlives/nested-structs.rs | 3 +- .../nested-structs.stderr | 4 +- .../rfc-2093-infer-outlives/nested-union.rs | 4 +- .../nested-union.stderr | 4 +- .../ui/rfc-2093-infer-outlives/privacy.rs | 20 + .../ui/rfc-2093-infer-outlives/projection.rs | 1 - .../rfc-2093-infer-outlives/projection.stderr | 2 +- .../ui/rfc-2093-infer-outlives/reference.rs | 1 - .../rfc-2093-infer-outlives/reference.stderr | 2 +- .../regions-enum-not-wf.rs | 50 + .../regions-enum-not-wf.stderr | 67 + ...egions-outlives-nominal-type-region-rev.rs | 32 + ...ns-outlives-nominal-type-region-rev.stderr | 20 + .../regions-outlives-nominal-type-region.rs | 32 + ...egions-outlives-nominal-type-region.stderr | 20 + .../regions-outlives-nominal-type-type-rev.rs | 32 + ...ions-outlives-nominal-type-type-rev.stderr | 20 + .../regions-outlives-nominal-type-type.rs | 32 + .../regions-outlives-nominal-type-type.stderr | 20 + .../regions-struct-not-wf.rs | 38 + .../regions-struct-not-wf.stderr | 49 + .../ui/rfc-2093-infer-outlives/self-dyn.rs | 3 +- .../rfc-2093-infer-outlives/self-dyn.stderr | 4 +- .../rfc-2093-infer-outlives/self-structs.rs | 3 +- .../self-structs.stderr | 4 +- .../crate-path-non-absolute.rs | 1 + .../crate-path-non-absolute.stderr | 15 + .../keyword-crate-as-identifier.rs | 3 +- .../keyword-crate-as-identifier.stderr | 9 + .../auxiliary/xcrate.rs | 0 .../ui/rfc-2126-extern-absolute-paths/meta.rs | 17 + .../meta.stderr | 9 + .../non-existent-1.rs | 15 + .../non-existent-1.stderr | 9 + .../non-existent-2.rs | 16 + .../non-existent-2.stderr | 9 + .../non-existent-3.rs | 15 + .../non-existent-3.stderr | 9 + .../not-whitelisted.rs | 19 + .../not-whitelisted.stderr | 21 + .../single-segment.rs | 21 + .../single-segment.stderr | 21 + .../auxiliary/xcrate.rs | 0 .../non-existent-1.rs | 15 + .../non-existent-1.stderr | 9 + .../non-existent-2.rs | 16 + .../non-existent-2.stderr | 9 + .../non-existent-3.rs | 15 + .../non-existent-3.stderr | 9 + .../single-segment.rs | 23 + .../single-segment.stderr | 22 + .../ui/rfc-2166-underscore-imports/basic.rs | 2 +- .../rfc-2166-underscore-imports/basic.stderr | 12 - .../ui/rfc-2306/convert-id-const-no-gate.rs | 17 + .../rfc-2306/convert-id-const-no-gate.stderr | 10 + .../ui/rfc-2306/convert-id-const-with-gate.rs | 20 + .../syntax-ambiguity-2015.rs | 49 + .../syntax-ambiguity-2015.stderr | 56 + .../syntax-ambiguity-2018.rs | 49 + .../syntax-ambiguity-2018.stderr | 56 + .../ui/rfc1445/feature-gate.no_gate.stderr | 11 + .../rfc1445/feature-gate.rs | 0 .../ui/rfc1445/feature-gate.with_gate.stderr | 14 + .../rfc1445/match-forbidden-without-eq.rs | 0 .../rfc1445/match-forbidden-without-eq.stderr | 18 + .../match-requires-both-partialeq-and-eq.rs | 0 ...atch-requires-both-partialeq-and-eq.stderr | 8 + .../collections.rs | 5 +- .../collections.stderr | 16 +- .../construct_with_other_type.rs | 5 +- .../construct_with_other_type.stderr | 12 +- .../empty_generics.rs | 1 + .../empty_generics.stderr | 8 +- .../gat-incomplete-warning.rs | 16 + .../gat-incomplete-warning.stderr | 6 + .../generic-associated-types-where.stderr | 6 + ...ic_associated_type_undeclared_lifetimes.rs | 5 +- ...ssociated_type_undeclared_lifetimes.stderr | 16 +- .../iterable.rs | 5 +- .../iterable.stderr | 18 +- .../parameter_number_and_kind.rs | 7 +- .../parameter_number_and_kind.stderr | 16 +- .../pointer_family.rs | 3 +- .../pointer_family.stderr | 14 +- .../shadowing.rs | 2 +- .../shadowing.stderr | 6 + .../streaming_iterator.rs | 3 +- .../streaming_iterator.stderr | 16 +- src/test/{compile-fail => ui}/rfc1623.rs | 0 src/test/ui/rfc1623.stderr | 19 + .../rfc1717/missing-link-attr.rs | 0 src/test/ui/rfc1717/missing-link-attr.stderr | 4 + .../rfc1717/multiple-renames.rs | 0 src/test/ui/rfc1717/multiple-renames.stderr | 4 + .../rfc1717/rename-to-empty.rs | 0 src/test/ui/rfc1717/rename-to-empty.stderr | 4 + .../{compile-fail => ui}/rmeta-lib-pass.rs | 0 src/test/{compile-fail => ui}/rmeta-pass.rs | 0 .../{compile-fail => ui}/rmeta-priv-warn.rs | 0 src/test/{compile-fail => ui}/rmeta.rs | 0 src/test/ui/rmeta.stderr | 9 + src/test/{compile-fail => ui}/rmeta_lib.rs | 0 src/test/ui/rmeta_lib.stderr | 4 + .../{compile-fail => ui}/rmeta_meta_main.rs | 0 src/test/ui/rmeta_meta_main.stderr | 9 + .../allocator/auxiliary/custom-as-global.rs | 0 .../ui/run-pass/allocator/auxiliary/custom.rs | 31 + .../run-pass/allocator/auxiliary/helper.rs | 0 src/test/ui/run-pass/allocator/custom.rs | 68 + .../{ => ui}/run-pass/allocator/xcrate-use.rs | 2 + .../run-pass/allocator/xcrate-use2.rs | 4 +- .../run-pass/array-slice-vec}/arr_cycle.rs | 2 + .../array-slice-vec}/array_const_index-1.rs | 3 + .../box-of-array-of-drop-1.rs | 3 + .../box-of-array-of-drop-2.rs | 3 + .../array-slice-vec}/cast-in-array-size.rs | 2 + .../check-static-mut-slices.rs | 2 + .../array-slice-vec}/check-static-slice.rs | 2 + .../array-slice-vec}/copy-out-of-array-1.rs | 2 + .../array-slice-vec}/destructure-array-1.rs | 2 + .../array-slice-vec}/empty-mutable-vec.rs | 2 + .../run-pass/array-slice-vec}/estr-slice.rs | 2 + .../run-pass/array-slice-vec}/evec-slice.rs | 2 +- .../array-slice-vec}/fixed_length_copy.rs | 2 + .../array-slice-vec}/huge-largest-array.rs | 2 + .../array-slice-vec}/ivec-pass-by-value.rs | 2 + ...ility-inherits-through-fixed-length-vec.rs | 2 + .../array-slice-vec}/mutable-alias-vec.rs | 2 + .../run-pass/array-slice-vec}/nested-vec-1.rs | 2 + .../run-pass/array-slice-vec}/nested-vec-2.rs | 2 + .../run-pass/array-slice-vec}/nested-vec-3.rs | 3 + .../new-style-fixed-length-vec.rs | 2 + .../rcvr-borrowed-to-slice.rs | 3 + .../repeated-vector-syntax.rs | 2 + .../array-slice-vec}/show-boxed-slice.rs | 2 + .../run-pass/array-slice-vec}/slice-2.rs | 2 + .../slice-of-zero-size-elements.rs | 3 + .../array-slice-vec}/slice-panic-1.rs | 2 + .../array-slice-vec}/slice-panic-2.rs | 2 + src/test/ui/run-pass/array-slice-vec/slice.rs | 90 + .../array-slice-vec}/slice_binary_search.rs | 2 + .../variance-vec-covariant.rs | 4 +- .../run-pass/array-slice-vec}/vec-concat.rs | 2 + .../run-pass/array-slice-vec}/vec-dst.rs | 2 +- .../array-slice-vec}/vec-fixed-length.rs | 2 + .../run-pass/array-slice-vec}/vec-growth.rs | 2 + .../array-slice-vec}/vec-late-init.rs | 2 + .../array-slice-vec}/vec-macro-no-std.rs | 2 + .../array-slice-vec}/vec-macro-repeat.rs | 2 + .../vec-macro-rvalue-scope.rs | 2 + .../vec-macro-with-brackets.rs | 2 + .../vec-macro-with-trailing-comma.rs | 2 + .../vec-matching-autoslice.rs | 3 + .../array-slice-vec}/vec-matching-fixed.rs | 2 + .../array-slice-vec}/vec-matching-fold.rs | 2 + .../vec-matching-legal-tail-element-borrow.rs | 2 + .../run-pass/array-slice-vec}/vec-matching.rs | 2 + .../run-pass/array-slice-vec}/vec-push.rs | 2 + .../array-slice-vec}/vec-repeat-with-cast.rs | 2 + .../array-slice-vec}/vec-slice-drop.rs | 4 + .../run-pass/array-slice-vec}/vec-slice.rs | 2 + .../array-slice-vec}/vec-tail-matching.rs | 2 + .../run-pass/array-slice-vec}/vec-to_str.rs | 2 + .../run-pass/array-slice-vec}/vec.rs | 2 + .../run-pass/array-slice-vec}/vec_cycle.rs | 2 + .../array-slice-vec}/vec_cycle_wrapped.rs | 2 + .../array-slice-vec}/vector-no-ann-2.rs | 3 +- .../associated-const-const-eval.rs | 1 + ...associated-const-cross-crate-const-eval.rs | 1 + .../associated-const-cross-crate-defaults.rs | 1 + .../associated-const-cross-crate.rs | 1 + .../associated-const-in-global-const.rs | 1 + .../associated-const-inherent-impl.rs | 1 + .../associated-const-marks-live-code.rs | 1 + .../associated-const-match-patterns.rs | 1 + .../associated-const-outer-ty-refs.rs | 1 + .../associated-const-overwrite-default.rs | 1 + .../associated-const-public-impl.rs | 1 + .../associated-const-range-match-patterns.rs | 1 + .../associated-const-resolution-order.rs | 1 + .../associated-const-self-type.rs | 1 + .../associated-const-type-parameters.rs | 1 + .../associated-const-ufcs-infer-trait.rs | 1 + .../associated-const-use-default.rs | 1 + ...associated-const-use-impl-of-same-trait.rs | 1 + .../associated-consts}/associated-const.rs | 1 + .../auxiliary/associated-const-cc-lib.rs | 0 .../auxiliary/empty-struct.rs | 0 .../associated-types-basic.rs | 1 + .../associated-types-binding-in-trait.rs | 1 + ...ssociated-types-binding-in-where-clause.rs | 1 + .../associated-types-bound.rs | 1 + .../associated-types}/associated-types-cc.rs | 1 + .../associated-types-conditional-dispatch.rs | 1 + .../associated-types-constant-type.rs | 1 + ...ciated-types-doubleendediterator-object.rs | 3 +- ...ted-types-duplicate-binding-in-env-hrtb.rs | 1 + ...sociated-types-duplicate-binding-in-env.rs | 1 + .../associated-types-enum-field-named.rs | 1 + .../associated-types-enum-field-numbered.rs | 1 + .../associated-types-eq-obj.rs | 1 + .../associated-types-impl-redirect.rs | 1 + .../associated-types-in-bound-type-arg.rs | 1 + .../associated-types-in-default-method.rs | 1 + .../associated-types-in-fn.rs | 1 + .../associated-types-in-impl-generics.rs | 1 + .../associated-types-in-inherent-method.rs | 1 + .../associated-types-issue-20220.rs | 1 + .../associated-types-issue-20371.rs | 1 + .../associated-types-issue-21212.rs | 1 + .../associated-types-iterator-binding.rs | 1 + .../associated-types-method.rs | 1 + .../associated-types-nested-projections.rs | 3 +- ...iated-types-normalize-in-bounds-binding.rs | 1 + ...sociated-types-normalize-in-bounds-ufcs.rs | 1 + .../associated-types-normalize-in-bounds.rs | 1 + ...ociated-types-normalize-unifield-struct.rs | 1 + ...ject-from-type-param-via-bound-in-where.rs | 1 + ...d-types-projection-bound-in-supertraits.rs | 1 + ...ypes-projection-from-known-type-in-impl.rs | 1 + ...ociated-types-projection-in-object-type.rs | 1 + ...sociated-types-projection-in-supertrait.rs | 1 + ...ciated-types-projection-in-where-clause.rs | 1 + ...ted-types-projection-to-unrelated-trait.rs | 1 + ...ed-path-with-trait-with-type-parameters.rs | 1 + .../associated-types-ref-from-struct.rs | 1 + .../associated-types-ref-in-struct-literal.rs | 1 + ...ciated-types-region-erasure-issue-20582.rs | 1 + .../associated-types-resolve-lifetime.rs | 1 + .../associated-types-return.rs | 1 + .../associated-types-simple.rs | 1 + .../associated-types-stream.rs | 1 + .../associated-types-struct-field-named.rs | 1 + .../associated-types-struct-field-numbered.rs | 1 + .../associated-types-sugar-path.rs | 1 + ...iated-types-where-clause-impl-ambiguity.rs | 1 + .../auxiliary/associated-types-cc-lib.rs | 0 .../auto-ref-bounded-ty-param.rs | 1 + .../autoref-autoderef}/auto-ref-sliceable.rs | 1 + .../run-pass/autoref-autoderef}/auto-ref.rs | 1 + .../autoderef-and-borrow-method-receiver.rs | 1 + .../autoderef-method-on-trait.rs | 4 +- .../autoderef-method-priority.rs | 4 +- .../autoderef-method-twice-but-not-thrice.rs | 4 +- .../autoderef-method-twice.rs | 4 +- .../autoref-autoderef}/autoderef-method.rs | 4 +- .../autoref-autoderef}/autoderef-privacy.rs | 1 + .../autoref-intermediate-types-issue-3585.rs | 4 +- .../{ => ui}/run-pass/bench/issue-32062.rs | 2 + .../allow_irrefutable_let_patterns.rs | 1 + .../bind-field-short-with-modifiers.rs | 2 + .../binding}/borrowed-ptr-pattern-2.rs | 1 + .../binding}/borrowed-ptr-pattern-3.rs | 1 + .../borrowed-ptr-pattern-infallible.rs | 1 + .../binding}/borrowed-ptr-pattern-option.rs | 1 + .../run-pass/binding}/borrowed-ptr-pattern.rs | 1 + .../binding}/empty-types-in-patterns.rs | 1 + .../binding}/exhaustive-bool-match-sanity.rs | 1 + .../binding}/expr-match-generic-unique1.rs | 3 +- .../binding}/expr-match-generic-unique2.rs | 3 +- .../run-pass/binding}/expr-match-generic.rs | 3 +- .../run-pass/binding}/expr-match-panic-all.rs | 1 + .../run-pass/binding}/expr-match-panic.rs | 1 + .../run-pass/binding}/expr-match-unique.rs | 3 +- .../run-pass/binding}/expr-match.rs | 1 + .../run-pass/binding}/fat-arrow-match.rs | 2 + .../binding}/fn-pattern-expected-type-2.rs | 1 + .../binding}/fn-pattern-expected-type.rs | 1 + .../binding}/func-arg-incomplete-pattern.rs | 3 +- .../run-pass/binding}/func-arg-ref-pattern.rs | 3 +- .../binding}/func-arg-wild-pattern.rs | 1 + .../run-pass/binding}/if-let.rs | 1 + .../inconsistent-lifetime-mismatch.rs | 1 + .../inferred-suffix-in-pattern-range.rs | 1 + .../binding}/irrefutable-slice-patterns.rs | 1 + .../run-pass/binding}/let-assignability.rs | 2 +- .../run-pass/binding}/let-destruct-ref.rs | 1 + .../run-pass/binding}/let-var-hygiene.rs | 1 + .../run-pass/binding}/match-arm-statics.rs | 1 + .../run-pass/binding}/match-beginning-vert.rs | 1 + .../run-pass/binding}/match-borrowed_str.rs | 3 +- .../run-pass/binding}/match-bot-2.rs | 1 + .../run-pass/binding}/match-bot.rs | 1 + .../binding}/match-byte-array-patterns.rs | 1 + .../run-pass/binding}/match-enum-struct-0.rs | 1 + .../run-pass/binding}/match-enum-struct-1.rs | 1 + .../binding}/match-implicit-copy-unique.rs | 4 +- .../run-pass/binding}/match-in-macro.rs | 1 + .../run-pass/binding}/match-join.rs | 1 + .../run-pass/binding}/match-larger-const.rs | 1 + .../binding}/match-naked-record-expr.rs | 1 + .../run-pass/binding}/match-naked-record.rs | 1 + .../run-pass/binding}/match-path.rs | 2 + .../binding}/match-pattern-bindings.rs | 1 + .../run-pass/binding}/match-pattern-lit.rs | 1 + .../binding}/match-pattern-no-type-params.rs | 3 + .../run-pass/binding}/match-pattern-simple.rs | 1 + .../run-pass/binding}/match-phi.rs | 4 +- .../run-pass/binding}/match-pipe-binding.rs | 1 + .../run-pass/binding}/match-range-infer.rs | 1 + .../run-pass/binding}/match-range-static.rs | 2 + .../run-pass/binding}/match-range.rs | 4 +- .../run-pass/binding}/match-reassign.rs | 3 +- .../match-ref-binding-in-guard-3256.rs | 1 + .../binding}/match-ref-binding-mut-option.rs | 1 + .../binding}/match-ref-binding-mut.rs | 2 + .../run-pass/binding}/match-ref-binding.rs | 1 + .../run-pass/binding}/match-ref-unsized.rs | 1 + .../binding}/match-static-const-rename.rs | 1 + .../run-pass/binding}/match-str.rs | 2 + .../run-pass/binding}/match-struct-0.rs | 1 + .../run-pass/binding}/match-tag.rs | 3 +- .../run-pass/binding}/match-unique-bind.rs | 2 +- .../run-pass/binding}/match-unsized.rs | 1 + .../match-value-binding-in-guard-3291.rs | 2 +- .../run-pass/binding}/match-var-hygiene.rs | 1 + .../binding}/match-vec-alternatives.rs | 1 + .../run-pass/binding}/match-vec-rvalue.rs | 1 + .../run-pass/binding}/match-with-ret-arm.rs | 1 + .../run-pass/binding}/multi-let.rs | 1 + .../binding}/mut-in-ident-patterns.rs | 3 + .../binding}/nested-exhaustive-match.rs | 1 + .../run-pass/binding}/nested-matchs.rs | 1 + .../run-pass/binding}/nested-pattern.rs | 3 +- .../run-pass/binding}/nil-pattern.rs | 1 + .../run-pass/binding}/nullary-or-pattern.rs | 2 + .../binding}/optional_comma_in_match_arm.rs | 2 + .../run-pass/binding}/or-pattern.rs | 2 + .../binding}/order-drop-with-match.rs | 1 + .../run-pass/binding}/pat-ranges.rs | 1 + .../run-pass/binding}/pat-tuple-1.rs | 1 + .../run-pass/binding}/pat-tuple-2.rs | 1 + .../run-pass/binding}/pat-tuple-3.rs | 1 + .../run-pass/binding}/pat-tuple-4.rs | 1 + .../run-pass/binding}/pat-tuple-5.rs | 1 + .../run-pass/binding}/pat-tuple-6.rs | 1 + .../run-pass/binding}/pat-tuple-7.rs | 1 + .../binding}/pattern-bound-var-in-for-each.rs | 1 + .../run-pass/binding}/pattern-in-closure.rs | 3 + .../range-inclusive-pattern-precedence.rs | 1 + .../run-pass/binding}/simple-generic-match.rs | 3 +- .../run-pass/binding}/use-uninit-match.rs | 2 + .../run-pass/binding}/use-uninit-match2.rs | 2 + .../binding}/zero_sized_subslice_match.rs | 1 + .../borrowck/borrowck-assign-to-subfield.rs | 1 + .../borrowck-assignment-to-static-mut.rs | 1 + .../borrowck/borrowck-binding-mutbl.rs | 2 + .../borrowck-borrow-from-expr-block.rs | 3 +- .../borrowck-borrow-of-mut-base-ptr-safe.rs | 1 + .../borrowck/borrowck-closures-two-imm.rs | 1 + .../borrowck/borrowck-field-sensitivity.rs | 2 +- .../borrowck/borrowck-fixed-length-vecs.rs | 1 + .../borrowck/borrowck-freeze-frozen-mut.rs | 1 + .../run-pass/borrowck/borrowck-lend-args.rs | 1 + .../borrowck-macro-interaction-issue-6304.rs | 3 + .../borrowck/borrowck-move-by-capture-ok.rs | 3 +- ...orrowck-multiple-borrows-interior-boxes.rs | 1 + .../run-pass/borrowck/borrowck-mut-uniq.rs | 2 +- .../borrowck/borrowck-mut-vec-as-imm-slice.rs | 1 + .../run-pass/borrowck/borrowck-pat-enum.rs | 1 + .../borrowck-pat-reassign-no-binding.rs | 1 + .../borrowck/borrowck-rvalues-mutable.rs | 1 + .../borrowck-scope-of-deref-issue-4666.rs | 1 + .../borrowck-slice-pattern-element-loan.rs | 1 + .../borrowck/borrowck-static-item-in-fn.rs | 1 + .../borrowck/borrowck-trait-lifetime.rs | 1 + .../borrowck/borrowck-uniq-via-ref.rs | 1 + .../borrowck/borrowck-univariant-enum.rs | 3 +- .../borrowck-unsafe-static-mutable-borrows.rs | 1 + .../borrowck/borrowck-unused-mut-locals.rs | 1 + .../borrowck/borrowck-use-mut-borrow.rs | 2 +- .../run-pass/borrowck/two-phase-baseline.rs | 1 + .../run-pass/borrowck/two-phase-bin-ops.rs | 1 + ...se-control-flow-split-before-activation.rs | 1 + .../cfg}/auxiliary/cfg_inner_static.rs | 0 .../crate-attributes-using-cfg_attr.rs | 0 .../run-pass/cfg}/cfg-attr-cfg.rs | 1 + .../run-pass/cfg}/cfg-attr-crate.rs | 1 + .../run-pass/cfg}/cfg-family.rs | 1 + .../run-pass/cfg}/cfg-in-crate-1.rs | 1 + .../run-pass/cfg}/cfg-macros-foo.rs | 1 + .../run-pass/cfg}/cfg-macros-notfoo.rs | 1 + .../run-pass/cfg}/cfg-match-arm.rs | 1 + .../run-pass/cfg}/cfg-target-family.rs | 1 + .../run-pass/cfg}/cfg-target-vendor.rs | 1 + .../{run-pass => ui/run-pass/cfg}/cfg_attr.rs | 1 + .../run-pass/cfg}/cfg_inner_static.rs | 1 + .../run-pass/cfg}/cfg_stmt_expr.rs | 1 + .../run-pass/cfg}/cfgs-on-items.rs | 1 + .../run-pass/cfg}/conditional-compile-arch.rs | 1 + .../run-pass/cfg}/conditional-compile.rs | 5 + .../cfg}/crate-attributes-using-cfg_attr.rs | 1 + .../run-pass/coerce}/coerce-expect-unsized.rs | 2 +- .../coerce}/coerce-overloaded-autoderef.rs | 1 + .../coerce}/coerce-reborrow-imm-ptr-arg.rs | 1 + .../coerce}/coerce-reborrow-imm-ptr-rcvr.rs | 1 + .../coerce}/coerce-reborrow-imm-vec-arg.rs | 1 + .../coerce}/coerce-reborrow-imm-vec-rcvr.rs | 1 + .../coerce}/coerce-reborrow-mut-ptr-arg.rs | 1 + .../coerce}/coerce-reborrow-mut-ptr-rcvr.rs | 1 + .../coerce}/coerce-reborrow-mut-vec-arg.rs | 1 + .../coerce}/coerce-reborrow-mut-vec-rcvr.rs | 1 + .../run-pass/coerce}/coerce-unify-return.rs | 1 + .../run-pass/coerce}/coerce-unify.rs | 1 + .../run-pass/coerce}/coerce-unsize-subtype.rs | 1 + .../auxiliary/coherence_copy_like_lib.rs | 0 .../coherence}/auxiliary/coherence_lib.rs | 0 .../coherence}/coherence-bigint-int.rs | 1 + .../coherence}/coherence-bigint-vecint.rs | 1 + .../run-pass/coherence}/coherence-blanket.rs | 1 + .../coherence-covered-type-parameter.rs | 1 + .../coherence}/coherence-impl-in-fn.rs | 3 + .../coherence-iterator-vec-any-elem.rs | 1 + .../coherence}/coherence-iterator-vec.rs | 1 + .../coherence-multidispatch-tuple.rs | 1 + .../coherence-negative-impls-safe.rs | 1 + .../coherence-rfc447-constrained.rs | 1 + .../coherence}/coherence-subtyping.rs | 1 + .../coherence}/coherence-where-clause.rs | 1 + .../coherence}/coherence_copy_like.rs | 1 + .../anon-extern-mod-cross-crate-1.rs | 19 + .../consts}/auxiliary/cci_borrow_lib.rs | 0 .../run-pass/consts}/auxiliary/cci_const.rs | 0 .../consts}/auxiliary/cci_const_block.rs | 0 .../run-pass/consts/auxiliary/const_fn_lib.rs | 16 + .../consts}/const-adt-align-mismatch.rs | 3 + .../run-pass/consts}/const-autoderef.rs | 1 + .../run-pass/consts}/const-big-enum.rs | 1 + .../run-pass/consts}/const-binops.rs | 1 + .../consts}/const-bitshift-rhs-inference.rs | 1 + .../consts}/const-block-cross-crate-fn.rs | 1 + .../consts}/const-block-item-macro-codegen.rs | 1 + .../run-pass/consts}/const-block-item.rs | 1 + .../run-pass/consts}/const-block.rs | 1 + .../run-pass/consts}/const-bound.rs | 1 + .../run-pass/consts}/const-byte-str-cast.rs | 1 + .../run-pass/consts}/const-cast-ptr-int.rs | 2 + .../run-pass/consts}/const-cast.rs | 3 + .../run-pass/consts}/const-const.rs | 2 + .../run-pass/consts}/const-contents.rs | 3 +- .../consts}/const-cross-crate-const.rs | 3 +- .../consts}/const-cross-crate-extern.rs | 3 +- .../run-pass/consts}/const-deref.rs | 1 + .../run-pass/consts}/const-endianess.rs | 3 +- .../run-pass/consts}/const-enum-byref-self.rs | 1 + .../run-pass/consts}/const-enum-byref.rs | 1 + .../run-pass/consts}/const-enum-cast.rs | 2 + .../run-pass/consts}/const-enum-ptr.rs | 1 + .../run-pass/consts}/const-enum-struct.rs | 1 + .../run-pass/consts}/const-enum-struct2.rs | 1 + .../run-pass/consts}/const-enum-structlike.rs | 1 + .../run-pass/consts}/const-enum-tuple.rs | 1 + .../run-pass/consts}/const-enum-tuple2.rs | 1 + .../consts}/const-enum-tuplestruct.rs | 1 + .../consts}/const-enum-tuplestruct2.rs | 1 + .../run-pass/consts}/const-enum-vec-index.rs | 1 + .../run-pass/consts}/const-enum-vec-ptr.rs | 1 + .../run-pass/consts}/const-enum-vector.rs | 1 + .../run-pass/consts}/const-err.rs | 1 + .../consts}/const-expr-in-fixed-length-vec.rs | 1 + .../consts}/const-expr-in-vec-repeat.rs | 1 + .../run-pass/consts}/const-extern-function.rs | 2 + .../consts}/const-fields-and-indexing.rs | 3 + .../run-pass/consts}/const-fn-const-eval.rs | 3 +- .../consts}/const-fn-feature-flags.rs | 1 + .../run-pass/consts}/const-fn-method.rs | 3 +- .../run-pass/consts}/const-fn-nested.rs | 3 +- .../consts}/const-fn-stability-calls.rs | 1 + .../run-pass/consts}/const-fn-val.rs | 3 + .../run-pass/consts}/const-fn.rs | 3 + .../consts}/const-index-feature-gate.rs | 1 + .../run-pass/consts}/const-meth-pattern.rs | 5 +- .../run-pass/consts}/const-negation.rs | 3 + .../run-pass/consts}/const-negative.rs | 3 +- .../run-pass/consts}/const-nullary-enum.rs | 1 + .../consts}/const-nullary-univariant-enum.rs | 1 + .../run-pass/consts}/const-pattern-variant.rs | 3 +- .../run-pass/consts}/const-rec-and-tup.rs | 4 + .../consts}/const-region-ptrs-noncopy.rs | 2 + .../run-pass/consts}/const-region-ptrs.rs | 3 + .../run-pass/consts}/const-repeated-values.rs | 1 + .../consts}/const-size_of-align_of.rs | 3 +- .../run-pass/consts}/const-str-ptr.rs | 1 + .../run-pass/consts}/const-struct-offsets.rs | 2 + .../run-pass/consts}/const-struct.rs | 4 + .../run-pass/consts}/const-trait-to-trait.rs | 1 + .../run-pass/consts}/const-tuple-struct.rs | 1 + .../run-pass/consts}/const-typeid-of.rs | 1 + .../run-pass/consts}/const-unit-struct.rs | 1 + .../run-pass/consts}/const-unsafe-fn.rs | 3 +- .../run-pass/consts}/const-vec-of-fns.rs | 2 + .../run-pass/consts}/const-vec-syntax.rs | 1 + .../run-pass/consts}/const-vecs-and-slices.rs | 3 + .../{run-pass => ui/run-pass/consts}/const.rs | 3 +- .../run-pass/consts}/consts-in-patterns.rs | 3 +- .../anon-extern-mod-cross-crate-2.rs | 1 + .../anon-extern-mod-cross-crate-1.rs | 19 + .../auxiliary/anon_trait_static_method_lib.rs | 0 .../cross-crate/auxiliary/cci_borrow_lib.rs | 13 + .../auxiliary/cci_capture_clause.rs | 0 .../cross-crate/auxiliary/cci_const.rs | 16 + .../cross-crate}/auxiliary/cci_impl_lib.rs | 0 .../cross-crate}/auxiliary/cci_iter_lib.rs | 0 .../cross-crate}/auxiliary/cci_nested_lib.rs | 1 - .../auxiliary/cci_no_inline_lib.rs | 0 .../auxiliary/moves_based_on_type_lib.rs | 0 .../auxiliary/newtype_struct_xc.rs | 0 .../auxiliary/pub_static_array.rs | 0 .../auxiliary/reexported_static_methods.rs | 0 .../auxiliary/xcrate-trait-lifetime-param.rs | 0 .../auxiliary/xcrate_address_insignificant.rs | 0 .../xcrate_associated_type_defaults.rs | 0 .../xcrate_generic_fn_nested_return.rs | 0 .../auxiliary/xcrate_static_addresses.rs | 0 .../auxiliary/xcrate_unit_struct.rs | 0 .../run-pass/cross-crate}/cci_borrow.rs | 2 +- .../cross-crate}/cci_capture_clause.rs | 1 + .../run-pass/cross-crate}/cci_impl_exe.rs | 1 + .../run-pass/cross-crate}/cci_iter_exe.rs | 1 + .../run-pass/cross-crate}/cci_nested_exe.rs | 1 + .../cross-crate}/cci_no_inline_exe.rs | 1 + .../cross-crate}/cross-crate-const-pat.rs | 1 + .../cross-crate-newtype-struct-pat.rs | 1 + .../moves-based-on-type-cross-crate.rs | 1 + .../reexported-static-methods-cross-crate.rs | 1 + .../cross-crate}/static-array-across-crate.rs | 1 + .../xcrate-address-insignificant.rs | 1 + .../xcrate-associated-type-defaults.rs | 1 + .../cross-crate}/xcrate-static-addresses.rs | 1 + .../xcrate-trait-lifetime-param.rs | 1 + .../cross-crate}/xcrate-unit-struct.rs | 2 + .../xcrate_generic_fn_nested_return.rs | 1 + .../{ => ui}/run-pass/ctfe/assoc-const.rs | 2 + .../{ => ui}/run-pass/ctfe/bswap-const.rs | 2 + .../ctfe/chained-constants-stackoverflow.rs | 2 + .../ctfe/const-block-non-item-statement-3.rs | 2 + .../ctfe/const-block-non-item-statement.rs | 2 + .../ctfe/const-fn-destructuring-arg.rs | 2 + .../run-pass/ctfe/deref_in_pattern.rs | 2 + src/test/{ => ui}/run-pass/ctfe/ice-48279.rs | 4 +- .../{ => ui}/run-pass/ctfe/issue-37550.rs | 2 + .../run-pass/ctfe/issue-broken-mir.rs | 2 + .../run-pass/ctfe/locals-in-const-fn.rs | 2 + .../run-pass/ctfe/match-const-fn-structs.rs | 4 +- .../{ => ui}/run-pass/ctfe/mozjs-error.rs | 3 + .../{ => ui}/run-pass/ctfe/non-scalar-cast.rs | 2 + src/test/ui/run-pass/ctfe/promotion.rs | 27 + src/test/{ => ui}/run-pass/ctfe/references.rs | 2 + .../{ => ui}/run-pass/ctfe/repeat_match.rs | 2 + .../run-pass/ctfe/return-in-const-fn.rs | 4 +- .../run-pass/ctfe/signed_enum_discr.rs | 2 + src/test/ui/run-pass/ctfe/transmute-const.rs | 24 + .../ctfe/tuple-struct-constructors.rs | 2 + .../deriving}/auxiliary/derive-no-std.rs | 0 .../run-pass/deriving}/derive-no-std.rs | 1 + .../derive-partialord-correctness.rs | 1 + .../deriving}/deriving-associated-types.rs | 3 +- .../run-pass/deriving}/deriving-bounds.rs | 1 + .../deriving}/deriving-clone-array.rs | 1 + .../run-pass/deriving}/deriving-clone-enum.rs | 1 + .../deriving}/deriving-clone-generic-enum.rs | 1 + .../deriving-clone-generic-struct.rs | 1 + .../deriving-clone-generic-tuple-struct.rs | 1 + .../deriving}/deriving-clone-struct.rs | 1 + .../deriving}/deriving-clone-tuple-struct.rs | 1 + .../deriving}/deriving-cmp-generic-enum.rs | 1 + .../deriving-cmp-generic-struct-enum.rs | 1 + .../deriving}/deriving-cmp-generic-struct.rs | 1 + .../deriving-cmp-generic-tuple-struct.rs | 1 + .../deriving}/deriving-cmp-shortcircuit.rs | 1 + .../run-pass/deriving}/deriving-copyclone.rs | 1 + .../deriving}/deriving-default-box.rs | 3 +- .../deriving}/deriving-enum-single-variant.rs | 2 + .../deriving}/deriving-eq-ord-boxed-slice.rs | 1 + .../run-pass/deriving}/deriving-hash.rs | 7 +- .../run-pass/deriving}/deriving-in-fn.rs | 1 + .../run-pass/deriving}/deriving-in-macro.rs | 2 + .../deriving}/deriving-meta-multiple.rs | 2 + .../run-pass/deriving}/deriving-meta.rs | 2 + ...deriving-self-lifetime-totalord-totaleq.rs | 1 + .../run-pass/deriving}/deriving-show-2.rs | 1 + .../run-pass/deriving}/deriving-show.rs | 1 + .../deriving-via-extension-c-enum.rs | 1 + .../deriving}/deriving-via-extension-enum.rs | 1 + .../deriving-via-extension-hash-enum.rs | 1 + .../deriving-via-extension-hash-struct.rs | 1 + .../deriving-via-extension-struct-empty.rs | 1 + ...-via-extension-struct-like-enum-variant.rs | 1 + .../deriving-via-extension-struct-tuple.rs | 1 + .../deriving-via-extension-struct.rs | 1 + .../deriving-via-extension-type-params.rs | 1 + .../deriving}/deriving-with-repr-packed.rs | 1 + .../auxiliary/dropck_eyepatch_extern_crate.rs | 0 .../drop}/drop-on-empty-block-exit.rs | 3 +- .../run-pass/drop}/drop-on-ret.rs | 1 + .../run-pass/drop}/drop-struct-as-object.rs | 5 +- .../run-pass/drop}/drop-trait-enum.rs | 2 +- .../run-pass/drop}/drop-trait-generic.rs | 1 + .../run-pass/drop}/drop-trait.rs | 1 + .../run-pass/drop}/drop-uninhabited-enum.rs | 1 + .../drop}/drop-with-type-ascription-1.rs | 1 + .../drop}/drop-with-type-ascription-2.rs | 1 + .../drop}/dropck-eyepatch-extern-crate.rs | 1 + .../run-pass/drop}/dropck-eyepatch-reorder.rs | 1 + .../run-pass/drop}/dropck-eyepatch.rs | 1 + .../run-pass/drop}/dropck_legal_cycles.rs | 3 +- .../run-pass/drop}/dynamic-drop.rs | 1 + .../run-pass/drop}/no-drop-flag-size.rs | 1 + .../run-pass/drop}/nondrop-cycle.rs | 1 + .../dst-coerce-custom.rs | 1 + .../dynamically-sized-types}/dst-coerce-rc.rs | 2 + .../dynamically-sized-types}/dst-coercions.rs | 1 + .../dynamically-sized-types}/dst-deref-mut.rs | 1 + .../dynamically-sized-types}/dst-deref.rs | 1 + .../dst-field-align.rs | 1 + .../dynamically-sized-types}/dst-index.rs | 4 +- .../dst-irrefutable-bind.rs | 1 + .../dynamically-sized-types}/dst-raw.rs | 1 + .../dst-struct-sole.rs | 1 + .../dynamically-sized-types}/dst-struct.rs | 3 +- .../dst-trait-tuple.rs | 2 + .../dynamically-sized-types}/dst-trait.rs | 3 +- .../dst-tuple-sole.rs | 4 + .../dynamically-sized-types}/dst-tuple.rs | 3 +- .../auxiliary/extern-crosscrate-source.rs | 0 .../extern}/auxiliary/extern-take-value.rs | 0 .../auxiliary/extern_calling_convention.rs | 0 .../auxiliary/extern_mod_ordering_lib.rs | 0 .../run-pass/extern}/auxiliary/fat_drop.rs | 0 .../run-pass/extern}/extern-1.rs | 1 + .../run-pass/extern}/extern-call-deep.rs | 1 + .../run-pass/extern}/extern-call-deep2.rs | 1 + .../run-pass/extern}/extern-call-direct.rs | 1 + .../run-pass/extern}/extern-call-indirect.rs | 1 + .../run-pass/extern}/extern-call-scrub.rs | 3 +- .../extern}/extern-calling-convention-test.rs | 1 + .../extern-compare-with-return-type.rs | 3 +- .../run-pass/extern}/extern-crosscrate.rs | 1 + .../run-pass/extern}/extern-foreign-crate.rs | 1 + .../run-pass/extern}/extern-methods.rs | 1 + .../run-pass/extern}/extern-mod-abi.rs | 1 + .../extern}/extern-mod-ordering-exe.rs | 1 + .../run-pass/extern}/extern-pass-TwoU16s.rs | 3 + .../run-pass/extern}/extern-pass-TwoU32s.rs | 3 + .../run-pass/extern}/extern-pass-TwoU64s.rs | 3 + .../run-pass/extern}/extern-pass-TwoU8s.rs | 3 + .../run-pass/extern}/extern-pass-char.rs | 1 + .../run-pass/extern}/extern-pass-double.rs | 1 + .../run-pass/extern}/extern-pass-empty.rs | 3 + .../run-pass/extern}/extern-pass-u32.rs | 1 + .../run-pass/extern}/extern-pass-u64.rs | 1 + .../run-pass/extern}/extern-prelude-core.rs | 1 + .../extern/extern-prelude-core.stderr | 8 + .../extern}/extern-prelude-no-speculative.rs | 1 + .../run-pass/extern}/extern-prelude-std.rs | 1 + .../run-pass/extern/extern-prelude-std.stderr | 8 + .../run-pass/extern}/extern-pub.rs | 1 + .../run-pass/extern}/extern-return-TwoU16s.rs | 3 + .../run-pass/extern}/extern-return-TwoU32s.rs | 3 + .../run-pass/extern}/extern-return-TwoU64s.rs | 3 + .../run-pass/extern}/extern-return-TwoU8s.rs | 3 + .../run-pass/extern}/extern-rust.rs | 1 + .../run-pass/extern}/extern-take-value.rs | 1 + .../run-pass/extern}/extern-thiscall.rs | 1 + .../extern}/extern-types-inherent-impl.rs | 1 + .../extern}/extern-types-manual-sync-send.rs | 1 + .../extern}/extern-types-pointer-cast.rs | 1 + .../extern}/extern-types-size_of_val.rs | 1 + .../extern}/extern-types-thin-pointer.rs | 1 + .../extern}/extern-types-trait-impl.rs | 1 + .../run-pass/extern}/extern-vectorcall.rs | 1 + .../run-pass/extern}/extern_fat_drop.rs | 1 + .../run-pass/for-loop-while}/auto-loop.rs | 1 + .../run-pass/for-loop-while}/break-value.rs | 1 + .../run-pass/for-loop-while}/break.rs | 1 + .../run-pass/for-loop-while}/for-destruct.rs | 1 + .../for-loop-while}/for-loop-goofiness.rs | 1 + .../for-loop-while}/for-loop-has-unit-body.rs | 1 + .../for-loop-while}/for-loop-into-iterator.rs | 1 + .../for-loop-lifetime-of-unbound-values.rs | 1 + .../for-loop-while}/for-loop-macro.rs | 1 + .../for-loop-mut-ref-element.rs | 1 + .../for-loop-while}/for-loop-no-std.rs | 1 + .../for-loop-while}/for-loop-panic.rs | 1 + ...unconstrained-element-type-i32-fallback.rs | 1 + .../foreach-external-iterators-break.rs | 1 + ...xternal-iterators-hashmap-break-restart.rs | 1 + .../foreach-external-iterators-hashmap.rs | 1 + .../foreach-external-iterators-loop.rs | 1 + .../foreach-external-iterators-nested.rs | 1 + .../foreach-external-iterators.rs | 1 + .../for-loop-while}/foreach-nested.rs | 1 + .../for-loop-while}/foreach-put-structured.rs | 1 + .../foreach-simple-outer-slot.rs | 1 + .../for-loop-while}/label_break_value.rs | 1 + .../run-pass/for-loop-while}/labeled-break.rs | 1 + .../for-loop-while}/linear-for-loop.rs | 1 + .../liveness-assign-imm-local-after-loop.rs | 2 +- .../for-loop-while}/liveness-loop-break.rs | 1 + .../for-loop-while}/liveness-move-in-loop.rs | 1 + .../for-loop-while}/loop-break-cont-1.rs | 1 + .../for-loop-while}/loop-break-cont.rs | 1 + .../for-loop-while}/loop-break-value.rs | 1 + .../run-pass/for-loop-while}/loop-diverges.rs | 1 + .../for-loop-while}/loop-label-shadowing.rs | 1 + .../loop-labeled-break-value.rs | 5 +- .../loop-no-reinit-needed-post-bot.rs | 1 + .../run-pass/for-loop-while}/loop-scope.rs | 1 + .../run-pass/for-loop-while}/while-cont.rs | 1 + .../for-loop-while}/while-flow-graph.rs | 1 + .../run-pass/for-loop-while}/while-label.rs | 1 + .../run-pass/for-loop-while}/while-let.rs | 5 +- .../while-loop-constraints-2.rs | 2 +- .../for-loop-while}/while-prelude-drop.rs | 3 + .../for-loop-while}/while-with-break.rs | 1 + .../run-pass/for-loop-while}/while.rs | 1 + .../run-pass/foreign}/auxiliary/fn-abi.rs | 0 .../run-pass/foreign/auxiliary/foreign_lib.rs | 48 + .../foreign}/foreign-call-no-runtime.rs | 1 + .../run-pass/foreign}/foreign-dupe.rs | 1 + .../run-pass/foreign}/foreign-fn-linkname.rs | 3 +- .../foreign}/foreign-fn-with-byval.rs | 3 + .../run-pass/foreign}/foreign-int-types.rs | 1 + .../foreign-mod-src/compiletest-ignore-dir | 0 .../foreign}/foreign-mod-src/inner.rs | 1 + .../foreign}/foreign-mod-unused-const.rs | 1 + .../run-pass/foreign}/foreign-no-abi.rs | 1 + .../foreign-src/compiletest-ignore-dir | 0 .../run-pass/foreign}/foreign-src/foreign.rs | 1 + .../foreign}/foreign-truncated-arguments.rs | 1 + .../run-pass/foreign}/foreign2.rs | 1 + .../functions-closures/auxiliary/fn-abi.rs | 12 + .../call-closure-from-overloaded-op.rs | 1 + .../capture-clauses-boxed-closures.rs | 1 + .../capture-clauses-unboxed-closures.rs | 1 + .../functions-closures}/clone-closure.rs | 1 + .../closure-bounds-can-capture-chan.rs | 1 + .../closure-expected-type/README.md | 0 .../expect-infer-supply-two-infers.rs | 1 + .../closure-expected-type/issue-38714.rs | 1 + .../supply-just-return-type.rs | 1 + .../closure-expected-type/supply-nothing.rs | 1 + .../functions-closures}/closure-immediate.rs | 1 + .../functions-closures}/closure-inference.rs | 1 + .../functions-closures}/closure-inference2.rs | 1 + .../functions-closures}/closure-reform.rs | 1 + .../closure-returning-closure.rs | 1 + .../closure-to-fn-coercion.rs | 1 + .../closure_to_fn_coercion-expected-types.rs | 2 + .../functions-closures}/copy-closure.rs | 1 + .../ui/run-pass/functions-closures/fn-abi.rs | 28 + .../functions-closures}/fn-bare-assign.rs | 1 + .../fn-bare-coerce-to-block.rs | 1 + .../functions-closures}/fn-bare-item.rs | 1 + .../functions-closures}/fn-bare-size.rs | 1 + .../functions-closures}/fn-bare-spawn.rs | 1 + .../functions-closures}/fn-coerce-field.rs | 2 + .../functions-closures}/fn-item-type-cast.rs | 1 + .../fn-item-type-coerce.rs | 1 + .../fn-item-type-zero-sized.rs | 1 + .../run-pass/functions-closures}/fn-lval.rs | 1 + .../functions-closures}/fn-type-infer.rs | 1 + .../implied-bounds-closure-arg-outlives.rs | 1 + .../nullable-pointer-opt-closures.rs | 1 + .../parallel-codegen-closures.rs | 4 +- .../return-from-closure.rs | 2 + .../generator/auxiliary/xcrate-reachable.rs | 0 .../run-pass/generator/auxiliary/xcrate.rs | 0 .../run-pass/generator/borrow-in-tail-expr.rs | 2 + .../run-pass/generator/conditional-drop.rs | 2 + .../run-pass/generator/control-flow.rs | 2 + .../{ => ui}/run-pass/generator/drop-env.rs | 2 + .../run-pass/generator/issue-44197.rs | 2 + src/test/ui/run-pass/generator/issue-52398.rs | 37 + .../run-pass/generator/iterator-count.rs | 2 + .../generator/live-upvar-across-yield.rs | 2 + .../run-pass/generator/match-bindings.rs | 2 + .../run-pass/generator/nested_generators.rs | 2 + .../run-pass/generator/panic-drops.rs | 2 + src/test/ui/run-pass/generator/panic-safe.rs | 39 + .../run-pass/generator/reborrow-mut-upvar.rs | 2 + .../run-pass/generator/resume-after-return.rs | 2 + src/test/{ => ui}/run-pass/generator/smoke.rs | 2 + .../run-pass/generator/static-generators.rs | 2 + .../too-live-local-in-immovable-gen.rs | 2 + .../run-pass/generator/xcrate-reachable.rs | 2 + src/test/ui/run-pass/generator/xcrate.rs | 39 + .../run-pass/generator/yield-in-args-rev.rs | 2 + .../run-pass/generator/yield-in-box.rs | 2 + .../generator/yield-in-initializer.rs | 27 + .../run-pass/generator/yield-subtype.rs | 2 + .../auxiliary/default_type_params_xc.rs | 0 .../generics}/generic-alias-unique.rs | 2 +- ...generic-default-type-params-cross-crate.rs | 1 + .../generics}/generic-default-type-params.rs | 1 + .../generics}/generic-derived-type.rs | 1 + .../generics}/generic-exterior-unique.rs | 3 +- .../generics}/generic-extern-mangle.rs | 4 +- .../run-pass/generics}/generic-fn-infer.rs | 1 + .../run-pass/generics}/generic-fn-twice.rs | 1 + .../run-pass/generics}/generic-fn-unique.rs | 2 +- .../run-pass/generics}/generic-fn.rs | 2 +- .../run-pass/generics}/generic-ivec-leak.rs | 2 + .../generics}/generic-newtype-struct.rs | 1 + .../run-pass/generics}/generic-object.rs | 3 +- .../generics}/generic-recursive-tag.rs | 3 +- .../generics}/generic-static-methods.rs | 2 + .../generics}/generic-tag-corruption.rs | 3 +- .../run-pass/generics}/generic-tag-local.rs | 3 +- .../run-pass/generics}/generic-tag-match.rs | 3 +- .../run-pass/generics}/generic-tag-values.rs | 3 + .../run-pass/generics}/generic-tag.rs | 5 +- .../run-pass/generics}/generic-temporary.rs | 1 + .../run-pass/generics}/generic-tup.rs | 1 + .../generics}/generic-type-synonym.rs | 1 + .../run-pass/generics}/generic-type.rs | 1 + .../run-pass/generics}/generic-unique.rs | 3 +- .../hrtb-binder-levels-in-object-types.rs | 1 + .../hrtb-debruijn-object-types-in-closures.rs | 1 + .../hrtb-fn-like-trait-object.rs | 1 + .../hrtb-fn-like-trait.rs | 1 + .../hrtb-opt-in-copy.rs | 1 + .../higher-rank-trait-bounds}/hrtb-parse.rs | 1 + .../hrtb-precedence-of-plus-where-clause.rs | 1 + .../hrtb-precedence-of-plus.rs | 3 +- .../hrtb-resolve-lifetime.rs | 1 + .../hrtb-trait-object-paren-notation.rs | 1 + .../hrtb-trait-object-passed-to-closure.rs | 1 + .../hrtb-type-outlives.rs | 1 + .../hrtb-unboxed-closure-trait.rs | 1 + .../hygiene/auxiliary/legacy_interaction.rs | 20 + .../run-pass/hygiene/auxiliary/my_crate.rs | 1 + .../hygiene/auxiliary/unhygienic_example.rs | 1 + .../ui/run-pass/hygiene/auxiliary/xcrate.rs | 39 + .../run-pass/hygiene}/hygiene-dodging-1.rs | 1 + .../run-pass/hygiene}/hygiene.rs | 1 + .../hygiene}/hygienic-labels-in-let.rs | 1 + .../hygiene/hygienic-labels-in-let.stderr | 300 ++ .../run-pass/hygiene}/hygienic-labels.rs | 1 + .../run-pass/hygiene/hygienic-labels.stderr | 299 ++ .../{ => ui}/run-pass/hygiene/issue-44128.rs | 1 + .../{ => ui}/run-pass/hygiene/issue-47311.rs | 1 + .../{ => ui}/run-pass/hygiene/issue-47312.rs | 1 + src/test/ui/run-pass/hygiene/items.rs | 37 + .../ui/run-pass/hygiene/legacy_interaction.rs | 51 + src/test/{ => ui}/run-pass/hygiene/lexical.rs | 1 + .../run-pass/hygiene/specialization.rs | 1 + .../{ => ui}/run-pass/hygiene/trait_items.rs | 1 + .../{ => ui}/run-pass/hygiene/ty_params.rs | 1 + .../hygiene/wrap_unhygienic_example.rs | 1 + src/test/ui/run-pass/hygiene/xcrate.rs | 22 + .../run-pass/impl-trait/auto-trait-leak.rs | 2 + .../run-pass/impl-trait/auxiliary/xcrate.rs | 0 .../run-pass/impl-trait/bounds_regression.rs | 2 + .../{ => ui}/run-pass/impl-trait/equality.rs | 2 + .../run-pass/impl-trait/example-calendar.rs | 2 + .../run-pass/impl-trait/example-st.rs | 2 + .../impl-trait/existential-minimal.rs | 2 + .../run-pass/impl-trait/issue-42479.rs | 2 + .../run-pass/impl-trait/issue-49376.rs | 2 + .../{ => ui}/run-pass/impl-trait/lifetimes.rs | 2 + .../{ => ui}/run-pass/impl-trait/nesting.rs | 2 + .../impl-trait/universal_hrtb_anon.rs | 2 + .../impl-trait/universal_hrtb_named.rs | 2 + .../universal_in_adt_in_parameters.rs | 2 + .../universal_in_impl_trait_in_parameters.rs | 2 + .../universal_in_trait_defn_parameters.rs | 2 + .../impl-trait/universal_multiple_bounds.rs | 2 + src/test/ui/run-pass/impl-trait/xcrate.rs | 21 + .../run-pass/impl-trait/xcrate_simple.rs | 2 + .../auxiliary/crate_with_invalid_spans.rs | 0 .../crate_with_invalid_spans_macros.rs | 0 .../import-crate-with-invalid-spans/main.rs | 23 + .../run-pass/imports}/import-from.rs | 1 + .../run-pass/imports}/import-glob-0.rs | 1 + .../run-pass/imports}/import-glob-1.rs | 1 + .../run-pass/imports}/import-glob-crate.rs | 1 + .../run-pass/imports}/import-in-block.rs | 1 + .../run-pass/imports}/import-prefix-macro.rs | 1 + .../run-pass/imports}/import-rename.rs | 1 + .../imports}/import-trailing-comma.rs | 1 + .../run-pass/imports}/import.rs | 1 + .../run-pass/imports}/import2.rs | 1 + .../run-pass/imports}/import3.rs | 1 + .../run-pass/imports}/import4.rs | 1 + .../run-pass/imports}/import5.rs | 1 + .../run-pass/imports}/import6.rs | 1 + .../run-pass/imports}/import7.rs | 1 + .../run-pass/imports}/import8.rs | 1 + .../run-pass/imports}/imports.rs | 1 + .../intrinsics}/auxiliary/cci_intrinsic.rs | 0 .../intrinsics}/intrinsic-alignment.rs | 1 + .../run-pass/intrinsics}/intrinsic-assume.rs | 1 + .../intrinsics}/intrinsic-atomics-cc.rs | 1 + .../run-pass/intrinsics}/intrinsic-atomics.rs | 3 +- .../intrinsic-move-val-cleanups.rs | 2 + .../intrinsics}/intrinsic-move-val.rs | 1 + .../run-pass/intrinsics}/intrinsic-uninit.rs | 1 + .../intrinsics}/intrinsic-unreachable.rs | 1 + .../intrinsics}/intrinsics-integer.rs | 1 + .../run-pass/intrinsics}/intrinsics-math.rs | 1 + .../run-pass/issues}/auxiliary/cgu_test.rs | 0 .../run-pass/issues}/auxiliary/cgu_test_a.rs | 0 .../run-pass/issues}/auxiliary/cgu_test_b.rs | 0 .../run-pass/issues}/auxiliary/i8.rs | 0 .../run-pass/issues}/auxiliary/iss.rs | 0 .../run-pass/issues}/auxiliary/issue-10028.rs | 0 .../run-pass/issues}/auxiliary/issue-11224.rs | 0 .../issues}/auxiliary/issue-11225-1.rs | 0 .../issues}/auxiliary/issue-11225-2.rs | 0 .../issues}/auxiliary/issue-11225-3.rs | 0 .../run-pass/issues}/auxiliary/issue-11508.rs | 0 .../run-pass/issues}/auxiliary/issue-11529.rs | 0 .../issues}/auxiliary/issue-12133-dylib.rs | 0 .../issues}/auxiliary/issue-12133-dylib2.rs | 0 .../issues}/auxiliary/issue-12133-rlib.rs | 0 .../issues}/auxiliary/issue-12660-aux.rs | 0 .../issues}/auxiliary/issue-13620-1.rs | 0 .../issues}/auxiliary/issue-13620-2.rs | 0 .../issues}/auxiliary/issue-13872-1.rs | 0 .../issues}/auxiliary/issue-13872-2.rs | 0 .../issues}/auxiliary/issue-13872-3.rs | 0 .../issues}/auxiliary/issue-14344-1.rs | 0 .../issues}/auxiliary/issue-14344-2.rs | 0 .../run-pass/issues}/auxiliary/issue-14421.rs | 0 .../run-pass/issues}/auxiliary/issue-14422.rs | 0 .../run-pass/issues}/auxiliary/issue-15562.rs | 0 .../run-pass/issues}/auxiliary/issue-16643.rs | 0 .../run-pass/issues}/auxiliary/issue-17662.rs | 0 .../issues}/auxiliary/issue-17718-aux.rs | 0 .../run-pass/issues}/auxiliary/issue-18501.rs | 0 .../run-pass/issues}/auxiliary/issue-18514.rs | 0 .../run-pass/issues}/auxiliary/issue-18711.rs | 0 .../issues}/auxiliary/issue-18913-1.rs | 0 .../issues}/auxiliary/issue-18913-2.rs | 0 .../issues}/auxiliary/issue-19340-1.rs | 0 .../run-pass/issues}/auxiliary/issue-2380.rs | 1 - .../issues}/auxiliary/issue-2414-a.rs | 0 .../issues}/auxiliary/issue-2414-b.rs | 0 .../issues}/auxiliary/issue-25185-1.rs | 0 .../issues}/auxiliary/issue-25185-2.rs | 0 .../run-pass/issues}/auxiliary/issue-2526.rs | 0 .../run-pass/issues}/auxiliary/issue-25467.rs | 0 .../issues}/auxiliary/issue-2631-a.rs | 0 .../run-pass/issues}/auxiliary/issue-29485.rs | 0 .../issues}/auxiliary/issue-3012-1.rs | 0 .../run-pass/issues/auxiliary/issue-36954.rs | 18 + .../run-pass/issues}/auxiliary/issue-41394.rs | 0 .../issues}/auxiliary/issue-4208-cc.rs | 0 .../run-pass/issues}/auxiliary/issue-4545.rs | 0 .../issues}/auxiliary/issue-48984-aux.rs | 0 .../run-pass/issues}/auxiliary/issue-5518.rs | 0 .../run-pass/issues}/auxiliary/issue-5521.rs | 0 .../run-pass/issues}/auxiliary/issue-7178.rs | 0 .../run-pass/issues}/auxiliary/issue-7899.rs | 0 .../run-pass/issues}/auxiliary/issue-8044.rs | 0 .../run-pass/issues}/auxiliary/issue-8259.rs | 0 .../run-pass/issues}/auxiliary/issue-9906.rs | 0 .../run-pass/issues}/auxiliary/issue-9968.rs | 0 .../run-pass/issues}/auxiliary/issue13507.rs | 34 +- .../issues}/auxiliary/issue2170lib.rs | 0 .../issues}/auxiliary/issue34796aux.rs | 0 .../issues}/auxiliary/issue_10031_aux.rs | 0 .../issues}/auxiliary/issue_12612_1.rs | 0 .../issues}/auxiliary/issue_12612_2.rs | 0 .../run-pass/issues}/auxiliary/issue_19293.rs | 0 .../run-pass/issues}/auxiliary/issue_20389.rs | 0 .../issues}/auxiliary/issue_2316_a.rs | 0 .../issues}/auxiliary/issue_2316_b.rs | 0 .../issues}/auxiliary/issue_2472_b.rs | 0 .../issues}/auxiliary/issue_2723_a.rs | 0 .../issues}/auxiliary/issue_3136_a.rc | 0 .../issues}/auxiliary/issue_3136_a.rs | 0 .../run-pass/issues}/auxiliary/issue_38190.rs | 0 .../issues}/auxiliary/issue_38226_aux.rs | 0 .../issues/auxiliary/issue_38715-modern.rs | 17 + .../run-pass/issues}/auxiliary/issue_38715.rs | 0 .../issues}/auxiliary/issue_3979_traits.rs | 0 .../run-pass/issues}/auxiliary/issue_39823.rs | 0 .../run-pass/issues}/auxiliary/issue_40469.rs | 0 .../run-pass/issues}/auxiliary/issue_41053.rs | 0 .../issues}/auxiliary/issue_42007_s.rs | 0 .../run-pass/issues}/auxiliary/issue_8401.rs | 0 .../run-pass/issues}/auxiliary/issue_9123.rs | 0 .../run-pass/issues}/auxiliary/issue_9155.rs | 0 .../run-pass/issues}/auxiliary/issue_9188.rs | 0 .../run-pass/issues}/issue-10025.rs | 1 + .../run-pass/issues}/issue-10028.rs | 1 + .../run-pass/issues}/issue-10031.rs | 1 + .../run-pass/issues}/issue-10228.rs | 1 + .../run-pass/issues}/issue-10392.rs | 1 + .../run-pass/issues}/issue-10396.rs | 1 + .../run-pass/issues}/issue-10436.rs | 1 + .../run-pass/issues}/issue-10456.rs | 1 + .../run-pass/issues}/issue-10626.rs | 1 + .../run-pass/issues}/issue-10638.rs | 1 + .../run-pass/issues}/issue-10682.rs | 2 +- .../run-pass/issues}/issue-10683.rs | 1 + .../run-pass/issues}/issue-10718.rs | 1 + .../run-pass/issues}/issue-10734.rs | 3 + .../run-pass/issues}/issue-10763.rs | 1 + .../run-pass/issues}/issue-10764.rs | 1 + .../run-pass/issues}/issue-10767.rs | 2 +- .../run-pass/issues}/issue-10802.rs | 3 +- .../run-pass/issues}/issue-10806.rs | 1 + .../run-pass/issues}/issue-10853.rs | 1 + .../run-pass/issues}/issue-10902.rs | 1 + .../run-pass/issues}/issue-11047.rs | 1 + .../run-pass/issues}/issue-11085.rs | 1 + .../run-pass/issues}/issue-1112.rs | 1 + .../run-pass/issues}/issue-11205.rs | 1 + .../run-pass/issues}/issue-11224.rs | 1 + .../run-pass/issues}/issue-11225-1.rs | 1 + .../run-pass/issues}/issue-11225-2.rs | 1 + .../run-pass/issues}/issue-11225-3.rs | 1 + .../run-pass/issues}/issue-11267.rs | 1 + .../run-pass/issues}/issue-11382.rs | 1 + .../run-pass/issues}/issue-11384.rs | 1 + .../run-pass/issues}/issue-11508.rs | 1 + .../run-pass/issues}/issue-11529.rs | 1 + .../run-pass/issues}/issue-11552.rs | 3 +- .../run-pass/issues}/issue-11577.rs | 1 + .../run-pass/issues}/issue-11592.rs | 1 + .../run-pass/issues}/issue-11612.rs | 1 + .../run-pass/issues}/issue-11677.rs | 1 + .../run-pass/issues}/issue-11709.rs | 1 + .../run-pass/issues}/issue-11820.rs | 1 + .../run-pass/issues}/issue-11869.rs | 1 + .../run-pass/issues}/issue-11940.rs | 1 + .../run-pass/issues}/issue-11958.rs | 1 + .../run-pass/issues}/issue-12033.rs | 1 + .../run-pass/issues}/issue-12133-1.rs | 1 + .../run-pass/issues}/issue-12133-2.rs | 1 + .../run-pass/issues}/issue-12133-3.rs | 1 + .../run-pass/issues}/issue-12285.rs | 1 + .../run-pass/issues}/issue-1251.rs | 1 + .../run-pass/issues}/issue-1257.rs | 1 + .../run-pass/issues}/issue-12582.rs | 3 +- .../run-pass/issues}/issue-12612.rs | 1 + .../run-pass/issues}/issue-12660.rs | 1 + .../run-pass/issues}/issue-12677.rs | 1 + .../run-pass/issues}/issue-12699.rs | 2 + .../run-pass/issues}/issue-12729.rs | 1 + .../run-pass/issues}/issue-12744.rs | 1 + .../run-pass/issues}/issue-12860.rs | 1 + .../run-pass/issues}/issue-12909.rs | 1 + .../run-pass/issues}/issue-13027.rs | 3 +- .../run-pass/issues}/issue-13105.rs | 1 + .../run-pass/issues}/issue-13167.rs | 1 + .../run-pass/issues}/issue-13204.rs | 1 + .../run-pass/issues}/issue-13214.rs | 1 + .../issues}/issue-13259-windows-tcb-trash.rs | 3 +- .../run-pass/issues}/issue-13264.rs | 4 + .../run-pass/issues}/issue-13304.rs | 3 +- .../run-pass/issues}/issue-13323.rs | 3 +- .../run-pass/issues}/issue-13405.rs | 1 + .../run-pass/issues}/issue-13434.rs | 1 + .../run-pass/issues}/issue-13494.rs | 1 + .../run-pass/issues}/issue-13507-2.rs | 1 + .../run-pass/issues}/issue-13620.rs | 1 + .../run-pass/issues}/issue-13655.rs | 1 + .../run-pass/issues}/issue-13665.rs | 1 + .../run-pass/issues}/issue-13703.rs | 1 + .../run-pass/issues}/issue-13763.rs | 1 + .../run-pass/issues}/issue-13775.rs | 1 + .../run-pass/issues}/issue-13808.rs | 1 + .../run-pass/issues}/issue-13837.rs | 1 + .../run-pass/issues}/issue-13867.rs | 1 + .../run-pass/issues}/issue-13872.rs | 1 + .../run-pass/issues}/issue-13902.rs | 3 + .../run-pass/issues}/issue-14082.rs | 1 + .../run-pass/issues}/issue-14229.rs | 1 + .../run-pass/issues}/issue-14254.rs | 1 + .../run-pass/issues}/issue-14308.rs | 1 + .../run-pass/issues}/issue-14330.rs | 1 + .../run-pass/issues}/issue-14344.rs | 1 + .../run-pass/issues}/issue-14382.rs | 1 + .../run-pass/issues}/issue-14393.rs | 1 + .../run-pass/issues}/issue-14399.rs | 2 +- .../run-pass/issues}/issue-14421.rs | 3 + .../run-pass/issues}/issue-14422.rs | 3 + .../run-pass/issues}/issue-14456.rs | 3 +- .../run-pass/issues}/issue-1451.rs | 3 +- .../run-pass/issues}/issue-14589.rs | 1 + .../run-pass/issues}/issue-1460.rs | 1 + .../run-pass/issues}/issue-14821.rs | 1 + .../run-pass/issues}/issue-14837.rs | 1 + .../run-pass/issues}/issue-14865.rs | 1 + .../run-pass/issues}/issue-14875.rs | 1 + .../run-pass/issues}/issue-14901.rs | 1 + .../run-pass/issues}/issue-14919.rs | 1 + .../run-pass/issues}/issue-14933.rs | 1 + .../run-pass/issues}/issue-14936.rs | 1 + .../run-pass/issues}/issue-14940.rs | 1 + .../run-pass/issues}/issue-14958.rs | 1 + .../run-pass/issues}/issue-14959.rs | 1 + .../run-pass/issues}/issue-15043.rs | 1 + .../run-pass/issues}/issue-15063.rs | 1 + .../run-pass/issues}/issue-15080.rs | 1 + .../run-pass/issues}/issue-15104.rs | 1 + .../run-pass/issues}/issue-15108.rs | 1 + .../run-pass/issues}/issue-15129.rs | 1 + .../run-pass/issues}/issue-15155.rs | 1 + .../run-pass/issues}/issue-15189.rs | 1 + .../run-pass/issues}/issue-15221.rs | 1 + .../run-pass/issues}/issue-15261.rs | 3 + .../run-pass/issues}/issue-15444.rs | 1 + .../run-pass/issues}/issue-15487.rs | 1 + .../run-pass/issues}/issue-15523-big.rs | 1 + .../run-pass/issues}/issue-15523.rs | 1 + .../run-pass/issues}/issue-15562.rs | 1 + .../run-pass/issues}/issue-15571.rs | 2 +- .../run-pass/issues}/issue-15673.rs | 3 + .../run-pass/issues}/issue-15689-1.rs | 1 + .../run-pass/issues}/issue-15689-2.rs | 1 + .../run-pass/issues}/issue-15730.rs | 1 + .../run-pass/issues}/issue-15734.rs | 4 +- .../run-pass/issues}/issue-15735.rs | 1 + .../run-pass/issues}/issue-15763.rs | 2 +- .../run-pass/issues}/issue-15774.rs | 1 + .../run-pass/issues}/issue-15793.rs | 1 + .../run-pass/issues}/issue-15858.rs | 1 + .../issue-15881-model-lexer-dotdotdot.rs | 7 +- .../run-pass/issues}/issue-16151.rs | 1 + .../run-pass/issues}/issue-16256.rs | 1 + .../run-pass/issues}/issue-16272.rs | 1 + .../run-pass/issues}/issue-16278.rs | 6 +- .../run-pass/issues}/issue-16441.rs | 1 + .../run-pass/issues}/issue-16452.rs | 1 + .../run-pass/issues}/issue-16492.rs | 3 + .../run-pass/issues}/issue-16530.rs | 3 + .../run-pass/issues}/issue-16560.rs | 1 + .../run-pass/issues}/issue-16596.rs | 1 + .../run-pass/issues}/issue-16597-empty.rs | 1 + .../run-pass/issues}/issue-16597.rs | 1 + .../run-pass/issues}/issue-1660.rs | 3 + .../run-pass/issues}/issue-16602-1.rs | 1 + .../run-pass/issues}/issue-16602-2.rs | 1 + .../run-pass/issues}/issue-16602-3.rs | 1 + .../run-pass/issues}/issue-16643.rs | 1 + .../run-pass/issues}/issue-16648.rs | 1 + .../run-pass/issues}/issue-16668.rs | 3 +- .../run-pass/issues}/issue-16671.rs | 1 + .../run-pass/issues}/issue-16739.rs | 3 +- .../run-pass/issues}/issue-16745.rs | 1 + .../run-pass/issues}/issue-16774.rs | 3 +- .../run-pass/issues}/issue-16783.rs | 1 + .../run-pass/issues}/issue-16819.rs | 1 + .../run-pass/issues}/issue-16922.rs | 1 + .../run-pass/issues}/issue-1696.rs | 1 + .../run-pass/issues}/issue-1701.rs | 3 + .../run-pass/issues}/issue-17068.rs | 1 + .../run-pass/issues}/issue-17074.rs | 1 + .../run-pass/issues}/issue-17121.rs | 1 + .../run-pass/issues}/issue-17170.rs | 1 + .../run-pass/issues}/issue-17216.rs | 1 + .../run-pass/issues}/issue-17233.rs | 1 + .../run-pass/issues}/issue-17302.rs | 1 + .../run-pass/issues}/issue-17322.rs | 4 +- .../run-pass/issues}/issue-17336.rs | 1 + .../run-pass/issues}/issue-17351.rs | 3 +- .../run-pass/issues}/issue-17361.rs | 1 + .../run-pass/issues}/issue-17450.rs | 1 + .../run-pass/issues}/issue-17503.rs | 1 + .../run-pass/issues}/issue-17662.rs | 1 + .../issues}/issue-17718-borrow-interior.rs | 1 + .../issues}/issue-17718-const-destructors.rs | 1 + .../issues}/issue-17718-parse-const.rs | 1 + .../issue-17718-static-unsafe-interior.rs | 1 + .../run-pass/issues}/issue-17718.rs | 1 + .../run-pass/issues}/issue-17732.rs | 1 + .../run-pass/issues}/issue-17734.rs | 1 + .../run-pass/issues}/issue-17746.rs | 1 + .../run-pass/issues}/issue-17756.rs | 3 + .../run-pass/issues}/issue-17771.rs | 1 + .../run-pass/issues}/issue-17816.rs | 1 + .../run-pass/issues}/issue-17877.rs | 1 + .../run-pass/issues}/issue-17897.rs | 1 + .../run-pass/issues}/issue-17904.rs | 1 + .../run-pass/issues}/issue-18060.rs | 1 + .../run-pass/issues}/issue-18075.rs | 1 + .../run-pass/issues}/issue-18083.rs | 1 + .../run-pass/issues}/issue-18088.rs | 1 + .../run-pass/issues}/issue-18110.rs | 1 + .../run-pass/issues}/issue-18173.rs | 1 + .../run-pass/issues}/issue-18188.rs | 1 + .../run-pass/issues}/issue-1821.rs | 3 + .../run-pass/issues}/issue-18232.rs | 1 + .../run-pass/issues}/issue-18352.rs | 1 + .../run-pass/issues}/issue-18353.rs | 1 + .../run-pass/issues}/issue-18412.rs | 1 + .../run-pass/issues}/issue-18425.rs | 1 + .../run-pass/issues}/issue-18446.rs | 1 + .../run-pass/issues}/issue-18464.rs | 1 + .../run-pass/issues}/issue-18501.rs | 1 + .../run-pass/issues}/issue-18514.rs | 1 + .../run-pass/issues}/issue-18539.rs | 1 + .../run-pass/issues}/issue-18652.rs | 1 + .../run-pass/issues}/issue-18655.rs | 1 + .../run-pass/issues}/issue-1866.rs | 3 + .../run-pass/issues}/issue-18661.rs | 1 + .../run-pass/issues}/issue-18685.rs | 1 + .../run-pass/issues}/issue-18711.rs | 1 + .../run-pass/issues}/issue-18738.rs | 1 + .../run-pass/issues}/issue-18767.rs | 1 + .../issues}/issue-18804/auxiliary/lib.rs | 0 .../ui/run-pass/issues/issue-18804/main.rs | 24 + .../run-pass/issues}/issue-18809.rs | 1 + .../run-pass/issues}/issue-18845.rs | 1 + .../run-pass/issues}/issue-18859.rs | 1 + .../run-pass/issues}/issue-18906.rs | 1 + .../run-pass/issues}/issue-18913.rs | 1 + .../run-pass/issues}/issue-18937-1.rs | 1 + .../run-pass/issues}/issue-18988.rs | 1 + .../run-pass/issues}/issue-19001.rs | 1 + .../run-pass/issues}/issue-19037.rs | 1 + .../run-pass/issues}/issue-19081.rs | 1 + .../run-pass/issues}/issue-19097.rs | 1 + .../run-pass/issues}/issue-19098.rs | 1 + .../run-pass/issues}/issue-19102.rs | 1 + .../run-pass/issues}/issue-19127.rs | 1 + .../run-pass/issues}/issue-19129-1.rs | 1 + .../run-pass/issues}/issue-19129-2.rs | 1 + .../run-pass/issues}/issue-19135.rs | 1 + .../run-pass/issues}/issue-19244.rs | 1 + .../run-pass/issues}/issue-19293.rs | 1 + .../run-pass/issues}/issue-19340-1.rs | 1 + .../run-pass/issues}/issue-19340-2.rs | 1 + .../run-pass/issues}/issue-19358.rs | 1 + .../run-pass/issues}/issue-19367.rs | 1 + .../run-pass/issues}/issue-19398.rs | 1 + .../run-pass/issues}/issue-19404.rs | 1 + .../run-pass/issues}/issue-19479.rs | 1 + .../run-pass/issues}/issue-19499.rs | 1 + .../run-pass/issues}/issue-19631.rs | 1 + .../run-pass/issues}/issue-19632.rs | 1 + .../run-pass/issues}/issue-1974.rs | 1 + .../issues}/issue-19811-escape-unicode.rs | 1 + .../run-pass/issues}/issue-19850.rs | 1 + .../run-pass/issues}/issue-19982.rs | 1 + .../run-pass/issues}/issue-20009.rs | 1 + .../run-pass/issues}/issue-20055-box-trait.rs | 1 + .../issues}/issue-20055-box-unsized-array.rs | 1 + .../run-pass/issues}/issue-20091.rs | 5 +- .../run-pass/issues}/issue-20174.rs | 1 + .../run-pass/issues}/issue-20186.rs | 1 + .../run-pass/issues}/issue-20313.rs | 2 + .../run-pass/issues}/issue-20343.rs | 1 + .../run-pass/issues}/issue-20389.rs | 1 + .../run-pass/issues}/issue-20396.rs | 1 + .../run-pass/issues}/issue-20414.rs | 1 + .../run-pass/issues}/issue-20427.rs | 4 + .../run-pass/issues}/issue-20454.rs | 3 +- .../run-pass/issues}/issue-20544.rs | 1 + .../run-pass/issues}/issue-20575.rs | 1 + .../run-pass/issues}/issue-20616.rs | 3 +- .../run-pass/issues}/issue-2063-resource.rs | 1 + .../run-pass/issues}/issue-2063.rs | 1 + .../run-pass/issues}/issue-20644.rs | 3 + .../run-pass/issues}/issue-20676.rs | 1 + .../run-pass/issues}/issue-2074.rs | 1 + .../run-pass/issues}/issue-20763-1.rs | 1 + .../run-pass/issues}/issue-20763-2.rs | 1 + .../run-pass/issues}/issue-20797.rs | 1 + .../run-pass/issues}/issue-20803.rs | 1 + .../run-pass/issues}/issue-20823.rs | 3 +- .../run-pass/issues}/issue-20825.rs | 1 + .../run-pass/issues}/issue-20847.rs | 1 + .../run-pass/issues}/issue-20953.rs | 1 + .../run-pass/issues}/issue-21033.rs | 2 + .../run-pass/issues}/issue-21058.rs | 1 + .../run-pass/issues}/issue-21140.rs | 1 + .../run-pass/issues}/issue-21174.rs | 1 + .../run-pass/issues}/issue-21245.rs | 1 + .../run-pass/issues}/issue-21291.rs | 1 + .../run-pass/issues}/issue-21306.rs | 1 + .../run-pass/issues}/issue-21361.rs | 1 + .../run-pass/issues}/issue-21363.rs | 1 + .../run-pass/issues}/issue-21384.rs | 1 + .../run-pass/issues}/issue-21400.rs | 1 + .../run-pass/issues}/issue-21402.rs | 1 + .../run-pass/issues}/issue-21475.rs | 1 + .../run-pass/issues}/issue-21486.rs | 1 + .../run-pass/issues}/issue-21520.rs | 1 + .../run-pass/issues}/issue-21562.rs | 3 +- .../run-pass/issues}/issue-21622.rs | 1 + .../run-pass/issues}/issue-21634.rs | 3 + .../run-pass/issues}/issue-21655.rs | 1 + .../run-pass/issues}/issue-21721.rs | 1 + .../run-pass/issues}/issue-21726.rs | 1 + .../run-pass/issues}/issue-21891.rs | 3 + .../run-pass/issues}/issue-2190-1.rs | 3 + .../run-pass/issues}/issue-21909.rs | 1 + .../run-pass/issues}/issue-21922.rs | 1 + .../run-pass/issues}/issue-22008.rs | 1 + .../run-pass/issues}/issue-22036.rs | 1 + .../run-pass/issues}/issue-22066.rs | 1 + .../run-pass/issues}/issue-2214.rs | 1 + .../run-pass/issues}/issue-2216.rs | 1 + .../run-pass/issues}/issue-22258.rs | 1 + .../run-pass/issues}/issue-22346.rs | 3 +- .../run-pass/issues}/issue-22356.rs | 3 + .../run-pass/issues}/issue-22375.rs | 1 + .../run-pass/issues}/issue-22403.rs | 1 + .../run-pass/issues}/issue-22426.rs | 1 + .../run-pass/issues}/issue-22463.rs | 1 + .../run-pass/issues}/issue-22471.rs | 3 + .../issues}/issue-22536-copy-mustnt-zero.rs | 1 + .../run-pass/issues}/issue-22546.rs | 1 + .../run-pass/issues}/issue-22577.rs | 3 +- .../run-pass/issues}/issue-22629.rs | 1 + .../run-pass/issues}/issue-22777.rs | 1 + .../run-pass/issues}/issue-22781.rs | 1 + .../run-pass/issues}/issue-22814.rs | 1 + .../run-pass/issues}/issue-22828.rs | 1 + .../run-pass/issues}/issue-2284.rs | 1 + .../run-pass/issues}/issue-22864-1.rs | 1 + .../run-pass/issues}/issue-22864-2.rs | 1 + .../run-pass/issues}/issue-2288.rs | 4 +- .../run-pass/issues}/issue-22894.rs | 1 + .../run-pass/issues}/issue-22992-2.rs | 1 + .../run-pass/issues}/issue-22992.rs | 1 + .../run-pass/issues}/issue-23036.rs | 1 + .../run-pass/issues}/issue-2311-2.rs | 3 + .../run-pass/issues}/issue-2311.rs | 3 + .../run-pass/issues}/issue-2312.rs | 3 + .../run-pass/issues}/issue-2316-c.rs | 1 + .../run-pass/issues}/issue-23208.rs | 1 + .../run-pass/issues}/issue-23261.rs | 1 + .../run-pass/issues}/issue-23304-1.rs | 1 + .../run-pass/issues}/issue-23304-2.rs | 1 + .../run-pass/issues}/issue-23311.rs | 1 + .../run-pass/issues}/issue-23336.rs | 1 + .../issue-23338-ensure-param-drop-order.rs | 3 + ...ssue-23338-params-outlive-temps-of-body.rs | 1 + .../run-pass/issues}/issue-23406.rs | 1 + .../run-pass/issues}/issue-23433.rs | 1 + .../run-pass/issues}/issue-23442.rs | 1 + .../run-pass/issues}/issue-23477.rs | 2 + .../run-pass/issues}/issue-23485.rs | 1 + .../run-pass/issues}/issue-23491.rs | 1 + .../run-pass/issues}/issue-23550.rs | 1 + .../issues}/issue-23611-enum-swap-in-drop.rs | 3 + .../run-pass/issues}/issue-23649-1.rs | 1 + .../run-pass/issues}/issue-23649-2.rs | 1 + .../run-pass/issues}/issue-23649-3.rs | 1 + .../run-pass/issues}/issue-23699.rs | 1 + .../run-pass/issues}/issue-23781.rs | 1 + .../run-pass/issues}/issue-2380-b.rs | 1 + .../run-pass/issues}/issue-23808.rs | 1 + .../run-pass/issues}/issue-23825.rs | 1 + .../run-pass/issues}/issue-2383.rs | 1 + .../run-pass/issues}/issue-23833.rs | 1 + .../run-pass/issues}/issue-23891.rs | 1 + .../run-pass/issues}/issue-23898.rs | 3 + .../run-pass/issues}/issue-23958.rs | 1 + .../issues}/issue-23968-const-not-overflow.rs | 1 + .../run-pass/issues}/issue-23992.rs | 1 + .../run-pass/issues}/issue-24085.rs | 1 + .../run-pass/issues}/issue-24086.rs | 1 + .../run-pass/issues}/issue-2414-c.rs | 1 + .../run-pass/issues}/issue-24161.rs | 1 + .../run-pass/issues}/issue-24227.rs | 1 + .../run-pass/issues}/issue-2428.rs | 3 + .../run-pass/issues}/issue-24308.rs | 1 + .../run-pass/issues}/issue-24313.rs | 1 + .../run-pass/issues}/issue-24353.rs | 1 + .../run-pass/issues}/issue-24389.rs | 1 + .../run-pass/issues}/issue-24434.rs | 1 + .../run-pass/issues}/issue-2445-b.rs | 3 + .../run-pass/issues}/issue-2445.rs | 3 + .../run-pass/issues}/issue-24533.rs | 1 + ...535-allow-mutable-borrow-in-match-guard.rs | 1 + .../run-pass/issues}/issue-24589.rs | 1 + .../run-pass/issues}/issue-2463.rs | 1 + .../run-pass/issues}/issue-2472.rs | 1 + .../run-pass/issues}/issue-24779.rs | 1 + .../issues}/issue-24805-dropck-itemless.rs | 3 + .../run-pass/issues}/issue-2487-a.rs | 3 + .../issues}/issue-24945-repeat-dash-opts.rs | 1 + .../run-pass/issues}/issue-24947.rs | 1 + .../run-pass/issues}/issue-24954.rs | 1 + .../run-pass/issues}/issue-2502.rs | 3 + .../run-pass/issues}/issue-25089.rs | 1 + .../run-pass/issues}/issue-25145.rs | 1 + .../run-pass/issues}/issue-25180.rs | 3 + .../run-pass/issues}/issue-25185.rs | 1 + .../run-pass/issues}/issue-2526-a.rs | 1 + .../run-pass/issues}/issue-25279.rs | 1 + .../run-pass/issues}/issue-25339.rs | 1 + .../run-pass/issues}/issue-25343.rs | 1 + .../run-pass/issues}/issue-25394.rs | 1 + .../run-pass/issues}/issue-25467.rs | 1 + .../run-pass/issues}/issue-25497.rs | 1 + .../run-pass/issues}/issue-2550.rs | 3 + .../run-pass/issues}/issue-25515.rs | 1 + .../issues}/issue-25549-multiple-drop.rs | 1 + .../run-pass/issues}/issue-25679.rs | 1 + .../run-pass/issues}/issue-25693.rs | 1 + .../run-pass/issues}/issue-25700-1.rs | 1 + .../run-pass/issues}/issue-25700-2.rs | 1 + .../issues}/issue-25746-bool-transmute.rs | 1 + .../run-pass/issues}/issue-25757.rs | 1 + .../run-pass/issues}/issue-25810.rs | 1 + .../run-pass/issues}/issue-25916.rs | 1 + .../run-pass/issues}/issue-26095.rs | 3 + .../run-pass/issues}/issue-2611-3.rs | 1 + .../run-pass/issues}/issue-26127.rs | 1 + .../run-pass/issues}/issue-26205.rs | 1 + .../run-pass/issues}/issue-26251.rs | 1 + .../run-pass/issues}/issue-2631-b.rs | 1 + .../run-pass/issues}/issue-26322.rs | 12 +- .../run-pass/issues}/issue-2633-2.rs | 2 +- .../run-pass/issues}/issue-2633.rs | 3 + .../run-pass/issues}/issue-2642.rs | 1 + .../run-pass/issues}/issue-26468.rs | 1 + .../run-pass/issues}/issue-26484.rs | 1 + .../run-pass/issues}/issue-26641.rs | 1 + .../run-pass/issues}/issue-26646.rs | 1 + .../run-pass/issues}/issue-26655.rs | 1 + .../run-pass/issues}/issue-26709.rs | 1 + .../run-pass/issues}/issue-26802.rs | 1 + .../run-pass/issues}/issue-26805.rs | 1 + .../run-pass/issues}/issue-26873-multifile.rs | 3 + .../run-pass/issues}/issue-26873-onefile.rs | 3 + .../run-pass/issues}/issue-26905.rs | 1 + .../run-pass/issues}/issue-26996.rs | 1 + .../run-pass/issues}/issue-26997.rs | 1 + .../run-pass/issues}/issue-27021.rs | 1 + .../issue-27054-primitive-binary-ops.rs | 1 + .../run-pass/issues}/issue-27060.rs | 1 + .../run-pass/issues}/issue-2708.rs | 4 +- .../run-pass/issues}/issue-27105.rs | 1 + .../run-pass/issues}/issue-2718.rs | 4 +- .../run-pass/issues}/issue-2723-b.rs | 1 + .../run-pass/issues}/issue-27240.rs | 1 + .../run-pass/issues}/issue-27268.rs | 1 + .../run-pass/issues}/issue-27281.rs | 1 + .../run-pass/issues}/issue-27320.rs | 1 + .../run-pass/issues}/issue-2734.rs | 4 +- .../run-pass/issues}/issue-2735-2.rs | 3 + .../run-pass/issues}/issue-2735-3.rs | 3 + .../run-pass/issues}/issue-2735.rs | 4 +- .../issues}/issue-27401-dropflag-reinit.rs | 1 + .../run-pass/issues}/issue-2748-a.rs | 3 + .../run-pass/issues}/issue-2748-b.rs | 1 + .../run-pass/issues}/issue-27583.rs | 1 + .../run-pass/issues}/issue-27639.rs | 3 + .../run-pass/issues}/issue-27859.rs | 1 + .../run-pass/issues}/issue-27889.rs | 1 + .../run-pass/issues}/issue-27890.rs | 1 + .../run-pass/issues}/issue-27901.rs | 1 + .../run-pass/issues}/issue-27997.rs | 1 + .../run-pass/issues}/issue-2804-2.rs | 1 + .../run-pass/issues}/issue-28181.rs | 1 + .../run-pass/issues}/issue-28279.rs | 1 + .../run-pass/issues}/issue-28550.rs | 1 + .../run-pass/issues}/issue-28561.rs | 1 + .../run-pass/issues}/issue-28600.rs | 1 + .../run-pass/issues}/issue-28676.rs | 3 + .../run-pass/issues}/issue-28777.rs | 1 + .../run-pass/issues}/issue-28822.rs | 3 +- .../run-pass/issues}/issue-28828.rs | 1 + .../run-pass/issues}/issue-28839.rs | 1 + .../run-pass/issues}/issue-28871.rs | 1 + .../run-pass/issues}/issue-28936.rs | 1 + .../run-pass/issues}/issue-2895.rs | 1 + .../run-pass/issues}/issue-28950.rs | 1 + .../run-pass/issues}/issue-28983.rs | 1 + .../run-pass/issues}/issue-28999.rs | 1 + .../run-pass/issues}/issue-29030.rs | 1 + .../run-pass/issues}/issue-29037.rs | 1 + .../run-pass/issues}/issue-2904.rs | 2 + .../run-pass/issues}/issue-29048.rs | 1 + .../run-pass/issues}/issue-29053.rs | 1 + .../run-pass/issues}/issue-29071-2.rs | 1 + .../run-pass/issues}/issue-29071.rs | 4 + .../run-pass/issues}/issue-29092.rs | 1 + .../run-pass/issues}/issue-29147.rs | 1 + .../run-pass/issues}/issue-29166.rs | 1 + .../run-pass/issues}/issue-29227.rs | 1 + .../run-pass/issues}/issue-29276.rs | 1 + .../run-pass/issues}/issue-2935.rs | 3 +- .../run-pass/issues}/issue-2936.rs | 2 + .../run-pass/issues}/issue-29466.rs | 1 + .../run-pass/issues}/issue-29485.rs | 1 + .../run-pass/issues}/issue-29488.rs | 1 + .../run-pass/issues}/issue-29516.rs | 1 + .../run-pass/issues}/issue-29522.rs | 1 + .../run-pass/issues}/issue-29540.rs | 1 + .../run-pass/issues}/issue-29663.rs | 2 + .../run-pass/issues}/issue-29668.rs | 1 + .../run-pass/issues}/issue-29710.rs | 1 + .../run-pass/issues}/issue-29740.rs | 2 + .../run-pass/issues}/issue-29746.rs | 1 + .../run-pass/issues}/issue-29844.rs | 1 + .../run-pass/issues}/issue-2989.rs | 3 + .../run-pass/issues}/issue-29914-2.rs | 1 + .../run-pass/issues}/issue-29914-3.rs | 1 + .../run-pass/issues}/issue-29914.rs | 4 + .../run-pass/issues}/issue-29927.rs | 3 +- .../run-pass/issues}/issue-29948.rs | 1 + .../run-pass/issues}/issue-30018-nopanic.rs | 1 + .../run-pass/issues}/issue-30018-panic.rs | 1 + .../run-pass/issues}/issue-30081.rs | 1 + .../run-pass/issues}/issue-3012-2.rs | 1 + .../run-pass/issues}/issue-30240.rs | 1 + .../run-pass/issues}/issue-3026.rs | 1 + .../run-pass/issues}/issue-3037.rs | 2 + .../run-pass/issues}/issue-30371.rs | 1 + .../run-pass/issues}/issue-30490.rs | 1 + .../run-pass/issues}/issue-3052.rs | 1 + .../run-pass/issues}/issue-30530.rs | 1 + .../run-pass/issues}/issue-30615.rs | 1 + .../run-pass/issues}/issue-30756.rs | 1 + .../run-pass/issues}/issue-30891.rs | 1 + .../run-pass/issues}/issue-3091.rs | 1 + .../run-pass/issues}/issue-3109.rs | 1 + .../run-pass/issues}/issue-3121.rs | 3 +- .../run-pass/issues}/issue-31260.rs | 1 + .../issues}/issue-31267-additional.rs | 1 + .../run-pass/issues}/issue-31267.rs | 1 + .../run-pass/issues}/issue-31299.rs | 1 + .../run-pass/issues}/issue-3149.rs | 2 + .../run-pass/issues}/issue-31597.rs | 1 + .../run-pass/issues}/issue-31702.rs | 1 + .../run-pass/issues}/issue-31776.rs | 1 + .../run-pass/issues}/issue-32008.rs | 1 + .../run-pass/issues}/issue-3211.rs | 1 + .../run-pass/issues}/issue-3220.rs | 2 + .../run-pass/issues}/issue-32292.rs | 1 + .../run-pass/issues}/issue-32324.rs | 1 + .../run-pass/issues}/issue-32389.rs | 1 + .../run-pass/issues}/issue-32518.rs | 1 + .../run-pass/issues}/issue-32805.rs | 1 + .../run-pass/issues}/issue-3290.rs | 3 +- .../run-pass/issues}/issue-32947.rs | 1 + .../run-pass/issues}/issue-33096.rs | 1 + .../run-pass/issues}/issue-33185.rs | 1 + .../run-pass/issues}/issue-33187.rs | 1 + .../run-pass/issues}/issue-33202.rs | 1 + .../run-pass/issues}/issue-33264.rs | 1 + .../run-pass/issues}/issue-33287.rs | 1 + .../run-pass/issues}/issue-333.rs | 1 + .../run-pass/issues}/issue-33387.rs | 1 + .../run-pass/issues}/issue-33461.rs | 1 + .../run-pass/issues}/issue-33498.rs | 1 + .../run-pass/issues}/issue-33537.rs | 3 +- .../run-pass/issues}/issue-33687.rs | 1 + .../run-pass/issues}/issue-33770.rs | 1 + .../run-pass/issues}/issue-3389.rs | 2 + .../run-pass/issues}/issue-33903.rs | 3 +- .../run-pass/issues}/issue-33992.rs | 1 + .../run-pass/issues}/issue-34053.rs | 1 + .../run-pass/issues}/issue-34074.rs | 1 + .../run-pass/issues}/issue-34194.rs | 1 + .../run-pass/issues}/issue-3424.rs | 2 + .../run-pass/issues}/issue-3429.rs | 1 + .../run-pass/issues}/issue-34427.rs | 1 + .../run-pass/issues}/issue-3447.rs | 4 +- .../run-pass/issues}/issue-34503.rs | 1 + .../run-pass/issues}/issue-34569.rs | 1 + .../run-pass/issues}/issue-34571.rs | 1 + .../run-pass/issues}/issue-34751.rs | 1 + .../run-pass/issues}/issue-34780.rs | 2 + .../run-pass/issues}/issue-34784.rs | 1 + .../run-pass/issues}/issue-34796.rs | 1 + .../run-pass/issues}/issue-34798.rs | 1 + .../run-pass/issues}/issue-34932.rs | 1 + .../run-pass/issues}/issue-3500.rs | 1 + .../run-pass/issues}/issue-35376.rs | 1 + .../run-pass/issues}/issue-35423.rs | 1 + .../run-pass/issues}/issue-35546.rs | 1 + .../run-pass/issues}/issue-3556.rs | 1 + .../run-pass/issues}/issue-3559.rs | 1 + .../run-pass/issues}/issue-35600.rs | 1 + .../run-pass/issues}/issue-3563-2.rs | 1 + .../run-pass/issues}/issue-3563-3.rs | 5 +- .../run-pass/issues}/issue-3574.rs | 1 + .../run-pass/issues}/issue-35815.rs | 1 + .../run-pass/issues}/issue-36023.rs | 1 + .../issue-36036-associated-type-layout.rs | 1 + .../run-pass/issues}/issue-36053.rs | 1 + .../run-pass/issues}/issue-36075.rs | 1 + .../run-pass/issues}/issue-3609.rs | 4 +- .../issue-36139-normalize-closure-sig.rs | 1 + .../run-pass/issues}/issue-36260.rs | 1 + .../issues}/issue-36278-prefix-nesting.rs | 1 + .../run-pass/issues}/issue-36381.rs | 1 + .../run-pass/issues}/issue-36401.rs | 1 + .../run-pass/issues}/issue-36474.rs | 1 + .../run-pass/issues}/issue-3656.rs | 3 + .../issue-36744-bitcast-args-if-needed.rs | 1 + .../issues}/issue-36744-without-calls.rs | 1 + .../run-pass/issues}/issue-36768.rs | 1 + .../issues}/issue-36786-resolve-call.rs | 1 + .../run-pass/issues}/issue-36792.rs | 1 + .../run-pass/issues}/issue-36816.rs | 1 + .../run-pass/issues}/issue-3683.rs | 2 +- .../run-pass/issues}/issue-36856.rs | 1 + .../run-pass/issues}/issue-36936.rs | 1 + src/test/ui/run-pass/issues/issue-36954.rs | 18 + .../run-pass/issues}/issue-3702.rs | 1 + .../run-pass/issues}/issue-37109.rs | 1 + .../run-pass/issues}/issue-37175.rs | 1 + .../run-pass/issues}/issue-37222.rs | 1 + .../issues}/issue-37291/auxiliary/lib.rs | 0 .../ui/run-pass/issues/issue-37291/main.rs | 30 + .../run-pass/issues}/issue-3743.rs | 1 + .../run-pass/issues}/issue-3753.rs | 3 +- .../run-pass/issues}/issue-37598.rs | 1 + .../run-pass/issues}/issue-37655.rs | 1 + .../run-pass/issues}/issue-37686.rs | 1 + .../run-pass/issues}/issue-37725.rs | 1 + .../run-pass/issues}/issue-37733.rs | 1 + .../run-pass/issues}/issue-3794.rs | 2 +- .../run-pass/issues}/issue-37991.rs | 3 +- .../run-pass/issues}/issue-38002.rs | 1 + .../run-pass/issues}/issue-38033.rs | 1 + .../run-pass/issues}/issue-38074.rs | 1 + .../run-pass/issues}/issue-38091.rs | 1 + .../run-pass/issues}/issue-38190.rs | 1 + .../run-pass/issues}/issue-38226.rs | 3 +- .../run-pass/issues}/issue-38437.rs | 1 + .../run-pass/issues}/issue-3847.rs | 1 + .../run-pass/issues}/issue-38556.rs | 1 + src/test/ui/run-pass/issues/issue-38715.rs | 25 + .../run-pass/issues}/issue-38727.rs | 1 + .../run-pass/issues}/issue-3874.rs | 1 + .../run-pass/issues}/issue-38763.rs | 1 + .../run-pass/issues}/issue-3878.rs | 2 +- .../run-pass/issues}/issue-3888-2.rs | 1 + .../run-pass/issues}/issue-38942.rs | 1 + .../run-pass/issues}/issue-3895.rs | 1 + .../run-pass/issues}/issue-38987.rs | 1 + .../run-pass/issues}/issue-3904.rs | 1 + .../run-pass/issues}/issue-39089.rs | 1 + .../run-pass/issues}/issue-39292.rs | 1 + .../run-pass/issues}/issue-3935.rs | 1 + .../run-pass/issues}/issue-39367.rs | 1 + .../run-pass/issues}/issue-39467.rs | 1 + .../run-pass/issues}/issue-39548.rs | 1 + .../run-pass/issues}/issue-39709.rs | 1 + .../run-pass/issues}/issue-39720.rs | 3 + .../ui/run-pass/issues/issue-39720.stderr | 16 + .../run-pass/issues}/issue-3979-2.rs | 1 + .../run-pass/issues}/issue-3979-generics.rs | 2 + .../run-pass/issues}/issue-3979-xcrate.rs | 1 + .../run-pass/issues}/issue-3979.rs | 2 + .../run-pass/issues}/issue-39808.rs | 1 + .../run-pass/issues}/issue-39823.rs | 1 + .../run-pass/issues}/issue-39827.rs | 2 + .../run-pass/issues}/issue-3991.rs | 1 + .../run-pass/issues}/issue-39984.rs | 1 + .../run-pass/issues}/issue-40003.rs | 1 + .../run-pass/issues}/issue-40085.rs | 1 + .../run-pass/issues}/issue-40136.rs | 1 + .../run-pass/issues}/issue-40235.rs | 1 + .../run-pass/issues}/issue-4025.rs | 1 + .../run-pass/issues}/issue-40408.rs | 1 + .../run-pass/issues}/issue-40469.rs | 1 + .../run-pass/issues}/issue-40770.rs | 1 + .../run-pass/issues}/issue-40847.rs | 1 + .../run-pass/issues}/issue-40883.rs | 1 + .../run-pass/issues}/issue-40951.rs | 1 + .../run-pass/issues}/issue-40962.rs | 1 + .../run-pass/issues}/issue-41053.rs | 1 + .../run-pass/issues}/issue-4107.rs | 1 + .../run-pass/issues}/issue-41213.rs | 1 + .../run-pass/issues}/issue-41272.rs | 1 + .../run-pass/issues}/issue-41298.rs | 1 + .../run-pass/issues}/issue-41394.rs | 1 + .../run-pass/issues}/issue-41479.rs | 1 + .../run-pass/issues}/issue-41498.rs | 1 + .../run-pass/issues}/issue-41604.rs | 1 + .../run-pass/issues}/issue-41628.rs | 2 +- .../run-pass/issues}/issue-41677.rs | 1 + .../run-pass/issues}/issue-41696.rs | 1 + .../run-pass/issues}/issue-41744.rs | 1 + .../run-pass/issues}/issue-41803.rs | 1 + .../issues}/issue-41849-variance-req.rs | 1 + .../run-pass/issues}/issue-41888.rs | 1 + ...sue-41936-variance-coerce-unsized-cycle.rs | 1 + .../run-pass/issues}/issue-42007.rs | 1 + .../run-pass/issues}/issue-4208.rs | 1 + .../run-pass/issues}/issue-42148.rs | 1 + .../run-pass/issues}/issue-42210.rs | 1 + .../run-pass/issues}/issue-4228.rs | 1 + .../run-pass/issues}/issue-42453.rs | 3 + .../run-pass/issues}/issue-42463.rs | 1 + .../run-pass/issues}/issue-42467.rs | 1 + .../run-pass/issues}/issue-4252.rs | 1 + .../run-pass/issues}/issue-42552.rs | 1 + .../run-pass/issues}/issue-42679.rs | 1 + .../run-pass/issues}/issue-42747.rs | 1 + .../run-pass/issues}/issue-42956.rs | 2 + .../run-pass/issues}/issue-43057.rs | 1 + .../run-pass/issues}/issue-43132.rs | 1 + .../run-pass/issues}/issue-43205.rs | 1 + .../run-pass/issues}/issue-43291.rs | 1 + .../run-pass/issues}/issue-4333.rs | 3 +- .../run-pass/issues}/issue-43357.rs | 1 + .../run-pass/issues}/issue-43483.rs | 1 + .../run-pass/issues}/issue-43692.rs | 1 + .../run-pass/issues}/issue-43853.rs | 1 + .../run-pass/issues}/issue-4387.rs | 1 + .../run-pass/issues}/issue-43910.rs | 1 + .../run-pass/issues}/issue-43923.rs | 1 + .../run-pass/issues}/issue-44005.rs | 1 + .../run-pass/issues}/issue-4401.rs | 1 + .../run-pass/issues}/issue-44056.rs | 1 + .../run-pass/issues}/issue-44247.rs | 1 + .../run-pass/issues}/issue-44333.rs | 1 + .../run-pass/issues}/issue-44373.rs | 1 + .../run-pass/issues}/issue-44402.rs | 1 + .../run-pass/issues}/issue-4446.rs | 1 + .../run-pass/issues}/issue-4448.rs | 1 + .../run-pass/issues}/issue-4464.rs | 1 + .../run-pass/issues}/issue-44730.rs | 1 + .../run-pass/issues}/issue-44851.rs | 1 + .../run-pass/issues}/issue-45124.rs | 7 +- .../run-pass/issues}/issue-45152.rs | 1 + .../run-pass/issues}/issue-4541.rs | 1 + .../run-pass/issues}/issue-4542.rs | 1 + .../run-pass/issues}/issue-45425.rs | 1 + .../run-pass/issues}/issue-4545.rs | 1 + .../run-pass/issues}/issue-45731.rs | 1 + .../run-pass/issues}/issue-46069.rs | 1 + .../run-pass/issues}/issue-46095.rs | 1 + .../run-pass/issues}/issue-46519.rs | 1 + .../run-pass/issues}/issue-46553.rs | 1 + .../run-pass/issues}/issue-46845.rs | 1 + .../run-pass/issues}/issue-46855.rs | 1 + .../issue-46920-byte-array-patterns.rs | 1 + .../run-pass/issues}/issue-46959.rs | 1 + .../run-pass/issues}/issue-46964.rs | 1 + .../run-pass/issues}/issue-47139-1.rs | 1 + .../run-pass/issues}/issue-47139-2.rs | 1 + .../run-pass/issues}/issue-4734.rs | 1 + .../run-pass/issues}/issue-4735.rs | 1 + .../run-pass/issues}/issue-47364.rs | 2 + .../run-pass/issues}/issue-4759-1.rs | 1 + .../run-pass/issues}/issue-4759.rs | 3 +- .../run-pass/issues}/issue-47638.rs | 1 + .../run-pass/issues}/issue-47673.rs | 2 +- .../run-pass/issues}/issue-47703-1.rs | 1 + .../run-pass/issues}/issue-47703-tuple.rs | 1 + .../run-pass/issues}/issue-47703.rs | 1 + .../run-pass/issues}/issue-47722.rs | 4 +- .../run-pass/issues}/issue-47789.rs | 2 + .../run-pass/issues}/issue-48159.rs | 1 + .../run-pass/issues}/issue-4830.rs | 1 + .../run-pass/issues}/issue-48508-aux.rs | 1 + .../run-pass/issues}/issue-48508.rs | 1 + .../run-pass/issues}/issue-48551.rs | 1 + .../run-pass/issues}/issue-4865-1.rs | 1 + .../run-pass/issues}/issue-4865-2.rs | 1 + .../run-pass/issues}/issue-4865-3.rs | 1 + .../run-pass/issues}/issue-4875.rs | 1 + .../run-pass/issues}/issue-48962.rs | 3 +- .../run-pass/issues}/issue-48984.rs | 1 + .../run-pass/issues}/issue-49298.rs | 1 + .../run-pass/issues}/issue-49556.rs | 1 + ...orthand-field-patterns-in-pattern-macro.rs | 1 + .../run-pass/issues}/issue-49632.rs | 1 + .../run-pass/issues}/issue-49685.rs | 1 + .../run-pass/issues}/issue-49854.rs | 1 + .../run-pass/issues}/issue-49955-2.rs | 1 + .../run-pass/issues}/issue-49955.rs | 1 + .../run-pass/issues}/issue-49973.rs | 1 + ...e-5008-borrowed-traitobject-method-call.rs | 1 + .../run-pass/issues}/issue-50415.rs | 1 + .../run-pass/issues}/issue-50442.rs | 1 + .../run-pass/issues}/issue-5060.rs | 1 + .../run-pass/issues}/issue-50689.rs | 1 + .../run-pass/issues}/issue-50731.rs | 1 + .../run-pass/issues}/issue-50811.rs | 1 + .../auxiliary/lib.rs | 24 + .../issue-50865-private-impl-trait/main.rs | 26 + .../run-pass/issues}/issue-51185.rs | 1 + .../run-pass/issues}/issue-51345.rs | 1 + .../run-pass/issues}/issue-51582.rs | 1 + .../run-pass/issues}/issue-51655.rs | 1 + .../run-pass/issues}/issue-51907.rs | 1 + .../run-pass/issues}/issue-5192.rs | 2 +- .../issue-52140/auxiliary/some_crate.rs | 15 + .../ui/run-pass/issues/issue-52140/main.rs | 23 + .../issue-52141/auxiliary/some_crate.rs | 15 + .../ui/run-pass/issues/issue-52141/main.rs | 26 + src/test/ui/run-pass/issues/issue-52169.rs | 25 + .../run-pass/issues}/issue-5239-2.rs | 1 + .../run-pass/issues}/issue-5243.rs | 1 + src/test/ui/run-pass/issues/issue-52557.rs | 39 + .../issues/issue-52705/auxiliary/png2.rs | 13 + .../ui/run-pass/issues/issue-52705/main.rs | 24 + .../run-pass/issues}/issue-5280.rs | 3 +- .../run-pass/issues}/issue-5315.rs | 1 + .../issue-5321-immediates-with-bare-self.rs | 3 +- src/test/ui/run-pass/issues/issue-53333.rs | 18 + .../run-pass/issues}/issue-5353.rs | 1 + .../run-pass/issues}/issue-5518.rs | 1 + .../run-pass/issues}/issue-5521.rs | 1 + .../run-pass/issues}/issue-5530.rs | 1 + .../run-pass/issues}/issue-5550.rs | 3 +- .../run-pass/issues}/issue-5554.rs | 1 + .../run-pass/issues}/issue-5572.rs | 1 + .../run-pass/issues}/issue-5666.rs | 2 +- .../run-pass/issues}/issue-5688.rs | 1 + .../run-pass/issues}/issue-5708.rs | 1 + .../run-pass/issues}/issue-5718.rs | 2 +- .../run-pass/issues}/issue-5741.rs | 3 +- .../run-pass/issues}/issue-5754.rs | 3 + .../run-pass/issues}/issue-5791.rs | 1 + .../run-pass/issues}/issue-5884.rs | 2 +- .../run-pass/issues}/issue-5900.rs | 1 + .../run-pass/issues}/issue-5917.rs | 2 + .../run-pass/issues}/issue-5950.rs | 1 + .../run-pass/issues}/issue-5988.rs | 1 + .../run-pass/issues}/issue-5997.rs | 1 + .../run-pass/issues}/issue-6117.rs | 1 + .../run-pass/issues}/issue-6128.rs | 1 + .../run-pass/issues}/issue-6130.rs | 3 +- .../run-pass/issues}/issue-6153.rs | 1 + .../run-pass/issues}/issue-6157.rs | 1 + .../run-pass/issues}/issue-6318.rs | 2 +- .../run-pass/issues}/issue-6334.rs | 1 + .../run-pass/issues}/issue-6341.rs | 1 + .../run-pass/issues}/issue-6344-let.rs | 3 + .../run-pass/issues}/issue-6344-match.rs | 3 + .../run-pass/issues}/issue-6449.rs | 1 + .../run-pass/issues}/issue-6470.rs | 4 + .../run-pass/issues}/issue-6557.rs | 2 +- .../run-pass/issues}/issue-6892.rs | 1 + .../run-pass/issues}/issue-6898.rs | 1 + .../run-pass/issues}/issue-6919.rs | 1 + .../run-pass/issues}/issue-6991.rs | 3 + .../run-pass/issues}/issue-7012.rs | 4 + .../run-pass/issues}/issue-7178.rs | 1 + .../run-pass/issues}/issue-7222.rs | 2 + .../run-pass/issues}/issue-7268.rs | 1 + .../run-pass/issues}/issue-7344.rs | 1 + .../issues}/issue-7519-match-unit-in-arg.rs | 1 + .../run-pass/issues}/issue-7563.rs | 1 + .../run-pass/issues}/issue-7575.rs | 1 + .../run-pass/issues}/issue-7607-2.rs | 1 + .../run-pass/issues}/issue-7660.rs | 1 + .../run-pass/issues}/issue-7663.rs | 1 + ...7673-cast-generically-implemented-trait.rs | 2 +- .../run-pass/issues}/issue-7784.rs | 1 + .../run-pass/issues}/issue-7899.rs | 1 + .../run-pass/issues}/issue-7911.rs | 1 + .../run-pass/issues}/issue-8044.rs | 1 + ...fault-method-self-inherit-builtin-trait.rs | 1 + .../run-pass/issues}/issue-8248.rs | 1 + .../run-pass/issues}/issue-8249.rs | 1 + .../run-pass/issues}/issue-8259.rs | 3 + .../run-pass/issues}/issue-8351-1.rs | 1 + .../run-pass/issues}/issue-8351-2.rs | 1 + .../run-pass/issues}/issue-8391.rs | 1 + .../run-pass/issues}/issue-8398.rs | 1 + .../run-pass/issues}/issue-8401.rs | 1 + .../run-pass/issues}/issue-8460.rs | 1 + .../run-pass/issues}/issue-8498.rs | 1 + .../run-pass/issues}/issue-8506.rs | 2 + .../run-pass/issues}/issue-8521.rs | 1 + .../run-pass/issues}/issue-8578.rs | 3 + .../run-pass/issues}/issue-868.rs | 1 + .../run-pass/issues}/issue-8709.rs | 1 + .../run-pass/issues}/issue-8783.rs | 1 + .../run-pass/issues}/issue-8827.rs | 3 +- .../run-pass/issues}/issue-8851.rs | 1 + .../run-pass/issues}/issue-8860.rs | 1 + .../run-pass/issues}/issue-8898.rs | 1 + .../run-pass/issues}/issue-9047.rs | 1 + .../run-pass/issues}/issue-9110.rs | 2 + .../run-pass/issues}/issue-9123.rs | 1 + .../run-pass/issues}/issue-9129.rs | 4 +- .../run-pass/issues}/issue-9188.rs | 1 + .../run-pass/issues}/issue-9243.rs | 2 + .../run-pass/issues}/issue-9249.rs | 1 + .../run-pass/issues}/issue-9259.rs | 1 + .../run-pass/issues}/issue-9382.rs | 3 +- .../issue-9394-inherited-trait-calls.rs | 1 + .../run-pass/issues}/issue-9396.rs | 2 + .../run-pass/issues}/issue-9446.rs | 1 + .../run-pass/issues}/issue-9719.rs | 1 + .../run-pass/issues}/issue-9737.rs | 1 + .../run-pass/issues}/issue-979.rs | 3 + .../run-pass/issues}/issue-9837.rs | 1 + .../run-pass/issues}/issue-9906.rs | 1 + .../run-pass/issues}/issue-9918.rs | 1 + .../run-pass/issues}/issue-9942.rs | 1 + .../run-pass/issues}/issue-9951.rs | 1 + .../run-pass/issues}/issue-9968.rs | 1 + .../run-pass/issues}/issue2170exe.rs | 1 + .../auxiliary/issue24687_lib.rs | 0 .../auxiliary/issue24687_mbcs_in_comments.rs | 0 .../issues/issue24687-embed-debuginfo/main.rs | 23 + .../issues}/issue28498-must-work-ex1.rs | 1 + .../issues}/issue28498-must-work-ex2.rs | 1 + .../run-pass/issues}/issue28498-ugeh-ex1.rs | 3 + .../issue28498-ugeh-with-lifetime-param.rs | 3 + .../issue28498-ugeh-with-passed-to-fn.rs | 3 + .../issue28498-ugeh-with-trait-bound.rs | 3 + .../run-pass/issues}/issue29927-1.rs | 3 +- .../issues}/issue_26873_multifile/A/B.rs | 1 + .../issues}/issue_26873_multifile/A/C.rs | 1 + .../issues/issue_26873_multifile/A/mod.rs | 16 + .../compiletest-ignore-dir | 0 .../issues/issue_26873_multifile/mod.rs | 15 + .../run-pass/issues}/issue_3136_b.rs | 1 + .../run-pass/issues}/issue_9155.rs | 1 + .../into-iterator-type-inference-shift.rs | 1 + .../iterators}/iter-cloned-type-inference.rs | 3 + .../run-pass/iterators}/iter-range.rs | 1 + .../iterators}/iter-step-overflow-debug.rs | 1 + .../iterators}/iter-step-overflow-ndebug.rs | 1 + .../iterators}/iter-sum-overflow-debug.rs | 1 + .../iterators}/iter-sum-overflow-ndebug.rs | 1 + .../iter-sum-overflow-overflow-checks.rs | 1 + .../run-pass/iterators}/iter-zip.rs | 1 + .../macros}/assert-eq-macro-success.rs | 1 + .../macros}/assert-eq-macro-unsized.rs | 1 + .../macros}/assert-ne-macro-success.rs | 1 + .../macros}/assert-ne-macro-unsized.rs | 1 + .../macros}/auxiliary/macro-comma-support.rs | 0 .../auxiliary/macro-include-items-expr.rs | 0 .../auxiliary/macro-include-items-item.rs | 0 .../macros}/auxiliary/macro_crate_def_only.rs | 0 .../auxiliary/macro_crate_nonterminal.rs | 0 .../auxiliary/macro_export_inner_module.rs | 0 .../macros}/auxiliary/macro_with_super_1.rs | 0 .../run-pass/macros}/auxiliary/two_macros.rs | 0 .../macros/auxiliary/unstable-macros.rs | 16 + .../macros}/auxiliary/use-macro-self.rs | 0 .../run-pass/macros}/colorful-write-macros.rs | 1 + .../macros}/conditional-debug-macro-on.rs | 1 + .../run-pass/macros}/die-macro.rs | 1 + ...log_syntax-trace_macros-macro-locations.rs | 1 + ...syntax-trace_macros-macro-locations.stdout | 3 + .../run-pass/macros}/macro-2.rs | 1 + .../macros}/macro-at-most-once-rep.rs | 3 +- .../macros}/macro-attribute-expansion.rs | 1 + .../run-pass/macros}/macro-attributes.rs | 1 + .../macros}/macro-block-nonterminal.rs | 1 + .../run-pass/macros}/macro-comma-behavior.rs | 1 + .../run-pass/macros}/macro-comma-support.rs | 1 + .../run-pass/macros}/macro-crate-def-only.rs | 1 + .../macro-crate-nonterminal-renamed.rs | 1 + .../macros}/macro-crate-nonterminal.rs | 1 + .../run-pass/macros}/macro-crate-use.rs | 1 + .../run-pass/macros}/macro-deep_expansion.rs | 1 + .../macros}/macro-delimiter-significance.rs | 1 + .../run-pass/macros}/macro-doc-comments.rs | 3 + .../run-pass/macros}/macro-doc-escapes.rs | 1 + .../macros}/macro-doc-raw-str-hashes.rs | 1 + .../macros}/macro-export-inner-module.rs | 1 + .../run-pass/macros}/macro-first-set.rs | 3 +- .../run-pass/macros}/macro-follow.rs | 1 + .../run-pass/macros}/macro-followed-by-seq.rs | 1 + .../run-pass/macros}/macro-include-items.rs | 3 + .../run-pass/macros}/macro-interpolation.rs | 1 + ...vocation-in-count-expr-fixed-array-type.rs | 1 + .../macros}/macro-lifetime-used-with-bound.rs | 1 + .../macro-lifetime-used-with-labels.rs | 3 + .../macro-lifetime-used-with-labels.stderr | 11 + .../macro-lifetime-used-with-static.rs | 1 + .../run-pass/macros}/macro-lifetime.rs | 1 + .../run-pass/macros}/macro-literal.rs | 1 + .../run-pass/macros}/macro-meta-items.rs | 1 + .../macros}/macro-method-issue-4621.rs | 1 + .../run-pass/macros}/macro-multiple-items.rs | 1 + .../run-pass/macros}/macro-named-default.rs | 1 + .../macro-nested_definition_issue-31946.rs | 1 + .../run-pass/macros}/macro-nested_expr.rs | 1 + .../macros}/macro-nested_stmt_macros.rs | 1 + .../run-pass/macros}/macro-nt-list.rs | 1 + .../run-pass/macros}/macro-of-higher-order.rs | 1 + .../run-pass/macros}/macro-pat-follow.rs | 1 + .../run-pass/macros}/macro-pat-neg-lit.rs | 1 + .../run-pass/macros}/macro-pat.rs | 1 + .../run-pass/macros}/macro-path.rs | 3 + .../run-pass/macros}/macro-pub-matcher.rs | 4 +- .../macros}/macro-seq-followed-by-seq.rs | 1 + .../run-pass/macros}/macro-stability.rs | 1 + .../run-pass/macros}/macro-stmt.rs | 1 + .../macros}/macro-stmt_macro_in_expr_macro.rs | 1 + .../macros}/macro-tt-followed-by-seq.rs | 1 + .../macros}/macro-use-all-and-none.rs | 1 + .../run-pass/macros}/macro-use-all.rs | 1 + .../run-pass/macros}/macro-use-both.rs | 1 + .../run-pass/macros}/macro-use-one.rs | 1 + .../run-pass/macros}/macro-with-attrs1.rs | 1 + .../run-pass/macros}/macro-with-attrs2.rs | 1 + .../macro-with-braces-in-expr-position.rs | 1 + .../run-pass/macros}/macro_with_super_2.rs | 1 + .../ui/run-pass/macros/macros-in-extern.rs | 40 + .../macros}/parse-complex-macro-invoc-op.rs | 3 + .../macros}/paths-in-macro-invocations.rs | 3 +- .../run-pass/macros}/pub-item-inside-macro.rs | 1 + .../macros}/pub-method-inside-macro.rs | 1 + .../run-pass/macros}/semi-after-macro-ty.rs | 1 + .../macros}/stmt_expr_attr_macro_parse.rs | 1 + .../run-pass/macros}/syntax-extension-cfg.rs | 1 + .../includeme.fragment | 0 .../macros}/syntax-extension-source-utils.rs | 9 +- src/test/ui/run-pass/macros/try-macro.rs | 58 + .../run-pass/macros}/two-macro-use.rs | 1 + .../run-pass/macros}/type-macros-hlist.rs | 1 + .../run-pass/macros}/type-macros-simple.rs | 1 + .../typeck-macro-interaction-issue-8852.rs | 1 + .../run-pass/macros}/use-macro-self.rs | 3 +- .../methods}/auxiliary/method_self_arg1.rs | 1 - .../methods}/auxiliary/method_self_arg2.rs | 1 - ...thod-argument-inference-associated-type.rs | 1 + .../run-pass/methods}/method-attributes.rs | 4 +- .../method-early-bound-lifetimes-on-self.rs | 1 + ...thod-mut-self-modifies-mut-slice-lvalue.rs | 3 +- .../method-normalize-bounds-issue-20604.rs | 3 + .../run-pass/methods}/method-projection.rs | 1 + .../methods}/method-recursive-blanket-impl.rs | 1 + .../run-pass/methods}/method-self-arg-aux1.rs | 3 +- .../run-pass/methods}/method-self-arg-aux2.rs | 3 +- .../methods}/method-self-arg-trait.rs | 3 +- .../run-pass/methods}/method-self-arg.rs | 3 +- .../method-two-trait-defer-resolution-1.rs | 3 + .../method-two-trait-defer-resolution-2.rs | 3 +- ...o-traits-distinguished-via-where-clause.rs | 3 +- .../run-pass/methods}/method-where-clause.rs | 1 + .../mir}/auxiliary/mir_external_refs.rs | 0 .../mir}/mir-inlining/ice-issue-45493.rs | 1 + .../mir}/mir-inlining/ice-issue-45885.rs | 1 + .../no-trait-method-issue-40473.rs | 1 + .../mir}/mir-typeck-normalize-fn-sig.rs | 1 + .../run-pass/mir}/mir_adt_construction.rs | 1 + .../run-pass/mir}/mir_ascription_coercion.rs | 1 + .../mir}/mir_augmented_assignments.rs | 1 + .../run-pass/mir}/mir_autoderef.rs | 1 + .../run-pass/mir}/mir_boxing.rs | 1 + .../mir}/mir_build_match_comparisons.rs | 1 + .../mir}/mir_call_with_associated_type.rs | 1 + .../run-pass/mir}/mir_calls_to_shims.rs | 1 + .../run-pass/mir}/mir_cast_fn_ret.rs | 1 + .../run-pass/mir}/mir_codegen_array.rs | 1 + .../run-pass/mir}/mir_codegen_array_2.rs | 1 + .../mir}/mir_codegen_call_converging.rs | 1 + .../run-pass/mir}/mir_codegen_calls.rs | 1 + .../mir}/mir_codegen_calls_variadic.rs | 1 + .../mir}/mir_codegen_critical_edge.rs | 1 + .../run-pass/mir}/mir_codegen_spike1.rs | 1 + .../run-pass/mir}/mir_codegen_switch.rs | 1 + .../run-pass/mir}/mir_codegen_switchint.rs | 1 + .../run-pass/mir}/mir_coercion_casts.rs | 1 + .../run-pass/mir}/mir_coercions.rs | 1 + .../run-pass/mir}/mir_constval_adts.rs | 1 + .../run-pass/mir}/mir_drop_order.rs | 1 + .../run-pass/mir}/mir_early_return_scope.rs | 1 + .../run-pass/mir}/mir_fat_ptr.rs | 1 + .../run-pass/mir}/mir_fat_ptr_drop.rs | 3 + .../run-pass/mir}/mir_heavy_promoted.rs | 1 + .../run-pass/mir}/mir_match_arm_guard.rs | 1 + .../run-pass/mir}/mir_misc_casts.rs | 1 + .../run-pass/mir}/mir_overflow_off.rs | 1 + .../run-pass/mir}/mir_raw_fat_ptr.rs | 1 + .../run-pass/mir}/mir_refs_correct.rs | 1 + .../run-pass/mir}/mir_small_agg_arg.rs | 1 + .../run-pass/mir}/mir_struct_with_assoc_ty.rs | 1 + .../run-pass/mir}/mir_temp_promotions.rs | 1 + .../run-pass/mir}/mir_void_return.rs | 1 + .../run-pass/mir}/mir_void_return_2.rs | 1 + .../modules}/auxiliary/two_macros_2.rs | 0 .../run-pass/modules}/mod-inside-fn.rs | 1 + .../run-pass/modules}/mod-view-items.rs | 1 + .../run-pass/modules}/mod_dir_implicit.rs | 1 + .../compiletest-ignore-dir | 0 .../modules/mod_dir_implicit_aux/mod.rs | 12 + .../run-pass/modules}/mod_dir_path.rs | 1 + .../run-pass/modules}/mod_dir_path2.rs | 1 + .../run-pass/modules}/mod_dir_path3.rs | 1 + .../run-pass/modules}/mod_dir_path_multi.rs | 1 + .../run-pass/modules}/mod_dir_recursive.rs | 1 + .../run-pass/modules}/mod_dir_simple.rs | 1 + .../mod_dir_simple/compiletest-ignore-dir | 0 .../mod_dir_simple/load_another_mod.rs | 1 + .../run-pass/modules/mod_dir_simple/test.rs | 12 + .../run-pass/modules}/mod_file.rs | 1 + .../run-pass/modules}/mod_file_aux.rs | 1 + .../modules}/mod_file_with_path_attr.rs | 1 + .../compiletest-ignore-dir | 0 .../float-template/inst_f32.rs | 0 .../float-template/inst_f64.rs | 0 .../float-template/inst_float.rs | 0 .../run-pass/moves}/move-1-unique.rs | 3 +- .../run-pass/moves}/move-2-unique.rs | 3 +- .../{run-pass => ui/run-pass/moves}/move-2.rs | 3 +- .../run-pass/moves}/move-3-unique.rs | 3 +- .../run-pass/moves}/move-4-unique.rs | 3 +- .../{run-pass => ui/run-pass/moves}/move-4.rs | 3 +- .../run-pass/moves}/move-arg-2-unique.rs | 3 +- .../run-pass/moves}/move-arg-2.rs | 3 +- .../run-pass/moves}/move-arg.rs | 1 + .../run-pass/moves}/move-nullary-fn.rs | 1 + .../run-pass/moves}/move-out-of-field.rs | 1 + .../run-pass/moves}/move-scalar.rs | 1 + .../moves-based-on-type-capture-clause.rs | 3 +- .../run-pass/nll/issue-47153-generic-const.rs | 2 + src/test/{ => ui}/run-pass/nll/issue-47589.rs | 2 + .../run-pass/nll/issue-48623-closure.rs | 2 + .../run-pass/nll/issue-48623-generator.rs | 2 + src/test/{ => ui}/run-pass/nll/issue-50343.rs | 2 + .../nll/issue-50461-used-mut-from-moves.rs | 2 + .../nll/issue-53123-raw-pointer-cast.rs | 37 + .../run-pass/nll/mutating_references.rs | 2 + .../run-pass/nll/process_or_insert_default.rs | 2 + src/test/{ => ui}/run-pass/nll/rc-loop.rs | 2 + .../run-pass/non_modrs_mods/foors_mod.rs | 0 .../foors_mod/compiletest-ignore-dir | 0 .../foors_mod/inner_foors_mod.rs | 0 .../foors_mod/inner_foors_mod/innest.rs | 0 .../foors_mod/inner_modrs_mod/innest.rs | 0 .../foors_mod/inner_modrs_mod/mod.rs | 0 .../modrs_mod/compiletest-ignore-dir | 0 .../modrs_mod/inner_foors_mod.rs | 0 .../modrs_mod/inner_foors_mod/innest.rs | 0 .../modrs_mod/inner_modrs_mod/innest.rs | 0 .../modrs_mod/inner_modrs_mod/mod.rs | 0 .../run-pass/non_modrs_mods/modrs_mod/mod.rs | 0 .../some_crazy_attr_mod_dir/arbitrary_name.rs | 0 .../compiletest-ignore-dir | 0 .../inner_modrs_mod/innest.rs | 0 .../inner_modrs_mod/mod.rs | 0 .../run-pass/numbers-arithmetic}/arith-0.rs | 1 + .../run-pass/numbers-arithmetic}/arith-1.rs | 1 + .../run-pass/numbers-arithmetic}/arith-2.rs | 1 + .../numbers-arithmetic}/arith-unsigned.rs | 4 +- .../run-pass/numbers-arithmetic}/div-mod.rs | 1 + .../float-int-invalid-const-cast.rs | 1 + .../float-literal-inference.rs | 1 + .../run-pass/numbers-arithmetic}/float-nan.rs | 1 + .../numbers-arithmetic}/float-signature.rs | 1 + .../ui/run-pass/numbers-arithmetic/float.rs | 19 + .../run-pass/numbers-arithmetic}/float2.rs | 1 + .../numbers-arithmetic}/float_math.rs | 1 + .../run-pass/numbers-arithmetic}/floatlits.rs | 1 + .../run-pass/numbers-arithmetic}/i128-ffi.rs | 3 + .../run-pass/numbers-arithmetic}/i128.rs | 3 + .../run-pass/numbers-arithmetic}/i32-sub.rs | 1 + .../run-pass/numbers-arithmetic}/i8-incr.rs | 1 + .../numbers-arithmetic}/int-abs-overflow.rs | 1 + .../run-pass/numbers-arithmetic}/int.rs | 1 + .../integer-literal-radix.rs | 1 + .../integer-literal-suffix-inference-2.rs | 1 + .../integer-literal-suffix-inference-3.rs | 1 + .../integer-literal-suffix-inference.rs | 1 + .../next-power-of-two-overflow-debug.rs | 1 + .../next-power-of-two-overflow-ndebug.rs | 1 + .../numbers-arithmetic}/num-wrapping.rs | 4 +- .../numeric-method-autoexport.rs | 1 + .../promoted_overflow_opt.rs | 1 + .../saturating-float-casts.rs | 1 + .../numbers-arithmetic}/shift-near-oflo.rs | 1 + .../shift-various-types.rs | 1 + .../run-pass/numbers-arithmetic}/shift.rs | 4 + .../signed-shift-const-eval.rs | 3 + .../numbers-arithmetic}/u128-as-f32.rs | 1 + .../run-pass/numbers-arithmetic}/u128.rs | 1 + .../run-pass/numbers-arithmetic}/u32-decr.rs | 1 + .../numbers-arithmetic}/u8-incr-decr.rs | 1 + .../run-pass/numbers-arithmetic}/u8-incr.rs | 1 + .../run-pass/numbers-arithmetic}/uint.rs | 1 + .../auxiliary/overloaded_autoderef_xc.rs | 0 .../overloaded}/overloaded-autoderef-count.rs | 1 + .../overloaded-autoderef-indexing.rs | 1 + .../overloaded}/overloaded-autoderef-order.rs | 1 + .../overloaded-autoderef-vtable.rs | 1 + .../overloaded-autoderef-xcrate.rs | 1 + .../overloaded}/overloaded-autoderef.rs | 4 +- .../overloaded-calls-object-one-arg.rs | 1 + .../overloaded-calls-object-two-args.rs | 1 + .../overloaded-calls-object-zero-args.rs | 1 + .../overloaded-calls-param-vtables.rs | 1 + .../overloaded}/overloaded-calls-simple.rs | 1 + .../overloaded}/overloaded-calls-zero-args.rs | 1 + .../overloaded}/overloaded-deref-count.rs | 1 + .../run-pass/overloaded}/overloaded-deref.rs | 1 + .../overloaded-index-assoc-list.rs | 4 +- .../overloaded}/overloaded-index-autoderef.rs | 5 +- .../overloaded}/overloaded-index-in-field.rs | 4 +- .../run-pass/overloaded}/overloaded-index.rs | 4 +- .../overloaded_deref_with_ref_pattern.rs | 1 + ...oaded_deref_with_ref_pattern_issue15609.rs | 1 + .../run-pass/packed}/auxiliary/packed.rs | 0 .../packed}/packed-struct-borrow-element.rs | 1 + .../packed}/packed-struct-drop-aligned.rs | 1 + .../packed}/packed-struct-generic-layout.rs | 3 + .../packed}/packed-struct-generic-size.rs | 4 + .../packed/packed-struct-generic-size.stderr | 36 + .../run-pass/packed}/packed-struct-layout.rs | 1 + .../run-pass/packed}/packed-struct-match.rs | 1 + .../packed}/packed-struct-optimized-enum.rs | 3 +- .../run-pass/packed}/packed-struct-size-xc.rs | 1 + .../run-pass/packed}/packed-struct-size.rs | 5 + .../run-pass/packed}/packed-struct-vec.rs | 1 + .../packed}/packed-tuple-struct-layout.rs | 1 + .../packed}/packed-tuple-struct-size.rs | 3 + .../abort-link-to-unwinding-crates.rs | 3 + .../{ => ui}/run-pass/panic-runtime/abort.rs | 3 + .../auxiliary/exit-success-if-unwind.rs | 0 .../run-pass/panic-runtime/link-to-abort.rs | 6 +- .../run-pass/panic-runtime/link-to-unwind.rs | 2 + .../run-pass/panic-runtime/lto-abort.rs | 2 + .../run-pass/panic-runtime/lto-unwind.rs | 2 + .../run-pass/panics}/panic-handler-chain.rs | 5 +- .../panics}/panic-handler-flail-wildly.rs | 6 +- .../panics}/panic-handler-set-twice.rs | 6 +- .../panics}/panic-in-dtor-drops-fields.rs | 3 + .../panics}/panic-recover-propagate.rs | 3 +- src/test/ui/run-pass/panics/panic-safe.rs | 61 + .../privacy}/auxiliary/priv-impl-prim-ty.rs | 0 .../privacy}/auxiliary/privacy_reexport.rs | 0 .../privacy}/auxiliary/pub_use_mods_xcrate.rs | 0 .../privacy}/auxiliary/pub_use_xcrate1.rs | 0 .../privacy}/auxiliary/pub_use_xcrate2.rs | 0 .../run-pass/privacy}/priv-impl-prim-ty.rs | 1 + .../run-pass/privacy}/privacy-ns.rs | 3 + .../run-pass/privacy}/privacy-reexport.rs | 1 + .../run-pass/privacy}/privacy1.rs | 1 + .../run-pass/privacy}/private-class-field.rs | 3 + .../run-pass/privacy}/private-method.rs | 3 + .../run-pass/privacy}/pub-extern-privacy.rs | 1 + .../run-pass/privacy}/pub-use-xcrate.rs | 1 + .../privacy}/pub_use_mods_xcrate_exe.rs | 1 + .../run-pass/process}/process-envs.rs | 1 + .../run-pass/process}/process-exit.rs | 1 + .../process}/process-remove-from-env.rs | 1 + .../run-pass/process}/process-sigpipe.rs | 3 + .../process}/process-spawn-nonexistent.rs | 1 + .../process-spawn-with-unicode-params.rs | 1 + .../process}/process-status-inherits-stdin.rs | 1 + .../regions-addr-of-interior-of-unique-box.rs | 1 + .../run-pass/regions}/regions-addr-of-ret.rs | 1 + .../regions-assoc-type-region-bound.rs | 1 + .../regions-assoc-type-static-bound.rs | 1 + .../run-pass/regions}/regions-borrow-at.rs | 2 +- .../regions}/regions-borrow-evec-fixed.rs | 1 + .../regions}/regions-borrow-evec-uniq.rs | 1 + .../run-pass/regions}/regions-borrow-uniq.rs | 3 +- .../run-pass/regions}/regions-bot.rs | 1 + .../regions-bound-lists-feature-gate-2.rs | 3 + .../regions-bound-lists-feature-gate.rs | 3 + ...-close-over-type-parameter-successfully.rs | 3 +- .../run-pass/regions}/regions-copy-closure.rs | 3 + .../regions}/regions-creating-enums2.rs | 3 + .../regions}/regions-creating-enums5.rs | 3 + .../regions}/regions-debruijn-of-object.rs | 3 + .../regions}/regions-dependent-addr-of.rs | 3 +- .../regions}/regions-dependent-autofn.rs | 1 + .../regions}/regions-dependent-autoslice.rs | 1 + .../regions}/regions-dependent-let-ref.rs | 1 + ...egions-early-bound-lifetime-in-assoc-fn.rs | 1 + .../regions-early-bound-trait-param.rs | 3 +- ...egions-early-bound-used-in-bound-method.rs | 1 + .../regions-early-bound-used-in-bound.rs | 1 + .../regions-early-bound-used-in-type-param.rs | 1 + .../regions}/regions-escape-into-other-fn.rs | 3 +- .../run-pass/regions}/regions-expl-self.rs | 1 + .../regions}/regions-fn-subtyping-2.rs | 1 + .../run-pass/regions}/regions-fn-subtyping.rs | 3 +- ...on-outlives-static-outlives-free-region.rs | 1 + .../regions-infer-borrow-scope-addr-of.rs | 1 + .../regions-infer-borrow-scope-view.rs | 1 + ...gions-infer-borrow-scope-within-loop-ok.rs | 3 +- .../regions}/regions-infer-borrow-scope.rs | 3 +- .../run-pass/regions}/regions-infer-call-2.rs | 1 + .../run-pass/regions}/regions-infer-call.rs | 1 + ...regions-infer-contravariance-due-to-ret.rs | 3 + .../regions-infer-reborrow-ref-mut-recurse.rs | 1 + ...regions-infer-region-in-fn-but-not-type.rs | 3 + .../regions-infer-static-from-proc.rs | 3 + .../run-pass/regions}/regions-issue-21422.rs | 1 + .../run-pass/regions}/regions-issue-22246.rs | 1 + .../regions-lifetime-nonfree-late-bound.rs | 2 +- ...-lifetime-static-items-enclosing-scopes.rs | 1 + .../run-pass/regions}/regions-link-fn-args.rs | 1 + .../regions}/regions-lub-ref-ref-rc.rs | 1 + .../run-pass/regions}/regions-mock-codegen.rs | 3 + .../regions-no-bound-in-argument-cleanup.rs | 1 + .../regions-no-variance-from-fn-generics.rs | 1 + .../regions}/regions-nullary-variant.rs | 3 + .../run-pass/regions}/regions-params.rs | 1 + .../regions-reassign-let-bound-pointer.rs | 1 + .../regions-reassign-match-bound-pointer.rs | 1 + .../run-pass/regions}/regions-refcell.rs | 1 + ...ions-on-closures-to-inference-variables.rs | 3 +- .../regions-return-interior-of-option.rs | 1 + .../regions}/regions-scope-chain-example.rs | 1 + .../run-pass/regions}/regions-self-impls.rs | 3 + .../regions}/regions-self-in-enums.rs | 3 + .../run-pass/regions}/regions-simple.rs | 1 + .../run-pass/regions/regions-static-bound.rs | 29 + .../regions}/regions-static-closure.rs | 3 + .../regions}/regions-trait-object-1.rs | 1 + ...ariance-contravariant-use-contravariant.rs | 1 + ...egions-variance-covariant-use-covariant.rs | 1 + .../run-pass/rfcs}/rfc-1014-2.rs | 3 + .../run-pass/rfcs}/rfc-1014.rs | 1 + .../rfcs}/rfc-1789-as-cell/from-mut.rs | 1 + .../termination-trait-for-box-dyn-error.rs | 1 + .../termination-trait-for-empty.rs | 1 + .../termination-trait-for-exitcode.rs | 1 + .../termination-trait-for-impl-termination.rs | 1 + ...rmination-trait-for-result-box-error_ok.rs | 1 + .../termination-trait-for-result.rs | 1 + .../termination-trait-for-str.rs | 1 + .../rfc-2005-default-binding-mode/box.rs | 1 + .../rfc-2005-default-binding-mode/constref.rs | 1 + .../rfc-2005-default-binding-mode/enum.rs | 1 + .../rfc-2005-default-binding-mode/for.rs | 1 + .../rfc-2005-default-binding-mode/general.rs | 1 + .../rfc-2005-default-binding-mode/lit.rs | 1 + .../rfc-2005-default-binding-mode/range.rs | 1 + .../ref-region.rs | 1 + .../reset-mode.rs | 1 + .../rfc-2005-default-binding-mode/slice.rs | 36 + .../rfc-2005-default-binding-mode/struct.rs | 1 + .../tuple-struct.rs | 1 + .../rfc-2005-default-binding-mode/tuple.rs | 1 + .../auxiliary/enums.rs | 20 + .../auxiliary/structs.rs | 24 + .../auxiliary/variants.rs | 19 + .../rfcs/rfc-2008-non-exhaustive/enums.rs | 63 + .../enums_same_crate.rs | 1 + .../rfcs/rfc-2008-non-exhaustive/structs.rs | 28 + .../structs_same_crate.rs | 1 + .../rfcs/rfc-2008-non-exhaustive/variants.rs | 32 + .../variants_same_crate.rs | 1 + .../crate-path-absolute.rs | 19 +- .../crate-path-absolute.stderr | 8 + .../crate-path-visibility-ambiguity.rs | 4 +- .../crate-path-visibility-ambiguity.stderr | 8 + .../auxiliary/xcrate.rs | 0 .../rfc-2126-extern-absolute-paths/basic.rs | 32 + .../rfc-2126-extern-absolute-paths/extern.rs | 2 + .../rfc-2126-extern-absolute-paths/test.rs | 20 + .../whitelisted.rs | 24 + .../rfcs}/rfc-2151-raw-identifiers/attr.rs | 3 +- .../rfcs/rfc-2151-raw-identifiers/basic.rs | 30 + .../rfcs/rfc-2151-raw-identifiers/items.rs | 42 + .../rfcs/rfc-2151-raw-identifiers/macros.rs | 48 + .../rfcs/rfc-2175-or-if-while-let/basic.rs | 31 + .../rfcs/rfc-2302-self-struct-ctor.rs | 129 + ...-unreserve-pure-offsetof-sizeof-alignof.rs | 1 + .../rfc1445/eq-allows-match-on-ty-in-macro.rs | 1 + .../run-pass/rfcs}/rfc1445/eq-allows-match.rs | 1 + .../{run-pass => ui/run-pass/rfcs}/rfc1623.rs | 3 + .../rfcs}/rfc1717/auxiliary/clibrary.rs | 0 .../rfcs}/rfc1717/library-override.rs | 1 + .../run-pass/rfcs}/rfc1857-drop-order.rs | 1 + ...arbitrary_self_types_raw_pointer_struct.rs | 1 + .../arbitrary_self_types_raw_pointer_trait.rs | 1 + .../self}/arbitrary_self_types_silly.rs | 2 + .../self}/arbitrary_self_types_struct.rs | 2 + .../self}/arbitrary_self_types_trait.rs | 2 + .../arbitrary_self_types_unsized_struct.rs | 2 + .../self}/auxiliary/explicit_self_xcrate.rs | 0 .../self}/builtin-superkinds-self-type.rs | 1 + .../self}/by-value-self-in-mut-slot.rs | 1 + .../run-pass/self}/explicit-self-closures.rs | 1 + .../run-pass/self}/explicit-self-generic.rs | 3 +- .../self}/explicit-self-objects-uniq.rs | 3 +- .../run-pass/self}/explicit-self.rs | 4 +- .../self}/explicit_self_xcrate_exe.rs | 1 + .../run-pass/self}/move-self.rs | 1 + .../object-safety-sized-self-by-value-self.rs | 1 + ...object-safety-sized-self-generic-method.rs | 1 + .../object-safety-sized-self-return-Self.rs | 1 + .../run-pass/self}/self-impl.rs | 2 +- .../self}/self-in-mut-slot-default-method.rs | 3 +- .../self}/self-in-mut-slot-immediate-value.rs | 1 + src/test/ui/run-pass/self/self-in-typedefs.rs | 43 + .../run-pass/self}/self-re-assign.rs | 3 +- .../run-pass/self}/self-shadowing-import.rs | 1 + .../run-pass/self}/self-type-param.rs | 1 + .../run-pass/self}/string-self-append.rs | 1 + .../run-pass/self}/ufcs-explicit-self.rs | 2 +- .../run-pass/self}/uniq-self-in-mut-slot.rs | 3 +- .../run-pass/self}/where-for-self.rs | 1 + .../sepcomp}/auxiliary/sepcomp-extern-lib.rs | 0 .../sepcomp}/auxiliary/sepcomp_cci_lib.rs | 0 .../sepcomp}/auxiliary/sepcomp_lib.rs | 0 .../run-pass/sepcomp}/sepcomp-cci.rs | 1 + .../run-pass/sepcomp}/sepcomp-extern.rs | 2 +- .../sepcomp}/sepcomp-fns-backwards.rs | 1 + .../run-pass/sepcomp}/sepcomp-fns.rs | 1 + .../run-pass/sepcomp}/sepcomp-lib-lto.rs | 1 + .../run-pass/sepcomp}/sepcomp-lib.rs | 1 + .../run-pass/sepcomp}/sepcomp-statics.rs | 1 + .../run-pass/sepcomp}/sepcomp-unwind.rs | 1 + .../run-pass/simd}/simd-generics.rs | 3 + .../simd}/simd-intrinsic-float-math.rs | 1 + .../simd}/simd-intrinsic-float-minmax.rs | 8 + .../simd-intrinsic-generic-arithmetic.rs | 3 + .../simd}/simd-intrinsic-generic-cast.rs | 1 + .../simd-intrinsic-generic-comparison.rs | 1 + .../simd}/simd-intrinsic-generic-elements.rs | 1 + .../simd}/simd-intrinsic-generic-gather.rs | 1 + .../simd}/simd-intrinsic-generic-reduction.rs | 3 + .../simd}/simd-intrinsic-generic-select.rs | 3 + .../run-pass/simd}/simd-size-align.rs | 3 + .../simd}/simd-target-feature-mixup.rs | 6 +- .../run-pass/simd}/simd-type.rs | 1 + .../run-pass/simd}/simd-upgraded.rs | 4 + .../run-pass/specialization/README.md | 0 .../specialization/assoc-ty-graph-cycle.rs | 2 + .../auxiliary/cross_crates_defaults.rs | 0 .../specialization}/auxiliary/go_trait.rs | 0 .../auxiliary/specialization_cross_crate.rs | 0 .../specialization/cross-crate-defaults.rs | 2 + .../defaultimpl/allowed-cross-crate.rs | 2 + .../defaultimpl/auxiliary/go_trait.rs | 0 .../defaultimpl/out-of-order.rs | 2 + .../defaultimpl/overlap-projection.rs | 2 + .../specialization/defaultimpl/projection.rs | 2 + ...ecialization-trait-item-not-implemented.rs | 2 + .../specialization-allowed-cross-crate.rs | 2 + .../specialization-assoc-fns.rs | 2 + .../specialization/specialization-basics.rs | 2 + .../specialization-cross-crate-no-gate.rs | 2 + .../specialization-cross-crate.rs | 2 + .../specialization-default-methods.rs | 2 + .../specialization-on-projection.rs | 2 + .../specialization-out-of-order.rs | 2 + .../specialization-overlap-projection.rs | 2 + .../specialization-projection-alias.rs | 2 + .../specialization-projection.rs | 2 + .../specialization-super-traits.rs | 2 + ...on-translate-projections-with-lifetimes.rs | 2 + ...ation-translate-projections-with-params.rs | 2 + .../specialization-translate-projections.rs | 2 + .../auxiliary/static-function-pointer-aux.rs | 0 .../auxiliary/static-methods-crate.rs | 0 .../auxiliary/static_fn_inline_xc_aux.rs | 0 .../auxiliary/static_fn_trait_xc_aux.rs | 0 .../statics}/auxiliary/static_mut_xc.rs | 0 .../run-pass/statics}/static-fn-inline-xc.rs | 1 + .../run-pass/statics}/static-fn-trait-xc.rs | 1 + .../statics}/static-function-pointer-xc.rs | 1 + .../statics}/static-function-pointer.rs | 1 + .../run-pass/statics}/static-impl.rs | 3 + ...tic-method-in-trait-with-tps-intracrate.rs | 1 + .../run-pass/statics}/static-method-xcrate.rs | 1 + .../statics}/static-methods-in-traits.rs | 1 + .../statics}/static-methods-in-traits2.rs | 1 + .../run-pass/statics}/static-mut-foreign.rs | 1 + .../run-pass/statics}/static-mut-xc.rs | 3 + .../run-pass/statics}/static-recursive.rs | 1 + .../run-pass/structs-enums}/align-struct.rs | 2 + .../structs-enums}/auxiliary/cci_class.rs | 0 .../structs-enums}/auxiliary/cci_class_2.rs | 0 .../structs-enums}/auxiliary/cci_class_3.rs | 0 .../structs-enums}/auxiliary/cci_class_4.rs | 0 .../structs-enums}/auxiliary/cci_class_6.rs | 0 .../auxiliary/cci_class_cast.rs | 0 .../auxiliary/cci_class_trait.rs | 0 .../structs-enums/auxiliary/empty-struct.rs | 19 + .../auxiliary/namespaced_enum_emulate_flat.rs | 0 .../auxiliary/namespaced_enums.rs | 20 + .../auxiliary/newtype_struct_xc.rs | 13 + .../struct_destructuring_cross_crate.rs | 0 .../auxiliary/struct_variant_xc_aux.rs | 0 .../auxiliary/xcrate_struct_aliases.rs | 0 .../structs-enums/borrow-tuple-fields.rs | 48 + .../structs-enums}/class-attributes-1.rs | 4 +- .../structs-enums}/class-attributes-2.rs | 5 +- .../class-cast-to-trait-cross-crate-2.rs | 2 +- .../class-cast-to-trait-multiple-types.rs | 2 + .../structs-enums}/class-cast-to-trait.rs | 3 + .../run-pass/structs-enums}/class-dtor.rs | 3 + .../run-pass/structs-enums}/class-exports.rs | 2 + .../class-impl-very-parameterized-trait.rs | 2 + .../class-implement-trait-cross-crate.rs | 3 + .../structs-enums}/class-implement-traits.rs | 2 + .../class-method-cross-crate.rs | 1 + .../class-methods-cross-crate.rs | 1 + .../run-pass/structs-enums}/class-methods.rs | 3 + .../class-poly-methods-cross-crate.rs | 1 + .../structs-enums}/class-poly-methods.rs | 2 + .../structs-enums}/class-separate-impl.rs | 4 +- .../structs-enums}/class-str-field.rs | 3 + .../run-pass/structs-enums}/class-typarams.rs | 3 + .../structs-enums}/classes-cross-crate.rs | 1 + .../classes-self-referential.rs | 3 + .../classes-simple-cross-crate.rs | 1 + .../structs-enums}/classes-simple-method.rs | 2 + .../run-pass/structs-enums}/classes-simple.rs | 2 + .../run-pass/structs-enums}/classes.rs | 3 + .../codegen-tag-static-padding.rs | 2 + .../structs-enums}/compare-generic-enums.rs | 3 + .../structs-enums}/discrim-explicit-23030.rs | 1 + .../structs-enums}/empty-struct-braces.rs | 3 + .../run-pass/structs-enums}/empty-tag.rs | 3 + .../run-pass/structs-enums}/enum-alignment.rs | 2 + .../structs-enums}/enum-clike-ffi-as-int.rs | 1 + .../run-pass/structs-enums}/enum-discr.rs | 1 + .../structs-enums/enum-discrim-autosizing.rs | 62 + .../enum-discrim-manual-sizing.rs | 1 + .../enum-discrim-range-overflow.rs | 3 + .../enum-discrim-width-stuff.rs | 4 + .../structs-enums}/enum-disr-val-pretty.rs | 2 + .../structs-enums}/enum-export-inheritance.rs | 1 + .../enum-layout-optimization.rs | 1 + .../enum-non-c-like-repr-c-and-int.rs | 1 + .../structs-enums}/enum-non-c-like-repr-c.rs | 1 + .../enum-non-c-like-repr-int.rs | 1 + .../structs-enums}/enum-null-pointer-opt.rs | 1 + .../enum-nullable-const-null-with-fields.rs | 1 + .../enum-nullable-simplifycfg-misopt.rs | 3 +- .../structs-enums}/enum-univariant-repr.rs | 1 + .../run-pass/structs-enums}/enum-variants.rs | 2 +- .../structs-enums}/enum-vec-initializer.rs | 1 + .../structs-enums}/export-abstract-tag.rs | 3 + .../structs-enums}/export-tag-variant.rs | 2 + .../run-pass/structs-enums}/expr-if-struct.rs | 2 + .../structs-enums}/expr-match-struct.rs | 2 + .../structs-enums}/field-destruction-order.rs | 3 + .../run-pass/structs-enums}/foreign-struct.rs | 3 + .../structs-enums}/functional-struct-upd.rs | 1 + .../run-pass/structs-enums}/ivec-tag.rs | 3 +- .../module-qualified-struct-destructure.rs | 1 + .../namespaced-enum-emulate-flat-xc.rs | 3 + .../namespaced-enum-emulate-flat.rs | 1 + .../namespaced-enum-glob-import-xcrate.rs | 1 + .../namespaced-enum-glob-import.rs | 1 + .../structs-enums}/namespaced-enums-xcrate.rs | 1 + .../structs-enums}/namespaced-enums.rs | 1 + .../structs-enums}/nested-enum-same-names.rs | 1 + .../structs-enums}/newtype-struct-drop-run.rs | 1 + .../newtype-struct-with-dtor.rs | 1 + .../structs-enums}/newtype-struct-xc-2.rs | 1 + .../structs-enums}/newtype-struct-xc.rs | 1 + .../run-pass/structs-enums}/nonzero-enum.rs | 1 + .../run-pass/structs-enums}/numeric-fields.rs | 1 + ...object-lifetime-default-from-ref-struct.rs | 1 + ...bject-lifetime-default-from-rptr-struct.rs | 1 + .../run-pass/structs-enums}/rec-align-u32.rs | 1 + .../run-pass/structs-enums}/rec-align-u64.rs | 1 + .../run-pass/structs-enums}/rec-auto.rs | 1 + .../run-pass/structs-enums}/rec-extend.rs | 1 + .../run-pass/structs-enums}/rec-tup.rs | 3 + .../run-pass/structs-enums}/rec.rs | 1 + .../run-pass/structs-enums}/record-pat.rs | 3 + .../structs-enums}/resource-in-struct.rs | 3 + .../structs-enums}/simple-generic-tag.rs | 3 + .../simple-match-generic-tag.rs | 3 + .../structs-enums}/small-enum-range-edge.rs | 9 +- .../structs-enums}/small-enums-with-fields.rs | 1 + .../structs-enums}/struct-aliases-xcrate.rs | 3 + .../run-pass/structs-enums}/struct-aliases.rs | 3 + .../struct-destructuring-cross-crate.rs | 1 + .../structs-enums}/struct-field-shorthand.rs | 1 + .../struct-like-variant-construct.rs | 1 + .../struct-like-variant-match.rs | 2 + .../struct-lit-functional-no-fields.rs | 1 + .../structs-enums}/struct-literal-dtor.rs | 3 + .../struct-new-as-field-name.rs | 1 + .../structs-enums}/struct-order-of-eval-1.rs | 1 + .../structs-enums}/struct-order-of-eval-2.rs | 1 + .../structs-enums}/struct-order-of-eval-3.rs | 1 + .../structs-enums}/struct-order-of-eval-4.rs | 1 + .../structs-enums}/struct-partial-move-1.rs | 1 + .../structs-enums}/struct-partial-move-2.rs | 1 + .../struct-path-associated-type.rs | 1 + .../structs-enums}/struct-path-self.rs | 1 + .../structs-enums}/struct-pattern-matching.rs | 3 + .../run-pass/structs-enums}/struct-return.rs | 1 + .../struct-variant-field-visibility.rs | 1 + .../structs-enums}/struct_variant_xc.rs | 1 + .../structs-enums}/struct_variant_xc_match.rs | 1 + .../structs-enums}/tag-align-dyn-u64.rs | 2 + .../structs-enums}/tag-align-dyn-variants.rs | 3 + .../structs-enums}/tag-align-shape.rs | 3 + .../run-pass/structs-enums}/tag-align-u64.rs | 2 + .../structs-enums}/tag-disr-val-shape.rs | 3 + .../run-pass/structs-enums}/tag-exports.rs | 2 + .../run-pass/structs-enums}/tag-in-block.rs | 3 + .../tag-variant-disr-type-mismatch.rs | 3 + .../structs-enums}/tag-variant-disr-val.rs | 3 + .../run-pass/structs-enums}/tag.rs | 2 + .../structs-enums}/tuple-struct-construct.rs | 1 + .../tuple-struct-constructor-pointer.rs | 1 + .../tuple-struct-destructuring.rs | 1 + .../structs-enums}/tuple-struct-matching.rs | 1 + .../structs-enums}/tuple-struct-trivial.rs | 1 + .../structs-enums}/uninstantiable-struct.rs | 1 + .../unit-like-struct-drop-run.rs | 1 + .../structs-enums}/unit-like-struct.rs | 1 + .../structs-enums}/variant-structs-trivial.rs | 1 + .../{ => ui}/run-pass/thinlto/all-crates.rs | 2 + .../run-pass/thinlto/auxiliary/dylib.rs | 0 .../thinlto/auxiliary/msvc-imp-present.rs | 0 .../thinlto/auxiliary/thin-lto-inlines-aux.rs | 0 .../{ => ui}/run-pass/thinlto/dylib-works.rs | 2 + .../run-pass/thinlto/msvc-imp-present.rs | 2 + .../run-pass/thinlto/thin-lto-inlines.rs | 2 + .../run-pass/thinlto/thin-lto-inlines2.rs | 2 + .../{ => ui}/run-pass/thinlto/weak-works.rs | 2 + .../auxiliary/thread-local-extern-static.rs | 0 .../run-pass/threads-sendsync}/comm.rs | 3 +- .../send-is-not-static-par-for.rs | 1 + .../threads-sendsync}/send-resource.rs | 5 +- .../threads-sendsync}/send-type-inference.rs | 1 + .../threads-sendsync}/send_str_hashmap.rs | 1 + .../threads-sendsync}/send_str_treemap.rs | 1 + .../threads-sendsync}/sendable-class.rs | 3 + .../threads-sendsync}/sendfn-is-a-block.rs | 1 + .../sendfn-spawn-with-fn-arg.rs | 2 +- .../run-pass/threads-sendsync}/spawn-fn.rs | 1 + .../run-pass/threads-sendsync}/spawn-types.rs | 3 + .../ui/run-pass/threads-sendsync/spawn.rs | 20 + .../run-pass/threads-sendsync}/spawn2.rs | 1 + .../threads-sendsync}/spawning-with-debug.rs | 1 + .../std-sync-right-kind-impls.rs | 4 +- .../threads-sendsync}/sync-send-atomics.rs | 2 + .../threads-sendsync}/sync-send-in-std.rs | 2 + .../sync-send-iterators-in-libcollections.rs | 4 +- .../sync-send-iterators-in-libcore.rs | 2 +- .../run-pass/threads-sendsync}/task-comm-0.rs | 3 +- .../run-pass/threads-sendsync}/task-comm-1.rs | 3 +- .../threads-sendsync}/task-comm-10.rs | 3 +- .../threads-sendsync}/task-comm-11.rs | 3 +- .../threads-sendsync}/task-comm-12.rs | 3 +- .../threads-sendsync}/task-comm-13.rs | 3 +- .../threads-sendsync}/task-comm-14.rs | 3 +- .../threads-sendsync}/task-comm-15.rs | 3 +- .../threads-sendsync}/task-comm-16.rs | 3 + .../threads-sendsync}/task-comm-17.rs | 3 +- .../run-pass/threads-sendsync}/task-comm-3.rs | 3 +- .../run-pass/threads-sendsync}/task-comm-4.rs | 2 +- .../run-pass/threads-sendsync}/task-comm-5.rs | 1 + .../run-pass/threads-sendsync}/task-comm-6.rs | 3 +- .../run-pass/threads-sendsync}/task-comm-7.rs | 4 +- .../run-pass/threads-sendsync}/task-comm-9.rs | 3 +- .../threads-sendsync}/task-comm-chan-nil.rs | 1 + .../run-pass/threads-sendsync}/task-life-0.rs | 3 +- .../task-spawn-move-and-copy.rs | 4 +- .../run-pass/threads-sendsync}/task-stderr.rs | 1 + .../thread-local-extern-static.rs | 1 + .../threads-sendsync}/thread-local-syntax.rs | 1 + .../run-pass/threads-sendsync}/threads.rs | 3 +- .../tls-dtors-are-run-in-a-static-binary.rs | 1 + .../threads-sendsync}/tls-init-on-init.rs | 3 + .../threads-sendsync}/tls-try-with.rs | 3 + .../traits}/anon-trait-static-method.rs | 1 + .../traits}/anon_trait_static_method_exe.rs | 3 + .../run-pass/traits}/assignability-trait.rs | 3 + .../astconv-cycle-between-trait-and-type.rs | 1 + .../traits}/augmented-assignments-trait.rs | 1 + .../run-pass/traits}/auto-traits.rs | 1 + .../auxiliary/anon_trait_static_method_lib.rs | 19 + .../run-pass/traits}/auxiliary/go_trait.rs | 0 .../auxiliary/trait_default_method_xc_aux.rs | 0 .../trait_default_method_xc_aux_2.rs | 0 .../trait_inheritance_auto_xc_2_aux.rs | 0 .../trait_inheritance_auto_xc_aux.rs | 0 .../trait_inheritance_overloading_xc.rs | 0 .../traits}/auxiliary/trait_safety_lib.rs | 0 .../traits}/auxiliary/trait_xc_call_aux.rs | 0 .../run-pass/traits}/auxiliary/traitimpl.rs | 0 .../traits}/conservative_impl_trait.rs | 1 + .../traits}/cycle-trait-type-trait.rs | 1 + .../default-method-supertrait-vtable.rs | 3 +- src/test/ui/run-pass/traits/dyn-trait.rs | 27 + .../run-pass/traits}/fmt-pointer-trait.rs | 1 + .../run-pass/traits}/impl-implicit-trait.rs | 3 + .../impl-inherent-prefer-over-trait.rs | 1 + .../infer-from-object-trait-issue-26952.rs | 1 + .../traits}/inherent-trait-method-order.rs | 1 + .../traits}/kindck-owned-trait-contains-1.rs | 4 +- .../run-pass/traits}/multiple-trait-bounds.rs | 1 + .../traits}/object-one-type-two-traits.rs | 2 +- ...overlap-permitted-for-marker-traits-neg.rs | 1 + .../overlap-permitted-for-marker-traits.rs | 1 + .../parameterized-trait-with-bounds.rs | 1 + .../traits}/supertrait-default-generics.rs | 3 + .../run-pass/traits}/syntax-trait-polarity.rs | 1 + .../run-pass/traits}/trait-bounds-basic.rs | 3 + ...trait-bounds-impl-comparison-duplicates.rs | 1 + .../run-pass/traits}/trait-bounds-in-arc.rs | 5 +- .../trait-bounds-on-structs-and-enums.rs | 3 +- .../traits}/trait-bounds-recursion.rs | 1 + .../run-pass/traits}/trait-bounds.rs | 3 + .../traits}/trait-cache-issue-18209.rs | 1 + .../traits}/trait-coercion-generic.rs | 1 + .../run-pass/traits}/trait-coercion.rs | 1 + .../traits}/trait-composition-trivial.rs | 1 + .../run-pass/traits}/trait-copy-guessing.rs | 1 + .../trait-default-method-bound-subst.rs | 1 + .../trait-default-method-bound-subst2.rs | 1 + .../trait-default-method-bound-subst3.rs | 1 + .../trait-default-method-bound-subst4.rs | 1 + .../traits}/trait-default-method-bound.rs | 1 + .../traits}/trait-default-method-xc-2.rs | 1 + .../traits}/trait-default-method-xc.rs | 3 + ...se-ambiguity-where-clause-builtin-bound.rs | 1 + .../run-pass/traits}/trait-generic.rs | 2 + .../run-pass/traits}/trait-impl-2.rs | 3 + .../run-pass/traits}/trait-impl.rs | 1 + .../traits}/trait-inheritance-auto-xc-2.rs | 1 + .../traits}/trait-inheritance-auto-xc.rs | 1 + .../traits}/trait-inheritance-auto.rs | 1 + .../trait-inheritance-call-bound-inherited.rs | 1 + ...trait-inheritance-call-bound-inherited2.rs | 1 + ...ritance-cast-without-call-to-supertrait.rs | 1 + .../traits}/trait-inheritance-cast.rs | 1 + .../trait-inheritance-cross-trait-call-xc.rs | 1 + .../trait-inheritance-cross-trait-call.rs | 1 + .../traits}/trait-inheritance-diamond.rs | 1 + .../trait-inheritance-multiple-inheritors.rs | 1 + .../trait-inheritance-multiple-params.rs | 1 + .../run-pass/traits}/trait-inheritance-num.rs | 1 + .../traits}/trait-inheritance-num0.rs | 3 +- .../traits}/trait-inheritance-num1.rs | 1 + .../traits}/trait-inheritance-num2.rs | 1 + .../traits}/trait-inheritance-num3.rs | 1 + .../traits}/trait-inheritance-num5.rs | 1 + .../trait-inheritance-overloading-simple.rs | 1 + .../trait-inheritance-overloading-xc-exe.rs | 1 + .../traits}/trait-inheritance-overloading.rs | 1 + .../trait-inheritance-self-in-supertype.rs | 1 + .../traits}/trait-inheritance-self.rs | 1 + .../traits}/trait-inheritance-simple.rs | 1 + .../traits}/trait-inheritance-static.rs | 1 + .../traits}/trait-inheritance-static2.rs | 1 + .../traits}/trait-inheritance-subst.rs | 1 + .../traits}/trait-inheritance-subst2.rs | 1 + .../traits}/trait-inheritance-visibility.rs | 1 + .../run-pass/traits}/trait-inheritance2.rs | 1 + .../traits}/trait-item-inside-macro.rs | 1 + .../traits}/trait-object-auto-dedup.rs | 1 + .../traits}/trait-object-exclusion.rs | 1 + .../run-pass/traits}/trait-object-generics.rs | 3 +- .../traits}/trait-object-lifetime-first.rs | 1 + .../trait-object-with-lifetime-bound.rs | 1 + .../traits}/trait-region-pointer-simple.rs | 1 + .../run-pass/traits}/trait-safety-ok-cc.rs | 1 + .../run-pass/traits}/trait-safety-ok.rs | 1 + .../trait-static-method-overwriting.rs | 1 + .../run-pass/traits}/trait-to-str.rs | 4 +- .../traits}/trait-where-clause-vs-impl.rs | 1 + .../traits}/trait-with-bounds-default.rs | 3 +- .../traits-assoc-type-in-supertrait.rs | 1 + .../traits}/traits-conditional-dispatch.rs | 3 +- .../traits}/traits-conditional-model-fn.rs | 1 + .../traits}/traits-default-method-macro.rs | 1 + .../traits}/traits-default-method-mut.rs | 2 +- .../traits}/traits-default-method-self.rs | 3 +- .../traits}/traits-default-method-trivial.rs | 3 +- .../traits}/traits-elaborate-type-region.rs | 1 + .../traits-impl-object-overlap-issue-23853.rs | 1 + .../run-pass/traits}/traits-issue-22019.rs | 1 + .../run-pass/traits}/traits-issue-22110.rs | 1 + .../run-pass/traits}/traits-issue-22655.rs | 1 + .../run-pass/traits}/traits-issue-23003.rs | 1 + .../run-pass/traits}/traits-issue-26339.rs | 1 + ...aits-multidispatch-infer-convert-target.rs | 1 + .../run-pass/traits}/traits-negative-impls.rs | 1 + .../traits}/traits-repeated-supertrait.rs | 1 + .../run-pass/traits}/ufcs-trait-object.rs | 1 + .../run-pass/traits}/use-trait-before-def.rs | 3 + .../auxiliary/unboxed-closures-cross-crate.rs | 0 .../unboxed-closures-all-traits.rs | 1 + .../unboxed-closures-blanket-fn-mut.rs | 1 + .../unboxed-closures-blanket-fn.rs | 1 + .../unboxed-closures-boxed.rs | 2 +- .../unboxed-closures-by-ref.rs | 1 + .../unboxed-closures-call-fn-autoderef.rs | 1 + .../unboxed-closures-call-sugar-autoderef.rs | 1 + ...ed-closures-call-sugar-object-autoderef.rs | 3 +- .../unboxed-closures-call-sugar-object.rs | 3 +- .../unboxed-closures-counter-not-moved.rs | 1 + .../unboxed-closures-cross-crate.rs | 3 + .../unboxed-closures-direct-sugary-call.rs | 1 + .../unboxed-closures-drop.rs | 1 + .../unboxed-closures-extern-fn-hr.rs | 1 + .../unboxed-closures-extern-fn.rs | 1 + ...unboxed-closures-fn-as-fnmut-and-fnonce.rs | 1 + .../unboxed-closures-fnmut-as-fnonce.rs | 1 + .../unboxed-closures-generic.rs | 1 + ...res-infer-arg-types-from-expected-bound.rs | 1 + ...fer-arg-types-from-expected-object-type.rs | 1 + ...-types-w-bound-regs-from-expected-bound.rs | 1 + ...oxed-closures-infer-explicit-call-early.rs | 1 + ...oxed-closures-infer-fnmut-calling-fnmut.rs | 1 + .../unboxed-closures-infer-fnmut-move.rs | 1 + .../unboxed-closures-infer-fnmut.rs | 1 + .../unboxed-closures-infer-fnonce-move.rs | 1 + .../unboxed-closures-infer-fnonce.rs | 1 + .../unboxed-closures-infer-kind.rs | 1 + .../unboxed-closures-infer-recursive-fn.rs | 1 + .../unboxed-closures-infer-upvar.rs | 1 + .../unboxed-closures-manual-impl.rs | 1 + .../unboxed-closures-monomorphization.rs | 1 + ...osures-move-from-projection-issue-30046.rs | 1 + .../unboxed-closures-move-mutable.rs | 1 + ...ures-move-some-upvars-in-by-ref-closure.rs | 1 + .../unboxed-closures-prelude.rs | 1 + .../unboxed-closures-simple.rs | 1 + .../unboxed-closures-single-word-env.rs | 1 + .../unboxed-closures-static-call-fn-once.rs | 1 + .../unboxed-closures-sugar-object.rs | 1 + .../unboxed-closures-unique-type-id.rs | 6 +- .../unboxed-closures-zero-args.rs | 1 + .../ui/run-pass/uniform-paths/basic-nested.rs | 70 + src/test/ui/run-pass/uniform-paths/basic.rs | 44 + .../run-pass/uniform-paths/macros-nested.rs | 65 + src/test/ui/run-pass/uniform-paths/macros.rs | 48 + .../ui/run-pass/uniform-paths/same-crate.rs | 111 + .../run-pass/union/auxiliary/union.rs | 0 .../{ => ui}/run-pass/union/union-align.rs | 2 + .../{ => ui}/run-pass/union/union-backcomp.rs | 2 + .../{ => ui}/run-pass/union/union-basic.rs | 2 + .../run-pass/union/union-c-interop.rs | 3 + .../run-pass/union/union-const-codegen.rs | 2 + .../run-pass/union/union-const-eval-field.rs | 55 + .../{ => ui}/run-pass/union/union-derive.rs | 3 + .../run-pass/union/union-drop-assign.rs | 3 + .../{ => ui}/run-pass/union/union-drop.rs | 3 + .../{ => ui}/run-pass/union/union-generic.rs | 3 + .../run-pass/union/union-inherent-method.rs | 2 + .../{ => ui}/run-pass/union/union-macro.rs | 2 + .../{ => ui}/run-pass/union/union-nodrop.rs | 2 + .../run-pass/union/union-overwrite.rs | 3 + .../{ => ui}/run-pass/union/union-packed.rs | 3 + .../run-pass/union/union-pat-refutability.rs | 3 + .../run-pass/union/union-trait-impl.rs | 2 + .../run-pass/union/union-transmute.rs | 2 + .../union/union-with-drop-fields-lint.rs | 2 + .../run-pass/unique}/unique-assign-copy.rs | 3 +- .../run-pass/unique}/unique-assign-drop.rs | 3 +- .../run-pass/unique}/unique-assign-generic.rs | 4 +- .../run-pass/unique}/unique-assign.rs | 3 +- .../unique}/unique-autoderef-field.rs | 3 +- .../unique}/unique-autoderef-index.rs | 3 +- .../run-pass/unique}/unique-cmp.rs | 3 +- .../run-pass/unique}/unique-containing-tag.rs | 4 +- .../run-pass/unique}/unique-create.rs | 2 +- .../run-pass/unique}/unique-decl-init-copy.rs | 3 +- .../run-pass/unique}/unique-decl-init.rs | 3 +- .../run-pass/unique}/unique-decl-move.rs | 3 +- .../run-pass/unique}/unique-decl.rs | 1 + .../run-pass/unique}/unique-deref.rs | 3 +- .../run-pass/unique}/unique-destructure.rs | 3 +- .../run-pass/unique}/unique-drop-complex.rs | 2 +- .../run-pass/unique}/unique-ffi-symbols.rs | 1 + .../run-pass/unique}/unique-fn-arg-move.rs | 3 +- .../run-pass/unique}/unique-fn-arg-mut.rs | 3 +- .../run-pass/unique}/unique-fn-arg.rs | 3 +- .../run-pass/unique}/unique-fn-ret.rs | 3 +- .../run-pass/unique}/unique-generic-assign.rs | 1 + .../run-pass/unique}/unique-in-tag.rs | 4 +- .../run-pass/unique}/unique-in-vec-copy.rs | 3 +- .../run-pass/unique}/unique-in-vec.rs | 3 +- .../run-pass/unique}/unique-init.rs | 2 +- .../run-pass/unique}/unique-kinds.rs | 3 +- .../run-pass/unique}/unique-log.rs | 2 +- .../run-pass/unique}/unique-match-discrim.rs | 1 + .../run-pass/unique}/unique-move-drop.rs | 2 +- .../run-pass/unique}/unique-move-temp.rs | 3 +- .../run-pass/unique}/unique-move.rs | 3 +- .../run-pass/unique}/unique-mutable.rs | 3 +- .../run-pass/unique}/unique-object-move.rs | 2 +- .../run-pass/unique}/unique-pat-2.rs | 4 +- .../run-pass/unique}/unique-pat-3.rs | 4 +- .../run-pass/unique}/unique-pat.rs | 2 +- .../run-pass/unique}/unique-rec.rs | 3 +- .../run-pass/unique}/unique-send-2.rs | 2 +- .../run-pass/unique}/unique-send.rs | 3 +- .../run-pass/unique}/unique-swap.rs | 3 +- .../reference-unsized-locals.rs | 19 + .../unsized-locals/simple-unsized-locals.rs | 18 + .../run-pass/unsized-locals/unsized-exprs.rs | 47 + .../unsized-locals/unsized-parameters.rs | 22 + .../auxiliary/where_clauses_xc.rs | 0 .../where-clause-bounds-inconsistency.rs | 1 + .../where-clause-early-bound-lifetimes.rs | 3 + .../where-clause-method-substituion.rs | 1 + .../where-clause-region-outlives.rs | 1 + .../where-clauses-cross-crate.rs | 1 + .../where-clauses}/where-clauses-lifetimes.rs | 1 + .../where-clauses}/where-clauses-method.rs | 1 + .../where-clauses-unboxed-closures.rs | 1 + .../run-pass/where-clauses}/where-clauses.rs | 1 + .../zero-sized}/zero-size-type-destructors.rs | 3 + .../zero-sized-binary-heap-push.rs | 1 + .../zero-sized}/zero-sized-btreemap-insert.rs | 1 + .../zero-sized}/zero-sized-linkedlist-push.rs | 1 + .../zero-sized}/zero-sized-tuple-struct.rs | 1 + .../zero-sized}/zero-sized-vec-deque-push.rs | 1 + .../zero-sized}/zero-sized-vec-push.rs | 1 + src/test/ui/rust-2018/async-ident-allowed.rs | 4 +- .../ui/rust-2018/async-ident-allowed.stderr | 4 +- src/test/ui/rust-2018/async-ident.fixed | 7 +- src/test/ui/rust-2018/async-ident.rs | 5 +- src/test/ui/rust-2018/async-ident.stderr | 45 +- .../auxiliary/remove-extern-crate.rs | 19 + .../edition-lint-fully-qualified-paths.fixed | 2 +- .../edition-lint-fully-qualified-paths.rs | 2 +- .../edition-lint-nested-empty-paths.fixed | 2 +- .../edition-lint-nested-empty-paths.rs | 2 +- .../rust-2018/edition-lint-nested-paths.fixed | 2 +- .../ui/rust-2018/edition-lint-nested-paths.rs | 2 +- .../ui/rust-2018/edition-lint-paths.fixed | 2 +- src/test/ui/rust-2018/edition-lint-paths.rs | 2 +- .../extern-crate-idiomatic-in-2018.fixed | 4 +- .../extern-crate-idiomatic-in-2018.rs | 4 +- .../ui/rust-2018/extern-crate-idiomatic.fixed | 1 + .../ui/rust-2018/extern-crate-idiomatic.rs | 1 + .../rust-2018/issue-52202-use-suggestions.rs | 2 +- src/test/ui/rust-2018/issue-54006.rs | 23 + src/test/ui/rust-2018/issue-54006.stderr | 17 + .../ui/rust-2018/macro-use-warned-against.rs | 3 +- .../rust-2018/macro-use-warned-against.stderr | 15 +- .../ui/rust-2018/remove-extern-crate.fixed | 40 + src/test/ui/rust-2018/remove-extern-crate.rs | 40 + .../ui/rust-2018/remove-extern-crate.stderr | 25 + src/test/ui/rust-2018/try-ident.fixed | 21 + src/test/ui/rust-2018/try-ident.rs | 21 + src/test/ui/rust-2018/try-ident.stderr | 24 + src/test/ui/rust-2018/try-macro.fixed | 16 + src/test/ui/rust-2018/try-macro.rs | 16 + src/test/ui/rust-2018/try-macro.stderr | 15 + .../ambiguity-macros-nested.rs | 29 + .../ambiguity-macros-nested.stderr | 16 + .../ambiguity-macros.rs | 27 + .../ambiguity-macros.stderr | 16 + .../ambiguity-nested.rs | 24 + .../ambiguity-nested.stderr | 16 + .../uniform-paths-forward-compat/ambiguity.rs | 20 + .../ambiguity.stderr | 16 + .../block-scoped-shadow.rs | 21 + .../block-scoped-shadow.stderr | 31 + .../issue-54253.rs | 27 + .../issue-54253.stderr | 9 + .../uniform-paths-forward-compat/redundant.rs | 30 + .../uniform-paths/ambiguity-macros-nested.rs | 31 + .../ambiguity-macros-nested.stderr | 16 + .../uniform-paths/ambiguity-macros.rs | 29 + .../uniform-paths/ambiguity-macros.stderr | 16 + .../uniform-paths/ambiguity-nested.rs | 26 + .../uniform-paths/ambiguity-nested.stderr | 16 + .../ui/rust-2018/uniform-paths/ambiguity.rs | 22 + .../rust-2018/uniform-paths/ambiguity.stderr | 16 + .../uniform-paths/block-scoped-shadow.rs | 31 + .../uniform-paths/block-scoped-shadow.stderr | 45 + .../ui/rust-2018/uniform-paths/issue-54253.rs | 29 + .../uniform-paths/issue-54253.stderr | 9 + .../ui/rust-2018/uniform-paths/redundant.rs | 32 + .../rust-unstable-column-gated.rs | 0 src/test/ui/rust-unstable-column-gated.stderr | 8 + .../rustc-args-required-const.rs | 2 +- src/test/ui/rustc-args-required-const.stderr | 14 + .../rustc-args-required-const2.rs | 2 +- src/test/ui/rustc-args-required-const2.stderr | 8 + src/test/{compile-fail => ui}/rustc-error.rs | 0 src/test/ui/rustc-error.stderr | 10 + .../safe-extern-statics-mut.rs | 0 src/test/ui/safe-extern-statics-mut.stderr | 35 + .../safe-extern-statics.rs | 0 src/test/ui/safe-extern-statics.stderr | 43 + src/test/ui/{ => self}/self-impl.rs | 0 src/test/ui/{ => self}/self-impl.stderr | 0 .../{compile-fail => ui/self}/self-infer.rs | 0 src/test/ui/self/self-infer.stderr | 15 + .../self}/self-vs-path-ambiguity.rs | 0 .../ui/self/self-vs-path-ambiguity.stderr | 8 + .../self}/self_type_keyword-2.rs | 3 + src/test/ui/self/self_type_keyword-2.stderr | 52 + .../self}/self_type_keyword.rs | 0 src/test/ui/self/self_type_keyword.stderr | 62 + src/test/{compile-fail => ui}/seq-args.rs | 0 src/test/ui/seq-args.stderr | 15 + .../ui/{ => shadowed}/shadowed-lifetime.rs | 0 .../{ => shadowed}/shadowed-lifetime.stderr | 0 .../shadowed}/shadowed-trait-methods.rs | 0 .../ui/shadowed/shadowed-trait-methods.stderr | 15 + .../{ => shadowed}/shadowed-type-parameter.rs | 0 .../shadowed-type-parameter.stderr | 0 .../shadowed}/shadowed-use-visibility.rs | 0 .../shadowed/shadowed-use-visibility.stderr | 15 + .../shadowing-in-the-same-pattern.rs | 0 .../shadowing-in-the-same-pattern.stderr | 15 + .../shift-various-bad-types.rs | 0 src/test/ui/shift-various-bad-types.stderr | 34 + ...fail-no_gate_irrefutable_if_let_pattern.rs | 0 ...-no_gate_irrefutable_if_let_pattern.stderr | 9 + ...fail-with_gate_irrefutable_pattern_deny.rs | 0 ...-with_gate_irrefutable_pattern_deny.stderr | 10 + .../simd-intrinsic-declaration-type.rs | 0 .../simd-intrinsic-declaration-type.stderr | 75 + .../simd-intrinsic-generic-arithmetic.rs | 0 .../simd-intrinsic-generic-arithmetic.stderr | 87 + .../simd-intrinsic-generic-cast.rs | 0 .../simd-intrinsic-generic-cast.stderr | 27 + .../simd-intrinsic-generic-comparison.rs | 0 .../simd-intrinsic-generic-comparison.stderr | 111 + .../simd-intrinsic-generic-elements.rs | 0 .../simd-intrinsic-generic-elements.stderr | 93 + .../simd-intrinsic-generic-reduction.rs | 0 .../simd-intrinsic-generic-reduction.stderr | 75 + .../simd-intrinsic-generic-select.rs | 0 .../simd-intrinsic-generic-select.stderr | 21 + .../simd-intrinsic-single-nominal-type.rs | 0 .../simd-intrinsic-single-nominal-type.stderr | 15 + .../simd-type-generic-monomorphisation.rs | 0 .../simd-type-generic-monomorphisation.stderr | 4 + src/test/{compile-fail => ui}/simd-type.rs | 0 src/test/ui/simd-type.stderr | 22 + .../single-primitive-inherent-impl.rs | 0 .../ui/single-primitive-inherent-impl.stderr | 19 + .../two-uses-in-fn-arguments.rs | 2 +- .../{compile-fail => ui}/sized-cycle-note.rs | 0 src/test/ui/sized-cycle-note.stderr | 23 + src/test/{compile-fail => ui}/slice-2.rs | 0 src/test/ui/slice-2.stderr | 27 + src/test/ui/slice-mut-2.nll.stderr | 12 + src/test/{compile-fail => ui}/slice-mut-2.rs | 0 src/test/ui/slice-mut-2.stderr | 9 + src/test/{compile-fail => ui}/slice-mut.rs | 0 src/test/ui/slice-mut.stderr | 12 + .../slightly-nice-generic-literal-messages.rs | 0 ...ghtly-nice-generic-literal-messages.stderr | 12 + ...orrow-overloaded-auto-deref-mut.nll.stderr | 4 +- ...ck-borrow-overloaded-auto-deref-mut.stderr | 8 +- ...wck-borrow-overloaded-deref-mut.nll.stderr | 4 +- ...orrowck-borrow-overloaded-deref-mut.stderr | 4 +- ...owck-call-is-borrow-issue-12224.nll.stderr | 28 +- ...orrowck-let-suggestion-suffixes.nll.stderr | 6 + .../ui/span/borrowck-object-mutability.stderr | 2 +- .../span/borrowck-ref-into-rvalue.nll.stderr | 2 + .../ui/span/dropck-object-cycle.nll.stderr | 2 - .../span/dropck_arr_cycle_checked.nll.stderr | 16 +- .../span/dropck_vec_cycle_checked.nll.stderr | 16 +- src/test/ui/span/issue-15480.nll.stderr | 2 + src/test/ui/span/issue-36530.rs | 3 + src/test/ui/span/issue-36530.stderr | 18 +- src/test/ui/span/macro-span-replacement.rs | 2 +- .../ui/span/macro-span-replacement.stderr | 4 +- src/test/ui/span/mut-arg-hint.nll.stderr | 2 +- src/test/ui/span/range-2.nll.stderr | 16 +- ...-close-over-borrowed-ref-in-obj.nll.stderr | 2 + ...ons-close-over-type-parameter-2.nll.stderr | 17 +- ...egions-escape-loop-via-variable.nll.stderr | 2 +- .../regions-escape-loop-via-vec.nll.stderr | 28 +- ...d-is-not-static-ensures-scoping.nll.stderr | 29 +- src/test/ui/span/slice-borrow.nll.stderr | 1 + .../span/unused-warning-point-at-signature.rs | 2 +- .../unused-warning-point-at-signature.stderr | 4 +- .../vec_refs_data_with_early_death.nll.stderr | 16 +- .../specialization/README.md | 0 .../specialization-feature-gate-default.rs | 0 ...specialization-feature-gate-default.stderr | 13 + .../defaultimpl/specialization-no-default.rs | 0 .../specialization-no-default.stderr | 70 + ...ecialization-trait-item-not-implemented.rs | 0 ...lization-trait-item-not-implemented.stderr | 12 + .../specialization-trait-not-implemented.rs | 0 ...pecialization-trait-not-implemented.stderr | 18 + .../defaultimpl/specialization-wfcheck.rs | 0 .../defaultimpl/specialization-wfcheck.stderr | 11 + .../specialization/defaultimpl/validation.rs | 2 + .../defaultimpl/validation.stderr | 29 + .../specialization/issue-52050.rs | 0 src/test/ui/specialization/issue-52050.stderr | 18 + .../specialization-default-projection.rs | 0 .../specialization-default-projection.stderr | 29 + .../specialization-default-types.rs | 0 .../specialization-default-types.stderr | 25 + .../specialization-feature-gate-default.rs | 0 ...specialization-feature-gate-default.stderr | 0 .../specialization-feature-gate-overlap.rs | 0 ...specialization-feature-gate-overlap.stderr | 0 .../specialization-no-default.rs | 0 .../specialization-no-default.stderr | 70 + .../specialization-overlap-negative.rs | 0 .../specialization-overlap-negative.stderr | 11 + .../specialization/specialization-overlap.rs | 0 .../specialization-overlap.stderr | 35 + .../specialization/specialization-polarity.rs | 0 .../specialization-polarity.stderr | 19 + .../auxiliary/stability_attribute_issue.rs | 19 + .../stability-attribute-issue-43027.rs | 0 .../stability-attribute-issue-43027.stderr | 8 + .../stability-attribute-issue.rs | 24 + .../stability-attribute-issue.stderr | 19 + ...ity-attribute-non-staged-force-unstable.rs | 0 ...attribute-non-staged-force-unstable.stderr | 20 + .../stability-attribute-non-staged.rs | 0 .../stability-attribute-non-staged.stderr | 20 + .../stability-attribute-sanity-2.rs | 2 +- .../stability-attribute-sanity-2.stderr | 22 + .../stability-attribute-sanity-3.rs | 2 +- .../stability-attribute-sanity-3.stderr | 10 + .../stability-attribute-sanity.rs | 16 +- .../stability-attribute-sanity.stderr | 142 + .../{compile-fail => ui}/stable-features.rs | 5 +- src/test/ui/stable-features.stderr | 20 + .../auxiliary}/static-priv-by-default.rs | 0 .../auxiliary/static_priv_by_default.rs | 0 .../static}/static-closures.rs | 0 src/test/ui/static/static-closures.stderr | 9 + .../static}/static-drop-scope.rs | 0 src/test/ui/static/static-drop-scope.stderr | 60 + .../static}/static-items-cant-move.rs | 0 .../ui/static/static-items-cant-move.stderr | 9 + .../static/static-lifetime-bound.nll.stderr | 21 + .../static}/static-lifetime-bound.rs | 0 .../ui/static/static-lifetime-bound.stderr | 21 + src/test/ui/{ => static}/static-lifetime.rs | 0 .../ui/{ => static}/static-lifetime.stderr | 0 .../static}/static-method-privacy.rs | 0 .../ui/static/static-method-privacy.stderr | 9 + .../static}/static-mut-bad-types.rs | 0 .../ui/static/static-mut-bad-types.stderr | 9 + .../static-mut-foreign-requires-unsafe.rs | 0 .../static-mut-foreign-requires-unsafe.stderr | 27 + .../static}/static-mut-not-constant.rs | 0 .../ui/static/static-mut-not-constant.stderr | 9 + .../static}/static-mut-not-pat.rs | 0 src/test/ui/static/static-mut-not-pat.stderr | 21 + .../static}/static-mut-requires-unsafe.rs | 0 .../static/static-mut-requires-unsafe.stderr | 27 + .../static}/static-priv-by-default2.rs | 0 .../ui/static/static-priv-by-default2.stderr | 15 + .../static}/static-reference-to-fn-1.rs | 0 .../ui/static/static-reference-to-fn-1.stderr | 12 + .../static-reference-to-fn-2.nll.stderr | 68 + .../static}/static-reference-to-fn-2.rs | 0 .../ui/static/static-reference-to-fn-2.stderr | 71 + .../static}/static-region-bound.rs | 0 src/test/ui/static/static-region-bound.stderr | 14 + .../static}/static-vec-repeat-not-constant.rs | 0 .../static-vec-repeat-not-constant.stderr | 9 + .../staticness-mismatch.rs | 0 src/test/ui/staticness-mismatch.stderr | 12 + src/test/ui/std-uncopyable-atomics.nll.stderr | 39 + .../std-uncopyable-atomics.rs | 0 src/test/ui/std-uncopyable-atomics.stderr | 39 + .../stmt_expr_attrs_no_feature.rs | 2 +- src/test/ui/stmt_expr_attrs_no_feature.stderr | 75 + src/test/ui/{ => str}/str-array-assignment.rs | 0 .../ui/{ => str}/str-array-assignment.stderr | 3 +- src/test/ui/{ => str}/str-as-char.fixed | 0 src/test/ui/{ => str}/str-as-char.rs | 0 src/test/ui/{ => str}/str-as-char.stderr | 0 .../ui/{ => str}/str-concat-on-double-ref.rs | 0 .../{ => str}/str-concat-on-double-ref.stderr | 0 src/test/{compile-fail => ui/str}/str-idx.rs | 0 src/test/ui/str/str-idx.stderr | 11 + .../ui/{ => str}/str-lit-type-mismatch.rs | 0 .../ui/{ => str}/str-lit-type-mismatch.stderr | 0 .../{compile-fail => ui/str}/str-mut-idx.rs | 0 src/test/ui/str/str-mut-idx.stderr | 35 + .../auxiliary/struct_field_privacy.rs | 0 .../auxiliary/struct_variant_privacy.rs | 0 .../structs}/struct-base-wrong-type-2.rs | 0 .../structs/struct-base-wrong-type-2.stderr | 21 + .../structs}/struct-base-wrong-type.rs | 0 .../ui/structs/struct-base-wrong-type.stderr | 21 + .../{ => structs}/struct-duplicate-comma.rs | 0 .../struct-duplicate-comma.stderr | 0 .../structs}/struct-field-cfg.rs | 0 src/test/ui/structs/struct-field-cfg.stderr | 30 + .../{ => structs}/struct-field-init-syntax.rs | 0 .../struct-field-init-syntax.stderr | 0 .../structs}/struct-field-privacy.rs | 0 .../ui/structs/struct-field-privacy.stderr | 33 + .../{ => structs}/struct-fields-decl-dupe.rs | 0 .../struct-fields-decl-dupe.stderr | 0 .../structs}/struct-fields-dupe.rs | 0 src/test/ui/structs/struct-fields-dupe.stderr | 11 + .../struct-fields-hints-no-dupe.rs | 0 .../struct-fields-hints-no-dupe.stderr | 0 .../ui/{ => structs}/struct-fields-hints.rs | 0 .../{ => structs}/struct-fields-hints.stderr | 0 .../structs}/struct-fields-missing.rs | 0 .../ui/structs/struct-fields-missing.stderr | 9 + .../struct-fields-shorthand-unresolved.rs | 0 .../struct-fields-shorthand-unresolved.stderr | 9 + .../structs}/struct-fields-shorthand.rs | 0 .../ui/structs/struct-fields-shorthand.stderr | 11 + .../{ => structs}/struct-fields-too-many.rs | 0 .../struct-fields-too-many.stderr | 0 .../structs}/struct-fields-typo.rs | 0 src/test/ui/structs/struct-fields-typo.stderr | 9 + .../struct-like-enum-nonexhaustive.rs | 0 .../struct-like-enum-nonexhaustive.stderr | 9 + .../ui/{ => structs}/struct-missing-comma.rs | 0 .../{ => structs}/struct-missing-comma.stderr | 0 .../structs}/struct-pat-derived-error.rs | 0 .../structs/struct-pat-derived-error.stderr | 22 + .../structs}/struct-path-alias-bounds.rs | 0 .../structs/struct-path-alias-bounds.stderr | 15 + .../structs}/struct-path-associated-type.rs | 0 .../struct-path-associated-type.stderr | 64 + .../struct-path-self-type-mismatch.rs | 0 .../struct-path-self-type-mismatch.stderr | 0 .../structs}/struct-path-self.rs | 0 src/test/ui/structs/struct-path-self.stderr | 40 + .../structs}/struct-pattern-match-useless.rs | 0 .../struct-pattern-match-useless.stderr | 14 + .../structs}/struct-variant-privacy-xc.rs | 0 .../structs/struct-variant-privacy-xc.stderr | 15 + .../structs}/struct-variant-privacy.rs | 0 .../ui/structs/struct-variant-privacy.stderr | 15 + .../structure-constructor-type-mismatch.rs | 0 ...structure-constructor-type-mismatch.stderr | 139 + src/test/ui/substs-ppaux.normal.stderr | 55 + src/test/{compile-fail => ui}/substs-ppaux.rs | 0 src/test/ui/substs-ppaux.verbose.stderr | 55 + .../suffixed-literal-meta.rs | 2 - src/test/ui/suffixed-literal-meta.stderr | 98 + .../auxiliary/struct_field_privacy.rs | 0 .../dont-suggest-ref/duplicate-suggestions.rs | 162 + .../duplicate-suggestions.stderr | 328 ++ .../dont-suggest-ref/move-into-closure.rs | 171 + .../dont-suggest-ref/move-into-closure.stderr | 420 ++ .../ui/suggestions/dont-suggest-ref/simple.rs | 376 ++ .../dont-suggest-ref/simple.stderr | 998 ++++ .../ui/{ => suggestions}/suggest-labels.rs | 0 .../{ => suggestions}/suggest-labels.stderr | 0 .../ui/{ => suggestions}/suggest-methods.rs | 0 .../{ => suggestions}/suggest-methods.stderr | 0 .../suggest-private-fields.rs | 0 .../suggest-private-fields.stderr | 0 .../ui/{ => suggestions}/suggest-ref-mut.rs | 0 .../{ => suggestions}/suggest-ref-mut.stderr | 0 .../suggest-remove-refs-1.rs | 0 .../suggest-remove-refs-1.stderr | 0 .../suggest-remove-refs-2.rs | 0 .../suggest-remove-refs-2.stderr | 0 .../suggest-remove-refs-3.rs | 0 .../suggest-remove-refs-3.stderr | 0 .../super-at-top-level.rs | 0 src/test/ui/super-at-top-level.stderr | 9 + .../{compile-fail => ui}/suppressed-error.rs | 0 src/test/ui/suppressed-error.stderr | 12 + src/test/ui/{ => svh}/auxiliary/svh-a-base.rs | 0 .../{ => svh}/auxiliary/svh-a-change-lit.rs | 0 .../auxiliary/svh-a-change-significant-cfg.rs | 0 .../auxiliary/svh-a-change-trait-bound.rs | 0 .../auxiliary/svh-a-change-type-arg.rs | 0 .../auxiliary/svh-a-change-type-ret.rs | 0 .../auxiliary/svh-a-change-type-static.rs | 1 - src/test/ui/{ => svh}/auxiliary/svh-b.rs | 0 .../ui/{ => svh}/auxiliary/svh-uta-base.rs | 0 .../auxiliary/svh-uta-change-use-trait.rs | 0 src/test/ui/{ => svh}/auxiliary/svh-utb.rs | 0 src/test/ui/{ => svh}/svh-change-lit.rs | 0 src/test/ui/{ => svh}/svh-change-lit.stderr | 0 .../{ => svh}/svh-change-significant-cfg.rs | 0 .../svh-change-significant-cfg.stderr | 0 .../ui/{ => svh}/svh-change-trait-bound.rs | 0 .../{ => svh}/svh-change-trait-bound.stderr | 0 src/test/ui/{ => svh}/svh-change-type-arg.rs | 0 .../ui/{ => svh}/svh-change-type-arg.stderr | 0 src/test/ui/{ => svh}/svh-change-type-ret.rs | 0 .../ui/{ => svh}/svh-change-type-ret.stderr | 0 .../ui/{ => svh}/svh-change-type-static.rs | 0 .../{ => svh}/svh-change-type-static.stderr | 0 src/test/ui/{ => svh}/svh-use-trait.rs | 0 src/test/ui/{ => svh}/svh-use-trait.stderr | 0 .../symbol-names/basic.rs | 0 src/test/ui/symbol-names/basic.stderr | 14 + .../symbol-names/impl1.rs | 0 src/test/ui/symbol-names/impl1.stderr | 26 + .../syntax-extension-minor.rs | 0 src/test/ui/syntax-extension-minor.stderr | 9 + .../syntax-trait-polarity-feature-gate.rs | 0 .../syntax-trait-polarity-feature-gate.stderr | 11 + .../syntax-trait-polarity.rs | 0 src/test/ui/syntax-trait-polarity.stderr | 40 + .../{compile-fail => ui}/synthetic-param.rs | 0 src/test/ui/synthetic-param.stderr | 21 + .../tag-that-dare-not-speak-its-name.rs | 0 .../tag-that-dare-not-speak-its-name.stderr | 12 + .../{compile-fail => ui}/tag-type-args.rs | 0 src/test/ui/tag-type-args.stderr | 9 + .../tag-variant-cast-non-nullary.rs | 0 .../ui/tag-variant-cast-non-nullary.stderr | 11 + .../tag-variant-disr-dup.rs | 0 src/test/ui/tag-variant-disr-dup.stderr | 11 + src/test/{compile-fail => ui}/tail-typeck.rs | 0 src/test/ui/tail-typeck.stderr | 9 + src/test/ui/target-feature-gate.rs | 3 + src/test/ui/target-feature-gate.stderr | 2 +- src/test/ui/target-feature-wrong.rs | 1 + src/test/ui/target-feature-wrong.stderr | 14 +- .../{compile-fail => ui}/terr-in-field.rs | 0 src/test/ui/terr-in-field.stderr | 12 + src/test/{compile-fail => ui}/terr-sorts.rs | 0 src/test/ui/terr-sorts.stderr | 12 + src/test/{compile-fail => ui}/test-cfg.rs | 0 src/test/ui/test-cfg.stderr | 9 + src/test/ui/test-on-macro.rs | 23 + src/test/ui/test-on-macro.stderr | 6 + .../ui/test-shadowing/auxiliary/test_macro.rs | 14 + .../test-shadowing/test-cant-be-shadowed.rs | 23 + .../test-warns-dead-code.rs | 0 src/test/ui/test-warns-dead-code.stderr | 14 + src/test/ui/thread-local-in-ctfe.nll.stderr | 50 + .../thread-local-in-ctfe.rs | 0 src/test/ui/thread-local-in-ctfe.stderr | 33 + src/test/ui/token/issue-10636-2.stderr | 13 +- .../tool-attributes-misplaced-1.rs | 28 + .../tool-attributes-misplaced-1.stderr | 40 + .../tool-attributes-misplaced-2.rs | 16 + .../tool-attributes-misplaced-2.stderr | 14 + .../tool-attributes-shadowing.rs | 14 + .../tool-attributes-shadowing.stderr | 9 + .../tool_lints.rs => ui/tool_lints-fail.rs} | 0 src/test/ui/tool_lints-fail.stderr | 14 + .../trace_macros-format.rs | 0 src/test/ui/trace_macros-format.stderr | 38 + .../{compile-fail => ui}/trace_macros-gate.rs | 0 src/test/ui/trace_macros-gate.stderr | 62 + .../trait-alias.rs => ui/trait-alias-fail.rs} | 0 src/test/ui/trait-alias-fail.stderr | 44 + .../traits}/auxiliary/crate_a1.rs | 0 .../trait_bounds_on_structs_and_enums_xc.rs | 0 .../traits}/auxiliary/trait_safety_lib.rs | 0 src/test/ui/{ => traits}/trait-alias.rs | 0 src/test/ui/{ => traits}/trait-alias.stderr | 0 .../traits}/trait-as-struct-constructor.rs | 0 .../traits/trait-as-struct-constructor.stderr | 9 + .../traits}/trait-bounds-not-on-bare-trait.rs | 0 .../trait-bounds-not-on-bare-trait.stderr | 14 + .../traits}/trait-bounds-not-on-struct.rs | 0 .../traits/trait-bounds-not-on-struct.stderr | 15 + ...rait-bounds-on-structs-and-enums-in-fns.rs | 0 ...-bounds-on-structs-and-enums-in-fns.stderr | 27 + ...it-bounds-on-structs-and-enums-in-impls.rs | 0 ...ounds-on-structs-and-enums-in-impls.stderr | 15 + ...rait-bounds-on-structs-and-enums-locals.rs | 0 ...-bounds-on-structs-and-enums-locals.stderr | 27 + ...rait-bounds-on-structs-and-enums-static.rs | 0 ...-bounds-on-structs-and-enums-static.stderr | 18 + .../trait-bounds-on-structs-and-enums-xc.rs | 0 ...rait-bounds-on-structs-and-enums-xc.stderr | 19 + .../trait-bounds-on-structs-and-enums-xc1.rs | 0 ...ait-bounds-on-structs-and-enums-xc1.stderr | 19 + .../trait-bounds-on-structs-and-enums.rs | 0 .../trait-bounds-on-structs-and-enums.stderr | 90 + .../traits}/trait-bounds-sugar.rs | 0 src/test/ui/traits/trait-bounds-sugar.stderr | 12 + .../traits}/trait-coercion-generic-bad.rs | 0 .../traits/trait-coercion-generic-bad.stderr | 13 + .../trait-coercion-generic-regions.nll.stderr | 14 + .../traits}/trait-coercion-generic-regions.rs | 0 .../trait-coercion-generic-regions.stderr | 14 + .../{ => traits}/trait-duplicate-methods.rs | 0 .../trait-duplicate-methods.stderr | 0 .../traits}/trait-impl-1.rs | 0 src/test/ui/traits/trait-impl-1.stderr | 9 + ...rait-impl-can-not-have-untraitful-items.rs | 0 ...-impl-can-not-have-untraitful-items.stderr | 22 + .../trait-impl-different-num-params.rs | 0 .../trait-impl-different-num-params.stderr | 12 + .../traits}/trait-impl-for-module.rs | 0 .../ui/traits/trait-impl-for-module.stderr | 9 + .../traits}/trait-impl-method-mismatch.rs | 0 .../traits/trait-impl-method-mismatch.stderr | 15 + ...upertrait-has-wrong-lifetime-parameters.rs | 0 ...trait-has-wrong-lifetime-parameters.stderr | 23 + .../traits}/trait-item-privacy.rs | 0 src/test/ui/traits/trait-item-privacy.stderr | 176 + .../traits}/trait-matching-lifetimes.rs | 0 .../ui/traits/trait-matching-lifetimes.stderr | 41 + .../ui/{ => traits}/trait-method-private.rs | 0 .../{ => traits}/trait-method-private.stderr | 0 .../trait-object-auto-dedup-in-impl.rs | 0 .../trait-object-auto-dedup-in-impl.stderr | 0 .../traits}/trait-object-macro-matcher.rs | 0 .../traits/trait-object-macro-matcher.stderr | 18 + .../traits}/trait-object-safety.rs | 0 src/test/ui/traits/trait-object-safety.stderr | 20 + .../traits}/trait-object-vs-lifetime-2.rs | 0 .../traits/trait-object-vs-lifetime-2.stderr | 9 + .../traits}/trait-object-vs-lifetime.rs | 2 +- .../ui/traits/trait-object-vs-lifetime.stderr | 34 + .../traits}/trait-or-new-type-instead.rs | 0 .../traits/trait-or-new-type-instead.stderr | 14 + .../traits}/trait-privacy.rs | 0 src/test/ui/traits/trait-privacy.stderr | 8 + .../trait-resolution-in-overloaded-op.rs | 0 .../trait-resolution-in-overloaded-op.stderr | 11 + .../ui/{ => traits}/trait-safety-fn-body.rs | 0 .../{ => traits}/trait-safety-fn-body.stderr | 0 .../traits}/trait-safety-inherent-impl.rs | 0 .../traits/trait-safety-inherent-impl.stderr | 11 + .../traits}/trait-safety-trait-impl-cc.rs | 0 .../traits/trait-safety-trait-impl-cc.stderr | 13 + .../traits}/trait-safety-trait-impl.rs | 0 .../ui/traits/trait-safety-trait-impl.stderr | 16 + .../trait-static-method-generic-inference.rs | 0 ...ait-static-method-generic-inference.stderr | 15 + .../trait-suggest-where-clause.rs | 0 .../trait-suggest-where-clause.stderr | 8 +- .../traits}/trait-test-2.rs | 4 +- src/test/ui/traits/trait-test-2.stderr | 41 + .../{compile-fail => ui/traits}/trait-test.rs | 0 src/test/ui/traits/trait-test.stderr | 9 + .../traits-assoc-type-in-supertrait-bad.rs | 0 ...traits-assoc-type-in-supertrait-bad.stderr | 12 + .../traits-inductive-overflow-simultaneous.rs | 0 ...its-inductive-overflow-simultaneous.stderr | 16 + ...its-inductive-overflow-supertrait-oibit.rs | 0 ...inductive-overflow-supertrait-oibit.stderr | 23 + .../traits-inductive-overflow-supertrait.rs | 0 ...raits-inductive-overflow-supertrait.stderr | 16 + .../traits-inductive-overflow-two-traits.rs | 0 ...raits-inductive-overflow-two-traits.stderr | 15 + .../traits}/traits-issue-23003-overflow.rs | 0 .../traits/traits-issue-23003-overflow.stderr | 8 + .../traits}/traits-multidispatch-bad.rs | 0 .../ui/traits/traits-multidispatch-bad.stderr | 9 + ...traits-multidispatch-convert-ambig-dest.rs | 0 ...ts-multidispatch-convert-ambig-dest.stderr | 0 .../traits}/traits-negative-impls.rs | 0 .../ui/traits/traits-negative-impls.stderr | 101 + .../traits-repeated-supertrait-ambig.rs | 0 .../traits-repeated-supertrait-ambig.stderr | 52 + .../transmute}/transmute-different-sizes.rs | 2 + .../transmute-different-sizes.stderr | 30 + .../transmute}/transmute-fat-pointers.rs | 2 + .../transmute/transmute-fat-pointers.stderr | 39 + .../transmute}/transmute-impl.rs | 2 + src/test/ui/transmute/transmute-impl.stderr | 12 + .../transmute}/transmute-imut-to-mut.rs | 0 .../ui/transmute/transmute-imut-to-mut.stderr | 10 + ...ounds-inconsistent-associated-functions.rs | 0 ...unds-inconsistent-copy-reborrow.nll.stderr | 4 +- ...ivial-bounds-inconsistent-copy-reborrow.rs | 0 ...l-bounds-inconsistent-copy-reborrow.stderr | 0 .../trivial-bounds-inconsistent-copy.rs | 0 .../trivial-bounds-inconsistent-copy.stderr | 0 ...al-bounds-inconsistent-projection-error.rs | 0 ...ounds-inconsistent-projection-error.stderr | 0 .../trivial-bounds-inconsistent-projection.rs | 0 ...vial-bounds-inconsistent-projection.stderr | 0 .../trivial-bounds-inconsistent-sized.rs | 0 .../trivial-bounds-inconsistent-sized.stderr | 0 ...trivial-bounds-inconsistent-well-formed.rs | 0 ...ial-bounds-inconsistent-well-formed.stderr | 0 .../trivial-bounds-inconsistent.rs | 0 .../trivial-bounds-inconsistent.stderr | 0 .../trivial-bounds-leak-copy.rs | 0 .../trivial-bounds-leak-copy.stderr | 0 .../trivial-bounds-leak.rs | 0 .../trivial-bounds-leak.stderr | 2 +- .../trivial-bounds-lint.rs | 0 .../trivial-bounds-lint.stderr | 0 .../trivial-bounds-object.rs | 0 .../{compile-fail => ui}/trivial_casts.rs | 0 src/test/ui/trivial_casts.stderr | 164 + .../ui/try-block/try-block-bad-lifetime.rs | 48 + .../try-block/try-block-bad-lifetime.stderr | 51 + src/test/ui/try-block/try-block-bad-type.rs | 30 + .../ui/try-block/try-block-bad-type.stderr | 52 + .../ui/try-block/try-block-in-edition2015.rs | 20 + .../try-block/try-block-in-edition2015.stderr | 18 + src/test/ui/try-block/try-block-in-match.rs | 17 + .../ui/try-block/try-block-in-match.stderr | 8 + src/test/ui/try-block/try-block-in-while.rs | 17 + .../ui/try-block/try-block-in-while.stderr | 8 + .../try-block/try-block-maybe-bad-lifetime.rs | 55 + .../try-block-maybe-bad-lifetime.stderr | 39 + src/test/ui/try-block/try-block-opt-init.rs | 27 + .../ui/try-block/try-block-opt-init.stderr | 11 + src/test/ui/try-block/try-block-type-error.rs | 28 + .../ui/try-block/try-block-type-error.stderr | 24 + src/test/ui/tuple-struct-fields/test.rs | 17 - src/test/ui/tuple-struct-fields/test.stderr | 20 - .../tuple}/tuple-arity-mismatch.rs | 0 src/test/ui/tuple/tuple-arity-mismatch.stderr | 21 + .../ui/{ => tuple}/tuple-float-index.fixed | 0 src/test/ui/{ => tuple}/tuple-float-index.rs | 0 .../ui/{ => tuple}/tuple-float-index.stderr | 0 .../tuple}/tuple-index-not-tuple.rs | 0 .../ui/tuple/tuple-index-not-tuple.stderr | 15 + .../tuple}/tuple-index-out-of-bounds.rs | 0 .../ui/tuple/tuple-index-out-of-bounds.stderr | 15 + src/test/ui/tuple/tuple-struct-fields/test.rs | 19 + .../ui/tuple/tuple-struct-fields/test.stderr | 15 + .../{ => tuple}/tuple-struct-fields/test2.rs | 0 .../tuple-struct-fields/test2.stderr | 0 .../{ => tuple}/tuple-struct-fields/test3.rs | 0 .../tuple-struct-fields/test3.stderr | 0 .../tuple}/tuple-struct-nonexhaustive.rs | 0 .../tuple/tuple-struct-nonexhaustive.stderr | 9 + .../tutorial-suffix-inference-test.rs | 0 .../ui/tutorial-suffix-inference-test.stderr | 25 + src/test/ui/type/auxiliary/crate_a1.rs | 21 + .../type}/auxiliary/crate_a2.rs | 0 src/test/ui/{ => type}/type-alias-bounds.rs | 0 .../ui/{ => type}/type-alias-bounds.stderr | 0 .../ui/{ => type}/type-annotation-needed.rs | 0 .../{ => type}/type-annotation-needed.stderr | 0 .../type}/type-arg-out-of-scope.rs | 0 src/test/ui/type/type-arg-out-of-scope.stderr | 23 + .../type-ascription-instead-of-initializer.rs | 0 ...e-ascription-instead-of-initializer.stderr | 0 ...ype-ascription-instead-of-statement-end.rs | 0 ...ascription-instead-of-statement-end.stderr | 0 .../type}/type-ascription-precedence.rs | 0 .../ui/type/type-ascription-precedence.stderr | 72 + .../type}/type-ascription-soundness.rs | 0 .../ui/type/type-ascription-soundness.stderr | 39 + .../type-ascription-with-fn-call.rs | 0 .../type-ascription-with-fn-call.stderr | 0 src/test/ui/{ => type}/type-check-defaults.rs | 0 .../ui/{ => type}/type-check-defaults.stderr | 0 .../{ => type}/type-check/assignment-in-if.rs | 0 .../type-check/assignment-in-if.stderr | 0 .../type-check/cannot_infer_local_or_array.rs | 0 .../cannot_infer_local_or_array.stderr | 0 .../type-check/cannot_infer_local_or_vec.rs | 0 .../cannot_infer_local_or_vec.stderr | 0 .../cannot_infer_local_or_vec_in_tuples.rs | 0 ...cannot_infer_local_or_vec_in_tuples.stderr | 0 .../ui/{ => type}/type-check/issue-22897.rs | 0 .../{ => type}/type-check/issue-22897.stderr | 0 .../ui/{ => type}/type-check/issue-40294.rs | 0 .../{ => type}/type-check/issue-40294.stderr | 0 .../ui/{ => type}/type-check/issue-41314.rs | 0 .../{ => type}/type-check/issue-41314.stderr | 0 .../type-check/missing_trait_impl.rs | 0 .../type-check/missing_trait_impl.stderr | 0 .../type-check/unknown_type_for_closure.rs | 0 .../unknown_type_for_closure.stderr | 0 .../type-dependent-def-issue-49241.rs | 0 .../type-dependent-def-issue-49241.stderr | 0 .../type}/type-mismatch-multiple.rs | 0 .../ui/type/type-mismatch-multiple.stderr | 18 + .../type}/type-mismatch-same-crate-name.rs | 0 .../type/type-mismatch-same-crate-name.stderr | 31 + src/test/ui/{ => type}/type-mismatch.rs | 0 src/test/ui/{ => type}/type-mismatch.stderr | 0 ...rameter-defaults-referencing-Self-ppaux.rs | 0 ...ter-defaults-referencing-Self-ppaux.stderr | 24 + ...ype-parameter-defaults-referencing-Self.rs | 0 ...parameter-defaults-referencing-Self.stderr | 11 + .../type}/type-parameter-names.rs | 0 src/test/ui/type/type-parameter-names.stderr | 14 + .../type-params-in-different-spaces-1.rs | 0 .../type-params-in-different-spaces-1.stderr | 12 + .../type-params-in-different-spaces-2.rs | 0 .../type-params-in-different-spaces-2.stderr | 29 + .../type-params-in-different-spaces-3.rs | 0 .../type-params-in-different-spaces-3.stderr | 14 + .../type}/type-path-err-node-types.rs | 0 .../ui/type/type-path-err-node-types.stderr | 28 + src/test/ui/{ => type}/type-recursive.rs | 0 src/test/ui/{ => type}/type-recursive.stderr | 0 .../{compile-fail => ui/type}/type-shadow.rs | 0 src/test/ui/type/type-shadow.stderr | 12 + .../{compile-fail => ui}/type_length_limit.rs | 0 src/test/ui/type_length_limit.stderr | 6 + ...ypeck-builtin-bound-type-parameters.stderr | 40 - .../typeck}/auxiliary/tdticc_coherence_lib.rs | 0 .../typeck-auto-trait-no-supertraits-2.rs | 0 .../typeck-auto-trait-no-supertraits-2.stderr | 9 + .../typeck-auto-trait-no-supertraits.rs | 0 .../typeck-auto-trait-no-supertraits.stderr | 9 + .../typeck-builtin-bound-type-parameters.rs | 12 +- ...ypeck-builtin-bound-type-parameters.stderr | 39 + .../typeck}/typeck-cast-pointer-to-float.rs | 0 .../typeck-cast-pointer-to-float.stderr | 9 + .../typeck-default-trait-impl-assoc-type.rs | 0 ...ypeck-default-trait-impl-assoc-type.stderr | 17 + ...-default-trait-impl-constituent-types-2.rs | 0 ...ault-trait-impl-constituent-types-2.stderr | 18 + ...ck-default-trait-impl-constituent-types.rs | 0 ...efault-trait-impl-constituent-types.stderr | 17 + ...efault-trait-impl-cross-crate-coherence.rs | 0 ...lt-trait-impl-cross-crate-coherence.stderr | 37 + ...typeck-default-trait-impl-negation-send.rs | 0 ...ck-default-trait-impl-negation-send.stderr | 16 + ...typeck-default-trait-impl-negation-sync.rs | 0 ...ck-default-trait-impl-negation-sync.stderr | 44 + .../typeck-default-trait-impl-negation.rs | 0 .../typeck-default-trait-impl-negation.stderr | 31 + .../typeck-default-trait-impl-precedence.rs | 0 ...ypeck-default-trait-impl-precedence.stderr | 16 + .../typeck-default-trait-impl-send-param.rs | 0 ...ypeck-default-trait-impl-send-param.stderr | 17 + .../typeck}/typeck-negative-impls-builtin.rs | 0 .../typeck-negative-impls-builtin.stderr | 9 + .../typeck}/typeck-unsafe-always-share.rs | 0 .../typeck/typeck-unsafe-always-share.stderr | 56 + .../typeck_type_placeholder_item.rs | 0 .../typeck_type_placeholder_item.stderr | 36 +- .../typeck_type_placeholder_lifetime_1.rs | 2 +- .../typeck_type_placeholder_lifetime_1.stderr | 9 + .../typeck_type_placeholder_lifetime_2.rs | 2 +- .../typeck_type_placeholder_lifetime_2.stderr | 9 + .../typeck_type_placeholder_mismatch.rs | 0 .../typeck_type_placeholder_mismatch.stderr | 21 + .../typeck_type_placeholder_lifetime_1.stderr | 9 - .../typeck_type_placeholder_lifetime_2.stderr | 9 - .../ufcs}/ufcs-explicit-self-bad.rs | 0 .../ui/ufcs/ufcs-explicit-self-bad.stderr | 107 + .../ufcs}/ufcs-partially-resolved.rs | 0 .../ui/ufcs/ufcs-partially-resolved.stderr | 206 + .../ufcs}/ufcs-qpath-missing-params.rs | 2 +- .../ui/ufcs/ufcs-qpath-missing-params.stderr | 9 + .../ufcs}/ufcs-qpath-self-mismatch.rs | 0 .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 24 + .../unboxed-closure-sugar-wrong-trait.stderr | 16 - .../unboxed-closure-feature-gate.rs | 0 .../unboxed-closure-feature-gate.stderr | 11 + .../unboxed-closure-illegal-move.nll.stderr | 35 + .../unboxed-closure-illegal-move.rs | 0 .../unboxed-closure-illegal-move.stderr | 35 + ...boxed-closure-immutable-capture.nll.stderr | 75 + .../unboxed-closure-immutable-capture.rs | 0 .../unboxed-closure-immutable-capture.stderr | 69 + .../unboxed-closure-no-cyclic-sig.rs | 0 .../unboxed-closure-no-cyclic-sig.stderr | 0 .../unboxed-closure-region.nll.stderr | 15 + .../unboxed-closure-region.rs | 3 + .../unboxed-closure-region.stderr | 16 + .../unboxed-closure-sugar-default.rs | 0 .../unboxed-closure-sugar-default.stderr | 15 + .../unboxed-closure-sugar-equiv.rs | 0 .../unboxed-closure-sugar-equiv.stderr | 16 + .../unboxed-closure-sugar-lifetime-elision.rs | 0 ...oxed-closure-sugar-lifetime-elision.stderr | 11 + .../unboxed-closure-sugar-not-used-on-fn.rs | 0 ...nboxed-closure-sugar-not-used-on-fn.stderr | 19 + .../unboxed-closure-sugar-region.rs | 2 +- .../unboxed-closure-sugar-region.stderr | 9 + .../unboxed-closure-sugar-used-on-struct-1.rs | 0 ...oxed-closure-sugar-used-on-struct-1.stderr | 9 + .../unboxed-closure-sugar-used-on-struct-3.rs | 0 ...oxed-closure-sugar-used-on-struct-3.stderr | 9 + .../unboxed-closure-sugar-used-on-struct.rs | 0 ...nboxed-closure-sugar-used-on-struct.stderr | 16 + ...r-wrong-number-number-type-parameters-1.rs | 0 ...ong-number-number-type-parameters-1.stderr | 9 + ...r-wrong-number-number-type-parameters-3.rs | 0 ...ong-number-number-type-parameters-3.stderr | 16 + ...gar-wrong-number-number-type-parameters.rs | 0 ...wrong-number-number-type-parameters.stderr | 16 + .../unboxed-closure-sugar-wrong-trait.rs | 2 +- .../unboxed-closure-sugar-wrong-trait.stderr | 16 + ...nboxed-closures-borrow-conflict.nll.stderr | 15 + .../unboxed-closures-borrow-conflict.rs | 3 + .../unboxed-closures-borrow-conflict.stderr | 11 + ...-closures-failed-recursive-fn-1.nll.stderr | 62 + .../unboxed-closures-failed-recursive-fn-1.rs | 0 ...oxed-closures-failed-recursive-fn-1.stderr | 30 + .../unboxed-closures-failed-recursive-fn-2.rs | 0 ...oxed-closures-failed-recursive-fn-2.stderr | 14 + .../unboxed-closures-fnmut-as-fn.rs | 0 .../unboxed-closures-fnmut-as-fn.stderr | 16 + ...ument-types-two-region-pointers.nll.stderr | 12 + ...nfer-argument-types-two-region-pointers.rs | 0 ...-argument-types-two-region-pointers.stderr | 26 + ...ures-infer-fn-once-move-from-projection.rs | 0 ...-infer-fn-once-move-from-projection.stderr | 0 ...nfer-fnmut-calling-fnmut-no-mut.nll.stderr | 21 + ...osures-infer-fnmut-calling-fnmut-no-mut.rs | 0 ...es-infer-fnmut-calling-fnmut-no-mut.stderr | 22 + ...losures-infer-fnmut-missing-mut.nll.stderr | 11 + ...nboxed-closures-infer-fnmut-missing-mut.rs | 0 ...ed-closures-infer-fnmut-missing-mut.stderr | 11 + ...es-infer-fnmut-move-missing-mut.nll.stderr | 11 + ...d-closures-infer-fnmut-move-missing-mut.rs | 0 ...osures-infer-fnmut-move-missing-mut.stderr | 11 + ...losures-infer-fnonce-call-twice.nll.stderr | 11 + ...nboxed-closures-infer-fnonce-call-twice.rs | 0 ...ed-closures-infer-fnonce-call-twice.stderr | 17 + ...es-infer-fnonce-move-call-twice.nll.stderr | 11 + ...d-closures-infer-fnonce-move-call-twice.rs | 0 ...osures-infer-fnonce-move-call-twice.stderr | 17 + .../unboxed-closures-mutate-upvar.nll.stderr | 45 + .../unboxed-closures-mutate-upvar.rs | 0 .../unboxed-closures-mutate-upvar.stderr | 53 + ...tated-upvar-from-fn-closure.ast.nll.stderr | 20 + ...s-mutated-upvar-from-fn-closure.ast.stderr | 20 + ...s-mutated-upvar-from-fn-closure.mir.stderr | 20 + ...-closures-mutated-upvar-from-fn-closure.rs | 0 ...sures-recursive-fn-using-fn-mut.nll.stderr | 13 + ...oxed-closures-recursive-fn-using-fn-mut.rs | 0 ...-closures-recursive-fn-using-fn-mut.stderr | 12 + ...nboxed-closures-static-call-wrong-trait.rs | 0 ...ed-closures-static-call-wrong-trait.stderr | 11 + .../unboxed-closures-type-mismatch.rs | 0 .../unboxed-closures-type-mismatch.stderr | 9 + .../unboxed-closures-unsafe-extern-fn.rs | 0 .../unboxed-closures-unsafe-extern-fn.stderr | 42 + .../unboxed-closures-wrong-abi.rs | 0 .../unboxed-closures-wrong-abi.stderr | 42 + ...boxed-closures-wrong-arg-type-extern-fn.rs | 0 ...d-closures-wrong-arg-type-extern-fn.stderr | 42 + .../dyn-trait-underscore.nll.stderr | 37 +- .../underscore-lifetime-binders.rs | 0 .../underscore-lifetime-binders.stderr | 45 + ...rscore-lifetime-elison-mismatch.nll.stderr | 11 + .../underscore-lifetime-elison-mismatch.rs | 0 ...underscore-lifetime-elison-mismatch.stderr | 11 + .../uninhabited}/uninhabited-enum-cast.rs | 0 .../uninhabited/uninhabited-enum-cast.stderr | 11 + .../uninhabited}/uninhabited-irrefutable.rs | 0 .../uninhabited-irrefutable.stderr | 9 + .../uninhabited-matches-feature-gated.rs | 0 .../uninhabited-matches-feature-gated.stderr | 64 + .../uninhabited}/uninhabited-patterns.rs | 0 .../uninhabited/uninhabited-patterns.stderr | 38 + src/test/ui/union-ub-fat-ptr.rs | 139 + src/test/ui/union-ub-fat-ptr.stderr | 115 + ...nion-borrow-move-parent-sibling.nll.stderr | 33 + .../union/union-borrow-move-parent-sibling.rs | 0 .../union-borrow-move-parent-sibling.stderr | 64 + src/test/ui/union/union-const-eval.rs | 1 + .../union/union-const-pat.rs | 0 src/test/ui/union/union-const-pat.stderr | 8 + .../{compile-fail => ui}/union/union-copy.rs | 0 src/test/ui/union/union-copy.stderr | 12 + .../union/union-derive-clone.rs | 0 src/test/ui/union/union-derive-clone.stderr | 27 + .../union/union-derive.rs | 0 src/test/ui/union/union-derive.stderr | 38 + .../{compile-fail => ui}/union/union-empty.rs | 0 src/test/ui/union/union-empty.stderr | 8 + .../union/union-generic.rs | 0 src/test/ui/union/union-generic.stderr | 27 + .../union/union-lint-dead-code.rs | 0 src/test/ui/union/union-lint-dead-code.stderr | 14 + .../union/union-nonrepresentable.rs | 0 .../ui/union/union-nonrepresentable.stderr | 14 + .../union/union-repr-c.rs | 0 src/test/ui/union/union-repr-c.stderr | 22 + src/test/ui/union/union-sized-field.stderr | 6 +- .../union/union-unsafe.rs | 0 src/test/ui/union/union-unsafe.stderr | 51 + .../union/union-unsized.rs | 0 src/test/ui/union/union-unsized.stderr | 23 + .../union/union-with-drop-fields-lint.rs | 0 .../union/union-with-drop-fields-lint.stderr | 26 + .../unique-object-noncopyable.rs | 0 src/test/ui/unique-object-noncopyable.stderr | 15 + .../unique-pinned-nocopy.rs | 0 src/test/ui/unique-pinned-nocopy.stderr | 15 + .../unknown-lint-tool-name.rs | 0 src/test/ui/unknown-lint-tool-name.stderr | 15 + src/test/ui/unknown-tool-name.rs | 12 + src/test/ui/unknown-tool-name.stderr | 9 + src/test/ui/unop-move-semantics.nll.stderr | 27 + .../unop-move-semantics.rs | 0 src/test/ui/unop-move-semantics.stderr | 45 + .../{compile-fail => ui}/unop-neg-bool.rs | 0 src/test/ui/unop-neg-bool.stderr | 11 + .../auxiliary/unreachable_variant.rs | 0 .../unreachable}/unreachable-arm.rs | 0 .../ui/unreachable/unreachable-arm.stderr | 14 + .../unreachable}/unreachable-code.rs | 0 .../ui/unreachable/unreachable-code.stderr | 14 + .../unreachable}/unreachable-in-call.rs | 0 .../ui/unreachable/unreachable-in-call.stderr | 22 + .../unreachable}/unreachable-loop-patterns.rs | 0 .../unreachable-loop-patterns.stderr | 14 + .../unreachable}/unreachable-try-pattern.rs | 0 .../unreachable-try-pattern.stderr | 43 + .../unreachable}/unreachable-variant.rs | 0 .../ui/unreachable/unreachable-variant.stderr | 9 + .../unresolved-extern-mod-suggestion.rs | 0 .../unresolved-extern-mod-suggestion.stderr | 17 + .../unresolved}/unresolved-import-recovery.rs | 0 .../unresolved-import-recovery.stderr | 9 + .../unresolved}/unresolved-import.rs | 2 + .../ui/unresolved/unresolved-import.stderr | 39 + src/test/ui/unrestricted-attribute-tokens.rs | 16 + ...unsafe-around-compiler-generated-unsafe.rs | 0 ...fe-around-compiler-generated-unsafe.stderr | 14 + .../unsafe-block-without-braces.rs | 0 .../unsafe-block-without-braces.stderr | 0 src/test/ui/{ => unsafe}/unsafe-const-fn.rs | 2 +- .../ui/{ => unsafe}/unsafe-const-fn.stderr | 0 .../unsafe}/unsafe-fn-assign-deref-ptr.rs | 0 .../unsafe/unsafe-fn-assign-deref-ptr.stderr | 11 + .../unsafe}/unsafe-fn-autoderef.rs | 0 src/test/ui/unsafe/unsafe-fn-autoderef.stderr | 9 + .../unsafe}/unsafe-fn-called-from-safe.rs | 0 .../unsafe/unsafe-fn-called-from-safe.stderr | 11 + .../unsafe}/unsafe-fn-deref-ptr.rs | 0 src/test/ui/unsafe/unsafe-fn-deref-ptr.stderr | 11 + .../unsafe}/unsafe-fn-used-as-value.rs | 0 .../ui/unsafe/unsafe-fn-used-as-value.stderr | 11 + .../unsafe}/unsafe-move-val-init.rs | 0 .../ui/unsafe/unsafe-move-val-init.stderr | 11 + .../unsafe}/unsafe-subtyping.rs | 0 src/test/ui/unsafe/unsafe-subtyping.stderr | 14 + .../unsafe}/unsafe-trait-impl.rs | 0 src/test/ui/unsafe/unsafe-trait-impl.stderr | 15 + .../unsized}/unsized-bare-typaram.rs | 0 .../ui/unsized/unsized-bare-typaram.stderr | 18 + .../unsized}/unsized-enum.rs | 0 src/test/ui/unsized/unsized-enum.stderr | 18 + src/test/ui/{ => unsized}/unsized-enum2.rs | 0 .../ui/{ => unsized}/unsized-enum2.stderr | 40 +- .../unsized-inherent-impl-self-type.rs | 0 .../unsized-inherent-impl-self-type.stderr | 18 + .../unsized}/unsized-struct.rs | 0 src/test/ui/unsized/unsized-struct.stderr | 34 + .../unsized}/unsized-trait-impl-self-type.rs | 0 .../unsized-trait-impl-self-type.stderr | 18 + .../unsized}/unsized-trait-impl-trait-arg.rs | 0 .../unsized-trait-impl-trait-arg.stderr | 13 + src/test/{compile-fail => ui}/unsized3.rs | 0 src/test/ui/unsized3.stderr | 91 + src/test/{compile-fail => ui}/unsized5.rs | 0 src/test/ui/unsized5.stderr | 67 + src/test/{compile-fail => ui}/unsized6.rs | 0 src/test/ui/unsized6.stderr | 156 + src/test/{compile-fail => ui}/unsized7.rs | 0 src/test/ui/unsized7.stderr | 13 + .../unspecified-self-in-trait-ref.rs | 0 .../ui/unspecified-self-in-trait-ref.stderr | 36 + .../{compile-fail => ui}/unsupported-cast.rs | 0 src/test/ui/unsupported-cast.stderr | 9 + .../unused}/unused-attr.rs | 0 src/test/ui/unused/unused-attr.stderr | 98 + .../unused}/unused-macro-rules.rs | 0 src/test/ui/unused/unused-macro-rules.stderr | 41 + .../unused-macro-with-bad-frag-spec.rs | 0 .../unused-macro-with-bad-frag-spec.stderr | 10 + .../unused-macro-with-follow-violation.rs | 0 .../unused-macro-with-follow-violation.stderr | 8 + .../unused}/unused-macro.rs | 0 src/test/ui/unused/unused-macro.stderr | 38 + .../unused-mut-warning-captured-var.rs | 0 .../unused-mut-warning-captured-var.stderr | 16 + .../unused}/unused-result.rs | 0 src/test/ui/unused/unused-result.stderr | 48 + src/test/ui/use-self-in-inner-fn.rs | 24 + src/test/ui/use-self-in-inner-fn.stderr | 15 + .../use}/auxiliary/use_from_trait_xc.rs | 0 .../use-after-move-based-on-type.nll.stderr | 13 + .../use}/use-after-move-based-on-type.rs | 0 .../use/use-after-move-based-on-type.stderr | 13 + ...r-move-implicity-coerced-object.nll.stderr | 13 + ...use-after-move-implicity-coerced-object.rs | 0 ...after-move-implicity-coerced-object.stderr | 13 + .../use}/use-after-move-self-based-on-type.rs | 0 .../use-after-move-self-based-on-type.stderr | 13 + .../ui/use/use-after-move-self.nll.stderr | 11 + .../use}/use-after-move-self.rs | 0 src/test/ui/use/use-after-move-self.stderr | 13 + .../use}/use-from-trait-xc.rs | 0 src/test/ui/use/use-from-trait-xc.stderr | 58 + .../use}/use-from-trait.rs | 0 src/test/ui/use/use-from-trait.stderr | 34 + .../{compile-fail => ui/use}/use-keyword.rs | 0 src/test/ui/use/use-keyword.stderr | 22 + .../use}/use-meta-mismatch.rs | 0 src/test/ui/use/use-meta-mismatch.stderr | 9 + src/test/ui/{ => use}/use-mod.rs | 0 src/test/ui/{ => use}/use-mod.stderr | 0 .../use/use-mod}/use-mod-2.rs | 0 src/test/ui/use/use-mod/use-mod-2.stderr | 15 + .../use/use-mod}/use-mod-3.rs | 0 src/test/ui/use/use-mod/use-mod-3.stderr | 15 + .../use/use-mod}/use-mod-4.rs | 0 src/test/ui/use/use-mod/use-mod-4.stderr | 22 + .../ui/{ => use}/use-nested-groups-error.rs | 0 .../{ => use}/use-nested-groups-error.stderr | 0 .../use-nested-groups-unused-imports.rs | 0 .../use-nested-groups-unused-imports.stderr | 0 .../use}/use-paths-as-items.rs | 0 src/test/ui/use/use-paths-as-items.stderr | 17 + .../{compile-fail => ui/use}/use-self-type.rs | 0 src/test/ui/use/use-self-type.stderr | 16 + .../use}/use-super-global-path.rs | 0 src/test/ui/use/use-super-global-path.stderr | 26 + src/test/{compile-fail => ui}/used.rs | 2 - src/test/ui/used.stderr | 26 + src/test/{compile-fail => ui}/useless-pub.rs | 0 src/test/ui/useless-pub.stderr | 21 + .../{compile-fail => ui}/useless_comment.rs | 0 src/test/ui/useless_comment.stderr | 32 + .../user-defined-macro-rules.rs | 2 + src/test/ui/user-defined-macro-rules.stderr | 8 + src/test/{compile-fail => ui}/utf8_idents.rs | 0 src/test/ui/utf8_idents.stderr | 35 + .../variadic}/variadic-ffi-2.rs | 2 +- src/test/ui/variadic/variadic-ffi-2.stderr | 9 + src/test/ui/{ => variadic}/variadic-ffi-3.rs | 0 .../ui/{ => variadic}/variadic-ffi-3.stderr | 0 .../variadic}/variadic-ffi.rs | 4 +- src/test/ui/variadic/variadic-ffi.stderr | 9 + .../variance}/variance-associated-types.rs | 0 .../variance/variance-associated-types.stderr | 19 + .../variance-btree-invariant-types.nll.stderr | 106 + .../variance-btree-invariant-types.rs | 0 .../variance-btree-invariant-types.stderr | 183 + .../variance}/variance-cell-is-invariant.rs | 2 + .../variance-cell-is-invariant.stderr | 15 + ...riance-contravariant-arg-object.nll.stderr | 24 + .../variance-contravariant-arg-object.rs | 0 .../variance-contravariant-arg-object.stderr | 41 + .../variance-contravariant-arg-trait-match.rs | 2 + ...iance-contravariant-arg-trait-match.stderr | 41 + ...variance-contravariant-self-trait-match.rs | 2 + ...ance-contravariant-self-trait-match.stderr | 41 + .../variance-covariant-arg-object.nll.stderr | 24 + .../variance-covariant-arg-object.rs | 0 .../variance-covariant-arg-object.stderr | 41 + .../variance-covariant-arg-trait-match.rs | 2 + .../variance-covariant-arg-trait-match.stderr | 41 + .../variance-covariant-self-trait-match.rs | 2 + ...variance-covariant-self-trait-match.stderr | 41 + .../variance-invariant-arg-object.nll.stderr | 24 + .../variance-invariant-arg-object.rs | 0 .../variance-invariant-arg-object.stderr | 41 + .../variance-invariant-arg-trait-match.rs | 2 + .../variance-invariant-arg-trait-match.stderr | 41 + .../variance-invariant-self-trait-match.rs | 2 + ...variance-invariant-self-trait-match.stderr | 41 + .../variance/variance-issue-20533.nll.stderr | 33 + .../variance}/variance-issue-20533.rs | 0 .../ui/variance/variance-issue-20533.stderr | 27 + .../variance}/variance-object-types.rs | 0 .../ui/variance/variance-object-types.stderr | 11 + .../variance}/variance-regions-direct.rs | 0 .../variance/variance-regions-direct.stderr | 65 + .../variance}/variance-regions-indirect.rs | 0 .../variance/variance-regions-indirect.stderr | 45 + .../variance-regions-unused-direct.rs | 0 .../variance-regions-unused-direct.stderr | 19 + .../variance-regions-unused-indirect.rs | 0 .../variance-regions-unused-indirect.stderr | 19 + .../variance}/variance-trait-bounds.rs | 0 .../ui/variance/variance-trait-bounds.stderr | 35 + .../variance-trait-matching.nll.stderr | 12 + .../variance}/variance-trait-matching.rs | 0 .../variance/variance-trait-matching.stderr | 12 + .../variance}/variance-trait-object-bound.rs | 0 .../variance-trait-object-bound.stderr | 11 + .../variance}/variance-types-bounds.rs | 0 .../ui/variance/variance-types-bounds.stderr | 47 + .../variance}/variance-types.rs | 0 src/test/ui/variance/variance-types.stderr | 53 + .../variance}/variance-unused-region-param.rs | 0 .../variance-unused-region-param.stderr | 19 + .../variance-unused-type-param.rs | 0 .../variance-unused-type-param.stderr | 0 ...ance-use-contravariant-struct-1.nll.stderr | 13 + .../variance-use-contravariant-struct-1.rs | 0 ...variance-use-contravariant-struct-1.stderr | 22 + .../variance-use-contravariant-struct-2.rs | 0 ...variance-use-contravariant-struct-2.stderr | 8 + ...variance-use-covariant-struct-1.nll.stderr | 13 + .../variance-use-covariant-struct-1.rs | 0 .../variance-use-covariant-struct-1.stderr | 22 + .../variance-use-covariant-struct-2.rs | 0 .../variance-use-covariant-struct-2.stderr | 8 + ...variance-use-invariant-struct-1.nll.stderr | 24 + .../variance-use-invariant-struct-1.rs | 0 .../variance-use-invariant-struct-1.stderr | 41 + .../auxiliary/variant-namespacing.rs | 0 .../variants}/variant-namespacing.rs | 0 .../ui/variants/variant-namespacing.stderr | 93 + .../variants}/variant-size-differences.rs | 0 .../variants/variant-size-differences.stderr | 14 + .../variants}/variant-used-as-type.rs | 0 .../ui/variants/variant-used-as-type.stderr | 31 + .../vec}/vec-macro-with-comma-only.rs | 0 .../ui/vec/vec-macro-with-comma-only.stderr | 8 + .../ui/vec/vec-mut-iter-borrow.nll.stderr | 14 + .../vec}/vec-mut-iter-borrow.rs | 0 src/test/ui/vec/vec-mut-iter-borrow.stderr | 14 + .../{compile-fail => ui/vec}/vec-res-add.rs | 0 src/test/ui/vec/vec-res-add.stderr | 11 + .../vector-cast-weirdness.rs | 0 src/test/ui/vector-cast-weirdness.stderr | 9 + .../vtable-res-trait-param.rs | 0 src/test/ui/vtable-res-trait-param.stderr | 9 + .../ui/walk-struct-literal-with.nll.stderr | 13 + .../walk-struct-literal-with.rs | 0 src/test/ui/walk-struct-literal-with.stderr | 13 + .../warn-path-statement.rs | 0 src/test/ui/warn-path-statement.stderr | 10 + .../ui/wasm-custom-section-relocations.rs | 2 + .../ui/wasm-custom-section-relocations.stderr | 7 +- .../wf}/wf-array-elem-sized.rs | 0 src/test/ui/wf/wf-array-elem-sized.stderr | 13 + .../{compile-fail => ui/wf}/wf-const-type.rs | 0 src/test/ui/wf/wf-const-type.stderr | 16 + .../{compile-fail => ui/wf}/wf-enum-bound.rs | 0 src/test/ui/wf/wf-enum-bound.stderr | 20 + .../wf}/wf-enum-fields-struct-variant.rs | 0 .../wf/wf-enum-fields-struct-variant.stderr | 16 + .../{compile-fail => ui/wf}/wf-enum-fields.rs | 0 src/test/ui/wf/wf-enum-fields.stderr | 16 + .../wf}/wf-fn-where-clause.rs | 5 +- src/test/ui/wf/wf-fn-where-clause.stderr | 37 + .../wf}/wf-impl-associated-type-region.rs | 0 .../wf/wf-impl-associated-type-region.stderr | 17 + .../wf}/wf-impl-associated-type-trait.rs | 0 .../wf/wf-impl-associated-type-trait.stderr | 16 + .../{compile-fail => ui/wf}/wf-in-fn-arg.rs | 0 src/test/ui/wf/wf-in-fn-arg.stderr | 18 + .../{compile-fail => ui/wf}/wf-in-fn-ret.rs | 0 src/test/ui/wf/wf-in-fn-ret.stderr | 18 + .../wf}/wf-in-fn-type-arg.rs | 0 src/test/ui/wf/wf-in-fn-type-arg.stderr | 16 + .../wf}/wf-in-fn-type-ret.rs | 0 src/test/ui/wf/wf-in-fn-type-ret.stderr | 16 + .../wf}/wf-in-fn-type-static.rs | 0 src/test/ui/wf/wf-in-fn-type-static.stderr | 33 + .../wf}/wf-in-fn-where-clause.rs | 0 src/test/ui/wf/wf-in-fn-where-clause.stderr | 19 + .../wf}/wf-in-obj-type-static.rs | 0 src/test/ui/wf/wf-in-obj-type-static.stderr | 18 + .../wf}/wf-in-obj-type-trait.rs | 0 src/test/ui/wf/wf-in-obj-type-trait.stderr | 16 + .../wf-inherent-impl-method-where-clause.rs | 0 ...f-inherent-impl-method-where-clause.stderr | 17 + .../wf}/wf-inherent-impl-where-clause.rs | 0 .../wf/wf-inherent-impl-where-clause.stderr | 18 + .../wf/wf-misc-methods-issue-28609.nll.stderr | 111 + .../wf}/wf-misc-methods-issue-28609.rs | 0 .../ui/wf/wf-misc-methods-issue-28609.stderr | 111 + .../{compile-fail => ui/wf}/wf-object-safe.rs | 0 src/test/ui/wf/wf-object-safe.stderr | 11 + .../ui/wf/wf-outlives-ty-in-fn-or-trait.rs | 33 + .../wf/wf-outlives-ty-in-fn-or-trait.stderr | 31 + src/test/ui/wf/wf-static-method.nll.stderr | 24 + .../wf}/wf-static-method.rs | 0 src/test/ui/wf/wf-static-method.stderr | 109 + .../{compile-fail => ui/wf}/wf-static-type.rs | 0 src/test/ui/wf/wf-static-type.stderr | 16 + .../wf}/wf-struct-bound.rs | 0 src/test/ui/wf/wf-struct-bound.stderr | 20 + .../wf}/wf-struct-field.rs | 0 src/test/ui/wf/wf-struct-field.stderr | 16 + .../wf}/wf-trait-associated-type-bound.rs | 0 .../wf/wf-trait-associated-type-bound.stderr | 18 + .../wf}/wf-trait-associated-type-region.rs | 0 .../wf/wf-trait-associated-type-region.stderr | 16 + .../wf}/wf-trait-associated-type-trait.rs | 0 .../wf/wf-trait-associated-type-trait.stderr | 16 + .../{compile-fail => ui/wf}/wf-trait-bound.rs | 0 src/test/ui/wf/wf-trait-bound.stderr | 19 + .../wf}/wf-trait-default-fn-arg.rs | 0 src/test/ui/wf/wf-trait-default-fn-arg.stderr | 20 + .../wf}/wf-trait-default-fn-ret.rs | 0 src/test/ui/wf/wf-trait-default-fn-ret.stderr | 21 + .../wf}/wf-trait-default-fn-where-clause.rs | 0 .../wf-trait-default-fn-where-clause.stderr | 20 + .../wf}/wf-trait-fn-arg.rs | 0 src/test/ui/wf/wf-trait-fn-arg.stderr | 16 + .../wf}/wf-trait-fn-ret.rs | 0 src/test/ui/wf/wf-trait-fn-ret.stderr | 16 + .../wf}/wf-trait-fn-where-clause.rs | 0 .../ui/wf/wf-trait-fn-where-clause.stderr | 16 + .../wf}/wf-trait-superbound.rs | 0 src/test/ui/wf/wf-trait-superbound.stderr | 17 + ...constraints-are-local-for-inherent-impl.rs | 0 ...traints-are-local-for-inherent-impl.stderr | 16 + ...se-constraints-are-local-for-trait-impl.rs | 0 ...onstraints-are-local-for-trait-impl.stderr | 16 + .../where-clause-method-substituion.rs | 0 .../where-clause-method-substituion.stderr | 9 + .../where-clauses-method-unsatisfied.rs | 0 .../where-clauses-method-unsatisfied.stderr | 9 + .../where-clauses-unsatisfied.rs | 0 .../where-clauses-unsatisfied.stderr | 15 + .../where-equality-constraints.rs | 0 .../where-equality-constraints.stderr | 14 + .../where-clauses}/where-for-self-2.rs | 2 +- .../ui/where-clauses/where-for-self-2.stderr | 19 + .../where-clauses}/where-for-self.rs | 0 .../ui/where-clauses/where-for-self.stderr | 9 + .../where-lifetime-resolution.rs | 0 .../where-lifetime-resolution.stderr | 22 + src/test/{compile-fail => ui}/while-let.rs | 0 src/test/ui/while-let.stderr | 21 + .../{compile-fail => ui}/while-type-error.rs | 0 src/test/ui/while-type-error.stderr | 12 + .../windows-subsystem-invalid.rs | 0 src/test/ui/windows-subsystem-invalid.stderr | 4 + .../write-to-static-mut-in-static.rs | 0 .../ui/write-to-static-mut-in-static.stderr | 19 + .../ui/writing-to-immutable-vec.nll.stderr | 11 + .../writing-to-immutable-vec.rs | 0 src/test/ui/writing-to-immutable-vec.stderr | 11 + .../wrong-mul-method-signature.rs | 0 src/test/ui/wrong-mul-method-signature.stderr | 30 + .../{compile-fail => ui}/wrong-ret-type.rs | 0 src/test/ui/wrong-ret-type.stderr | 9 + .../{compile-fail => ui}/xc-private-method.rs | 0 src/test/ui/xc-private-method.stderr | 15 + .../xc-private-method2.rs | 0 src/test/ui/xc-private-method2.stderr | 15 + .../auxiliary/static_priv_by_default.rs | 61 + .../xcrate}/auxiliary/xcrate_unit_struct.rs | 0 .../xcrate}/xcrate-private-by-default.rs | 0 .../xcrate/xcrate-private-by-default.stderr | 63 + .../xcrate}/xcrate-unit-struct.rs | 0 src/test/ui/xcrate/xcrate-unit-struct.stderr | 9 + src/tools/build-manifest/README.md | 30 + src/tools/build-manifest/src/main.rs | 173 +- src/tools/cargotest/main.rs | 2 +- src/tools/compiletest/Cargo.toml | 4 +- src/tools/compiletest/src/common.rs | 2 +- src/tools/compiletest/src/header.rs | 19 +- src/tools/compiletest/src/json.rs | 4 +- src/tools/compiletest/src/main.rs | 2 - src/tools/compiletest/src/raise_fd_limit.rs | 16 +- src/tools/compiletest/src/runtest.rs | 114 +- src/tools/compiletest/src/util.rs | 1 + src/tools/error_index_generator/main.rs | 13 +- src/tools/rust-installer/Cargo.toml | 2 +- src/tools/rust-installer/src/lib.rs | 1 - src/tools/rust-installer/src/main.rs | 1 - src/tools/rust-installer/src/tarballer.rs | 38 +- src/tools/rust-installer/src/util.rs | 17 +- src/tools/rustc-workspace-hack/Cargo.toml | 30 +- src/tools/tidy/Cargo.toml | 6 +- src/tools/tidy/src/cargo.rs | 5 +- src/tools/tidy/src/deps.rs | 57 +- src/tools/tidy/src/errors.rs | 6 +- src/tools/tidy/src/extdeps.rs | 8 +- src/tools/tidy/src/features.rs | 68 +- src/tools/tidy/src/lib.rs | 24 +- src/tools/tidy/src/main.rs | 7 +- src/tools/tidy/src/pal.rs | 18 +- src/tools/tidy/src/style.rs | 61 +- src/tools/tidy/src/unstable_book.rs | 6 +- src/vendor/aho-corasick/.cargo-checksum.json | 2 +- src/vendor/aho-corasick/.travis.yml | 2 +- src/vendor/aho-corasick/Cargo.toml | 66 +- src/vendor/aho-corasick/Cargo.toml.orig | 50 - src/vendor/aho-corasick/ci/script.sh | 2 +- src/vendor/aho-corasick/src/lib.rs | 5 +- src/vendor/bitflags/.cargo-checksum.json | 2 +- src/vendor/bitflags/.travis.yml | 19 - src/vendor/bitflags/CHANGELOG.md | 6 + src/vendor/bitflags/CODE_OF_CONDUCT.md | 73 + src/vendor/bitflags/Cargo.toml | 9 +- src/vendor/bitflags/Cargo.toml.orig | 13 +- src/vendor/bitflags/README.md | 11 +- src/vendor/bitflags/src/lib.rs | 26 +- src/vendor/cc/.cargo-checksum.json | 2 +- src/vendor/cc/.travis.yml | 15 +- src/vendor/cc/Cargo.toml | 2 +- src/vendor/cc/Cargo.toml.orig | 2 +- src/vendor/cc/README.md | 2 +- src/vendor/cc/src/lib.rs | 135 +- src/vendor/cc/src/windows_registry.rs | 8 +- src/vendor/cc/tests/test.rs | 27 + src/vendor/cfg-if/.cargo-checksum.json | 2 +- src/vendor/cfg-if/Cargo.toml | 2 +- src/vendor/cfg-if/Cargo.toml.orig | 2 +- src/vendor/cfg-if/src/lib.rs | 45 +- src/vendor/chalk-engine/.cargo-checksum.json | 2 +- src/vendor/chalk-engine/Cargo.toml | 2 +- src/vendor/chalk-engine/Cargo.toml.orig | 2 +- src/vendor/chalk-engine/src/lib.rs | 5 - src/vendor/chalk-engine/src/logic.rs | 6 +- src/vendor/cloudabi/.cargo-checksum.json | 1 + src/vendor/{dtoa => cloudabi}/.cargo-ok | 0 src/vendor/cloudabi/Cargo.toml | 31 + src/vendor/cloudabi/Cargo.toml.orig | 19 + src/vendor/cloudabi/bitflags.rs | 51 + src/vendor/cloudabi/cloudabi.rs | 2847 +++++++++++ src/vendor/cmake/.cargo-checksum.json | 2 +- src/vendor/cmake/Cargo.toml | 2 +- src/vendor/cmake/Cargo.toml.orig | 2 +- src/vendor/cmake/README.md | 2 +- src/vendor/cmake/src/lib.rs | 160 +- src/vendor/dtoa/.cargo-checksum.json | 1 - src/vendor/dtoa/.travis.yml | 9 - src/vendor/dtoa/Cargo.toml | 23 - src/vendor/dtoa/Cargo.toml.orig | 11 - src/vendor/dtoa/LICENSE-MIT | 23 - src/vendor/dtoa/README.md | 69 - src/vendor/dtoa/benches/bench.rs | 54 - src/vendor/dtoa/src/diyfp.rs | 254 - src/vendor/dtoa/src/dtoa.rs | 501 -- src/vendor/dtoa/src/lib.rs | 148 - src/vendor/dtoa/tests/test.rs | 38 - src/vendor/env_logger/.cargo-checksum.json | 2 +- src/vendor/env_logger/.travis.yml | 2 +- src/vendor/env_logger/Cargo.toml | 10 +- src/vendor/env_logger/Cargo.toml.orig | 13 +- src/vendor/env_logger/README.md | 10 +- .../examples/custom_default_format.rs | 2 +- src/vendor/env_logger/src/fmt.rs | 17 +- src/vendor/env_logger/src/lib.rs | 41 +- src/vendor/error-chain/.cargo-checksum.json | 1 + .../{rand-0.4.2 => error-chain}/.cargo-ok | 0 src/vendor/error-chain/.gitignore | 3 + src/vendor/error-chain/.travis.yml | 46 + src/vendor/error-chain/CHANGELOG.md | 125 + src/vendor/error-chain/Cargo.toml | 32 + src/vendor/error-chain/Cargo.toml.orig | 26 + .../{dtoa => error-chain}/LICENSE-APACHE | 0 src/vendor/error-chain/LICENSE-MIT | 26 + src/vendor/error-chain/README.md | 36 + src/vendor/error-chain/examples/all.rs | 36 + src/vendor/error-chain/examples/chain_err.rs | 69 + src/vendor/error-chain/examples/doc.rs | 28 + src/vendor/error-chain/examples/quickstart.rs | 80 + src/vendor/error-chain/examples/size.rs | 30 + src/vendor/error-chain/src/backtrace.rs | 111 + .../error-chain/src/bin/has_backtrace.rs | 18 + src/vendor/error-chain/src/error_chain.rs | 441 ++ .../error-chain/src/example_generated.rs | 38 + .../error-chain/src/impl_error_chain_kind.rs | 367 ++ src/vendor/error-chain/src/lib.rs | 803 +++ src/vendor/error-chain/src/quick_main.rs | 77 + src/vendor/error-chain/tests/quick_main.rs | 28 + src/vendor/error-chain/tests/tests.rs | 643 +++ src/vendor/flate2/.cargo-checksum.json | 2 +- src/vendor/flate2/.travis.yml | 28 +- src/vendor/flate2/Cargo.toml | 7 +- src/vendor/flate2/Cargo.toml.orig | 9 +- src/vendor/flate2/README.md | 10 +- .../flate2/examples/deflatedecoder-bufread.rs | 2 +- .../flate2/examples/deflatedecoder-read.rs | 2 +- .../flate2/examples/deflatedecoder-write.rs | 4 +- .../flate2/examples/deflateencoder-read.rs | 2 +- .../flate2/examples/deflateencoder-write.rs | 2 +- src/vendor/flate2/examples/gzbuilder.rs | 8 +- .../flate2/examples/gzdecoder-bufread.rs | 2 +- src/vendor/flate2/examples/gzdecoder-read.rs | 2 +- src/vendor/flate2/examples/gzdecoder-write.rs | 26 + src/vendor/flate2/examples/gzencoder-read.rs | 2 +- src/vendor/flate2/examples/gzencoder-write.rs | 2 +- .../flate2/examples/gzmultidecoder-bufread.rs | 2 +- .../flate2/examples/gzmultidecoder-read.rs | 2 +- .../flate2/examples/zlibdecoder-bufread.rs | 2 +- .../flate2/examples/zlibdecoder-read.rs | 2 +- .../flate2/examples/zlibdecoder-write.rs | 4 +- .../flate2/examples/zlibencoder-read.rs | 2 +- .../flate2/examples/zlibencoder-write.rs | 2 +- src/vendor/flate2/src/bufreader.rs | 18 +- src/vendor/flate2/src/crc.rs | 72 +- src/vendor/flate2/src/deflate/bufread.rs | 3 +- src/vendor/flate2/src/deflate/mod.rs | 47 +- src/vendor/flate2/src/deflate/read.rs | 4 +- src/vendor/flate2/src/deflate/write.rs | 17 +- src/vendor/flate2/src/ffi.rs | 90 +- src/vendor/flate2/src/gz/bufread.rs | 102 +- src/vendor/flate2/src/gz/mod.rs | 10 +- src/vendor/flate2/src/gz/read.rs | 8 +- src/vendor/flate2/src/gz/write.rs | 324 +- src/vendor/flate2/src/lib.rs | 16 +- src/vendor/flate2/src/mem.rs | 320 +- src/vendor/flate2/src/zio.rs | 169 +- src/vendor/flate2/src/zlib/bufread.rs | 3 +- src/vendor/flate2/src/zlib/mod.rs | 31 +- src/vendor/flate2/src/zlib/read.rs | 3 +- src/vendor/flate2/src/zlib/write.rs | 19 +- src/vendor/flate2/tests/early-flush.rs | 2 +- src/vendor/flate2/tests/empty-read.rs | 82 + src/vendor/flate2/tests/gunzip.rs | 36 +- src/vendor/flate2/tests/tokio.rs | 61 +- src/vendor/lazy_static/.cargo-checksum.json | 2 +- src/vendor/lazy_static/.travis.yml | 2 + src/vendor/lazy_static/Cargo.toml | 5 +- src/vendor/lazy_static/Cargo.toml.orig | 7 +- src/vendor/lazy_static/README.md | 2 +- src/vendor/lazy_static/build.rs | 44 + src/vendor/lazy_static/src/heap_lazy.rs | 43 + src/vendor/lazy_static/src/inline_lazy.rs | 59 + src/vendor/lazy_static/src/lazy.rs | 40 - src/vendor/lazy_static/src/lib.rs | 15 +- src/vendor/lazy_static/src/nightly_lazy.rs | 45 - src/vendor/lazy_static/tests/test.rs | 2 - src/vendor/libc/.cargo-checksum.json | 2 +- src/vendor/libc/.travis.yml | 19 +- src/vendor/libc/Cargo.toml | 3 +- src/vendor/libc/Cargo.toml.orig | 3 +- src/vendor/libc/README.md | 14 +- .../aarch64-unknown-linux-musl/Dockerfile | 12 +- .../arm-unknown-linux-musleabihf/Dockerfile | 12 +- .../docker/i686-unknown-linux-musl/Dockerfile | 13 +- .../sparc64-unknown-linux-gnu/Dockerfile | 5 +- .../x86_64-unknown-linux-musl/Dockerfile | 12 +- .../ci/ios/deploy_and_run_on_ios_simulator.rs | 1 + src/vendor/libc/ci/run.sh | 12 +- src/vendor/libc/src/fuchsia/mod.rs | 148 +- src/vendor/libc/src/lib.rs | 4 +- src/vendor/libc/src/macros.rs | 21 +- src/vendor/libc/src/redox/mod.rs | 1 + src/vendor/libc/src/redox/net.rs | 2 + src/vendor/libc/src/unix/bsd/apple/b64.rs | 2 - src/vendor/libc/src/unix/bsd/apple/mod.rs | 40 +- .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 24 + .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 28 + .../libc/src/unix/bsd/freebsdlike/mod.rs | 10 +- .../libc/src/unix/bsd/netbsdlike/mod.rs | 6 - .../src/unix/bsd/netbsdlike/netbsd/mod.rs | 14 + .../unix/bsd/netbsdlike/openbsdlike/mod.rs | 12 +- .../bsd/netbsdlike/openbsdlike/openbsd/mod.rs | 204 +- src/vendor/libc/src/unix/haiku/mod.rs | 26 +- src/vendor/libc/src/unix/hermit/aarch64.rs | 2 + src/vendor/libc/src/unix/hermit/mod.rs | 736 +++ src/vendor/libc/src/unix/hermit/x86_64.rs | 2 + src/vendor/libc/src/unix/mod.rs | 30 +- src/vendor/libc/src/unix/newlib/mod.rs | 95 +- .../libc/src/unix/notbsd/android/mod.rs | 7 + src/vendor/libc/src/unix/notbsd/emscripten.rs | 54 +- .../libc/src/unix/notbsd/linux/mips/mips32.rs | 106 +- .../libc/src/unix/notbsd/linux/mips/mips64.rs | 106 +- .../libc/src/unix/notbsd/linux/mips/mod.rs | 5 + src/vendor/libc/src/unix/notbsd/linux/mod.rs | 185 +- .../src/unix/notbsd/linux/musl/b32/arm.rs | 85 + .../src/unix/notbsd/linux/musl/b32/mips.rs | 85 + .../src/unix/notbsd/linux/musl/b32/mod.rs | 24 +- .../src/unix/notbsd/linux/musl/b32/powerpc.rs | 866 ++++ .../src/unix/notbsd/linux/musl/b32/x86.rs | 85 + .../src/unix/notbsd/linux/musl/b64/aarch64.rs | 135 + .../src/unix/notbsd/linux/musl/b64/mod.rs | 62 - .../unix/notbsd/linux/musl/b64/powerpc64.rs | 155 +- .../src/unix/notbsd/linux/musl/b64/x86_64.rs | 136 + .../libc/src/unix/notbsd/linux/musl/mod.rs | 77 +- .../src/unix/notbsd/linux/other/b32/mod.rs | 106 +- .../unix/notbsd/linux/other/b64/aarch64.rs | 55 +- .../unix/notbsd/linux/other/b64/not_x32.rs | 106 +- .../unix/notbsd/linux/other/b64/powerpc64.rs | 106 +- .../unix/notbsd/linux/other/b64/sparc64.rs | 86 +- .../src/unix/notbsd/linux/other/b64/x32.rs | 49 +- .../libc/src/unix/notbsd/linux/other/mod.rs | 5 + .../libc/src/unix/notbsd/linux/s390x.rs | 54 +- src/vendor/libc/src/unix/notbsd/mod.rs | 95 +- src/vendor/libc/src/unix/solaris/mod.rs | 5 +- .../libc/src/unix/uclibc/mips/mips32.rs | 5 + .../libc/src/unix/uclibc/mips/mips64.rs | 5 + src/vendor/libc/src/unix/uclibc/mod.rs | 97 +- src/vendor/libc/src/unix/uclibc/x86_64/mod.rs | 78 +- src/vendor/lock_api/.cargo-checksum.json | 1 + .../{termcolor-0.3.6 => lock_api}/.cargo-ok | 0 src/vendor/lock_api/Cargo.toml | 31 + src/vendor/lock_api/Cargo.toml.orig | 16 + src/vendor/lock_api/src/lib.rs | 106 + src/vendor/lock_api/src/mutex.rs | 496 ++ src/vendor/lock_api/src/remutex.rs | 564 +++ src/vendor/lock_api/src/rwlock.rs | 1345 +++++ src/vendor/log/.cargo-checksum.json | 2 +- src/vendor/log/CHANGELOG.md | 9 +- src/vendor/log/Cargo.toml | 2 +- src/vendor/log/Cargo.toml.orig | 2 +- src/vendor/log/README.md | 3 + src/vendor/log/src/lib.rs | 19 +- src/vendor/log/src/macros.rs | 62 +- src/vendor/macro-utils/.cargo-checksum.json | 1 + .../{wincolor-0.1.6 => macro-utils}/.cargo-ok | 0 src/vendor/macro-utils/.gitignore | 2 + src/vendor/macro-utils/.travis.yml | 18 + src/vendor/macro-utils/Cargo.toml | 24 + src/vendor/macro-utils/Cargo.toml.orig | 15 + src/vendor/macro-utils/LICENSE | 21 + src/vendor/macro-utils/README.md | 39 + src/vendor/macro-utils/appveyor.yml | 28 + src/vendor/macro-utils/src/if_match.rs | 205 + src/vendor/macro-utils/src/lib.rs | 61 + src/vendor/macro-utils/src/tern_c.rs | 49 + src/vendor/macro-utils/src/tern_haskell.rs | 49 + src/vendor/macro-utils/src/tern_python.rs | 75 + src/vendor/matches/.cargo-checksum.json | 2 +- src/vendor/matches/Cargo.toml | 2 +- src/vendor/matches/Cargo.toml.orig | 2 +- src/vendor/matches/lib.rs | 38 +- src/vendor/matches/tests/macro_use_one.rs | 11 + src/vendor/memchr/.cargo-checksum.json | 2 +- src/vendor/memchr/.travis.yml | 12 +- src/vendor/memchr/Cargo.toml | 4 +- src/vendor/memchr/Cargo.toml.orig | 4 +- src/vendor/memchr/README.md | 2 +- src/vendor/memchr/appveyor.yml | 5 +- src/vendor/memchr/ci/script.sh | 20 + src/vendor/memchr/src/lib.rs | 16 +- src/vendor/memmap/.appveyor.yml | 19 + src/vendor/memmap/.cargo-checksum.json | 1 + src/vendor/memmap/.cargo-ok | 0 src/vendor/{dtoa => memmap}/.gitignore | 0 src/vendor/memmap/.travis.yml | 69 + src/vendor/memmap/Cargo.toml | 33 + src/vendor/memmap/Cargo.toml.orig | 23 + src/vendor/memmap/LICENSE-APACHE | 201 + src/vendor/memmap/LICENSE-MIT | 25 + src/vendor/memmap/README.md | 53 + src/vendor/memmap/ci/install.sh | 31 + src/vendor/memmap/ci/script.sh | 21 + src/vendor/memmap/examples/cat.rs | 23 + src/vendor/memmap/src/lib.rs | 1017 ++++ src/vendor/memmap/src/unix.rs | 208 + src/vendor/memmap/src/windows.rs | 318 ++ src/vendor/minifier/.cargo-checksum.json | 2 +- src/vendor/minifier/.travis.yml | 1 + src/vendor/minifier/Cargo.toml | 13 +- src/vendor/minifier/Cargo.toml.orig | 10 +- src/vendor/minifier/README.md | 4 +- src/vendor/minifier/appveyor.yml | 13 +- src/vendor/minifier/src/css/css.rs | 38 + src/vendor/minifier/src/css/token.rs | 162 +- src/vendor/minifier/src/js/js.rs | 77 +- src/vendor/minifier/src/js/token.rs | 184 +- src/vendor/minifier/src/json/json_minifier.rs | 52 + src/vendor/minifier/src/json/mod.rs | 98 + .../minifier/src/json/read/byte_to_char.rs | 135 + .../minifier/src/json/read/internal_buffer.rs | 42 + .../minifier/src/json/read/internal_reader.rs | 58 + .../minifier/src/json/read/json_read.rs | 105 + src/vendor/minifier/src/json/string.rs | 65 + src/vendor/minifier/src/lib.rs | 7 +- src/vendor/minifier/src/main.rs | 10 +- src/vendor/minifier/tests/files/test.json | 5 + src/vendor/miow/.cargo-checksum.json | 2 +- src/vendor/miow/Cargo.toml | 6 +- src/vendor/miow/Cargo.toml.orig | 5 +- src/vendor/miow/README.md | 4 +- src/vendor/miow/src/handle.rs | 85 +- src/vendor/miow/src/net.rs | 25 +- src/vendor/miow/src/overlapped.rs | 22 +- src/vendor/miow/src/pipe.rs | 120 +- src/vendor/parking_lot/.cargo-checksum.json | 2 +- src/vendor/parking_lot/.travis.yml | 21 +- src/vendor/parking_lot/CHANGELOG.md | 48 + src/vendor/parking_lot/Cargo.toml | 16 +- src/vendor/parking_lot/Cargo.toml.orig | 13 +- src/vendor/parking_lot/README.md | 12 +- src/vendor/parking_lot/src/condvar.rs | 26 +- src/vendor/parking_lot/src/deadlock.rs | 4 +- src/vendor/parking_lot/src/lib.rs | 50 +- src/vendor/parking_lot/src/mutex.rs | 286 +- src/vendor/parking_lot/src/once.rs | 9 +- src/vendor/parking_lot/src/raw_mutex.rs | 151 +- src/vendor/parking_lot/src/raw_remutex.rs | 102 - src/vendor/parking_lot/src/raw_rwlock.rs | 666 ++- src/vendor/parking_lot/src/remutex.rs | 289 +- src/vendor/parking_lot/src/rwlock.rs | 978 +--- .../.cargo-checksum.json | 1 + src/vendor/parking_lot_core-0.2.14/.cargo-ok | 0 src/vendor/parking_lot_core-0.2.14/Cargo.toml | 47 + .../parking_lot_core-0.2.14/Cargo.toml.orig | 27 + src/vendor/parking_lot_core-0.2.14/src/lib.rs | 81 + .../src/parking_lot.rs | 1389 ++++++ .../parking_lot_core-0.2.14/src/spinwait.rs | 125 + .../src/thread_parker/generic.rs | 98 + .../src/thread_parker/linux.rs | 137 + .../src/thread_parker/unix.rs | 225 + .../src/thread_parker/windows/keyed_event.rs | 197 + .../src/thread_parker/windows/mod.rs | 136 + .../src/thread_parker/windows/waitaddress.rs | 134 + .../parking_lot_core-0.2.14/src/util.rs | 32 + .../parking_lot_core-0.2.14/src/word_lock.rs | 278 ++ .../parking_lot_core/.cargo-checksum.json | 2 +- src/vendor/parking_lot_core/Cargo.toml | 6 +- src/vendor/parking_lot_core/Cargo.toml.orig | 6 +- src/vendor/parking_lot_core/src/lib.rs | 8 +- .../parking_lot_core/src/parking_lot.rs | 56 +- src/vendor/parking_lot_core/src/spinwait.rs | 14 +- .../src/thread_parker/generic.rs | 2 +- .../src/thread_parker/linux.rs | 2 +- .../src/thread_parker/unix.rs | 17 +- .../src/thread_parker/windows/keyed_event.rs | 4 +- .../src/thread_parker/windows/waitaddress.rs | 5 +- src/vendor/parking_lot_core/src/word_lock.rs | 30 +- src/vendor/petgraph/.cargo-checksum.json | 2 +- src/vendor/petgraph/Cargo.toml | 2 +- src/vendor/petgraph/Cargo.toml.orig | 2 +- src/vendor/petgraph/README.rst | 6 + src/vendor/petgraph/src/algo/dominators.rs | 2 +- src/vendor/petgraph/src/astar.rs | 10 +- src/vendor/petgraph/src/csr.rs | 49 +- .../src/graph_impl/stable_graph/mod.rs | 16 +- src/vendor/petgraph/src/iter_utils.rs | 6 +- src/vendor/petgraph/src/lib.rs | 2 + src/vendor/petgraph/src/visit/dfsvisit.rs | 2 +- src/vendor/petgraph/src/visit/traversal.rs | 4 +- src/vendor/pkg-config/.cargo-checksum.json | 2 +- src/vendor/pkg-config/.travis.yml | 1 + src/vendor/pkg-config/CHANGELOG.md | 19 + src/vendor/pkg-config/Cargo.toml | 2 +- src/vendor/pkg-config/Cargo.toml.orig | 2 +- src/vendor/pkg-config/README.md | 3 + src/vendor/pkg-config/src/lib.rs | 50 +- src/vendor/proc-macro2/.cargo-checksum.json | 2 +- src/vendor/proc-macro2/.travis.yml | 3 + src/vendor/proc-macro2/Cargo.toml | 5 +- src/vendor/proc-macro2/Cargo.toml.orig | 6 +- src/vendor/proc-macro2/build.rs | 21 + src/vendor/proc-macro2/src/lib.rs | 22 +- src/vendor/proc-macro2/src/stable.rs | 11 +- src/vendor/proc-macro2/src/unstable.rs | 40 +- src/vendor/quote/.cargo-checksum.json | 2 +- src/vendor/quote/Cargo.toml | 6 +- src/vendor/quote/Cargo.toml.orig | 7 +- src/vendor/quote/README.md | 4 +- src/vendor/quote/src/ext.rs | 4 +- src/vendor/quote/src/lib.rs | 397 +- src/vendor/quote/src/to_tokens.rs | 9 +- src/vendor/rand-0.4.2/.cargo-checksum.json | 1 - src/vendor/rand-0.4.2/CHANGELOG.md | 265 - src/vendor/rand-0.4.2/Cargo.toml | 39 - src/vendor/rand-0.4.2/Cargo.toml.orig | 35 - src/vendor/rand-0.4.2/README.md | 142 - src/vendor/rand-0.4.2/src/lib.rs | 1214 ----- src/vendor/rand-0.4.2/src/os.rs | 617 --- src/vendor/rand-0.4.3/.cargo-checksum.json | 1 + src/vendor/rand-0.4.3/.cargo-ok | 0 .../{rand-0.4.2 => rand-0.4.3}/.gitignore | 0 .../{rand-0.4.2 => rand-0.4.3}/.travis.yml | 0 src/vendor/rand-0.4.3/CHANGELOG.md | 269 + src/vendor/rand-0.4.3/Cargo.toml | 39 + src/vendor/rand-0.4.3/Cargo.toml.orig | 35 + .../{rand-0.4.2 => rand-0.4.3}/LICENSE-APACHE | 0 .../{rand-0.4.2 => rand-0.4.3}/LICENSE-MIT | 0 src/vendor/rand-0.4.3/README.md | 139 + .../{rand-0.4.2 => rand-0.4.3}/appveyor.yml | 0 .../benches/bench.rs | 0 .../benches/distributions/exponential.rs | 0 .../benches/distributions/gamma.rs | 0 .../benches/distributions/mod.rs | 0 .../benches/distributions/normal.rs | 0 .../benches/generators.rs | 0 .../benches/misc.rs | 0 .../src/distributions/exponential.rs | 0 .../src/distributions/gamma.rs | 0 .../src/distributions/mod.rs | 0 .../src/distributions/normal.rs | 0 .../src/distributions/range.rs | 0 .../src/distributions/ziggurat_tables.rs | 0 .../{rand-0.4.2 => rand-0.4.3}/src/jitter.rs | 0 src/vendor/rand-0.4.3/src/lib.rs | 1214 +++++ src/vendor/rand-0.4.3/src/os.rs | 617 +++ .../src/prng/chacha.rs | 0 .../src/prng/isaac.rs | 0 .../src/prng/isaac64.rs | 0 .../src/prng/mod.rs | 0 .../src/prng/xorshift.rs | 0 .../src/rand_impls.rs | 0 .../{rand-0.4.2 => rand-0.4.3}/src/read.rs | 0 .../src/reseeding.rs | 0 .../{rand-0.4.2 => rand-0.4.3}/src/seq.rs | 0 .../utils/ziggurat_tables.py | 0 src/vendor/rand/.cargo-checksum.json | 1 + src/vendor/rand/.cargo-ok | 0 src/vendor/rand/.gitignore | 2 + src/vendor/rand/.travis.yml | 113 + src/vendor/rand/CHANGELOG.md | 406 ++ src/vendor/rand/CONTRIBUTING.md | 93 + src/vendor/rand/Cargo.toml | 72 + src/vendor/rand/Cargo.toml.orig | 59 + src/vendor/rand/LICENSE-APACHE | 201 + src/vendor/rand/LICENSE-MIT | 25 + src/vendor/rand/README.md | 143 + src/vendor/rand/UPDATING.md | 260 + src/vendor/rand/appveyor.yml | 39 + src/vendor/rand/benches/distributions.rs | 161 + src/vendor/rand/benches/generators.rs | 176 + src/vendor/rand/benches/misc.rs | 194 + src/vendor/rand/examples/monte-carlo.rs | 52 + src/vendor/rand/examples/monty-hall.rs | 117 + .../rand/src/distributions/bernoulli.rs | 120 + src/vendor/rand/src/distributions/binomial.rs | 178 + src/vendor/rand/src/distributions/cauchy.rs | 116 + .../rand/src/distributions/exponential.rs | 122 + src/vendor/rand/src/distributions/float.rs | 206 + src/vendor/rand/src/distributions/gamma.rs | 360 ++ src/vendor/rand/src/distributions/integer.rs | 113 + .../rand/src/distributions/log_gamma.rs | 51 + src/vendor/rand/src/distributions/mod.rs | 784 +++ src/vendor/rand/src/distributions/normal.rs | 192 + src/vendor/rand/src/distributions/other.rs | 215 + src/vendor/rand/src/distributions/pareto.rs | 76 + src/vendor/rand/src/distributions/poisson.rs | 158 + src/vendor/rand/src/distributions/uniform.rs | 856 ++++ .../rand/src/distributions/ziggurat_tables.rs | 280 ++ src/vendor/rand/src/lib.rs | 1252 +++++ src/vendor/rand/src/prelude.rs | 28 + src/vendor/rand/src/prng/chacha.rs | 477 ++ src/vendor/rand/src/prng/hc128.rs | 464 ++ src/vendor/rand/src/prng/isaac.rs | 486 ++ src/vendor/rand/src/prng/isaac64.rs | 478 ++ src/vendor/rand/src/prng/isaac_array.rs | 137 + src/vendor/rand/src/prng/mod.rs | 330 ++ src/vendor/rand/src/prng/xorshift.rs | 225 + src/vendor/rand/src/rngs/adapter/mod.rs | 17 + src/vendor/rand/src/rngs/adapter/read.rs | 137 + src/vendor/rand/src/rngs/adapter/reseeding.rs | 260 + src/vendor/rand/src/rngs/entropy.rs | 296 ++ src/vendor/rand/src/rngs/jitter.rs | 887 ++++ src/vendor/rand/src/rngs/mock.rs | 61 + src/vendor/rand/src/rngs/mod.rs | 218 + src/vendor/rand/src/rngs/os.rs | 1186 +++++ src/vendor/rand/src/rngs/small.rs | 101 + src/vendor/rand/src/rngs/std.rs | 83 + src/vendor/rand/src/rngs/thread.rs | 141 + src/vendor/rand/src/seq.rs | 334 ++ src/vendor/rand/tests/bool.rs | 23 + src/vendor/rand/utils/ci/install.sh | 49 + src/vendor/rand/utils/ci/script.sh | 29 + src/vendor/rand/utils/ziggurat_tables.py | 127 + src/vendor/rand_core/.cargo-checksum.json | 1 + src/vendor/rand_core/.cargo-ok | 0 src/vendor/rand_core/CHANGELOG.md | 30 + src/vendor/rand_core/Cargo.toml | 42 + src/vendor/rand_core/Cargo.toml.orig | 28 + src/vendor/rand_core/LICENSE-APACHE | 201 + src/vendor/rand_core/LICENSE-MIT | 25 + src/vendor/rand_core/README.md | 62 + src/vendor/rand_core/src/block.rs | 502 ++ src/vendor/rand_core/src/error.rs | 179 + src/vendor/rand_core/src/impls.rs | 167 + src/vendor/rand_core/src/le.rs | 70 + src/vendor/rand_core/src/lib.rs | 404 ++ src/vendor/regex-syntax/.cargo-checksum.json | 2 +- src/vendor/regex-syntax/Cargo.toml | 2 +- src/vendor/regex-syntax/Cargo.toml.orig | 2 +- src/vendor/regex-syntax/src/hir/print.rs | 20 +- src/vendor/regex-syntax/src/hir/translate.rs | 8 +- src/vendor/regex-syntax/src/parser.rs | 8 +- src/vendor/regex/.cargo-checksum.json | 2 +- src/vendor/regex/.travis.yml | 30 +- src/vendor/regex/CHANGELOG.md | 25 + src/vendor/regex/Cargo.toml | 20 +- src/vendor/regex/Cargo.toml.orig | 22 +- src/vendor/regex/HACKING.md | 11 + src/vendor/regex/README.md | 22 +- src/vendor/regex/build.rs | 10 +- src/vendor/regex/ci/script.sh | 31 +- src/vendor/regex/ci/test-regex-capi | 7 + src/vendor/regex/scripts/scrape_crates_io.py | 189 + src/vendor/regex/src/exec.rs | 10 +- src/vendor/regex/src/lib.rs | 5 +- src/vendor/regex/src/re_builder.rs | 6 +- src/vendor/regex/src/re_bytes.rs | 140 +- src/vendor/regex/src/re_trait.rs | 14 +- src/vendor/regex/src/re_unicode.rs | 130 +- src/vendor/regex/tests/consistent.rs | 213 + src/vendor/regex/tests/crates_regex.rs | 3129 ++++++++++++ src/vendor/regex/tests/test_crates_regex.rs | 57 + src/vendor/rls-data/.cargo-checksum.json | 2 +- src/vendor/rls-data/Cargo.toml | 2 +- src/vendor/rls-data/Cargo.toml.orig | 2 +- src/vendor/rls-data/src/lib.rs | 5 + .../rustc-demangle/.cargo-checksum.json | 2 +- src/vendor/rustc-demangle/Cargo.toml | 2 +- src/vendor/rustc-demangle/Cargo.toml.orig | 2 +- src/vendor/rustc-demangle/src/lib.rs | 116 +- src/vendor/rustc-demangle/src/main.rs | 4 - src/vendor/ryu/.cargo-checksum.json | 1 + src/vendor/ryu/.cargo-ok | 0 src/vendor/ryu/.gitignore | 3 + src/vendor/ryu/.travis.yml | 13 + src/vendor/ryu/Cargo.toml | 39 + src/vendor/ryu/Cargo.toml.orig | 31 + src/vendor/ryu/LICENSE-APACHE | 201 + src/vendor/ryu/LICENSE-BOOST | 23 + src/vendor/ryu/README.md | 77 + src/vendor/ryu/benchmark/benchmark.rs | 86 + src/vendor/ryu/build.rs | 60 + src/vendor/ryu/src/buffer/mod.rs | 97 + src/vendor/ryu/src/common.rs | 72 + src/vendor/ryu/src/d2s.rs | 581 +++ src/vendor/ryu/src/d2s_full_table.rs | 643 +++ src/vendor/ryu/src/d2s_intrinsics.rs | 79 + src/vendor/ryu/src/d2s_small_table.rs | 206 + src/vendor/ryu/src/digit_table.rs | 28 + src/vendor/ryu/src/f2s.rs | 494 ++ src/vendor/ryu/src/lib.rs | 66 + src/vendor/ryu/src/pretty/exponent.rs | 49 + src/vendor/ryu/src/pretty/mantissa.rs | 51 + src/vendor/ryu/src/pretty/mod.rs | 154 + src/vendor/ryu/tests/d2s_table_test.rs | 52 + src/vendor/ryu/tests/d2s_test.rs | 154 + src/vendor/ryu/tests/exhaustive.rs | 55 + src/vendor/ryu/tests/f2s_test.rs | 183 + src/vendor/ryu/tests/macros/mod.rs | 12 + src/vendor/same-file/.cargo-checksum.json | 2 +- src/vendor/same-file/COPYING | 28 +- src/vendor/same-file/Cargo.toml | 7 +- src/vendor/same-file/Cargo.toml.orig | 13 +- src/vendor/same-file/LICENSE-MIT | 21 + .../{termcolor-0.3.6 => same-file}/UNLICENSE | 0 src/vendor/same-file/examples/is_stderr.rs | 2 +- src/vendor/same-file/src/lib.rs | 6 +- src/vendor/same-file/src/win.rs | 139 +- src/vendor/serde/.cargo-checksum.json | 2 +- src/vendor/serde/Cargo.toml | 2 +- src/vendor/serde/Cargo.toml.orig | 2 +- src/vendor/serde/build.rs | 14 +- src/vendor/serde/src/de/ignored_any.rs | 10 +- src/vendor/serde/src/de/impls.rs | 274 +- src/vendor/serde/src/de/mod.rs | 57 +- src/vendor/serde/src/lib.rs | 21 +- src/vendor/serde/src/private/de.rs | 12 +- src/vendor/serde/src/ser/impls.rs | 22 +- src/vendor/serde/src/ser/mod.rs | 81 +- src/vendor/serde_derive/.cargo-checksum.json | 2 +- src/vendor/serde_derive/Cargo.toml | 7 +- src/vendor/serde_derive/Cargo.toml.orig | 5 +- src/vendor/serde_derive/src/bound.rs | 21 +- src/vendor/serde_derive/src/de.rs | 23 +- src/vendor/serde_derive/src/internals/ast.rs | 6 +- src/vendor/serde_derive/src/internals/attr.rs | 32 +- src/vendor/serde_derive/src/internals/case.rs | 9 +- src/vendor/serde_derive/src/lib.rs | 23 +- src/vendor/serde_derive/src/pretend.rs | 3 +- src/vendor/serde_derive/src/ser.rs | 31 +- src/vendor/serde_json/.cargo-checksum.json | 2 +- src/vendor/serde_json/Cargo.toml | 8 +- src/vendor/serde_json/Cargo.toml.orig | 4 +- src/vendor/serde_json/src/lib.rs | 4 +- src/vendor/serde_json/src/macros.rs | 21 +- src/vendor/serde_json/src/number.rs | 6 +- src/vendor/serde_json/src/ser.rs | 10 +- src/vendor/smallvec/.cargo-checksum.json | 2 +- src/vendor/smallvec/.travis.yml | 3 + src/vendor/smallvec/Cargo.toml | 2 +- src/vendor/smallvec/Cargo.toml.orig | 2 +- src/vendor/smallvec/benches/bench.rs | 23 +- src/vendor/smallvec/lib.rs | 153 +- src/vendor/syn/.cargo-checksum.json | 2 +- src/vendor/syn/Cargo.toml | 4 +- src/vendor/syn/Cargo.toml.orig | 5 +- src/vendor/syn/src/attr.rs | 4 +- src/vendor/syn/src/buffer.rs | 12 +- src/vendor/syn/src/data.rs | 28 +- src/vendor/syn/src/derive.rs | 49 +- src/vendor/syn/src/expr.rs | 488 +- src/vendor/syn/src/gen/fold.rs | 4410 ++++++++--------- src/vendor/syn/src/gen/visit.rs | 4204 ++++++++++------ src/vendor/syn/src/gen/visit_mut.rs | 4016 +++++++++------ src/vendor/syn/src/item.rs | 165 +- src/vendor/syn/src/lib.rs | 61 +- src/vendor/syn/src/lifetime.rs | 3 +- src/vendor/syn/src/macros.rs | 16 +- src/vendor/syn/src/parsers.rs | 37 +- src/vendor/syn/src/path.rs | 2 + src/vendor/syn/src/punctuated.rs | 20 +- src/vendor/syn/src/synom.rs | 33 +- src/vendor/syn/src/token.rs | 4 + src/vendor/syn/src/ty.rs | 5 +- src/vendor/syn/src/verbatim.rs | 20 + src/vendor/tempfile/.cargo-checksum.json | 2 +- src/vendor/tempfile/.travis.yml | 2 +- src/vendor/tempfile/Cargo.toml | 4 +- src/vendor/tempfile/Cargo.toml.orig | 4 +- src/vendor/tempfile/appveyor.yml | 4 +- src/vendor/tempfile/src/dir.rs | 13 +- src/vendor/tempfile/src/lib.rs | 4 +- src/vendor/tempfile/src/util.rs | 2 +- .../termcolor-0.3.6/.cargo-checksum.json | 1 - src/vendor/termcolor-0.3.6/Cargo.toml | 29 - src/vendor/termcolor-0.3.6/Cargo.toml.orig | 20 - src/vendor/termcolor-0.3.6/README.md | 86 - src/vendor/termcolor-0.3.6/src/lib.rs | 1697 ------- src/vendor/termcolor/.cargo-checksum.json | 1 + src/vendor/termcolor/.cargo-ok | 0 src/vendor/termcolor/.gitignore | 5 + .../{termcolor-0.3.6 => termcolor}/COPYING | 0 src/vendor/termcolor/Cargo.toml | 30 + src/vendor/termcolor/Cargo.toml.orig | 21 + .../LICENSE-MIT | 0 src/vendor/termcolor/README.md | 86 + .../{wincolor-0.1.6 => termcolor}/UNLICENSE | 0 src/vendor/termcolor/src/lib.rs | 1832 +++++++ src/vendor/thread_local/.cargo-checksum.json | 2 +- src/vendor/thread_local/.travis.yml | 2 +- src/vendor/thread_local/Cargo.toml | 5 +- src/vendor/thread_local/Cargo.toml.orig | 3 +- src/vendor/thread_local/src/lib.rs | 4 +- src/vendor/thread_local/src/unreachable.rs | 74 + src/vendor/utf8-ranges/.cargo-checksum.json | 2 +- src/vendor/utf8-ranges/.travis.yml | 8 +- src/vendor/utf8-ranges/Cargo.toml | 26 +- src/vendor/utf8-ranges/Cargo.toml.orig | 17 + src/vendor/utf8-ranges/ci/script.sh | 17 + src/vendor/version_check/.cargo-checksum.json | 1 + src/vendor/version_check/.cargo-ok | 0 src/vendor/version_check/.gitignore | 2 + src/vendor/version_check/Cargo.toml | 24 + src/vendor/version_check/Cargo.toml.orig | 12 + src/vendor/version_check/LICENSE-APACHE | 201 + src/vendor/version_check/LICENSE-MIT | 19 + src/vendor/version_check/README.md | 67 + src/vendor/version_check/src/lib.rs | 246 + src/vendor/walkdir/.cargo-checksum.json | 2 +- src/vendor/walkdir/.travis.yml | 7 +- src/vendor/walkdir/Cargo.toml | 13 +- src/vendor/walkdir/Cargo.toml.orig | 14 +- src/vendor/walkdir/README.md | 4 +- src/vendor/walkdir/appveyor.yml | 3 + src/vendor/walkdir/ci/script.sh | 13 + src/vendor/walkdir/examples/walkdir.rs | 100 +- src/vendor/walkdir/src/lib.rs | 127 +- src/vendor/walkdir/src/tests.rs | 54 +- src/vendor/winapi-util/.cargo-checksum.json | 1 + src/vendor/winapi-util/.cargo-ok | 0 src/vendor/winapi-util/.gitignore | 4 + src/vendor/winapi-util/.travis.yml | 8 + .../{wincolor-0.1.6 => winapi-util}/COPYING | 0 src/vendor/winapi-util/Cargo.toml | 27 + src/vendor/winapi-util/Cargo.toml.orig | 26 + src/vendor/winapi-util/LICENSE-MIT | 21 + src/vendor/winapi-util/README.md | 51 + src/vendor/winapi-util/UNLICENSE | 24 + src/vendor/winapi-util/appveyor.yml | 26 + src/vendor/winapi-util/ci/script.sh | 7 + src/vendor/winapi-util/src/console.rs | 121 + src/vendor/winapi-util/src/file.rs | 158 + src/vendor/winapi-util/src/lib.rs | 35 + src/vendor/winapi-util/src/win.rs | 247 + .../wincolor-0.1.6/.cargo-checksum.json | 1 - src/vendor/wincolor-0.1.6/Cargo.toml | 30 - src/vendor/wincolor-0.1.6/Cargo.toml.orig | 21 - src/vendor/wincolor-0.1.6/src/lib.rs | 33 - src/vendor/wincolor-0.1.6/src/win.rs | 266 - src/vendor/wincolor/.cargo-checksum.json | 1 + src/vendor/wincolor/.cargo-ok | 0 src/vendor/wincolor/COPYING | 3 + src/vendor/wincolor/Cargo.toml | 33 + src/vendor/wincolor/Cargo.toml.orig | 24 + .../{wincolor-0.1.6 => wincolor}/LICENSE-MIT | 0 .../{wincolor-0.1.6 => wincolor}/README.md | 0 src/vendor/wincolor/UNLICENSE | 24 + src/vendor/wincolor/src/lib.rs | 35 + src/vendor/wincolor/src/win.rs | 261 + version | 2 +- 12441 files changed, 205602 insertions(+), 63436 deletions(-) delete mode 100644 src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile create mode 100644 src/doc/nomicon/src/beneath-std.md create mode 100644 src/doc/nomicon/src/panic-handler.md create mode 100644 src/doc/reference/src/conditional-compilation.md create mode 100644 src/doc/rust-by-example/src/compatibility.md create mode 100644 src/doc/rust-by-example/src/compatibility/raw_identifiers.md delete mode 100644 src/doc/unstable-book/src/language-features/attr-literals.md delete mode 100644 src/doc/unstable-book/src/language-features/catch-expr.md delete mode 100644 src/doc/unstable-book/src/language-features/crate-in-paths.md create mode 100644 src/doc/unstable-book/src/language-features/custom-test-frameworks.md delete mode 100644 src/doc/unstable-book/src/language-features/extern-absolute-paths.md delete mode 100644 src/doc/unstable-book/src/language-features/infer-outlives-requirements.md delete mode 100644 src/doc/unstable-book/src/language-features/macro-vis-matcher.md create mode 100644 src/doc/unstable-book/src/language-features/self-in-typedefs.md create mode 100644 src/doc/unstable-book/src/language-features/self-struct-ctor.md delete mode 100644 src/doc/unstable-book/src/language-features/tool-attributes.md create mode 100644 src/doc/unstable-book/src/language-features/try-blocks.md create mode 100644 src/doc/unstable-book/src/language-features/unsized-locals.md delete mode 100644 src/doc/unstable-book/src/language-features/used.md delete mode 100644 src/doc/unstable-book/src/library-features/future-atomic-orderings.md delete mode 100644 src/doc/unstable-book/src/library-features/io-error-internals.md create mode 100755 src/etc/rust-gdbgui create mode 100644 src/liballoc/benches/vec_deque_append.rs create mode 100644 src/liballoc/pin.rs delete mode 100644 src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt create mode 100644 src/libcompiler_builtins/compiler-rt/lib/builtins/arm/chkstk.S create mode 100644 src/libcompiler_builtins/crates/panic-handler/Cargo.toml create mode 100644 src/libcompiler_builtins/crates/panic-handler/src/lib.rs delete mode 100644 src/libcompiler_builtins/crates/panic-implementation/Cargo.toml delete mode 100644 src/libcompiler_builtins/crates/panic-implementation/src/lib.rs create mode 100644 src/libcompiler_builtins/src/riscv32.rs create mode 100644 src/libcore/ffi.rs delete mode 100644 src/libcore/manually_drop_stage0.rs create mode 100644 src/libcore/pin.rs delete mode 100644 src/libcore/task/executor.rs create mode 100644 src/libcore/task/spawn.rs delete mode 100644 src/liblibc/src/fuchsia/powerpc64.rs create mode 100644 src/liblibc/src/switch.rs create mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/aarch64.rs create mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/arm.rs delete mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/b32/mod.rs delete mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/b64/mod.rs delete mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/mod.rs create mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/powerpc.rs create mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/sparc64.rs create mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/x86.rs create mode 100644 src/liblibc/src/unix/bsd/netbsdlike/netbsd/x86_64.rs create mode 100644 src/liblibc/src/unix/hermit/aarch64.rs create mode 100644 src/liblibc/src/unix/hermit/mod.rs create mode 100644 src/liblibc/src/unix/hermit/x86_64.rs create mode 100644 src/liblibc/src/unix/notbsd/linux/musl/b32/powerpc.rs rename src/libpanic_unwind/{wasm32.rs => dummy.rs} (100%) create mode 100644 src/libpanic_unwind/macros.rs delete mode 100644 src/librustc/infer/anon_types/mod.rs create mode 100644 src/librustc/infer/opaque_types/mod.rs create mode 100644 src/librustc/middle/lib_features.rs create mode 100644 src/librustc/traits/query/type_op/implied_outlives_bounds.rs create mode 100644 src/librustc/util/bug.rs delete mode 100644 src/librustc/util/fs.rs create mode 100644 src/librustc/util/profiling.rs rename src/{librustc/middle => librustc_borrowck}/dataflow.rs (96%) create mode 100644 src/librustc_codegen_llvm/llvm/archive_ro.rs rename src/{librustc_llvm => librustc_codegen_llvm/llvm}/diagnostic.rs (75%) create mode 100644 src/librustc_codegen_llvm/llvm/ffi.rs create mode 100644 src/librustc_codegen_llvm/llvm/mod.rs delete mode 100644 src/librustc_data_structures/accumulate_vec.rs delete mode 100644 src/librustc_data_structures/bitslice.rs create mode 100644 src/librustc_data_structures/const_cstr.rs rename src/{librustc/ich => librustc_data_structures}/fingerprint.rs (89%) create mode 100644 src/librustc_data_structures/small_c_str.rs rename src/{librustc/hir => librustc_data_structures}/svh.rs (85%) rename src/{libsyntax/util => librustc_data_structures}/thin_vec.rs (100%) create mode 100644 src/librustc_data_structures/vec_linked_list.rs create mode 100644 src/librustc_fs_util/Cargo.toml create mode 100644 src/librustc_fs_util/lib.rs rename src/librustc_lint/{bad_style.rs => nonstandard_style.rs} (100%) delete mode 100644 src/librustc_llvm/archive_ro.rs delete mode 100644 src/librustc_llvm/ffi.rs create mode 100644 src/librustc_metadata_utils/Cargo.toml create mode 100644 src/librustc_metadata_utils/lib.rs delete mode 100644 src/librustc_mir/borrow_check/nll/liveness_map.rs delete mode 100644 src/librustc_mir/borrow_check/nll/region_infer/annotation.rs delete mode 100644 src/librustc_mir/borrow_check/nll/type_check/liveness.rs create mode 100644 src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs create mode 100644 src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs create mode 100644 src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs create mode 100644 src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs create mode 100644 src/librustc_mir/const_eval.rs delete mode 100644 src/librustc_mir/interpret/const_eval.rs create mode 100644 src/librustc_mir/interpret/intrinsics.rs create mode 100644 src/librustc_mir/interpret/operand.rs create mode 100644 src/librustc_mir/interpret/snapshot.rs create mode 100644 src/librustc_mir/interpret/terminator.rs delete mode 100644 src/librustc_mir/interpret/terminator/drop.rs delete mode 100644 src/librustc_mir/interpret/terminator/mod.rs create mode 100644 src/librustc_mir/interpret/validity.rs create mode 100644 src/librustc_mir/transform/qualify_min_const_fn.rs create mode 100644 src/librustc_target/abi/call/amdgpu.rs create mode 100644 src/librustc_target/abi/call/riscv.rs create mode 100644 src/librustc_target/spec/aarch64_pc_windows_msvc.rs create mode 100644 src/librustc_target/spec/aarch64_unknown_hermit.rs create mode 100644 src/librustc_target/spec/aarch64_unknown_netbsd.rs create mode 100644 src/librustc_target/spec/aarch64_unknown_none.rs create mode 100644 src/librustc_target/spec/armebv7r_none_eabi.rs create mode 100644 src/librustc_target/spec/armv7r_none_eabi.rs create mode 100644 src/librustc_target/spec/armv7r_none_eabihf.rs create mode 100644 src/librustc_target/spec/hermit_base.rs create mode 100644 src/librustc_target/spec/riscv32imac_unknown_none_elf.rs create mode 100644 src/librustc_target/spec/riscv32imc_unknown_none_elf.rs create mode 100644 src/librustc_target/spec/riscv_base.rs create mode 100644 src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs create mode 100644 src/librustc_target/spec/x86_64_unknown_hermit.rs create mode 100644 src/librustdoc/clean/blanket_impl.rs create mode 100644 src/librustdoc/clean/def_ctor.rs create mode 100644 src/librustdoc/passes/collect_intra_doc_links.rs create mode 100644 src/libstd/os/hermit/fs.rs create mode 100644 src/libstd/os/hermit/mod.rs create mode 100644 src/libstd/os/hermit/raw.rs delete mode 100644 src/libstd_unicode/Cargo.toml delete mode 100644 src/libstd_unicode/lib.rs delete mode 100644 src/libsyntax/codemap.rs create mode 100644 src/libsyntax/source_map.rs create mode 100644 src/libsyntax/util/rc_vec.rs delete mode 100644 src/libsyntax/util/small_vector.rs create mode 100644 src/libsyntax_ext/test.rs create mode 100644 src/libsyntax_ext/test_case.rs delete mode 100644 src/libsyntax_pos/analyze_filemap.rs create mode 100644 src/libsyntax_pos/analyze_source_file.rs create mode 100644 src/test/codegen/issue-13018.rs create mode 100644 src/test/codegen/no-assumes-on-casts.rs create mode 100644 src/test/codegen/no-dllimport-w-cross-lang-lto.rs create mode 100644 src/test/codegen/slice-position-bounds-check.rs create mode 100644 src/test/codegen/target-cpu-on-functions.rs create mode 100644 src/test/codegen/vec-clear.rs delete mode 100644 src/test/compile-fail-fulldeps/proc-macro/proc-macro-custom-attr-mutex.rs delete mode 100644 src/test/compile-fail/anon-params-deprecated.rs delete mode 100644 src/test/compile-fail/auxiliary/const_fn_lib.rs delete mode 100644 src/test/compile-fail/auxiliary/lint_output_format.rs delete mode 100644 src/test/compile-fail/auxiliary/lint_stability.rs delete mode 100644 src/test/compile-fail/auxiliary/lint_stability_fields.rs rename src/test/compile-fail/{panic-runtime => }/auxiliary/panic-runtime-lang-items.rs (100%) rename src/test/compile-fail/{panic-runtime => }/auxiliary/panic-runtime-unwind.rs (100%) rename src/test/compile-fail/{panic-runtime => }/auxiliary/panic-runtime-unwind2.rs (100%) delete mode 100644 src/test/compile-fail/auxiliary/stability_attribute_issue.rs delete mode 100644 src/test/compile-fail/auxiliary/stability_cfg2.rs delete mode 100644 src/test/compile-fail/auxiliary/unstable-macros.rs rename src/test/compile-fail/{panic-runtime => }/auxiliary/wants-panic-runtime-unwind.rs (100%) delete mode 100644 src/test/compile-fail/borrow-tuple-fields.rs delete mode 100644 src/test/compile-fail/borrowck/borrowck-closures-two-mut.rs delete mode 100644 src/test/compile-fail/borrowck/borrowck-closures-unique.rs delete mode 100644 src/test/compile-fail/borrowck/borrowck-object-lifetime.rs delete mode 100644 src/test/compile-fail/borrowck/borrowck-overloaded-index-autoderef.rs delete mode 100644 src/test/compile-fail/cast-ptr-to-int-const.rs delete mode 100644 src/test/compile-fail/catch-bad-lifetime.rs delete mode 100644 src/test/compile-fail/catch-bad-type.rs delete mode 100644 src/test/compile-fail/catch-in-match.rs delete mode 100644 src/test/compile-fail/catch-in-while.rs delete mode 100644 src/test/compile-fail/catch-maybe-bad-lifetime.rs delete mode 100644 src/test/compile-fail/catch-opt-init.rs delete mode 100644 src/test/compile-fail/directory_ownership/mod_file_not_owning.rs delete mode 100644 src/test/compile-fail/directory_ownership/unowned_mod_with_path.rs delete mode 100644 src/test/compile-fail/dollar-crate-is-keyword.rs delete mode 100644 src/test/compile-fail/enum-discrim-autosizing.rs delete mode 100644 src/test/compile-fail/feature-gate-tool_attributes.rs delete mode 100644 src/test/compile-fail/gated-attr-literals.rs delete mode 100644 src/test/compile-fail/invalid-crate-type.rs delete mode 100644 src/test/compile-fail/lint-renamed-cmdline.rs delete mode 100644 src/test/compile-fail/macro-with-seps-err-msg.rs delete mode 100644 src/test/compile-fail/macros-in-extern.rs delete mode 100644 src/test/compile-fail/method-call-lifetime-args.rs create mode 100644 src/test/compile-fail/panic-handler-missing.rs create mode 100644 src/test/compile-fail/panic-handler-twice.rs delete mode 100644 src/test/compile-fail/panic-implementation-bad-signature-1.rs delete mode 100644 src/test/compile-fail/panic-implementation-bad-signature-2.rs delete mode 100644 src/test/compile-fail/panic-implementation-bad-signature-3.rs delete mode 100644 src/test/compile-fail/panic-implementation-bad-signature-4.rs delete mode 100644 src/test/compile-fail/panic-implementation-duplicate.rs delete mode 100644 src/test/compile-fail/panic-implementation-missing.rs delete mode 100644 src/test/compile-fail/panic-implementation-requires-panic-info.rs delete mode 100644 src/test/compile-fail/panic-implementation-std.rs delete mode 100644 src/test/compile-fail/panic-implementation-twice.rs delete mode 100644 src/test/compile-fail/regions-enum-not-wf.rs delete mode 100644 src/test/compile-fail/regions-static-bound.rs delete mode 100644 src/test/compile-fail/regions-struct-not-wf.rs delete mode 100644 src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-1.rs delete mode 100644 src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-2.rs delete mode 100644 src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-3.rs delete mode 100644 src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs delete mode 100644 src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-1.rs delete mode 100644 src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-2.rs delete mode 100644 src/test/compile-fail/rfc-2126-extern-in-paths/non-existent-3.rs delete mode 100644 src/test/compile-fail/rfc-2126-extern-in-paths/single-segment.rs delete mode 100644 src/test/compile-fail/stability-attribute-issue.rs rename src/test/compile-fail/{panic-runtime => }/two-panic-runtimes.rs (100%) delete mode 100644 src/test/compile-fail/union-ub-fat-ptr.rs delete mode 100644 src/test/compile-fail/unknown-tool-name.rs delete mode 100644 src/test/compile-fail/unknown_tool_attributes-1.rs create mode 100644 src/test/compile-fail/unsized-locals/unsized-exprs.rs create mode 100644 src/test/compile-fail/unsized-locals/unsized-exprs2.rs rename src/test/compile-fail/{panic-runtime => }/want-abort-got-unwind.rs (100%) rename src/test/compile-fail/{panic-runtime => }/want-abort-got-unwind2.rs (100%) delete mode 100644 src/test/compile-fail/wf-outlives-ty-in-fn-or-trait.rs create mode 100644 src/test/debuginfo/pretty-std-collections.rs create mode 100644 src/test/incremental-fulldeps/auxiliary/issue_49482_macro_def.rs create mode 100644 src/test/incremental-fulldeps/auxiliary/issue_49482_reexport.rs create mode 100644 src/test/incremental-fulldeps/auxiliary/issue_54059.rs create mode 100644 src/test/incremental-fulldeps/issue-49482.rs create mode 100644 src/test/incremental-fulldeps/issue-54059.rs delete mode 100644 src/test/mir-opt/nll/reborrow-basic.rs create mode 100644 src/test/parse-fail/attr-bad-meta-2.rs create mode 100644 src/test/parse-fail/attr-bad-meta-3.rs create mode 100644 src/test/parse-fail/do-catch-suggests-try.rs create mode 100644 src/test/parse-fail/keyword-try-as-identifier-edition2018.rs create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/Makefile create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/staticlib.rs create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs/upstream.rs delete mode 100644 src/test/run-make-fulldeps/extern-prelude/feature-gate.rs create mode 100644 src/test/run-make-fulldeps/issue-53964/Makefile create mode 100644 src/test/run-make-fulldeps/issue-53964/app.rs create mode 100644 src/test/run-make-fulldeps/issue-53964/panic.rs delete mode 100644 src/test/run-make-fulldeps/symbols-are-reasonable/Makefile delete mode 100644 src/test/run-make-fulldeps/symbols-are-reasonable/lib.rs create mode 100644 src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile create mode 100644 src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs create mode 100644 src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs create mode 100644 src/test/run-make/git_clone_sha1.sh create mode 100644 src/test/run-make/thumb-none-cortex-m/Makefile create mode 100644 src/test/run-make/wasm-symbols-not-exported/Makefile create mode 100644 src/test/run-make/wasm-symbols-not-exported/bar.rs create mode 100644 src/test/run-make/wasm-symbols-not-exported/foo.rs create mode 100644 src/test/run-make/wasm-symbols-not-exported/verify-exported-symbols.js create mode 100644 src/test/run-make/wasm-symbols-not-imported/Makefile create mode 100644 src/test/run-make/wasm-symbols-not-imported/foo.rs create mode 100644 src/test/run-make/wasm-symbols-not-imported/verify-no-imports.js create mode 100644 src/test/run-pass-fulldeps/newtype_index.rs create mode 100644 src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs delete mode 100644 src/test/run-pass/allocator/auxiliary/custom.rs delete mode 100644 src/test/run-pass/allocator/custom.rs delete mode 100644 src/test/run-pass/auxiliary/const_fn_lib.rs delete mode 100644 src/test/run-pass/auxiliary/issue-36954.rs delete mode 100644 src/test/run-pass/auxiliary/unstable-macros.rs delete mode 100644 src/test/run-pass/borrow-tuple-fields.rs delete mode 100644 src/test/run-pass/catch-expr.rs create mode 100644 src/test/run-pass/const-int-conversion.rs create mode 100644 src/test/run-pass/const-int-overflowing.rs create mode 100644 src/test/run-pass/const-int-rotate.rs create mode 100644 src/test/run-pass/const-int-sign.rs create mode 100644 src/test/run-pass/const-int-wrapping.rs delete mode 100644 src/test/run-pass/ctfe/promotion.rs delete mode 100644 src/test/run-pass/dyn-trait.rs delete mode 100644 src/test/run-pass/enum-discrim-autosizing.rs create mode 100644 src/test/run-pass/env-null-vars.rs delete mode 100644 src/test/run-pass/float.rs delete mode 100644 src/test/run-pass/fn-abi.rs delete mode 100644 src/test/run-pass/generator/panic-safe.rs delete mode 100644 src/test/run-pass/generator/xcrate.rs delete mode 100644 src/test/run-pass/hygiene/auxiliary/legacy_interaction.rs delete mode 100644 src/test/run-pass/hygiene/auxiliary/xcrate.rs delete mode 100644 src/test/run-pass/hygiene/items.rs delete mode 100644 src/test/run-pass/hygiene/legacy_interaction.rs delete mode 100644 src/test/run-pass/hygiene/xcrate.rs delete mode 100644 src/test/run-pass/impl-trait/xcrate.rs delete mode 100644 src/test/run-pass/import-crate-with-invalid-spans/main.rs delete mode 100644 src/test/run-pass/issue-18804/main.rs delete mode 100644 src/test/run-pass/issue-36954.rs delete mode 100644 src/test/run-pass/issue-37291/main.rs delete mode 100644 src/test/run-pass/issue-38715.rs create mode 100644 src/test/run-pass/issue-48006.rs create mode 100644 src/test/run-pass/issue-53728.rs delete mode 100644 src/test/run-pass/issue24687-embed-debuginfo/main.rs delete mode 100644 src/test/run-pass/issue_26873_multifile/A/mod.rs delete mode 100644 src/test/run-pass/issue_26873_multifile/mod.rs delete mode 100644 src/test/run-pass/macros-in-extern.rs delete mode 100644 src/test/run-pass/mod_dir_implicit_aux/mod.rs delete mode 100644 src/test/run-pass/mod_dir_simple/test.rs delete mode 100644 src/test/run-pass/non_modrs_mods/non_modrs_mods.rs delete mode 100644 src/test/run-pass/panic-safe.rs delete mode 100644 src/test/run-pass/regions-static-bound.rs delete mode 100644 src/test/run-pass/rfc-2005-default-binding-mode/slice.rs delete mode 100644 src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/enums.rs delete mode 100644 src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/structs.rs delete mode 100644 src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/variants.rs delete mode 100644 src/test/run-pass/rfc-2008-non-exhaustive/enums.rs delete mode 100644 src/test/run-pass/rfc-2008-non-exhaustive/structs.rs delete mode 100644 src/test/run-pass/rfc-2008-non-exhaustive/variants.rs delete mode 100644 src/test/run-pass/rfc-2126-extern-absolute-paths/basic.rs delete mode 100644 src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs delete mode 100644 src/test/run-pass/rfc-2151-raw-identifiers/basic.rs delete mode 100644 src/test/run-pass/rfc-2151-raw-identifiers/items.rs delete mode 100644 src/test/run-pass/rfc-2151-raw-identifiers/macros.rs delete mode 100644 src/test/run-pass/rfc-2175-or-if-while-let/basic.rs delete mode 100644 src/test/run-pass/slice.rs delete mode 100644 src/test/run-pass/spawn.rs create mode 100644 src/test/run-pass/try-block.rs create mode 100644 src/test/run-pass/try-from-int-error-partial-eq.rs create mode 100644 src/test/run-pass/try-is-identifier-edition2015.rs delete mode 100644 src/test/run-pass/try-macro.rs create mode 100644 src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs create mode 100644 src/test/run-pass/uniform-paths/issue-53691.rs delete mode 100644 src/test/run-pass/union/union-const-eval-field.rs create mode 100644 src/test/rustdoc-js/substring.js create mode 100644 src/test/rustdoc-ui/intra-doc-alias-ice.rs create mode 100644 src/test/rustdoc-ui/intra-doc-alias-ice.stderr create mode 100644 src/test/rustdoc/async-fn.rs create mode 100644 src/test/rustdoc/auxiliary/intra-link-extern-crate.rs create mode 100644 src/test/rustdoc/auxiliary/issue-53689.rs create mode 100644 src/test/rustdoc/blanket-reexport-item.rs create mode 100644 src/test/rustdoc/extern-html-root-url.rs create mode 100644 src/test/rustdoc/generic-impl.rs create mode 100644 src/test/rustdoc/impl-everywhere.rs create mode 100644 src/test/rustdoc/intra-link-extern-crate.rs create mode 100644 src/test/rustdoc/intra-link-private.rs create mode 100644 src/test/rustdoc/issue-51236.rs create mode 100644 src/test/rustdoc/issue-53689.rs create mode 100644 src/test/rustdoc/issue-53812.rs create mode 100644 src/test/rustdoc/primitive-generic-impl.rs create mode 100644 src/test/rustdoc/primitive/primitive-generic-impl.rs create mode 100644 src/test/rustdoc/synthetic_auto/static-region.rs create mode 100644 src/test/rustdoc/traits-in-bodies.rs create mode 100644 src/test/ui-fulldeps/attribute-order-restricted.rs create mode 100644 src/test/ui-fulldeps/attribute-order-restricted.stderr create mode 100644 src/test/ui-fulldeps/auxiliary/lint_tool_test.rs create mode 100644 src/test/ui-fulldeps/lint_tool_cmdline_allow.rs create mode 100644 src/test/ui-fulldeps/lint_tool_cmdline_allow.stderr create mode 100644 src/test/ui-fulldeps/lint_tool_test.rs create mode 100644 src/test/ui-fulldeps/lint_tool_test.stderr create mode 100644 src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.rs create mode 100644 src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs-test.stderr create mode 100644 src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.rs create mode 100644 src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr rename src/test/{compile-fail-fulldeps => ui-fulldeps}/proc-macro/auxiliary/attr_proc_macro.rs (100%) rename src/test/{compile-fail-fulldeps => ui-fulldeps}/proc-macro/auxiliary/bang_proc_macro.rs (100%) create mode 100644 src/test/ui-fulldeps/proc-macro/auxiliary/builtin-attrs.rs create mode 100644 src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed-2.rs create mode 100644 src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowed.rs create mode 100644 src/test/ui-fulldeps/proc-macro/auxiliary/derive-helper-shadowing.rs create mode 100644 src/test/ui-fulldeps/proc-macro/auxiliary/issue-53481.rs create mode 100644 src/test/ui-fulldeps/proc-macro/auxiliary/multispan.rs create mode 100644 src/test/ui-fulldeps/proc-macro/derive-helper-shadowed.rs create mode 100644 src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.rs create mode 100644 src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr create mode 100644 src/test/ui-fulldeps/proc-macro/issue-53481.rs rename src/test/{compile-fail-fulldeps => ui-fulldeps}/proc-macro/macro-use-attr.rs (84%) rename src/test/{compile-fail-fulldeps => ui-fulldeps}/proc-macro/macro-use-bang.rs (89%) create mode 100644 src/test/ui-fulldeps/proc-macro/multispan.rs create mode 100644 src/test/ui-fulldeps/proc-macro/multispan.stderr create mode 100644 src/test/ui-fulldeps/proc-macro/reserved-macro-names.rs create mode 100644 src/test/ui-fulldeps/proc-macro/reserved-macro-names.stderr create mode 100644 src/test/ui-fulldeps/rust-2018/auxiliary/suggestions-not-always-applicable.rs create mode 100644 src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed create mode 100644 src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs create mode 100644 src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.stderr create mode 100644 src/test/ui/E0501.ast.nll.stderr create mode 100644 src/test/ui/E0501.ast.stderr create mode 100644 src/test/ui/E0501.mir.stderr rename src/test/{compile-fail => ui}/E0501.rs (100%) create mode 100644 src/test/ui/E0506.ast.nll.stderr create mode 100644 src/test/ui/E0506.ast.stderr create mode 100644 src/test/ui/E0506.mir.stderr rename src/test/{compile-fail => ui}/E0506.rs (100%) create mode 100644 src/test/ui/E0508-fail.ast.nll.stderr create mode 100644 src/test/ui/E0508-fail.ast.stderr create mode 100644 src/test/ui/E0508-fail.mir.stderr rename src/test/{compile-fail/E0508.rs => ui/E0508-fail.rs} (100%) create mode 100644 src/test/ui/E0508.ast.stderr create mode 100644 src/test/ui/E0508.mir.stderr create mode 100644 src/test/ui/E0508.nll.stderr rename src/test/{compile-fail => ui}/E0583.rs (100%) create mode 100644 src/test/ui/E0583.stderr create mode 100644 src/test/ui/E0594.ast.nll.stderr create mode 100644 src/test/ui/E0594.ast.stderr create mode 100644 src/test/ui/E0594.mir.stderr rename src/test/{compile-fail => ui}/E0594.rs (100%) create mode 100644 src/test/ui/E0596.ast.nll.stderr create mode 100644 src/test/ui/E0596.ast.stderr create mode 100644 src/test/ui/E0596.mir.stderr rename src/test/{compile-fail => ui}/E0596.rs (100%) create mode 100644 src/test/ui/E0642.rs create mode 100644 src/test/ui/E0642.stderr create mode 100644 src/test/ui/E0705.rs create mode 100644 src/test/ui/E0705.stderr rename src/test/{compile-fail => ui}/absolute-paths-in-nested-use-groups.rs (100%) create mode 100644 src/test/ui/absolute-paths-in-nested-use-groups.stderr create mode 100644 src/test/ui/access-mode-in-closures.nll.stderr rename src/test/{compile-fail => ui}/access-mode-in-closures.rs (100%) create mode 100644 src/test/ui/access-mode-in-closures.stderr rename src/test/{compile-fail => ui/alloc-error}/alloc-error-handler-bad-signature-1.rs (90%) create mode 100644 src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr rename src/test/{compile-fail => ui/alloc-error}/alloc-error-handler-bad-signature-2.rs (90%) create mode 100644 src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr rename src/test/{compile-fail => ui/alloc-error}/alloc-error-handler-bad-signature-3.rs (89%) create mode 100644 src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr rename src/test/{compile-fail => ui}/allocator/auxiliary/system-allocator.rs (100%) rename src/test/{compile-fail => ui}/allocator/auxiliary/system-allocator2.rs (100%) rename src/test/{compile-fail => ui}/allocator/function-allocator.rs (100%) create mode 100644 src/test/ui/allocator/function-allocator.stderr rename src/test/{compile-fail => ui}/allocator/not-an-allocator.rs (100%) create mode 100644 src/test/ui/allocator/not-an-allocator.stderr rename src/test/{compile-fail => ui}/allocator/two-allocators.rs (100%) create mode 100644 src/test/ui/allocator/two-allocators.stderr rename src/test/{compile-fail => ui}/allocator/two-allocators2.rs (100%) create mode 100644 src/test/ui/allocator/two-allocators2.stderr rename src/test/{compile-fail => ui}/allocator/two-allocators3.rs (100%) create mode 100644 src/test/ui/allocator/two-allocators3.stderr create mode 100644 src/test/ui/anon-params-denied-2018.rs create mode 100644 src/test/ui/anon-params-denied-2018.stderr create mode 100644 src/test/ui/anon-params-deprecated.fixed create mode 100644 src/test/ui/anon-params-deprecated.rs create mode 100644 src/test/ui/anon-params-deprecated.stderr rename src/test/{compile-fail => ui}/arg-count-mismatch.rs (100%) create mode 100644 src/test/ui/arg-count-mismatch.stderr rename src/test/{compile-fail => ui}/arg-type-mismatch.rs (100%) create mode 100644 src/test/ui/arg-type-mismatch.stderr rename src/test/{compile-fail => ui}/array-not-vector.rs (100%) create mode 100644 src/test/ui/array-not-vector.stderr rename src/test/{compile-fail => ui}/array_const_index-0.rs (100%) create mode 100644 src/test/ui/array_const_index-0.stderr rename src/test/{compile-fail => ui}/array_const_index-1.rs (100%) create mode 100644 src/test/ui/array_const_index-1.stderr rename src/test/{compile-fail => ui/asm}/asm-bad-clobber.rs (100%) create mode 100644 src/test/ui/asm/asm-bad-clobber.stderr rename src/test/{compile-fail => ui/asm}/asm-in-bad-modifier.rs (100%) create mode 100644 src/test/ui/asm/asm-in-bad-modifier.stderr rename src/test/{compile-fail => ui/asm}/asm-misplaced-option.rs (100%) create mode 100644 src/test/ui/asm/asm-misplaced-option.stderr rename src/test/ui/{ => asm}/asm-out-assign-imm.nll.stderr (81%) rename src/test/ui/{ => asm}/asm-out-assign-imm.rs (98%) rename src/test/ui/{ => asm}/asm-out-assign-imm.stderr (90%) rename src/test/{compile-fail => ui/asm}/asm-out-no-modifier.rs (100%) create mode 100644 src/test/ui/asm/asm-out-no-modifier.stderr create mode 100644 src/test/ui/asm/asm-out-read-uninit.ast.stderr create mode 100644 src/test/ui/asm/asm-out-read-uninit.mir.stderr rename src/test/{compile-fail => ui/asm}/asm-out-read-uninit.rs (100%) create mode 100644 src/test/ui/assign-imm-local-twice.ast.nll.stderr create mode 100644 src/test/ui/assign-imm-local-twice.ast.stderr create mode 100644 src/test/ui/assign-imm-local-twice.mir.stderr rename src/test/{compile-fail => ui}/assign-imm-local-twice.rs (92%) rename src/test/{compile-fail => ui}/assign-to-method.rs (100%) create mode 100644 src/test/ui/assign-to-method.stderr rename src/test/{compile-fail => ui}/assignment-operator-unimplemented.rs (100%) create mode 100644 src/test/ui/assignment-operator-unimplemented.stderr rename src/test/{compile-fail => ui}/assoc-inherent.rs (100%) create mode 100644 src/test/ui/assoc-inherent.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-ambiguity-report.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-ambiguity-report.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-array-len.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-array-len.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-dead-code.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-dead-code.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-generic-obligations.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-generic-obligations.stderr rename src/test/ui/{ => associated-const}/associated-const-impl-wrong-lifetime.rs (100%) rename src/test/ui/{ => associated-const}/associated-const-impl-wrong-lifetime.stderr (100%) rename src/test/ui/{ => associated-const}/associated-const-impl-wrong-type.rs (100%) rename src/test/ui/{ => associated-const}/associated-const-impl-wrong-type.stderr (100%) rename src/test/{compile-fail => ui/associated-const}/associated-const-in-trait.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-in-trait.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-no-item.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-no-item.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-private-impl.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-private-impl.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-type-parameter-arms.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-type-parameter-arms.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-type-parameter-arrays-2.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-type-parameter-arrays.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr rename src/test/{compile-fail => ui/associated-const}/associated-const-upper-case-lint.rs (100%) create mode 100644 src/test/ui/associated-const/associated-const-upper-case-lint.stderr rename src/test/{compile-fail => ui/associated-item}/associated-item-duplicate-names-2.rs (100%) create mode 100644 src/test/ui/associated-item/associated-item-duplicate-names-2.stderr rename src/test/{compile-fail => ui/associated-item}/associated-item-duplicate-names-3.rs (100%) create mode 100644 src/test/ui/associated-item/associated-item-duplicate-names-3.stderr rename src/test/{compile-fail => ui/associated-item}/associated-item-duplicate-names.rs (100%) create mode 100644 src/test/ui/associated-item/associated-item-duplicate-names.stderr rename src/test/{compile-fail => ui}/associated-path-shl.rs (100%) create mode 100644 src/test/ui/associated-path-shl.stderr rename src/test/{compile-fail => ui/associated-type}/associated-type-projection-ambig-between-bound-and-where-clause.rs (100%) create mode 100644 src/test/ui/associated-type/associated-type-projection-ambig-between-bound-and-where-clause.stderr rename src/test/ui/{ => associated-type}/associated-type-projection-from-multiple-supertraits.rs (100%) rename src/test/ui/{ => associated-type}/associated-type-projection-from-multiple-supertraits.stderr (100%) rename src/test/{compile-fail => ui/associated-type}/associated-type-projection-from-supertrait.rs (100%) create mode 100644 src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr rename src/test/ui/{ => associated-types}/associated-types-ICE-when-projecting-out-of-err.rs (100%) rename src/test/ui/{ => associated-types}/associated-types-ICE-when-projecting-out-of-err.stderr (100%) rename src/test/{compile-fail => ui/associated-types}/associated-types-binding-to-type-defined-in-supertrait.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-bound-failure.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-bound-failure.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-coherence-failure.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-coherence-failure.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-eq-1.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-eq-1.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-eq-2.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-eq-2.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-eq-3.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-eq-3.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-eq-expr-path.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-eq-expr-path.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-eq-hr.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-eq-hr.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-for-unimpl-trait.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr rename src/test/ui/{ => associated-types}/associated-types-in-ambiguous-context.rs (100%) rename src/test/ui/{ => associated-types}/associated-types-in-ambiguous-context.stderr (100%) rename src/test/{compile-fail => ui/associated-types}/associated-types-incomplete-object.rs (94%) create mode 100644 src/test/ui/associated-types/associated-types-incomplete-object.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-invalid-trait-ref-issue-18865.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-issue-17359.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-issue-17359.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-issue-20346.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-issue-20346.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-multiple-types-one-trait.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-multiple-types-one-trait.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-no-suitable-bound.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-no-suitable-bound.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-no-suitable-supertrait-2.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-no-suitable-supertrait.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr create mode 100644 src/test/ui/associated-types/associated-types-outlives.nll.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-outlives.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-outlives.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-overridden-default.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-overridden-default.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-path-1.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-path-1.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-path-2.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-path-2.stderr create mode 100644 src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-project-from-hrtb-in-fn-body.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-project-from-hrtb-in-fn.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-project-from-hrtb-in-struct.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-project-from-hrtb-in-trait-method.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-projection-to-unrelated-trait-in-method-without-default.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-subtyping-1.rs (86%) create mode 100644 src/test/ui/associated-types/associated-types-subtyping-1.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-unconstrained.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-unconstrained.stderr rename src/test/{compile-fail => ui/associated-types}/associated-types-unsized.rs (100%) create mode 100644 src/test/ui/associated-types/associated-types-unsized.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-constrained.clause.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-constrained.func.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-constrained.object.stderr rename src/test/{compile-fail => ui}/associated-types/bound-lifetime-constrained.rs (100%) create mode 100644 src/test/ui/associated-types/bound-lifetime-in-binding-only.angle.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-in-binding-only.paren.stderr rename src/test/{compile-fail => ui}/associated-types/bound-lifetime-in-binding-only.rs (100%) create mode 100644 src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-in-return-only.local.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-in-return-only.ok.stderr rename src/test/{compile-fail => ui}/associated-types/bound-lifetime-in-return-only.rs (100%) create mode 100644 src/test/ui/associated-types/bound-lifetime-in-return-only.sig.stderr create mode 100644 src/test/ui/associated-types/bound-lifetime-in-return-only.structure.stderr rename src/test/{compile-fail => ui}/associated-types/cache/chrono-scan.rs (100%) create mode 100644 src/test/ui/associated-types/cache/chrono-scan.stderr rename src/test/{compile-fail => ui}/associated-types/cache/elision.rs (100%) create mode 100644 src/test/ui/associated-types/cache/elision.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-contravariant.ok.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-contravariant.oneuse.stderr rename src/test/{compile-fail => ui}/associated-types/cache/project-fn-ret-contravariant.rs (100%) create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr rename src/test/{compile-fail => ui}/associated-types/cache/project-fn-ret-invariant.rs (100%) create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr create mode 100644 src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr create mode 100644 src/test/ui/associated-types/higher-ranked-projection.bad.stderr create mode 100644 src/test/ui/associated-types/higher-ranked-projection.good.stderr rename src/test/{compile-fail => ui}/associated-types/higher-ranked-projection.rs (100%) rename src/test/{compile-fail => ui}/associated-types/issue-36499.rs (100%) create mode 100644 src/test/ui/associated-types/issue-36499.stderr create mode 100644 src/test/ui/async-matches-expr.rs rename src/test/{compile-fail => ui}/attempted-access-non-fatal.rs (100%) create mode 100644 src/test/ui/attempted-access-non-fatal.stderr rename src/test/{compile-fail => ui}/attr-bad-crate-attr.rc (100%) create mode 100644 src/test/ui/attr-eq-token-tree.rs rename src/test/{compile-fail => ui}/attr-usage-inline.rs (100%) create mode 100644 src/test/ui/attr-usage-inline.stderr rename src/test/{compile-fail => ui/attrs-with-no-formal-in-generics}/attrs-with-no-formal-in-generics-1.rs (100%) create mode 100644 src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr rename src/test/{compile-fail => ui/attrs-with-no-formal-in-generics}/attrs-with-no-formal-in-generics-2.rs (100%) create mode 100644 src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr rename src/test/{compile-fail => ui/attrs-with-no-formal-in-generics}/attrs-with-no-formal-in-generics-3.rs (100%) create mode 100644 src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr rename src/test/{compile-fail => ui}/auto-ref-slice-plus-ref.rs (100%) create mode 100644 src/test/ui/auto-ref-slice-plus-ref.stderr rename src/test/{compile-fail => ui}/auto-trait-validation.rs (100%) create mode 100644 src/test/ui/auto-trait-validation.stderr rename src/test/{compile-fail => ui}/autoderef-full-lval.rs (100%) create mode 100644 src/test/ui/autoderef-full-lval.stderr rename src/test/{compile-fail => ui}/auxiliary/cdylib-dep.rs (100%) delete mode 100644 src/test/ui/auxiliary/coherence_lib.rs rename src/test/{compile-fail => ui}/auxiliary/default_ty_param_cross_crate_crate.rs (100%) rename src/test/{compile-fail => ui}/auxiliary/define_macro.rs (100%) rename src/test/{compile-fail => ui}/auxiliary/extern-statics.rs (100%) delete mode 100644 src/test/ui/auxiliary/lint_output_format.rs create mode 100644 src/test/ui/auxiliary/lto-duplicate-symbols1.rs create mode 100644 src/test/ui/auxiliary/lto-duplicate-symbols2.rs delete mode 100644 src/test/ui/auxiliary/macro-in-other-crate.rs rename src/test/{compile-fail => ui}/auxiliary/namespaced_enums.rs (100%) rename src/test/{compile-fail => ui}/auxiliary/noexporttypelib.rs (100%) rename src/test/{compile-fail => ui}/auxiliary/orphan_check_diagnostics.rs (100%) rename src/test/{compile-fail => ui}/auxiliary/rmeta_meta.rs (100%) rename src/test/{compile-fail => ui}/auxiliary/rmeta_rlib.rs (100%) create mode 100644 src/test/ui/auxiliary/stability_cfg2.rs create mode 100644 src/test/ui/auxiliary/weak-lang-items.rs rename src/test/{compile-fail => ui}/auxiliary/xc_private_method_lib.rs (100%) rename src/test/{compile-fail => ui/bad}/bad-const-type.rs (100%) create mode 100644 src/test/ui/bad/bad-const-type.stderr rename src/test/ui/{ => bad}/bad-crate-name.rs (100%) rename src/test/ui/{ => bad}/bad-crate-name.stderr (100%) rename src/test/{compile-fail => ui/bad}/bad-env-capture.rs (100%) create mode 100644 src/test/ui/bad/bad-env-capture.stderr rename src/test/{compile-fail => ui/bad}/bad-env-capture2.rs (100%) create mode 100644 src/test/ui/bad/bad-env-capture2.stderr rename src/test/{compile-fail => ui/bad}/bad-env-capture3.rs (100%) create mode 100644 src/test/ui/bad/bad-env-capture3.stderr rename src/test/{compile-fail => ui/bad}/bad-expr-lhs.rs (100%) create mode 100644 src/test/ui/bad/bad-expr-lhs.stderr rename src/test/{compile-fail => ui/bad}/bad-expr-path.rs (100%) create mode 100644 src/test/ui/bad/bad-expr-path.stderr rename src/test/{compile-fail => ui/bad}/bad-expr-path2.rs (100%) create mode 100644 src/test/ui/bad/bad-expr-path2.stderr rename src/test/{compile-fail => ui/bad}/bad-extern-link-attrs.rs (100%) create mode 100644 src/test/ui/bad/bad-extern-link-attrs.stderr rename src/test/{compile-fail => ui/bad}/bad-intrinsic-monomorphization.rs (100%) create mode 100644 src/test/ui/bad/bad-intrinsic-monomorphization.stderr rename src/test/{compile-fail => ui/bad}/bad-lint-cap.rs (100%) create mode 100644 src/test/ui/bad/bad-lint-cap.stderr rename src/test/{compile-fail => ui/bad}/bad-lint-cap2.rs (100%) create mode 100644 src/test/ui/bad/bad-lint-cap2.stderr rename src/test/{compile-fail => ui/bad}/bad-lint-cap3.rs (100%) create mode 100644 src/test/ui/bad/bad-lint-cap3.stderr rename src/test/{compile-fail => ui/bad}/bad-main.rs (100%) create mode 100644 src/test/ui/bad/bad-main.stderr rename src/test/{compile-fail => ui/bad}/bad-method-typaram-kind.rs (100%) create mode 100644 src/test/ui/bad/bad-method-typaram-kind.stderr rename src/test/{compile-fail => ui/bad}/bad-mid-path-type-params.rs (83%) create mode 100644 src/test/ui/bad/bad-mid-path-type-params.stderr rename src/test/{compile-fail => ui/bad}/bad-module.rs (100%) create mode 100644 src/test/ui/bad/bad-module.stderr rename src/test/{compile-fail => ui/bad}/bad-sized.rs (100%) create mode 100644 src/test/ui/bad/bad-sized.stderr rename src/test/{compile-fail => ui/bad}/bad-type-env-capture.rs (100%) create mode 100644 src/test/ui/bad/bad-type-env-capture.stderr create mode 100644 src/test/ui/bastion-of-the-turbofish.rs rename src/test/{compile-fail => ui/bind-by-move}/bind-by-move-neither-can-live-while-the-other-survives-2.rs (100%) create mode 100644 src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.stderr rename src/test/{compile-fail => ui/bind-by-move}/bind-by-move-neither-can-live-while-the-other-survives-3.rs (100%) create mode 100644 src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.stderr rename src/test/{compile-fail => ui/bind-by-move}/bind-by-move-neither-can-live-while-the-other-survives-4.rs (100%) create mode 100644 src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.stderr rename src/test/{compile-fail => ui/bind-by-move}/bind-by-move-no-guards.rs (100%) create mode 100644 src/test/ui/bind-by-move/bind-by-move-no-guards.stderr rename src/test/{compile-fail => ui/binop}/binop-bitxor-str.rs (100%) create mode 100644 src/test/ui/binop/binop-bitxor-str.stderr rename src/test/{compile-fail => ui/binop}/binop-consume-args.rs (100%) create mode 100644 src/test/ui/binop/binop-consume-args.stderr rename src/test/{compile-fail => ui/binop}/binop-logic-float.rs (100%) create mode 100644 src/test/ui/binop/binop-logic-float.stderr rename src/test/{compile-fail => ui/binop}/binop-logic-int.rs (100%) create mode 100644 src/test/ui/binop/binop-logic-int.stderr create mode 100644 src/test/ui/binop/binop-move-semantics.nll.stderr rename src/test/{compile-fail => ui/binop}/binop-move-semantics.rs (100%) create mode 100644 src/test/ui/binop/binop-move-semantics.stderr rename src/test/{compile-fail => ui/binop}/binop-mul-bool.rs (100%) create mode 100644 src/test/ui/binop/binop-mul-bool.stderr rename src/test/{compile-fail => ui/binop}/binop-typeck.rs (100%) create mode 100644 src/test/ui/binop/binop-typeck.stderr rename src/test/{compile-fail => ui/blind}/blind-item-block-item-shadow.rs (100%) create mode 100644 src/test/ui/blind/blind-item-block-item-shadow.stderr rename src/test/{compile-fail => ui/blind}/blind-item-block-middle.rs (100%) create mode 100644 src/test/ui/blind/blind-item-block-middle.stderr rename src/test/ui/{ => blind}/blind-item-item-shadow.rs (100%) rename src/test/ui/{ => blind}/blind-item-item-shadow.stderr (100%) create mode 100644 src/test/ui/borrowck/assign_mutable_fields.nll.stderr create mode 100644 src/test/ui/borrowck/assign_mutable_fields.rs create mode 100644 src/test/ui/borrowck/assign_mutable_fields.stderr create mode 100644 src/test/ui/borrowck/borrow-immutable-upvar-mutation.nll.stderr rename src/test/{compile-fail => ui/borrowck}/borrow-immutable-upvar-mutation.rs (100%) create mode 100644 src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr create mode 100644 src/test/ui/borrowck/borrow-tuple-fields.nll.stderr create mode 100644 src/test/ui/borrowck/borrow-tuple-fields.rs create mode 100644 src/test/ui/borrowck/borrow-tuple-fields.stderr create mode 100644 src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-access-permissions.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-access-permissions.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-access-permissions.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-and-init.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-and-init.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-and-init.stderr create mode 100644 src/test/ui/borrowck/borrowck-anon-fields-struct.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-anon-fields-struct.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-anon-fields-struct.stderr create mode 100644 src/test/ui/borrowck/borrowck-anon-fields-tuple.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-anon-fields-tuple.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-anon-fields-tuple.stderr create mode 100644 src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-anon-fields-variant.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-anon-fields-variant.stderr create mode 100644 src/test/ui/borrowck/borrowck-argument.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-argument.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-argument.stderr create mode 100644 src/test/ui/borrowck/borrowck-asm.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-asm.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-asm.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-asm.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-assign-comp-idx.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-assign-comp-idx.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-assign-comp-idx.stderr create mode 100644 src/test/ui/borrowck/borrowck-assign-comp.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-assign-comp.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-assign-comp.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-assign-comp.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr create mode 100644 src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr create mode 100644 src/test/ui/borrowck/borrowck-assign-to-constants.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-assign-to-constants.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-assign-to-constants.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-assign-to-constants.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-auto-mut-ref-to-immut-var.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr create mode 100644 src/test/ui/borrowck/borrowck-autoref-3261.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-autoref-3261.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-autoref-3261.stderr create mode 100644 src/test/ui/borrowck/borrowck-bad-nested-calls-free.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-bad-nested-calls-free.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-bad-nested-calls-free.stderr create mode 100644 src/test/ui/borrowck/borrowck-bad-nested-calls-move.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-bad-nested-calls-move.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-bad-nested-calls-move.stderr create mode 100644 src/test/ui/borrowck/borrowck-block-unint.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-block-unint.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-block-unint.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrow-from-owned-ptr.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrow-from-stack-variable.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrow-from-stack-variable.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrow-from-temporary.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrow-from-temporary.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrow-mut-object-twice.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrow-mut-object-twice.rs (84%) create mode 100644 src/test/ui/borrowck/borrowck-borrow-mut-object-twice.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrow-overloaded-auto-deref.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrow-overloaded-deref.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrow-overloaded-deref.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrowed-uniq-rvalue-2.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr create mode 100644 src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-borrowed-uniq-rvalue.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr create mode 100644 src/test/ui/borrowck/borrowck-break-uninit-2.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-break-uninit-2.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-break-uninit-2.stderr create mode 100644 src/test/ui/borrowck/borrowck-break-uninit.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-break-uninit.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-break-uninit.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-closures-mut-and-imm.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-closures-mut-of-imm.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-closures-mut-of-imm.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-two-mut-fail.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs create mode 100644 src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-unique-imm.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-closures-unique-imm.rs (85%) create mode 100644 src/test/ui/borrowck/borrowck-closures-unique-imm.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-unique.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-unique.rs create mode 100644 src/test/ui/borrowck/borrowck-closures-unique.stderr create mode 100644 src/test/ui/borrowck/borrowck-closures-use-after-free.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-closures-use-after-free.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-closures-use-after-free.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-consume-unsize-vec.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr create mode 100644 src/test/ui/borrowck/borrowck-consume-upcast-box.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-consume-upcast-box.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-consume-upcast-box.stderr create mode 100644 src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-describe-lvalue.rs (100%) rename src/test/{compile-fail => ui}/borrowck/borrowck-drop-from-guard.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-drop-from-guard.stderr create mode 100644 src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-field-sensitivity.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-field-sensitivity.stderr create mode 100644 src/test/ui/borrowck/borrowck-fn-in-const-a.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-fn-in-const-a.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-fn-in-const-a.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-fn-in-const-c.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-fn-in-const-c.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-fn-in-const-c.stderr create mode 100644 src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr create mode 100644 src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-for-loop-head-linkage.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-for-loop-head-linkage.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-if-no-else.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-if-no-else.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-if-with-else.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-if-with-else.stderr create mode 100644 src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs (100%) rename src/test/{compile-fail => ui}/borrowck/borrowck-init-in-called-fn-expr.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-init-in-fn-expr.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr create mode 100644 src/test/ui/borrowck/borrowck-init-in-fru.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-init-in-fru.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-init-in-fru.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-init-in-fru.rs (100%) rename src/test/{compile-fail => ui}/borrowck/borrowck-init-op-equal.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-init-op-equal.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-init-plus-equal.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-init-plus-equal.stderr create mode 100644 src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-insert-during-each.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-insert-during-each.stderr create mode 100644 src/test/ui/borrowck/borrowck-issue-14498.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-issue-14498.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-issue-14498.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-issue-14498.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-issue-2657-1.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-issue-2657-1.rs (85%) create mode 100644 src/test/ui/borrowck/borrowck-issue-2657-1.stderr create mode 100644 src/test/ui/borrowck/borrowck-issue-2657-2.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-issue-2657-2.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-issue-2657-2.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-issue-48962.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-issue-48962.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-lend-flow-if.rs (98%) create mode 100644 src/test/ui/borrowck/borrowck-lend-flow-if.stderr create mode 100644 src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-lend-flow-loop.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-lend-flow-loop.stderr create mode 100644 src/test/ui/borrowck/borrowck-lend-flow-match.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-lend-flow-match.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-lend-flow-match.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-lend-flow-match.rs (100%) rename src/test/{compile-fail => ui}/borrowck/borrowck-lend-flow.rs (98%) create mode 100644 src/test/ui/borrowck/borrowck-lend-flow.stderr create mode 100644 src/test/ui/borrowck/borrowck-loan-blocks-move-cc.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-loan-blocks-move-cc.rs (85%) create mode 100644 src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr create mode 100644 src/test/ui/borrowck/borrowck-loan-blocks-move.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-loan-blocks-move.rs (83%) create mode 100644 src/test/ui/borrowck/borrowck-loan-blocks-move.stderr create mode 100644 src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-loan-blocks-mut-uniq.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr create mode 100644 src/test/ui/borrowck/borrowck-loan-in-overloaded-op.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-loan-in-overloaded-op.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr create mode 100644 src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-loan-of-static-data-issue-27616.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr create mode 100644 src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-loan-rcvr-overloaded-op.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr create mode 100644 src/test/ui/borrowck/borrowck-loan-rcvr.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-loan-rcvr.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-loan-rcvr.stderr create mode 100644 src/test/ui/borrowck/borrowck-loan-vec-content.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-loan-vec-content.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-loan-vec-content.stderr create mode 100644 src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-local-borrow-outlives-fn.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-local-borrow-outlives-fn.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-match-already-borrowed.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-match-already-borrowed.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-match-already-borrowed.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-match-already-borrowed.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-match-binding-is-assignment.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-match-binding-is-assignment.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-match-binding-is-assignment.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-by-capture.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-by-capture.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-by-capture.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs (86%) create mode 100644 src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-from-unsafe-ptr.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-in-irrefut-pat.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-in-irrefut-pat.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-moved-value-into-closure.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-moved-value-into-closure.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-moved-value-into-closure.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-mut-base-ptr.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-mut-base-ptr.rs (87%) create mode 100644 src/test/ui/borrowck/borrowck-move-mut-base-ptr.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-out-from-array.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-out-from-array.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-out-from-array.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-out-of-overloaded-deref.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-static-item.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-static-item.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-out-of-static-item.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-out-of-struct-with-dtor.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr create mode 100644 src/test/ui/borrowck/borrowck-move-subcomponent.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-move-subcomponent.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-move-subcomponent.stderr create mode 100644 src/test/ui/borrowck/borrowck-multiple-captures.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-multiple-captures.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-multiple-captures.stderr create mode 100644 src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-mut-addr-of-imm-var.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr create mode 100644 src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-mut-borrow-linear-errors.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs (90%) create mode 100644 src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr create mode 100644 src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-mut-slice-of-imm-vec.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-mutate-in-guard.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-mutate-in-guard.stderr create mode 100644 src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-no-cycle-in-exchange-heap.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr create mode 100644 src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-object-lifetime.rs create mode 100644 src/test/ui/borrowck/borrowck-object-lifetime.stderr create mode 100644 src/test/ui/borrowck/borrowck-or-init.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-or-init.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-or-init.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-call.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-overloaded-call.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-overloaded-call.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-autoderef.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-autoderef.rs create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-autoderef.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-overloaded-index-move-from-vec.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-move-index.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-overloaded-index-move-index.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-overloaded-index-ref-index.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-overloaded-index-ref-index.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-partial-reinit-1.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-partial-reinit-1.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-partial-reinit-1.stderr create mode 100644 src/test/ui/borrowck/borrowck-partial-reinit-2.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-partial-reinit-2.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-partial-reinit-2.stderr create mode 100644 src/test/ui/borrowck/borrowck-partial-reinit-3.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-partial-reinit-3.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-partial-reinit-3.stderr create mode 100644 src/test/ui/borrowck/borrowck-partial-reinit-4.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-partial-reinit-4.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-partial-reinit-4.stderr create mode 100644 src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-pat-reassign-binding.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-pat-reassign-binding.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-pat-reassign-binding.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-reborrow-from-mut.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-reborrow-from-mut.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr create mode 100644 src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr create mode 100644 src/test/ui/borrowck/borrowck-ref-mut-of-imm.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-ref-mut-of-imm.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr create mode 100644 src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-return-variable-on-stack-via-clone.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-return.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-return.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-storage-dead.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-storage-dead.stderr create mode 100644 src/test/ui/borrowck/borrowck-struct-update-with-dtor.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-struct-update-with-dtor.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-struct-update-with-dtor.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-struct-update-with-dtor.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-swap-mut-base-ptr.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-swap-mut-base-ptr.rs (88%) create mode 100644 src/test/ui/borrowck/borrowck-swap-mut-base-ptr.stderr create mode 100644 src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs (93%) create mode 100644 src/test/ui/borrowck/borrowck-unary-move.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-unary-move.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-unary-move.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-unary-move.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-unboxed-closures.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-unboxed-closures.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-unboxed-closures.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-uninit-after-item.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-uninit-after-item.stderr create mode 100644 src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-uninit-field-access.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-uninit-field-access.rs (100%) rename src/test/{compile-fail => ui}/borrowck/borrowck-uninit-in-assignop.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr create mode 100644 src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-uninit-ref-chain.rs (100%) rename src/test/{compile-fail => ui}/borrowck/borrowck-uninit.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-uninit.stderr create mode 100644 src/test/ui/borrowck/borrowck-union-borrow-nested.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-union-borrow-nested.rs (86%) create mode 100644 src/test/ui/borrowck/borrowck-union-borrow-nested.stderr create mode 100644 src/test/ui/borrowck/borrowck-union-borrow.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-union-borrow.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-union-borrow.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-union-borrow.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-union-move-assign.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-union-move-assign.stderr create mode 100644 src/test/ui/borrowck/borrowck-union-move.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-union-move.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-union-move.stderr create mode 100644 src/test/ui/borrowck/borrowck-union-uninitialized.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-union-uninitialized.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-union-uninitialized.stderr create mode 100644 src/test/ui/borrowck/borrowck-uniq-via-lend.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-uniq-via-lend.rs (83%) create mode 100644 src/test/ui/borrowck/borrowck-uniq-via-lend.stderr create mode 100644 src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-use-in-index-lvalue.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-use-mut-borrow.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-use-mut-borrow.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-use-mut-borrow.stderr create mode 100644 src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-use-uninitialized-in-cast-trait.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-use-uninitialized-in-cast.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-element-loan.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-vec-pattern-element-loan.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-vec-pattern-loan-from-mut.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.stderr create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-vec-pattern-move-tail.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-vec-pattern-tail-element-loan.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr create mode 100644 src/test/ui/borrowck/borrowck-while-break.nll.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-while-break.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-while-break.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-while-cond.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-while-cond.stderr rename src/test/{compile-fail => ui}/borrowck/borrowck-while.rs (100%) create mode 100644 src/test/ui/borrowck/borrowck-while.stderr create mode 100644 src/test/ui/borrowck/index-mut-help-with-impl.nll.stderr create mode 100644 src/test/ui/borrowck/index-mut-help-with-impl.rs create mode 100644 src/test/ui/borrowck/index-mut-help-with-impl.stderr create mode 100644 src/test/ui/borrowck/index-mut-help.nll.stderr create mode 100644 src/test/ui/borrowck/index-mut-help.rs create mode 100644 src/test/ui/borrowck/index-mut-help.stderr create mode 100644 src/test/ui/borrowck/issue-52713-bug.rs create mode 100644 src/test/ui/borrowck/issue-52713-bug.stderr create mode 100644 src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs create mode 100644 src/test/ui/borrowck/move-in-static-initializer-issue-38520.ast.stderr create mode 100644 src/test/ui/borrowck/move-in-static-initializer-issue-38520.mir.stderr rename src/test/{compile-fail => ui}/borrowck/move-in-static-initializer-issue-38520.rs (97%) create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields.nll.stderr create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields.rs create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields.stderr create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields_overlapping.rs create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields_twice.nll.stderr create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields_twice.rs create mode 100644 src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr rename src/test/{compile-fail => ui}/borrowck/two-phase-across-loop.rs (100%) create mode 100644 src/test/ui/borrowck/two-phase-across-loop.stderr create mode 100644 src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr rename src/test/{compile-fail => ui}/borrowck/two-phase-activation-sharing-interference.rs (100%) create mode 100644 src/test/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr rename src/test/{compile-fail => ui}/borrowck/two-phase-allow-access-during-reservation.rs (100%) rename src/test/{compile-fail => ui}/borrowck/two-phase-cannot-nest-mut-self-calls.rs (100%) create mode 100644 src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr create mode 100644 src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr create mode 100644 src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.stderr create mode 100644 src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr rename src/test/{compile-fail => ui}/borrowck/two-phase-nonrecv-autoref.rs (100%) rename src/test/{compile-fail => ui}/borrowck/two-phase-reservation-sharing-interference-2.rs (100%) create mode 100644 src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr create mode 100644 src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr rename src/test/{compile-fail => ui}/borrowck/two-phase-reservation-sharing-interference.rs (100%) create mode 100644 src/test/ui/borrowck/two-phase-sneaky.nll.stderr rename src/test/{compile-fail => ui}/borrowck/two-phase-sneaky.rs (100%) create mode 100644 src/test/ui/borrowck/two-phase-sneaky.stderr create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.ast.stderr create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.rs rename src/test/{compile-fail => ui}/bounds-lifetime.rs (100%) create mode 100644 src/test/ui/bounds-lifetime.stderr rename src/test/{compile-fail => ui}/break-outside-loop.rs (100%) create mode 100644 src/test/ui/break-outside-loop.stderr rename src/test/{compile-fail => ui/builtin-superkinds}/auxiliary/trait_superkinds_in_metadata.rs (100%) rename src/test/{compile-fail => ui/builtin-superkinds}/builtin-superkinds-double-superkind.rs (100%) create mode 100644 src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr rename src/test/{compile-fail => ui/builtin-superkinds}/builtin-superkinds-in-metadata.rs (100%) create mode 100644 src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr rename src/test/{compile-fail => ui/builtin-superkinds}/builtin-superkinds-self-type.rs (100%) create mode 100644 src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr rename src/test/{compile-fail => ui/builtin-superkinds}/builtin-superkinds-simple.rs (100%) create mode 100644 src/test/ui/builtin-superkinds/builtin-superkinds-simple.stderr rename src/test/{compile-fail => ui/builtin-superkinds}/builtin-superkinds-typaram-not-send.rs (100%) create mode 100644 src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr create mode 100644 src/test/ui/by-move-pattern-binding.nll.stderr rename src/test/{compile-fail => ui}/by-move-pattern-binding.rs (100%) create mode 100644 src/test/ui/by-move-pattern-binding.stderr rename src/test/{compile-fail => ui}/call-fn-never-arg-wrong-type.rs (100%) create mode 100644 src/test/ui/call-fn-never-arg-wrong-type.stderr rename src/test/{compile-fail => ui}/can-begin-expr-check.rs (100%) create mode 100644 src/test/ui/can-begin-expr-check.stderr create mode 100644 src/test/ui/cannot-mutate-captured-non-mut-var.ast.nll.stderr create mode 100644 src/test/ui/cannot-mutate-captured-non-mut-var.ast.stderr create mode 100644 src/test/ui/cannot-mutate-captured-non-mut-var.mir.stderr rename src/test/{compile-fail => ui}/cannot-mutate-captured-non-mut-var.rs (100%) rename src/test/{compile-fail => ui}/capture1.rs (100%) create mode 100644 src/test/ui/capture1.stderr rename src/test/ui/{ => cast}/cast-as-bool.rs (100%) rename src/test/ui/{ => cast}/cast-as-bool.stderr (100%) rename src/test/ui/{ => cast}/cast-errors-issue-43825.rs (100%) rename src/test/ui/{ => cast}/cast-errors-issue-43825.stderr (100%) rename src/test/{compile-fail => ui/cast}/cast-from-nil.rs (100%) create mode 100644 src/test/ui/cast/cast-from-nil.stderr create mode 100644 src/test/ui/cast/cast-ptr-to-int-const.rs create mode 100644 src/test/ui/cast/cast-ptr-to-int-const.stderr rename src/test/ui/{ => cast}/cast-rfc0401-2.rs (100%) rename src/test/ui/{ => cast}/cast-rfc0401-2.stderr (100%) rename src/test/{compile-fail => ui/cast}/cast-to-bare-fn.rs (100%) create mode 100644 src/test/ui/cast/cast-to-bare-fn.stderr rename src/test/{compile-fail => ui/cast}/cast-to-nil.rs (100%) create mode 100644 src/test/ui/cast/cast-to-nil.stderr rename src/test/ui/{ => cast}/cast-to-unsized-trait-object-suggestion.rs (100%) rename src/test/ui/{ => cast}/cast-to-unsized-trait-object-suggestion.stderr (100%) delete mode 100644 src/test/ui/catch-block-type-error.rs delete mode 100644 src/test/ui/catch-block-type-error.stderr rename src/test/{compile-fail => ui}/cdylib-deps-must-be-static.rs (100%) create mode 100644 src/test/ui/cdylib-deps-must-be-static.stderr rename src/test/{compile-fail => ui}/cfg-attr-cfg-2.rs (100%) create mode 100644 src/test/ui/cfg-attr-cfg-2.stderr rename src/test/{compile-fail => ui}/cfg-attr-crate-2.rs (100%) create mode 100644 src/test/ui/cfg-attr-crate-2.stderr rename src/test/{compile-fail => ui}/cfg-attr-invalid-predicate.rs (100%) create mode 100644 src/test/ui/cfg-attr-invalid-predicate.stderr rename src/test/{compile-fail => ui}/cfg-attr-unknown-attribute-macro-expansion.rs (100%) create mode 100644 src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr rename src/test/{compile-fail => ui}/cfg-empty-codemap.rs (79%) rename src/test/{compile-fail => ui}/cfg-in-crate-1.rs (100%) create mode 100644 src/test/ui/cfg-in-crate-1.stderr rename src/test/{compile-fail => ui}/cfg-non-opt-expr.rs (89%) create mode 100644 src/test/ui/cfg-non-opt-expr.stderr rename src/test/{compile-fail => ui}/cfg_attr_path.rs (100%) create mode 100644 src/test/ui/cfg_attr_path.stderr rename src/test/{compile-fail => ui}/check-static-immutable-mut-slices.rs (100%) create mode 100644 src/test/ui/check-static-immutable-mut-slices.stderr create mode 100644 src/test/ui/check-static-values-constraints.nll.stderr rename src/test/{compile-fail => ui}/check-static-values-constraints.rs (100%) create mode 100644 src/test/ui/check-static-values-constraints.stderr rename src/test/{compile-fail => ui}/class-cast-to-trait.rs (100%) create mode 100644 src/test/ui/class-cast-to-trait.stderr rename src/test/{compile-fail => ui}/class-method-missing.rs (100%) create mode 100644 src/test/ui/class-method-missing.stderr rename src/test/{compile-fail => ui}/class-missing-self.rs (100%) create mode 100644 src/test/ui/class-missing-self.stderr rename src/test/{compile-fail => ui}/cleanup-rvalue-scopes-cf.rs (98%) create mode 100644 src/test/ui/cleanup-rvalue-scopes-cf.stderr rename src/test/{compile-fail => ui}/closure-expected-type/README.md (100%) rename src/test/{compile-fail => ui}/closure-expected-type/expect-fn-supply-fn-multiple.rs (100%) create mode 100644 src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr rename src/test/{compile-fail => ui}/closure-expected-type/expect-fn-supply-fn.rs (100%) create mode 100644 src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr rename src/test/{compile-fail => ui}/closure-expected-type/expect-infer-var-appearing-twice.rs (100%) create mode 100644 src/test/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr rename src/test/{compile-fail => ui}/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs (100%) rename src/test/{compile-fail => ui}/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs (100%) delete mode 100644 src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr rename src/test/{compile-fail => ui}/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs (100%) create mode 100644 src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr create mode 100644 src/test/ui/closure-expected.rs create mode 100644 src/test/ui/closure-expected.stderr rename src/test/{compile-fail => ui}/closure_promotion.rs (96%) create mode 100644 src/test/ui/closure_promotion.stderr rename src/test/ui/{ => closures}/closure-array-break-length.rs (100%) rename src/test/ui/{ => closures}/closure-array-break-length.stderr (100%) rename src/test/{compile-fail => ui/closures}/closure-bounds-cant-promote-superkind-in-struct.rs (100%) create mode 100644 src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr create mode 100644 src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.nll.stderr rename src/test/{compile-fail => ui/closures}/closure-bounds-static-cant-capture-borrowed.rs (100%) create mode 100644 src/test/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr rename src/test/{compile-fail => ui/closures}/closure-bounds-subtype.rs (100%) create mode 100644 src/test/ui/closures/closure-bounds-subtype.stderr create mode 100644 src/test/ui/closures/closure-expected-type/expect-region-supply-region.nll.stderr rename src/test/ui/{ => closures}/closure-expected-type/expect-region-supply-region.rs (100%) rename src/test/ui/{ => closures}/closure-expected-type/expect-region-supply-region.stderr (100%) rename src/test/ui/{ => closures}/closure-immutable-outer-variable.fixed (100%) rename src/test/ui/{ => closures}/closure-immutable-outer-variable.nll.stderr (100%) rename src/test/ui/{ => closures}/closure-immutable-outer-variable.rs (100%) rename src/test/ui/{ => closures}/closure-immutable-outer-variable.rs.fixed (100%) rename src/test/ui/{ => closures}/closure-immutable-outer-variable.stderr (100%) rename src/test/ui/{ => closures}/closure-move-sync.rs (100%) rename src/test/ui/{ => closures}/closure-move-sync.stderr (100%) rename src/test/{compile-fail => ui/closures}/closure-no-fn-1.rs (100%) create mode 100644 src/test/ui/closures/closure-no-fn-1.stderr rename src/test/{compile-fail => ui/closures}/closure-no-fn-2.rs (100%) create mode 100644 src/test/ui/closures/closure-no-fn-2.stderr rename src/test/{compile-fail => ui/closures}/closure-no-fn-3.rs (100%) create mode 100644 src/test/ui/closures/closure-no-fn-3.stderr rename src/test/{compile-fail => ui/closures}/closure-referencing-itself-issue-25954.rs (100%) create mode 100644 src/test/ui/closures/closure-referencing-itself-issue-25954.stderr rename src/test/{compile-fail => ui/closures}/closure-reform-bad.rs (100%) create mode 100644 src/test/ui/closures/closure-reform-bad.stderr rename src/test/{compile-fail => ui/closures}/closure-wrong-kind.rs (100%) create mode 100644 src/test/ui/closures/closure-wrong-kind.stderr rename src/test/{compile-fail => ui/coercion}/coerce-expect-unsized-ascribed.rs (100%) create mode 100644 src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr rename src/test/{compile-fail => ui/coercion}/coerce-mut.rs (100%) create mode 100644 src/test/ui/coercion/coerce-mut.stderr create mode 100644 src/test/ui/coercion/coerce-overloaded-autoderef.ast.nll.stderr create mode 100644 src/test/ui/coercion/coerce-overloaded-autoderef.ast.stderr create mode 100644 src/test/ui/coercion/coerce-overloaded-autoderef.mir.nll.stderr create mode 100644 src/test/ui/coercion/coerce-overloaded-autoderef.mir.stderr rename src/test/{compile-fail => ui/coercion}/coerce-overloaded-autoderef.rs (100%) rename src/test/{compile-fail => ui/coercion}/coerce-to-bang-cast.rs (100%) create mode 100644 src/test/ui/coercion/coerce-to-bang-cast.stderr rename src/test/{compile-fail => ui/coercion}/coerce-to-bang.rs (100%) create mode 100644 src/test/ui/coercion/coerce-to-bang.stderr rename src/test/ui/{ => coercion}/coercion-missing-tail-expected-type.rs (100%) rename src/test/ui/{ => coercion}/coercion-missing-tail-expected-type.stderr (100%) rename src/test/{compile-fail => ui/coercion}/coercion-slice.rs (100%) create mode 100644 src/test/ui/coercion/coercion-slice.stderr rename src/test/{compile-fail => ui/coherence}/auxiliary/coherence_copy_like_lib.rs (100%) rename src/test/{compile-fail => ui/coherence}/auxiliary/coherence_inherent_cc_lib.rs (100%) rename src/test/{compile-fail => ui/coherence}/auxiliary/coherence_lib.rs (100%) rename src/test/{compile-fail => ui/coherence}/auxiliary/coherence_orphan_lib.rs (100%) rename src/test/{compile-fail => ui/coherence}/auxiliary/go_trait.rs (100%) rename src/test/{compile-fail => ui/coherence}/auxiliary/trait_impl_conflict.rs (100%) rename src/test/{compile-fail => ui/coherence}/coherence-all-remote.rs (100%) create mode 100644 src/test/ui/coherence/coherence-all-remote.stderr rename src/test/{compile-fail => ui/coherence}/coherence-bigint-param.rs (100%) create mode 100644 src/test/ui/coherence/coherence-bigint-param.stderr rename src/test/{compile-fail => ui/coherence}/coherence-blanket-conflicts-with-blanket-implemented.rs (100%) create mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr rename src/test/{compile-fail => ui/coherence}/coherence-blanket-conflicts-with-blanket-unimplemented.rs (100%) create mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr rename src/test/{compile-fail => ui/coherence}/coherence-blanket-conflicts-with-specific-cross-crate.rs (100%) create mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr rename src/test/{compile-fail => ui/coherence}/coherence-blanket-conflicts-with-specific-multidispatch.rs (100%) create mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr rename src/test/{compile-fail => ui/coherence}/coherence-blanket-conflicts-with-specific-trait.rs (100%) create mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr rename src/test/{compile-fail => ui/coherence}/coherence-blanket-conflicts-with-specific.rs (100%) create mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-specific.stderr rename src/test/{compile-fail => ui/coherence}/coherence-conflicting-negative-trait-impl.rs (100%) create mode 100644 src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr create mode 100644 src/test/ui/coherence/coherence-cow.a.stderr create mode 100644 src/test/ui/coherence/coherence-cow.b.stderr create mode 100644 src/test/ui/coherence/coherence-cow.c.stderr rename src/test/{compile-fail => ui/coherence}/coherence-cow.rs (100%) rename src/test/{compile-fail => ui/coherence}/coherence-cross-crate-conflict.rs (100%) create mode 100644 src/test/ui/coherence/coherence-cross-crate-conflict.stderr rename src/test/{compile-fail => ui/coherence}/coherence-default-trait-impl.rs (100%) create mode 100644 src/test/ui/coherence/coherence-default-trait-impl.stderr rename src/test/ui/{ => coherence}/coherence-error-suppression.rs (100%) rename src/test/ui/{ => coherence}/coherence-error-suppression.stderr (100%) rename src/test/{compile-fail => ui/coherence}/coherence-impl-trait-for-trait-object-safe.rs (100%) create mode 100644 src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr rename src/test/{compile-fail => ui/coherence}/coherence-impl-trait-for-trait.rs (100%) create mode 100644 src/test/ui/coherence/coherence-impl-trait-for-trait.stderr rename src/test/ui/{ => coherence}/coherence-impls-copy.rs (100%) rename src/test/ui/{ => coherence}/coherence-impls-copy.stderr (100%) rename src/test/{compile-fail => ui/coherence}/coherence-impls-send.rs (100%) create mode 100644 src/test/ui/coherence/coherence-impls-send.stderr rename src/test/{compile-fail => ui/coherence}/coherence-impls-sized.rs (100%) create mode 100644 src/test/ui/coherence/coherence-impls-sized.stderr rename src/test/{compile-fail => ui/coherence}/coherence-inherited-assoc-ty-cycle-err.rs (100%) create mode 100644 src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr rename src/test/{compile-fail => ui/coherence}/coherence-lone-type-parameter.rs (100%) create mode 100644 src/test/ui/coherence/coherence-lone-type-parameter.stderr rename src/test/{compile-fail => ui/coherence}/coherence-negative-impls-safe.rs (100%) create mode 100644 src/test/ui/coherence/coherence-negative-impls-safe.stderr rename src/test/{compile-fail => ui/coherence}/coherence-no-direct-lifetime-dispatch.rs (100%) create mode 100644 src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr rename src/test/{compile-fail => ui/coherence}/coherence-orphan.rs (100%) create mode 100644 src/test/ui/coherence/coherence-orphan.stderr rename src/test/{compile-fail => ui/coherence}/coherence-overlap-all-t-and-tuple.rs (100%) create mode 100644 src/test/ui/coherence/coherence-overlap-all-t-and-tuple.stderr rename src/test/ui/{ => coherence}/coherence-overlap-downstream-inherent.rs (100%) rename src/test/ui/{ => coherence}/coherence-overlap-downstream-inherent.stderr (100%) rename src/test/ui/{ => coherence}/coherence-overlap-downstream.rs (100%) rename src/test/ui/{ => coherence}/coherence-overlap-downstream.stderr (100%) rename src/test/ui/{ => coherence}/coherence-overlap-issue-23516-inherent.rs (100%) rename src/test/ui/{ => coherence}/coherence-overlap-issue-23516-inherent.stderr (100%) rename src/test/ui/{ => coherence}/coherence-overlap-issue-23516.rs (100%) rename src/test/ui/{ => coherence}/coherence-overlap-issue-23516.stderr (100%) rename src/test/{compile-fail => ui/coherence}/coherence-overlap-messages.rs (100%) create mode 100644 src/test/ui/coherence/coherence-overlap-messages.stderr rename src/test/ui/{ => coherence}/coherence-overlap-upstream-inherent.rs (100%) rename src/test/ui/{ => coherence}/coherence-overlap-upstream-inherent.stderr (100%) rename src/test/ui/{ => coherence}/coherence-overlap-upstream.rs (100%) rename src/test/ui/{ => coherence}/coherence-overlap-upstream.stderr (100%) rename src/test/{compile-fail => ui/coherence}/coherence-overlapping-pairs.rs (100%) create mode 100644 src/test/ui/coherence/coherence-overlapping-pairs.stderr rename src/test/{compile-fail => ui/coherence}/coherence-pair-covered-uncovered-1.rs (100%) create mode 100644 src/test/ui/coherence/coherence-pair-covered-uncovered-1.stderr rename src/test/{compile-fail => ui/coherence}/coherence-pair-covered-uncovered.rs (100%) create mode 100644 src/test/ui/coherence/coherence-pair-covered-uncovered.stderr rename src/test/{compile-fail => ui/coherence}/coherence-projection-conflict-orphan.rs (100%) create mode 100644 src/test/ui/coherence/coherence-projection-conflict-orphan.stderr rename src/test/{compile-fail => ui/coherence}/coherence-projection-conflict-ty-param.rs (100%) create mode 100644 src/test/ui/coherence/coherence-projection-conflict-ty-param.stderr rename src/test/{compile-fail => ui/coherence}/coherence-projection-conflict.rs (100%) create mode 100644 src/test/ui/coherence/coherence-projection-conflict.stderr rename src/test/{compile-fail => ui/coherence}/coherence-projection-ok-orphan.rs (100%) create mode 100644 src/test/ui/coherence/coherence-projection-ok-orphan.stderr rename src/test/{compile-fail => ui/coherence}/coherence-projection-ok.rs (100%) create mode 100644 src/test/ui/coherence/coherence-projection-ok.stderr rename src/test/{compile-fail => ui/coherence}/coherence-tuple-conflict.rs (100%) create mode 100644 src/test/ui/coherence/coherence-tuple-conflict.stderr rename src/test/{compile-fail => ui/coherence}/coherence-vec-local-2.rs (100%) create mode 100644 src/test/ui/coherence/coherence-vec-local-2.stderr rename src/test/{compile-fail => ui/coherence}/coherence-vec-local.rs (100%) create mode 100644 src/test/ui/coherence/coherence-vec-local.stderr rename src/test/{compile-fail => ui/coherence}/coherence_copy_like_err_fundamental_struct.rs (100%) create mode 100644 src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.stderr rename src/test/{compile-fail => ui/coherence}/coherence_copy_like_err_fundamental_struct_ref.rs (100%) create mode 100644 src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_ref.stderr rename src/test/{compile-fail => ui/coherence}/coherence_copy_like_err_fundamental_struct_tuple.rs (100%) create mode 100644 src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr rename src/test/{compile-fail => ui/coherence}/coherence_copy_like_err_struct.rs (100%) create mode 100644 src/test/ui/coherence/coherence_copy_like_err_struct.stderr rename src/test/{compile-fail => ui/coherence}/coherence_copy_like_err_tuple.rs (100%) create mode 100644 src/test/ui/coherence/coherence_copy_like_err_tuple.stderr rename src/test/{compile-fail => ui/coherence}/coherence_inherent.rs (100%) create mode 100644 src/test/ui/coherence/coherence_inherent.stderr rename src/test/{compile-fail => ui/coherence}/coherence_inherent_cc.rs (100%) create mode 100644 src/test/ui/coherence/coherence_inherent_cc.stderr rename src/test/{compile-fail => ui/coherence}/coherence_local.rs (100%) create mode 100644 src/test/ui/coherence/coherence_local.stderr rename src/test/{compile-fail => ui/coherence}/coherence_local_err_struct.rs (100%) create mode 100644 src/test/ui/coherence/coherence_local_err_struct.stderr rename src/test/{compile-fail => ui/coherence}/coherence_local_err_tuple.rs (100%) create mode 100644 src/test/ui/coherence/coherence_local_err_tuple.stderr rename src/test/{compile-fail => ui/coherence}/coherence_local_ref.rs (100%) create mode 100644 src/test/ui/coherence/coherence_local_ref.stderr rename src/test/{compile-fail => ui}/compile_error_macro.rs (100%) create mode 100644 src/test/ui/compile_error_macro.stderr rename src/test/{compile-fail => ui}/concat.rs (100%) create mode 100644 src/test/ui/concat.stderr rename src/test/{compile-fail => ui}/conflicting-repr-hints.rs (100%) create mode 100644 src/test/ui/conflicting-repr-hints.stderr rename src/test/{compile-fail => ui}/conservative_impl_trait.rs (100%) create mode 100644 src/test/ui/conservative_impl_trait.stderr delete mode 100644 src/test/ui/const-deref-ptr.stderr delete mode 100644 src/test/ui/const-eval/dont_promote_unstable_const_fn.nll.stderr delete mode 100644 src/test/ui/const-eval/match-test-ptr-null.stderr delete mode 100644 src/test/ui/const-eval/ref_to_float_transmute.rs delete mode 100644 src/test/ui/const-eval/ub-enum-ptr.rs delete mode 100644 src/test/ui/const-eval/ub-enum-ptr.stderr delete mode 100644 src/test/ui/const-eval/ub-ptr-in-usize.rs delete mode 100644 src/test/ui/const-eval/union-const-eval-field.rs delete mode 100644 src/test/ui/const-eval/union-const-eval-field.stderr delete mode 100644 src/test/ui/const-eval/union-ice.stderr rename src/test/{compile-fail => ui}/constructor-lifetime-args.rs (79%) create mode 100644 src/test/ui/constructor-lifetime-args.stderr create mode 100644 src/test/ui/consts/auxiliary/const_fn_lib.rs rename src/test/{compile-fail => ui/consts}/const-array-oob-arith.rs (100%) create mode 100644 src/test/ui/consts/const-array-oob-arith.stderr rename src/test/{compile-fail => ui/consts}/const-array-oob.rs (100%) create mode 100644 src/test/ui/consts/const-array-oob.stderr rename src/test/{compile-fail => ui/consts}/const-block-non-item-statement-2.rs (100%) create mode 100644 src/test/ui/consts/const-block-non-item-statement-2.stderr rename src/test/{compile-fail => ui/consts}/const-block-non-item-statement-3.rs (100%) create mode 100644 src/test/ui/consts/const-block-non-item-statement-3.stderr rename src/test/{compile-fail => ui/consts}/const-block-non-item-statement.rs (100%) create mode 100644 src/test/ui/consts/const-block-non-item-statement.stderr rename src/test/{compile-fail => ui/consts}/const-call.rs (100%) create mode 100644 src/test/ui/consts/const-call.stderr rename src/test/{compile-fail => ui/consts}/const-cast-different-types.rs (100%) create mode 100644 src/test/ui/consts/const-cast-different-types.stderr rename src/test/{compile-fail => ui/consts}/const-cast-wrong-type.rs (100%) create mode 100644 src/test/ui/consts/const-cast-wrong-type.stderr rename src/test/ui/{ => consts}/const-deref-ptr.rs (82%) create mode 100644 src/test/ui/consts/const-deref-ptr.stderr rename src/test/{compile-fail => ui/consts}/const-err-early.rs (100%) create mode 100644 src/test/ui/consts/const-err-early.stderr rename src/test/{compile-fail => ui/consts}/const-err-multi.rs (100%) create mode 100644 src/test/ui/consts/const-err-multi.stderr rename src/test/{compile-fail => ui/consts}/const-err.rs (100%) create mode 100644 src/test/ui/consts/const-err.stderr rename src/test/{compile-fail => ui/consts}/const-err2.rs (100%) create mode 100644 src/test/ui/consts/const-err2.stderr rename src/test/{compile-fail => ui/consts}/const-err4.rs (88%) create mode 100644 src/test/ui/consts/const-err4.stderr rename src/test/ui/{ => consts}/const-eval/conditional_array_execution.nll.stderr (100%) rename src/test/ui/{ => consts}/const-eval/conditional_array_execution.rs (100%) rename src/test/ui/{ => consts}/const-eval/conditional_array_execution.stderr (100%) rename src/test/ui/{ => consts/const-eval}/const-eval-overflow-2.rs (100%) rename src/test/ui/{ => consts/const-eval}/const-eval-overflow-2.stderr (100%) rename src/test/{compile-fail => ui/consts/const-eval}/const-eval-overflow-3.rs (100%) create mode 100644 src/test/ui/consts/const-eval/const-eval-overflow-3.stderr rename src/test/{compile-fail => ui/consts/const-eval}/const-eval-overflow-3b.rs (100%) create mode 100644 src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr rename src/test/ui/{ => consts/const-eval}/const-eval-overflow-4.rs (100%) rename src/test/ui/{ => consts/const-eval}/const-eval-overflow-4.stderr (100%) rename src/test/{compile-fail => ui/consts/const-eval}/const-eval-overflow-4b.rs (100%) create mode 100644 src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr rename src/test/{compile-fail => ui/consts/const-eval}/const-eval-overflow2.rs (100%) create mode 100644 src/test/ui/consts/const-eval/const-eval-overflow2.stderr rename src/test/{compile-fail => ui/consts/const-eval}/const-eval-overflow2b.rs (100%) create mode 100644 src/test/ui/consts/const-eval/const-eval-overflow2b.stderr rename src/test/{compile-fail => ui/consts/const-eval}/const-eval-overflow2c.rs (100%) create mode 100644 src/test/ui/consts/const-eval/const-eval-overflow2c.stderr rename src/test/ui/{ => consts/const-eval}/const-eval-span.rs (100%) rename src/test/ui/{ => consts/const-eval}/const-eval-span.stderr (100%) create mode 100644 src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs create mode 100644 src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr rename src/test/ui/{ => consts}/const-eval/const_let.rs (100%) rename src/test/ui/{ => consts}/const-eval/const_let.stderr (100%) create mode 100644 src/test/ui/consts/const-eval/const_panic.rs create mode 100644 src/test/ui/consts/const-eval/const_panic.stderr create mode 100644 src/test/ui/consts/const-eval/const_panic_libcore.rs create mode 100644 src/test/ui/consts/const-eval/const_panic_libcore.stderr create mode 100644 src/test/ui/consts/const-eval/const_panic_libcore_main.rs create mode 100644 src/test/ui/consts/const-eval/const_panic_libcore_main.stderr rename src/test/ui/{ => consts}/const-eval/const_prop_errors.rs (100%) create mode 100644 src/test/ui/consts/const-eval/const_raw_ptr_ops.rs create mode 100644 src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr rename src/test/ui/{ => consts}/const-eval/const_signed_pat.rs (100%) rename src/test/ui/{ => consts}/const-eval/const_transmute.rs (98%) rename src/test/ui/{ => consts}/const-eval/dont_promote_unstable_const_fn.rs (100%) rename src/test/ui/{ => consts}/const-eval/dont_promote_unstable_const_fn.stderr (100%) delete mode 100644 src/test/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.nll.stderr rename src/test/ui/{ => consts}/const-eval/double_check.rs (100%) rename src/test/ui/{ => consts}/const-eval/double_check2.rs (100%) rename src/test/ui/{ => consts}/const-eval/double_check2.stderr (84%) rename src/test/ui/{ => consts}/const-eval/duration_conversion.rs (100%) rename src/test/ui/{ => consts}/const-eval/enum_discr.rs (100%) rename src/test/ui/{ => consts}/const-eval/extern_fat_pointer.rs (100%) create mode 100644 src/test/ui/consts/const-eval/feature-gate-const_fn_union.rs create mode 100644 src/test/ui/consts/const-eval/feature-gate-const_fn_union.stderr create mode 100644 src/test/ui/consts/const-eval/feature-gate-const_panic.rs create mode 100644 src/test/ui/consts/const-eval/feature-gate-const_panic.stderr rename src/test/ui/{ => consts}/const-eval/ice-generic-assoc-const.rs (100%) rename src/test/ui/{ => consts}/const-eval/ice-packed.rs (100%) rename src/test/ui/{ => consts}/const-eval/index_out_of_bounds.rs (100%) rename src/test/ui/{ => consts}/const-eval/index_out_of_bounds.stderr (100%) rename src/test/ui/{ => consts}/const-eval/index_out_of_bounds_propagated.rs (100%) rename src/test/ui/{ => consts}/const-eval/index_out_of_bounds_propagated.stderr (100%) rename src/test/ui/{ => consts}/const-eval/infinite_loop.rs (100%) rename src/test/ui/{ => consts}/const-eval/infinite_loop.stderr (100%) rename src/test/ui/{ => consts}/const-eval/issue-43197.nll.stderr (100%) rename src/test/ui/{ => consts}/const-eval/issue-43197.rs (96%) rename src/test/ui/{ => consts}/const-eval/issue-43197.stderr (100%) rename src/test/ui/{ => consts}/const-eval/issue-44578.nll.stderr (100%) rename src/test/ui/{ => consts}/const-eval/issue-44578.rs (100%) rename src/test/ui/{ => consts}/const-eval/issue-44578.stderr (100%) rename src/test/ui/{ => consts}/const-eval/issue-47971.rs (95%) rename src/test/ui/{ => consts}/const-eval/issue-50706.rs (100%) rename src/test/ui/{ => consts}/const-eval/issue-50814-2.rs (100%) rename src/test/ui/{ => consts}/const-eval/issue-50814-2.stderr (100%) rename src/test/ui/{ => consts}/const-eval/issue-50814.rs (100%) rename src/test/ui/{ => consts}/const-eval/issue-50814.stderr (100%) rename src/test/ui/{ => consts}/const-eval/issue-51300.rs (100%) rename src/test/ui/{ => consts}/const-eval/issue-52442.rs (100%) rename src/test/ui/{ => consts}/const-eval/issue-52442.stderr (100%) rename src/test/ui/{ => consts}/const-eval/issue-52443.rs (100%) rename src/test/ui/{ => consts}/const-eval/issue-52443.stderr (100%) create mode 100644 src/test/ui/consts/const-eval/issue-52475.rs create mode 100644 src/test/ui/consts/const-eval/issue-52475.stderr rename src/test/ui/{ => consts}/const-eval/issue-53157.rs (100%) rename src/test/ui/{ => consts}/const-eval/match-test-ptr-null.rs (91%) create mode 100644 src/test/ui/consts/const-eval/match-test-ptr-null.stderr create mode 100644 src/test/ui/consts/const-eval/mod-static-with-const-fn.rs create mode 100644 src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr rename src/test/ui/{ => consts}/const-eval/no_lint_for_statically_known_error.rs (100%) rename src/test/ui/{ => consts}/const-eval/promote_mutable_zst_mir_borrowck.rs (100%) rename src/test/ui/{ => consts}/const-eval/promoted_const_fn_fail.rs (96%) rename src/test/ui/{ => consts}/const-eval/promoted_errors.rs (100%) rename src/test/ui/{ => consts}/const-eval/promoted_errors.stderr (100%) create mode 100644 src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs create mode 100644 src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr rename src/test/ui/{ => consts}/const-eval/pub_const_err.rs (100%) rename src/test/ui/{ => consts}/const-eval/pub_const_err.stderr (100%) rename src/test/ui/{ => consts}/const-eval/pub_const_err_bin.rs (100%) rename src/test/ui/{ => consts}/const-eval/pub_const_err_bin.stderr (100%) rename src/test/ui/{ => consts}/const-eval/ref_to_int_match.rs (96%) rename src/test/ui/{ => consts}/const-eval/ref_to_int_match.stderr (90%) rename src/test/ui/{ => consts}/const-eval/shift_overflow.rs (100%) rename src/test/ui/{ => consts}/const-eval/shift_overflow.stderr (100%) create mode 100644 src/test/ui/consts/const-eval/simple_with_undef.rs rename src/test/ui/{ => consts}/const-eval/strlen.rs (100%) create mode 100644 src/test/ui/consts/const-eval/transmute-const-promotion.rs create mode 100644 src/test/ui/consts/const-eval/transmute-const-promotion.stderr create mode 100644 src/test/ui/consts/const-eval/transmute-const.rs create mode 100644 src/test/ui/consts/const-eval/transmute-const.stderr create mode 100644 src/test/ui/consts/const-eval/ub-enum.rs create mode 100644 src/test/ui/consts/const-eval/ub-enum.stderr rename src/test/ui/{ => consts}/const-eval/ub-uninhabit.rs (100%) rename src/test/ui/{ => consts}/const-eval/ub-uninhabit.stderr (100%) rename src/test/ui/{ => consts}/const-eval/ub-usize-in-ref.rs (100%) create mode 100644 src/test/ui/consts/const-eval/union-const-eval-field.rs create mode 100644 src/test/ui/consts/const-eval/union-const-eval-field.stderr rename src/test/ui/{ => consts}/const-eval/union-ice.rs (89%) create mode 100644 src/test/ui/consts/const-eval/union-ice.stderr rename src/test/ui/{ => consts}/const-eval/union-ub.rs (100%) rename src/test/ui/{ => consts}/const-eval/union-ub.stderr (100%) rename src/test/ui/{ => consts}/const-eval/union_promotion.rs (100%) rename src/test/ui/{ => consts}/const-eval/union_promotion.stderr (100%) create mode 100644 src/test/ui/consts/const-eval/zst_operand_eval.rs rename src/test/ui/{ => consts}/const-expr-addr-operator.rs (100%) rename src/test/{compile-fail => ui/consts}/const-fn-destructuring-arg.rs (100%) create mode 100644 src/test/ui/consts/const-fn-destructuring-arg.stderr rename src/test/ui/{ => consts}/const-fn-error.rs (100%) rename src/test/ui/{ => consts}/const-fn-error.stderr (100%) rename src/test/ui/{ => consts}/const-fn-mismatch.rs (100%) rename src/test/ui/{ => consts}/const-fn-mismatch.stderr (100%) rename src/test/ui/{ => consts}/const-fn-not-in-trait.rs (100%) rename src/test/ui/{ => consts}/const-fn-not-in-trait.stderr (100%) rename src/test/{compile-fail => ui/consts}/const-fn-not-safe-for-const.rs (95%) create mode 100644 src/test/ui/consts/const-fn-not-safe-for-const.stderr rename src/test/{compile-fail => ui/consts}/const-fn-stability-calls-3.rs (100%) create mode 100644 src/test/ui/consts/const-fn-stability-calls-3.stderr create mode 100644 src/test/ui/consts/const-int-conversion.rs create mode 100644 src/test/ui/consts/const-int-conversion.stderr create mode 100644 src/test/ui/consts/const-int-overflowing.rs create mode 100644 src/test/ui/consts/const-int-overflowing.stderr create mode 100644 src/test/ui/consts/const-int-rotate.rs create mode 100644 src/test/ui/consts/const-int-rotate.stderr create mode 100644 src/test/ui/consts/const-int-sign.rs create mode 100644 src/test/ui/consts/const-int-sign.stderr create mode 100644 src/test/ui/consts/const-int-unchecked.rs create mode 100644 src/test/ui/consts/const-int-unchecked.stderr create mode 100644 src/test/ui/consts/const-int-wrapping.rs create mode 100644 src/test/ui/consts/const-int-wrapping.stderr rename src/test/{compile-fail => ui/consts}/const-integer-bool-ops.rs (100%) create mode 100644 src/test/ui/consts/const-integer-bool-ops.stderr rename src/test/ui/{ => consts}/const-len-underflow-separate-spans.rs (100%) rename src/test/ui/{ => consts}/const-len-underflow-separate-spans.stderr (100%) rename src/test/{compile-fail => ui/consts}/const-len-underflow-subspans.rs (100%) create mode 100644 src/test/ui/consts/const-len-underflow-subspans.stderr create mode 100644 src/test/ui/consts/const-match-check.eval1.stderr create mode 100644 src/test/ui/consts/const-match-check.eval2.stderr create mode 100644 src/test/ui/consts/const-match-check.matchck.stderr rename src/test/{compile-fail => ui/consts}/const-match-check.rs (100%) rename src/test/{compile-fail => ui/consts}/const-match-pattern-arm.rs (100%) create mode 100644 src/test/ui/consts/const-match-pattern-arm.stderr rename src/test/ui/{ => consts}/const-pattern-irrefutable.rs (100%) rename src/test/ui/{ => consts}/const-pattern-irrefutable.stderr (100%) rename src/test/ui/{ => consts}/const-pattern-not-const-evaluable.rs (97%) rename src/test/{compile-fail => ui/consts}/const-size_of-cycle.rs (95%) create mode 100644 src/test/ui/consts/const-size_of-cycle.stderr rename src/test/{compile-fail => ui/consts}/const-slice-oob.rs (100%) create mode 100644 src/test/ui/consts/const-slice-oob.stderr rename src/test/{compile-fail => ui/consts}/const-tup-index-span.rs (100%) create mode 100644 src/test/ui/consts/const-tup-index-span.stderr rename src/test/ui/{ => consts}/const-type-mismatch.rs (100%) rename src/test/ui/{ => consts}/const-type-mismatch.stderr (100%) rename src/test/{compile-fail => ui/consts}/const-typeid-of.rs (100%) create mode 100644 src/test/ui/consts/const-typeid-of.stderr rename src/test/ui/{ => consts}/const-unsized.rs (100%) rename src/test/ui/{ => consts}/const-unsized.stderr (96%) create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr rename src/test/{compile-fail => ui}/copy-a-resource.rs (100%) create mode 100644 src/test/ui/copy-a-resource.stderr create mode 100644 src/test/ui/crate-in-paths.rs create mode 100644 src/test/ui/crate-in-paths.stderr rename src/test/{compile-fail => ui}/crate-name-mismatch.rs (100%) create mode 100644 src/test/ui/crate-name-mismatch.stderr rename src/test/{compile-fail => ui/cross}/cross-borrow-trait.rs (100%) create mode 100644 src/test/ui/cross/cross-borrow-trait.stderr rename src/test/ui/{ => cross}/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs (100%) rename src/test/ui/{ => cross}/cross-crate-macro-backtrace/main.rs (100%) rename src/test/ui/{ => cross}/cross-crate-macro-backtrace/main.stderr (100%) rename src/test/ui/{ => cross}/cross-file-errors/main.rs (100%) rename src/test/ui/{ => cross}/cross-file-errors/main.stderr (100%) rename src/test/ui/{ => cross}/cross-file-errors/underscore.rs (100%) rename src/test/{compile-fail => ui/cross}/cross-fn-cache-hole.rs (100%) create mode 100644 src/test/ui/cross/cross-fn-cache-hole.stderr create mode 100644 src/test/ui/custom-attribute-multisegment.rs create mode 100644 src/test/ui/custom-attribute-multisegment.stderr create mode 100644 src/test/ui/custom-test-frameworks-simple.rs rename src/test/{compile-fail => ui}/custom_attribute.rs (100%) create mode 100644 src/test/ui/custom_attribute.stderr create mode 100644 src/test/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs create mode 100644 src/test/ui/custom_test_frameworks/auxiliary/example_runner.rs create mode 100644 src/test/ui/custom_test_frameworks/dynamic.rs create mode 100644 src/test/ui/custom_test_frameworks/full.rs create mode 100644 src/test/ui/custom_test_frameworks/mismatch.rs create mode 100644 src/test/ui/custom_test_frameworks/mismatch.stderr rename src/test/{compile-fail => ui}/cycle-projection-based-on-where-clause.rs (100%) create mode 100644 src/test/ui/cycle-projection-based-on-where-clause.stderr rename src/test/{compile-fail => ui/cycle-trait}/cycle-trait-default-type-trait.rs (100%) create mode 100644 src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr rename src/test/{compile-fail => ui/cycle-trait}/cycle-trait-supertrait-direct.rs (100%) create mode 100644 src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr rename src/test/ui/{ => cycle-trait}/cycle-trait-supertrait-indirect.rs (100%) rename src/test/ui/{ => cycle-trait}/cycle-trait-supertrait-indirect.stderr (100%) rename src/test/{compile-fail => ui}/dead-code-closure-bang.rs (100%) rename src/test/{compile-fail => ui}/dead-code-ret.rs (100%) create mode 100644 src/test/ui/dead-code-ret.stderr rename src/test/{compile-fail => ui}/defaulted-never-note.rs (94%) create mode 100644 src/test/ui/defaulted-never-note.stderr rename src/test/{compile-fail => ui/dep-graph}/dep-graph-assoc-type-codegen.rs (100%) create mode 100644 src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr rename src/test/{compile-fail => ui/dep-graph}/dep-graph-caller-callee.rs (100%) create mode 100644 src/test/ui/dep-graph/dep-graph-caller-callee.stderr rename src/test/{compile-fail => ui/dep-graph}/dep-graph-struct-signature.rs (97%) create mode 100644 src/test/ui/dep-graph/dep-graph-struct-signature.stderr rename src/test/{compile-fail => ui/dep-graph}/dep-graph-trait-impl-two-traits-same-method.rs (100%) create mode 100644 src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr rename src/test/{compile-fail => ui/dep-graph}/dep-graph-trait-impl-two-traits.rs (100%) create mode 100644 src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr rename src/test/{compile-fail => ui/dep-graph}/dep-graph-trait-impl.rs (100%) create mode 100644 src/test/ui/dep-graph/dep-graph-trait-impl.stderr rename src/test/{compile-fail => ui/dep-graph}/dep-graph-type-alias.rs (100%) create mode 100644 src/test/ui/dep-graph/dep-graph-type-alias.stderr rename src/test/{compile-fail => ui/dep-graph}/dep-graph-variance-alias.rs (100%) create mode 100644 src/test/ui/dep-graph/dep-graph-variance-alias.stderr rename src/test/{compile-fail => ui/deprecation}/auxiliary/deprecation-lint.rs (100%) rename src/test/ui/{ => deprecation}/deprecated-macro_escape-inner.rs (100%) rename src/test/ui/{ => deprecation}/deprecated-macro_escape-inner.stderr (100%) rename src/test/ui/{ => deprecation}/deprecated-macro_escape.rs (100%) rename src/test/ui/{ => deprecation}/deprecated-macro_escape.stderr (100%) rename src/test/{compile-fail => ui/deprecation}/deprecated_no_stack_check.rs (100%) create mode 100644 src/test/ui/deprecation/deprecated_no_stack_check.stderr rename src/test/{compile-fail => ui/deprecation}/deprecation-in-staged-api.rs (91%) create mode 100644 src/test/ui/deprecation/deprecation-in-staged-api.stderr rename src/test/{compile-fail => ui/deprecation}/deprecation-lint-2.rs (100%) create mode 100644 src/test/ui/deprecation/deprecation-lint-2.stderr rename src/test/{compile-fail => ui/deprecation}/deprecation-lint-3.rs (100%) create mode 100644 src/test/ui/deprecation/deprecation-lint-3.stderr rename src/test/{compile-fail => ui/deprecation}/deprecation-lint-nested.rs (100%) create mode 100644 src/test/ui/deprecation/deprecation-lint-nested.stderr rename src/test/{compile-fail => ui/deprecation}/deprecation-lint.rs (100%) create mode 100644 src/test/ui/deprecation/deprecation-lint.stderr rename src/test/ui/{ => deprecation}/deprecation-sanity.rs (100%) rename src/test/ui/{ => deprecation}/deprecation-sanity.stderr (100%) rename src/test/{compile-fail => ui}/deref-non-pointer.rs (100%) create mode 100644 src/test/ui/deref-non-pointer.stderr rename src/test/{compile-fail => ui}/derived-errors/issue-30580.rs (100%) create mode 100644 src/test/ui/derived-errors/issue-30580.stderr rename src/test/{compile-fail => ui}/derived-errors/issue-31997.rs (100%) create mode 100644 src/test/ui/derived-errors/issue-31997.stderr rename src/test/{compile-fail => ui/derives}/derive-assoc-type-not-impl.rs (100%) create mode 100644 src/test/ui/derives/derive-assoc-type-not-impl.stderr rename src/test/{compile-fail => ui/derives}/derive-on-trait-item-or-impl-item.rs (100%) create mode 100644 src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Clone-enum-struct-variant.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Clone-enum.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Clone-enum.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Clone-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Clone-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Clone-tuple-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Clone-tuple-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Debug-enum-struct-variant.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Debug-enum.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Debug-enum.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Debug-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Debug-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Debug-tuple-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Debug-tuple-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Default-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Default-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Default-tuple-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Default-tuple-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Eq-enum-struct-variant.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Eq-enum.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Eq-enum.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Eq-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Eq-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Eq-tuple-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Eq-tuple-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Hash-enum-struct-variant.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Hash-enum.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Hash-enum.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Hash-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Hash-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Hash-tuple-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Hash-tuple-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Ord-enum-struct-variant.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Ord-enum.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Ord-enum.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Ord-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Ord-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-Ord-tuple-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-Ord-tuple-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-PartialEq-enum-struct-variant.rs (100%) create mode 100644 src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr rename src/test/{compile-fail => ui/derives}/derives-span-PartialEq-enum.rs (100%) create mode 100644 src/test/ui/derives/derives-span-PartialEq-enum.stderr rename src/test/{compile-fail => ui/derives}/derives-span-PartialEq-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-PartialEq-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-PartialEq-tuple-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-PartialOrd-enum-struct-variant.rs (100%) create mode 100644 src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr rename src/test/{compile-fail => ui/derives}/derives-span-PartialOrd-enum.rs (100%) create mode 100644 src/test/ui/derives/derives-span-PartialOrd-enum.stderr rename src/test/{compile-fail => ui/derives}/derives-span-PartialOrd-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-PartialOrd-struct.stderr rename src/test/{compile-fail => ui/derives}/derives-span-PartialOrd-tuple-struct.rs (100%) create mode 100644 src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr rename src/test/{compile-fail => ui/derives}/deriving-bounds.rs (100%) create mode 100644 src/test/ui/derives/deriving-bounds.stderr rename src/test/{compile-fail => ui/derives}/deriving-copyclone.rs (100%) create mode 100644 src/test/ui/derives/deriving-copyclone.stderr rename src/test/ui/{ => derives}/deriving-meta-empty-trait-list.rs (100%) rename src/test/ui/{ => derives}/deriving-meta-empty-trait-list.stderr (100%) rename src/test/{compile-fail => ui/derives}/deriving-meta-unknown-trait.rs (100%) create mode 100644 src/test/ui/derives/deriving-meta-unknown-trait.stderr rename src/test/{compile-fail => ui/derives}/deriving-no-inner-impl-error-message.rs (100%) create mode 100644 src/test/ui/derives/deriving-no-inner-impl-error-message.stderr rename src/test/{compile-fail => ui/derives}/deriving-non-type.rs (100%) create mode 100644 src/test/ui/derives/deriving-non-type.stderr rename src/test/{compile-fail => ui/derives}/deriving-primitive.rs (100%) create mode 100644 src/test/ui/derives/deriving-primitive.stderr rename src/test/ui/{ => derives}/deriving-with-repr-packed.rs (100%) rename src/test/ui/{ => derives}/deriving-with-repr-packed.stderr (100%) rename src/test/{compile-fail => ui}/destructure-trait-ref.rs (100%) create mode 100644 src/test/ui/destructure-trait-ref.stderr create mode 100644 src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs create mode 100644 src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr create mode 100644 src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs create mode 100644 src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr rename src/test/{compile-fail => ui}/directory_ownership/foo/compiletest-ignore-dir (100%) rename src/test/{compile-fail => ui}/directory_ownership/foo/mod_file_not_owning/aux2.rs (100%) rename src/test/{compile-fail => ui}/directory_ownership/foo/mod_file_not_owning_aux2.rs (100%) rename src/test/{compile-fail => ui}/directory_ownership/macro-expanded-mod.rs (100%) create mode 100644 src/test/ui/directory_ownership/macro-expanded-mod.stderr rename src/test/{compile-fail => ui}/directory_ownership/macro_expanded_mod_helper/foo/bar.rs (100%) rename src/test/{compile-fail => ui}/directory_ownership/macro_expanded_mod_helper/foo/mod.rs (100%) rename src/test/{compile-fail => ui}/directory_ownership/mod_file_not_owning_aux1.rs (100%) rename src/test/{compile-fail => ui}/directory_ownership/mod_file_not_owning_aux1/compiletest-ignore-dir (100%) rename src/test/{compile-fail => ui}/directory_ownership/mod_file_not_owning_aux1/mod_file_not_owning_aux2.rs (100%) rename src/test/{compile-fail => ui}/directory_ownership/mod_file_not_owning_aux2.rs (100%) rename src/test/{compile-fail => ui}/directory_ownership/mod_file_not_owning_aux3.rs (100%) rename src/test/{compile-fail => ui}/directory_ownership/non-inline-mod-restriction.rs (100%) create mode 100644 src/test/ui/directory_ownership/non-inline-mod-restriction.stderr create mode 100644 src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.nll.stderr rename src/test/{compile-fail => ui/disallowed-deconstructing}/disallowed-deconstructing-destructing-struct-let.rs (100%) create mode 100644 src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr create mode 100644 src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.nll.stderr rename src/test/{compile-fail => ui/disallowed-deconstructing}/disallowed-deconstructing-destructing-struct-match.rs (100%) create mode 100644 src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr rename src/test/{compile-fail => ui/discrim}/discrim-ill-typed.rs (100%) create mode 100644 src/test/ui/discrim/discrim-ill-typed.stderr rename src/test/ui/{ => discrim}/discrim-overflow-2.rs (100%) rename src/test/ui/{ => discrim}/discrim-overflow-2.stderr (100%) rename src/test/ui/{ => discrim}/discrim-overflow.rs (100%) rename src/test/ui/{ => discrim}/discrim-overflow.stderr (100%) rename src/test/{compile-fail => ui}/diverging-fn-tail-35849.rs (100%) create mode 100644 src/test/ui/diverging-fn-tail-35849.stderr rename src/test/{compile-fail => ui}/diverging-tuple-parts-39485.rs (100%) create mode 100644 src/test/ui/diverging-tuple-parts-39485.stderr rename src/test/{compile-fail => ui}/does-nothing.rs (100%) create mode 100644 src/test/ui/does-nothing.stderr rename src/test/{compile-fail => ui/dollar-crate}/dollar-crate-is-keyword-2.rs (100%) create mode 100644 src/test/ui/dollar-crate/dollar-crate-is-keyword-2.stderr create mode 100644 src/test/ui/dollar-crate/dollar-crate-is-keyword.rs create mode 100644 src/test/ui/dollar-crate/dollar-crate-is-keyword.stderr rename src/test/{compile-fail => ui}/double-type-import.rs (100%) create mode 100644 src/test/ui/double-type-import.stderr rename src/test/{compile-fail => ui/dropck}/drop-on-non-struct.rs (100%) create mode 100644 src/test/ui/dropck/drop-on-non-struct.stderr create mode 100644 src/test/ui/dropck/drop-with-active-borrows-1.nll.stderr rename src/test/{compile-fail => ui/dropck}/drop-with-active-borrows-1.rs (100%) create mode 100644 src/test/ui/dropck/drop-with-active-borrows-1.stderr create mode 100644 src/test/ui/dropck/drop-with-active-borrows-2.nll.stderr rename src/test/{compile-fail => ui/dropck}/drop-with-active-borrows-2.rs (100%) create mode 100644 src/test/ui/dropck/drop-with-active-borrows-2.stderr create mode 100644 src/test/ui/dropck/dropck-union.nll.stderr create mode 100644 src/test/ui/dropck/dropck-union.rs create mode 100644 src/test/ui/dropck/dropck-union.stderr rename src/test/{compile-fail => ui/dropck}/dropck_no_diverge_on_nonregular_1.rs (100%) create mode 100644 src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr rename src/test/{compile-fail => ui/dropck}/dropck_no_diverge_on_nonregular_2.rs (100%) create mode 100644 src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr rename src/test/{compile-fail => ui/dropck}/dropck_no_diverge_on_nonregular_3.rs (100%) create mode 100644 src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr create mode 100644 src/test/ui/dropck/dropck_trait_cycle_checked.nll.stderr rename src/test/{compile-fail => ui/dropck}/dropck_trait_cycle_checked.rs (100%) create mode 100644 src/test/ui/dropck/dropck_trait_cycle_checked.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-assign-2.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-assign-2.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-assign-3.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-assign-3.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-assign.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-assign.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-coerce1.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-coerce1.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-coerce2.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-coerce2.stderr create mode 100644 src/test/ui/dst/dst-bad-coerce3.nll.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-coerce3.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-coerce3.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-coerce4.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-coerce4.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-coercions.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-coercions.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-deep-2.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-deep-2.stderr rename src/test/{compile-fail => ui/dst}/dst-bad-deep.rs (100%) create mode 100644 src/test/ui/dst/dst-bad-deep.stderr create mode 100644 src/test/ui/dst/dst-index.nll.stderr rename src/test/{compile-fail => ui/dst}/dst-index.rs (100%) create mode 100644 src/test/ui/dst/dst-index.stderr rename src/test/{compile-fail => ui/dst}/dst-object-from-unsized-type.rs (100%) create mode 100644 src/test/ui/dst/dst-object-from-unsized-type.stderr create mode 100644 src/test/ui/dst/dst-rvalue.nll.stderr rename src/test/{compile-fail => ui/dst}/dst-rvalue.rs (100%) create mode 100644 src/test/ui/dst/dst-rvalue.stderr rename src/test/{compile-fail => ui/dst}/dst-sized-trait-param.rs (100%) create mode 100644 src/test/ui/dst/dst-sized-trait-param.stderr delete mode 100644 src/test/ui/duplicate-check-macro-exports.stderr rename src/test/{compile-fail => ui/duplicate}/dupe-symbols-1.rs (100%) create mode 100644 src/test/ui/duplicate/dupe-symbols-1.stderr rename src/test/{compile-fail => ui/duplicate}/dupe-symbols-2.rs (100%) create mode 100644 src/test/ui/duplicate/dupe-symbols-2.stderr rename src/test/{compile-fail => ui/duplicate}/dupe-symbols-3.rs (100%) create mode 100644 src/test/ui/duplicate/dupe-symbols-3.stderr rename src/test/{compile-fail => ui/duplicate}/dupe-symbols-4.rs (100%) create mode 100644 src/test/ui/duplicate/dupe-symbols-4.stderr rename src/test/{compile-fail => ui/duplicate}/dupe-symbols-5.rs (100%) create mode 100644 src/test/ui/duplicate/dupe-symbols-5.stderr rename src/test/{compile-fail => ui/duplicate}/dupe-symbols-6.rs (100%) create mode 100644 src/test/ui/duplicate/dupe-symbols-6.stderr rename src/test/{compile-fail => ui/duplicate}/dupe-symbols-7.rs (100%) create mode 100644 src/test/ui/duplicate/dupe-symbols-7.stderr rename src/test/ui/{ => duplicate}/duplicate-check-macro-exports.rs (80%) create mode 100644 src/test/ui/duplicate/duplicate-check-macro-exports.stderr rename src/test/{compile-fail => ui/duplicate}/duplicate-parameter.rs (100%) create mode 100644 src/test/ui/duplicate/duplicate-parameter.stderr rename src/test/{compile-fail => ui/duplicate}/duplicate-type-parameter.rs (100%) create mode 100644 src/test/ui/duplicate/duplicate-type-parameter.stderr rename src/test/{compile-fail => ui}/duplicate_entry_error.rs (100%) create mode 100644 src/test/ui/duplicate_entry_error.stderr rename src/test/{compile-fail => ui}/dyn-trait-compatibility.rs (100%) create mode 100644 src/test/ui/dyn-trait-compatibility.stderr rename src/test/{compile-fail => ui/editions}/auxiliary/edition-extern-crate-allowed.rs (100%) rename src/test/ui/{ => editions}/auxiliary/edition-kw-macro-2015.rs (94%) rename src/test/ui/{ => editions}/auxiliary/edition-kw-macro-2018.rs (94%) rename src/test/{compile-fail => ui/editions}/edition-extern-crate-allowed.rs (95%) create mode 100644 src/test/ui/editions/edition-extern-crate-allowed.stderr rename src/test/{compile-fail => ui/editions}/edition-feature-ok.rs (94%) create mode 100644 src/test/ui/editions/edition-feature-redundant.rs create mode 100644 src/test/ui/editions/edition-feature-redundant.stderr rename src/test/ui/{ => editions}/edition-keywords-2015-2015-expansion.rs (92%) rename src/test/ui/{ => editions}/edition-keywords-2015-2015-parsing.rs (97%) rename src/test/ui/{ => editions}/edition-keywords-2015-2015-parsing.stderr (79%) rename src/test/ui/{ => editions}/edition-keywords-2015-2018-expansion.rs (95%) rename src/test/ui/{ => editions}/edition-keywords-2015-2018-expansion.stderr (87%) rename src/test/ui/{ => editions}/edition-keywords-2015-2018-parsing.rs (97%) rename src/test/ui/{ => editions}/edition-keywords-2015-2018-parsing.stderr (79%) rename src/test/ui/{ => editions}/edition-keywords-2018-2015-expansion.rs (92%) rename src/test/ui/{ => editions}/edition-keywords-2018-2015-parsing.rs (97%) rename src/test/ui/{ => editions}/edition-keywords-2018-2015-parsing.stderr (82%) rename src/test/ui/{ => editions}/edition-keywords-2018-2018-expansion.rs (96%) rename src/test/ui/{ => editions}/edition-keywords-2018-2018-expansion.stderr (88%) rename src/test/ui/{ => editions}/edition-keywords-2018-2018-parsing.rs (97%) rename src/test/ui/{ => editions}/edition-keywords-2018-2018-parsing.stderr (82%) rename src/test/{compile-fail => ui/editions}/edition-raw-pointer-method-2015.rs (100%) create mode 100644 src/test/ui/editions/edition-raw-pointer-method-2015.stderr rename src/test/{compile-fail => ui/editions}/edition-raw-pointer-method-2018.rs (100%) create mode 100644 src/test/ui/editions/edition-raw-pointer-method-2018.stderr create mode 100644 src/test/ui/elide-errors-on-mismatched-tuple.rs create mode 100644 src/test/ui/elide-errors-on-mismatched-tuple.stderr rename src/test/{compile-fail => ui}/elided-test.rs (100%) create mode 100644 src/test/ui/elided-test.stderr rename src/test/{compile-fail => ui/empty}/auxiliary/empty-struct.rs (100%) rename src/test/{compile-fail => ui/empty}/auxiliary/two_macros.rs (100%) rename src/test/{compile-fail => ui/empty}/empty-comment.rs (100%) create mode 100644 src/test/ui/empty/empty-comment.stderr rename src/test/{compile-fail => ui/empty}/empty-linkname.rs (100%) create mode 100644 src/test/ui/empty/empty-linkname.stderr rename src/test/{compile-fail => ui/empty}/empty-macro-use.rs (100%) create mode 100644 src/test/ui/empty/empty-macro-use.stderr rename src/test/{compile-fail => ui/empty}/empty-never-array.rs (100%) create mode 100644 src/test/ui/empty/empty-never-array.stderr rename src/test/{compile-fail => ui/empty}/empty-struct-braces-expr.rs (100%) create mode 100644 src/test/ui/empty/empty-struct-braces-expr.stderr rename src/test/{compile-fail => ui/empty}/empty-struct-braces-pat-1.rs (100%) create mode 100644 src/test/ui/empty/empty-struct-braces-pat-1.stderr rename src/test/{compile-fail => ui/empty}/empty-struct-braces-pat-2.rs (100%) create mode 100644 src/test/ui/empty/empty-struct-braces-pat-2.stderr rename src/test/{compile-fail => ui/empty}/empty-struct-braces-pat-3.rs (100%) create mode 100644 src/test/ui/empty/empty-struct-braces-pat-3.stderr rename src/test/{compile-fail => ui/empty}/empty-struct-tuple-pat.rs (100%) create mode 100644 src/test/ui/empty/empty-struct-tuple-pat.stderr rename src/test/ui/{ => empty}/empty-struct-unit-expr.rs (100%) rename src/test/ui/{ => empty}/empty-struct-unit-expr.stderr (100%) rename src/test/{compile-fail => ui/empty}/empty-struct-unit-pat.rs (100%) create mode 100644 src/test/ui/empty/empty-struct-unit-pat.stderr rename src/test/{compile-fail => ui}/enable-unstable-lib-feature.rs (95%) create mode 100644 src/test/ui/enable-unstable-lib-feature.stderr rename src/test/ui/{ => enum}/enum-and-module-in-same-scope.rs (100%) rename src/test/ui/{ => enum}/enum-and-module-in-same-scope.stderr (100%) create mode 100644 src/test/ui/enum/enum-discrim-autosizing.rs create mode 100644 src/test/ui/enum/enum-discrim-autosizing.stderr rename src/test/{compile-fail => ui/enum}/enum-discrim-too-small.rs (100%) create mode 100644 src/test/ui/enum/enum-discrim-too-small.stderr rename src/test/{compile-fail => ui/enum}/enum-discrim-too-small2.rs (100%) create mode 100644 src/test/ui/enum/enum-discrim-too-small2.stderr rename src/test/{compile-fail => ui/enum}/enum-in-scope.rs (100%) create mode 100644 src/test/ui/enum/enum-in-scope.stderr rename src/test/ui/{ => enum}/enum-size-variance.rs (100%) rename src/test/ui/{ => enum}/enum-size-variance.stderr (100%) rename src/test/{compile-fail => ui/enum}/enum-to-float-cast-2.rs (100%) create mode 100644 src/test/ui/enum/enum-to-float-cast-2.stderr rename src/test/{compile-fail => ui/enum}/enum-to-float-cast.rs (100%) create mode 100644 src/test/ui/enum/enum-to-float-cast.stderr rename src/test/{compile-fail => ui/enum}/enum-variant-type-2.rs (100%) create mode 100644 src/test/ui/enum/enum-variant-type-2.stderr rename src/test/{compile-fail => ui}/enums-pats-not-idents.rs (100%) create mode 100644 src/test/ui/enums-pats-not-idents.stderr delete mode 100644 src/test/ui/error-codes/E0087.rs delete mode 100644 src/test/ui/error-codes/E0087.stderr delete mode 100644 src/test/ui/error-codes/E0088.rs delete mode 100644 src/test/ui/error-codes/E0088.stderr delete mode 100644 src/test/ui/error-codes/E0089.rs delete mode 100644 src/test/ui/error-codes/E0089.stderr delete mode 100644 src/test/ui/error-codes/E0090.rs delete mode 100644 src/test/ui/error-codes/E0090.stderr create mode 100644 src/test/ui/error-codes/E0161.ast.stderr create mode 100644 src/test/ui/error-codes/E0161.astul.stderr create mode 100644 src/test/ui/error-codes/E0161.edition.stderr create mode 100644 src/test/ui/error-codes/E0161.editionul.stderr create mode 100644 src/test/ui/error-codes/E0161.nll.stderr create mode 100644 src/test/ui/error-codes/E0161.nllul.stderr create mode 100644 src/test/ui/error-codes/E0161.zflags.stderr create mode 100644 src/test/ui/error-codes/E0161.zflagsul.stderr delete mode 100644 src/test/ui/error-codes/E0243.rs delete mode 100644 src/test/ui/error-codes/E0243.stderr delete mode 100644 src/test/ui/error-codes/E0244.rs delete mode 100644 src/test/ui/error-codes/E0244.stderr create mode 100644 src/test/ui/error-codes/E0396-fixed.rs create mode 100644 src/test/ui/error-codes/E0396-fixed.stderr create mode 100644 src/test/ui/error-codes/E0509.nll.stderr rename src/test/{compile-fail => ui}/error-should-say-copy-not-pod.rs (100%) create mode 100644 src/test/ui/error-should-say-copy-not-pod.stderr rename src/test/{compile-fail => ui}/estr-subtyping.rs (100%) create mode 100644 src/test/ui/estr-subtyping.stderr rename src/test/{compile-fail => ui}/eval-enum.rs (100%) create mode 100644 src/test/ui/eval-enum.stderr rename src/test/{compile-fail => ui}/exclusive-drop-and-copy.rs (100%) create mode 100644 src/test/ui/exclusive-drop-and-copy.stderr rename src/test/{compile-fail => ui/exclusive-range}/exclusive_range_pattern_syntax_collision.rs (100%) create mode 100644 src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr rename src/test/{compile-fail => ui/exclusive-range}/exclusive_range_pattern_syntax_collision2.rs (100%) create mode 100644 src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr rename src/test/{compile-fail => ui/exclusive-range}/exclusive_range_pattern_syntax_collision3.rs (100%) create mode 100644 src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr create mode 100644 src/test/ui/exhaustive_integer_patterns.rs create mode 100644 src/test/ui/exhaustive_integer_patterns.stderr create mode 100644 src/test/ui/existential_types/nested_existential_types.rs create mode 100644 src/test/ui/existential_types/no_inferrable_concrete_type.rs create mode 100644 src/test/ui/existential_types/no_inferrable_concrete_type.stderr rename src/test/{compile-fail => ui}/expanded-cfg.rs (100%) create mode 100644 src/test/ui/expanded-cfg.stderr rename src/test/{compile-fail => ui/explicit}/explicit-call-to-dtor.rs (100%) create mode 100644 src/test/ui/explicit/explicit-call-to-dtor.stderr rename src/test/{compile-fail => ui/explicit}/explicit-call-to-supertrait-dtor.rs (100%) create mode 100644 src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr rename src/test/{compile-fail => ui/explicit}/explicit-self-lifetime-mismatch.rs (100%) create mode 100644 src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr rename src/test/{compile-fail => ui}/export-fully-qualified.rs (100%) create mode 100644 src/test/ui/export-fully-qualified.stderr rename src/test/{compile-fail => ui}/export-import.rs (100%) create mode 100644 src/test/ui/export-import.stderr rename src/test/{compile-fail => ui}/export-tag-variant.rs (100%) create mode 100644 src/test/ui/export-tag-variant.stderr rename src/test/{compile-fail => ui}/export.rs (100%) create mode 100644 src/test/ui/export.stderr rename src/test/{compile-fail => ui}/export2.rs (100%) create mode 100644 src/test/ui/export2.stderr rename src/test/{compile-fail => ui}/expr_attr_paren_order.rs (100%) create mode 100644 src/test/ui/expr_attr_paren_order.stderr rename src/test/{compile-fail => ui}/ext-nonexistent.rs (100%) create mode 100644 src/test/ui/ext-nonexistent.stderr rename src/test/{compile-fail => ui/extenv}/extenv-arg-2-not-string-literal.rs (100%) create mode 100644 src/test/ui/extenv/extenv-arg-2-not-string-literal.stderr rename src/test/{compile-fail => ui/extenv}/extenv-no-args.rs (100%) create mode 100644 src/test/ui/extenv/extenv-no-args.stderr rename src/test/{compile-fail => ui/extenv}/extenv-not-defined-custom.rs (100%) create mode 100644 src/test/ui/extenv/extenv-not-defined-custom.stderr rename src/test/{compile-fail => ui/extenv}/extenv-not-defined-default.rs (100%) create mode 100644 src/test/ui/extenv/extenv-not-defined-default.stderr rename src/test/{compile-fail => ui/extenv}/extenv-not-string-literal.rs (100%) create mode 100644 src/test/ui/extenv/extenv-not-string-literal.stderr rename src/test/{compile-fail => ui/extenv}/extenv-too-many-args.rs (100%) create mode 100644 src/test/ui/extenv/extenv-too-many-args.stderr rename src/test/ui/{ => extern}/auxiliary/m1.rs (100%) rename src/test/ui/{ => extern}/auxiliary/m2.rs (100%) rename src/test/ui/{ => extern}/extern-const.fixed (100%) rename src/test/ui/{ => extern}/extern-const.rs (100%) rename src/test/ui/{ => extern}/extern-const.stderr (100%) rename src/test/ui/{ => extern}/extern-crate-rename.rs (100%) rename src/test/ui/{ => extern}/extern-crate-rename.stderr (100%) rename src/test/{compile-fail => ui/extern}/extern-crate-visibility.rs (100%) create mode 100644 src/test/ui/extern/extern-crate-visibility.stderr rename src/test/{compile-fail => ui/extern}/extern-macro.rs (94%) create mode 100644 src/test/ui/extern/extern-macro.stderr rename src/test/{compile-fail => ui/extern}/extern-main-fn.rs (100%) create mode 100644 src/test/ui/extern/extern-main-fn.stderr rename src/test/{compile-fail => ui/extern}/extern-types-distinct-types.rs (100%) create mode 100644 src/test/ui/extern/extern-types-distinct-types.stderr rename src/test/{compile-fail => ui/extern}/extern-types-not-sync-send.rs (100%) create mode 100644 src/test/ui/extern/extern-types-not-sync-send.stderr rename src/test/{compile-fail => ui/extern}/extern-types-unsized.rs (100%) create mode 100644 src/test/ui/extern/extern-types-unsized.stderr rename src/test/{compile-fail => ui/extern}/extern-with-type-bounds.rs (100%) create mode 100644 src/test/ui/extern/extern-with-type-bounds.stderr rename src/test/{compile-fail => ui/extern}/extern-wrong-value-type.rs (88%) create mode 100644 src/test/ui/extern/extern-wrong-value-type.stderr rename src/test/{compile-fail => ui/extern}/external-doc-error.rs (82%) create mode 100644 src/test/ui/extern/external-doc-error.stderr rename src/test/{compile-fail => ui}/extoption_env-no-args.rs (100%) create mode 100644 src/test/ui/extoption_env-no-args.stderr rename src/test/{compile-fail => ui}/extoption_env-not-string-literal.rs (100%) create mode 100644 src/test/ui/extoption_env-not-string-literal.stderr rename src/test/{compile-fail => ui}/extoption_env-too-many-args.rs (100%) create mode 100644 src/test/ui/extoption_env-too-many-args.stderr rename src/test/{compile-fail => ui}/fail-no-dead-code-core.rs (100%) create mode 100644 src/test/ui/fail-no-dead-code-core.stderr rename src/test/{compile-fail => ui}/fail-no-dead-code.rs (100%) create mode 100644 src/test/ui/fail-no-dead-code.stderr rename src/test/{compile-fail => ui}/fail-simple.rs (100%) create mode 100644 src/test/ui/fail-simple.stderr delete mode 100644 src/test/ui/feature-gate-catch_expr.rs delete mode 100644 src/test/ui/feature-gate-catch_expr.stderr delete mode 100644 src/test/ui/feature-gate-const_fn.stderr delete mode 100644 src/test/ui/feature-gate-crate_in_paths.rs delete mode 100644 src/test/ui/feature-gate-crate_in_paths.stderr create mode 100644 src/test/ui/feature-gate-custom_test_frameworks.rs create mode 100644 src/test/ui/feature-gate-custom_test_frameworks.stderr create mode 100644 src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.rs create mode 100644 src/test/ui/feature-gate-doc_cfg-cfg-rustdoc.stderr create mode 100644 src/test/ui/feature-gate-exhaustive_integer_patterns.rs create mode 100644 src/test/ui/feature-gate-exhaustive_integer_patterns.stderr delete mode 100644 src/test/ui/feature-gate-in_band_lifetimes-impl.stderr delete mode 100644 src/test/ui/feature-gate-infer_outlives_requirements.rs delete mode 100644 src/test/ui/feature-gate-infer_outlives_requirements.stderr delete mode 100644 src/test/ui/feature-gate-linker-flavor.stderr delete mode 100644 src/test/ui/feature-gate-macro-vis-matcher.rs delete mode 100644 src/test/ui/feature-gate-macro-vis-matcher.stderr delete mode 100644 src/test/ui/feature-gate-raw-identifiers.rs delete mode 100644 src/test/ui/feature-gate-raw-identifiers.stderr delete mode 100644 src/test/ui/feature-gate-rustc-attrs.stderr delete mode 100644 src/test/ui/feature-gate-tool_attributes.rs delete mode 100644 src/test/ui/feature-gate-tool_attributes.stderr create mode 100644 src/test/ui/feature-gate-unsized_locals.rs create mode 100644 src/test/ui/feature-gate-unsized_locals.stderr delete mode 100644 src/test/ui/feature-gate-used.rs delete mode 100644 src/test/ui/feature-gate-used.stderr create mode 100644 src/test/ui/feature-gate/duplicate-features.rs create mode 100644 src/test/ui/feature-gate/duplicate-features.stderr create mode 100644 src/test/ui/feature-gate/stability-attribute-consistency.rs create mode 100644 src/test/ui/feature-gate/stability-attribute-consistency.stderr create mode 100644 src/test/ui/feature-gate/unknown-feature.rs create mode 100644 src/test/ui/feature-gate/unknown-feature.stderr rename src/test/{compile-fail => ui}/feature-gated-feature-in-macro-arg.rs (100%) create mode 100644 src/test/ui/feature-gated-feature-in-macro-arg.stderr rename src/test/ui/{ => feature-gates}/auxiliary/cfg-target-thread-local.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-abi-msp430-interrupt.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-abi-msp430-interrupt.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-abi.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-abi.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-abi_unadjusted.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-abi_unadjusted.stderr (100%) rename src/test/{compile-fail => ui/feature-gates}/feature-gate-alloc-error-handler.rs (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-alloc-error-handler.stderr rename src/test/ui/{ => feature-gates}/feature-gate-allocator_internals.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allocator_internals.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow-internal-unsafe-nested-macro.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow-internal-unsafe-nested-macro.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow-internal-unstable-nested-macro.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow-internal-unstable-nested-macro.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow-internal-unstable-struct.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow-internal-unstable-struct.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow-internal-unstable.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow-internal-unstable.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow_fail.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-allow_fail.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-arbitrary-self-types.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-arbitrary-self-types.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-arbitrary_self_types-raw-pointer.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-arbitrary_self_types-raw-pointer.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-asm.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-asm.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-asm2.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-asm2.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-assoc-type-defaults.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-assoc-type-defaults.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-async-await-2015-edition.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-async-await-2015-edition.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-async-await.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-async-await.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-box-expr.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-box-expr.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-box_patterns.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-box_patterns.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-box_syntax.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-box_syntax.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-cfg-target-has-atomic.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-cfg-target-has-atomic.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-cfg-target-thread-local.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-cfg-target-thread-local.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-cfg-target-vendor.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-cfg-target-vendor.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-compiler-builtins.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-compiler-builtins.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-concat_idents.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-concat_idents.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-concat_idents2.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-concat_idents2.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-concat_idents3.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-concat_idents3.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-const-indexing.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-const_fn.rs (76%) create mode 100644 src/test/ui/feature-gates/feature-gate-const_fn.stderr rename src/test/ui/{ => feature-gates}/feature-gate-const_let.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-const_let.stderr (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-const_transmute.rs create mode 100644 src/test/ui/feature-gates/feature-gate-const_transmute.stderr rename src/test/ui/{ => feature-gates}/feature-gate-crate_visibility_modifier.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-crate_visibility_modifier.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-custom_attribute.rs (97%) rename src/test/ui/{ => feature-gates}/feature-gate-custom_attribute.stderr (80%) rename src/test/ui/{ => feature-gates}/feature-gate-custom_attribute2.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-custom_attribute2.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-custom_derive.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-custom_derive.stderr (82%) rename src/test/ui/{ => feature-gates}/feature-gate-decl_macro.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-decl_macro.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-default_type_parameter_fallback.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-default_type_parameter_fallback.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_alias.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_alias.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_cfg.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_cfg.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_keyword.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_keyword.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_masked.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_masked.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_spotlight.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-doc_spotlight.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-dropck-ugeh-2.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-dropck-ugeh-2.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-dropck-ugeh.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-dropck-ugeh.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-exclusive-range-pattern.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-exclusive-range-pattern.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-exhaustive-patterns.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-exhaustive-patterns.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-existential-type.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-existential-type.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-extern_absolute_paths.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-extern_absolute_paths.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-extern_in_paths.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-extern_in_paths.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-extern_prelude.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-extern_prelude.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-extern_types.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-extern_types.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-external_doc.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-external_doc.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-feature-gate.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-feature-gate.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-format_args_nl.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-format_args_nl.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-fundamental.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-fundamental.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-generators.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-generators.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-generic_associated_types.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-generic_associated_types.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-global_asm.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-global_asm.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-if_while_or_patterns.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-if_while_or_patterns.stderr (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-impl_header_lifetime_elision-with-in_band.rs create mode 100644 src/test/ui/feature-gates/feature-gate-impl_header_lifetime_elision-with-in_band.stderr rename src/test/ui/{feature-gate-in_band_lifetimes-impl.rs => feature-gates/feature-gate-impl_header_lifetime_elision.rs} (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-impl_header_lifetime_elision.stderr rename src/test/ui/{ => feature-gates}/feature-gate-in_band_lifetimes.rs (94%) rename src/test/ui/{ => feature-gates}/feature-gate-in_band_lifetimes.stderr (75%) rename src/test/ui/{ => feature-gates}/feature-gate-infer_static_outlives_requirements.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-infer_static_outlives_requirements.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-intrinsics.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-intrinsics.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-label_break_value.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-label_break_value.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-lang-items.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-lang-items.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-link_args.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-link_args.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-link_cfg.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-link_cfg.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-link_llvm_intrinsics.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-link_llvm_intrinsics.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-linkage.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-linkage.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-linker-flavor.rs (84%) create mode 100644 src/test/ui/feature-gates/feature-gate-linker-flavor.stderr rename src/test/ui/{ => feature-gates}/feature-gate-log_syntax.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-log_syntax.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-log_syntax2.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-log_syntax2.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-macro-literal-matcher.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-macro-literal-matcher.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-macros_in_extern.rs (97%) rename src/test/ui/{ => feature-gates}/feature-gate-macros_in_extern.stderr (92%) rename src/test/ui/{ => feature-gates}/feature-gate-main.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-main.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-may-dangle.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-may-dangle.stderr (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-min_const_fn.rs create mode 100644 src/test/ui/feature-gates/feature-gate-min_const_fn.stderr rename src/test/ui/{ => feature-gates}/feature-gate-naked_functions.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-naked_functions.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-needs-allocator.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-needs-allocator.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-negate-unsigned.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-negate-unsigned.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-never_type.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-never_type.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-nll.nll.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-nll.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-nll.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-no-debug-2.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-no-debug-2.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-no-debug.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-no-debug.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-no_core.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-no_core.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-non_ascii_idents.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-non_ascii_idents.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-non_exhaustive.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-non_exhaustive.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-omit-gdb-pretty-printer-section.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-omit-gdb-pretty-printer-section.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-on-unimplemented.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-on-unimplemented.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-optin-builtin-traits.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-optin-builtin-traits.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-overlapping_marker_traits.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-overlapping_marker_traits.stderr (100%) rename src/test/{compile-fail => ui/feature-gates}/feature-gate-panic-implementation.rs (85%) create mode 100644 src/test/ui/feature-gates/feature-gate-panic-implementation.stderr rename src/test/ui/{ => feature-gates}/feature-gate-pattern_parentheses.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-pattern_parentheses.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-plugin.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-plugin.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-plugin_registrar.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-plugin_registrar.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-prelude_import.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-prelude_import.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-profiler-runtime.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-profiler-runtime.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-repr-simd.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-repr-simd.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-repr128.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-repr128.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-repr_packed.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-repr_packed.stderr (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs create mode 100644 src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr rename src/test/ui/{ => feature-gates}/feature-gate-rustc-attrs.rs (75%) create mode 100644 src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr rename src/test/ui/{ => feature-gates}/feature-gate-rustc-diagnostic-macros.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-rustc-diagnostic-macros.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-rustc_const_unstable.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-rustc_const_unstable.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-sanitizer-runtime.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-sanitizer-runtime.stderr (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-self-in-typedefs.rs create mode 100644 src/test/ui/feature-gates/feature-gate-self-in-typedefs.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-self-struct-ctor.rs create mode 100644 src/test/ui/feature-gates/feature-gate-self-struct-ctor.stderr rename src/test/ui/{ => feature-gates}/feature-gate-simd-ffi.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-simd-ffi.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-simd.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-simd.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-slice-patterns.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-slice-patterns.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-staged_api.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-staged_api.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-start.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-start.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-static-nobundle.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-static-nobundle.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-stmt_expr_attributes.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-stmt_expr_attributes.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-thread_local.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-thread_local.stderr (100%) rename src/test/{compile-fail/feature-gate-tool_lints.rs => ui/feature-gates/feature-gate-tool_lints-fail.rs} (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-tool_lints-fail.stderr rename src/test/ui/{ => feature-gates}/feature-gate-tool_lints.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-tool_lints.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-trace_macros.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-trace_macros.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-trivial_bounds-lint.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-trivial_bounds.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-trivial_bounds.stderr (98%) create mode 100644 src/test/ui/feature-gates/feature-gate-try_blocks.rs create mode 100644 src/test/ui/feature-gates/feature-gate-try_blocks.stderr rename src/test/ui/{ => feature-gates}/feature-gate-try_reserve.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-try_reserve.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-type_ascription.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-type_ascription.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unboxed-closures-manual-impls.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unboxed-closures-manual-impls.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unboxed-closures-method-calls.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unboxed-closures-method-calls.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unboxed-closures-ufcs-calls.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unboxed-closures-ufcs-calls.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unboxed-closures.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unboxed-closures.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-underscore-imports.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-underscore-imports.stderr (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-uniform-paths.rs create mode 100644 src/test/ui/feature-gates/feature-gate-uniform-paths.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-unrestricted-attribute-tokens.rs create mode 100644 src/test/ui/feature-gates/feature-gate-unrestricted-attribute-tokens.stderr rename src/test/ui/{ => feature-gates}/feature-gate-unsized_tuple_coercion.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unsized_tuple_coercion.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-untagged_unions.rs (100%) rename src/test/ui/{ => feature-gates}/feature-gate-untagged_unions.stderr (100%) rename src/test/ui/{ => feature-gates}/feature-gate-unwind-attributes.rs (92%) rename src/test/ui/{ => feature-gates}/feature-gate-unwind-attributes.stderr (100%) rename src/test/{compile-fail => ui/feature-gates}/feature-gate-without_gate_irrefutable_pattern.rs (100%) create mode 100644 src/test/ui/feature-gates/feature-gate-without_gate_irrefutable_pattern.stderr rename src/test/{compile-fail => ui}/float-literal-inference-restrictions.rs (100%) create mode 100644 src/test/ui/float-literal-inference-restrictions.stderr rename src/test/{compile-fail => ui/fn}/fn-bad-block-type.rs (100%) create mode 100644 src/test/ui/fn/fn-bad-block-type.stderr rename src/test/ui/{ => fn}/fn-closure-mutable-capture.nll.stderr (100%) rename src/test/ui/{ => fn}/fn-closure-mutable-capture.rs (100%) rename src/test/ui/{ => fn}/fn-closure-mutable-capture.stderr (100%) rename src/test/{compile-fail => ui/fn}/fn-compare-mismatch.rs (100%) create mode 100644 src/test/ui/fn/fn-compare-mismatch.stderr rename src/test/{compile-fail => ui/fn}/fn-item-type.rs (100%) create mode 100644 src/test/ui/fn/fn-item-type.stderr rename src/test/{compile-fail => ui/fn}/fn-trait-formatting.rs (93%) create mode 100644 src/test/ui/fn/fn-trait-formatting.stderr rename src/test/ui/{ => for}/for-c-in-str.rs (100%) rename src/test/ui/{ => for}/for-c-in-str.stderr (100%) rename src/test/{compile-fail => ui/for}/for-expn.rs (100%) create mode 100644 src/test/ui/for/for-expn.stderr rename src/test/{compile-fail => ui/for}/for-loop-bogosity.rs (100%) create mode 100644 src/test/ui/for/for-loop-bogosity.stderr rename src/test/{compile-fail => ui/for}/for-loop-refutable-pattern-error-message.rs (100%) create mode 100644 src/test/ui/for/for-loop-refutable-pattern-error-message.stderr rename src/test/{compile-fail => ui/for}/for-loop-type-error.rs (100%) create mode 100644 src/test/ui/for/for-loop-type-error.stderr rename src/test/{compile-fail => ui/for}/for-loop-unconstrained-element-type.rs (100%) create mode 100644 src/test/ui/for/for-loop-unconstrained-element-type.stderr rename src/test/{compile-fail => ui}/foreign-fn-return-lifetime.rs (100%) create mode 100644 src/test/ui/foreign-fn-return-lifetime.stderr rename src/test/{compile-fail => ui}/foreign-unsafe-fn-called.rs (100%) create mode 100644 src/test/ui/foreign-unsafe-fn-called.stderr rename src/test/{compile-fail => ui/fully-qualified-type}/fully-qualified-type-name1.rs (100%) create mode 100644 src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr rename src/test/{compile-fail => ui/fully-qualified-type}/fully-qualified-type-name2.rs (100%) create mode 100644 src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr rename src/test/{compile-fail => ui/fully-qualified-type}/fully-qualified-type-name3.rs (100%) rename src/test/{compile-fail => ui/fully-qualified-type}/fully-qualified-type-name4.rs (100%) create mode 100644 src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr create mode 100644 src/test/ui/functional-struct-update/functional-struct-update-noncopyable.nll.stderr rename src/test/{compile-fail => ui/functional-struct-update}/functional-struct-update-noncopyable.rs (100%) create mode 100644 src/test/ui/functional-struct-update/functional-struct-update-noncopyable.stderr rename src/test/{compile-fail => ui/functional-struct-update}/functional-struct-update-respects-privacy.rs (100%) create mode 100644 src/test/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr rename src/test/{compile-fail => ui}/future-incompatible-lint-group.rs (100%) create mode 100644 src/test/ui/future-incompatible-lint-group.stderr rename src/test/{compile-fail => ui}/gated-bad-feature.rs (98%) create mode 100644 src/test/ui/gated-bad-feature.stderr rename src/test/{compile-fail => ui}/generator-yielding-or-returning-itself.rs (100%) create mode 100644 src/test/ui/generator-yielding-or-returning-itself.stderr delete mode 100644 src/test/ui/generic-type-less-params-with-defaults.stderr delete mode 100644 src/test/ui/generic-type-more-params-with-defaults.stderr create mode 100644 src/test/ui/generic/generic-arg-mismatch-recover.rs create mode 100644 src/test/ui/generic/generic-arg-mismatch-recover.stderr rename src/test/{compile-fail => ui/generic}/generic-extern-lifetime.rs (100%) create mode 100644 src/test/ui/generic/generic-extern-lifetime.stderr rename src/test/{compile-fail => ui/generic}/generic-extern.rs (100%) create mode 100644 src/test/ui/generic/generic-extern.stderr rename src/test/{compile-fail => ui/generic}/generic-impl-less-params-with-defaults.rs (100%) create mode 100644 src/test/ui/generic/generic-impl-less-params-with-defaults.stderr rename src/test/{compile-fail => ui/generic}/generic-impl-more-params-with-defaults.rs (100%) create mode 100644 src/test/ui/generic/generic-impl-more-params-with-defaults.stderr rename src/test/{compile-fail => ui/generic}/generic-lifetime-trait-impl.rs (100%) create mode 100644 src/test/ui/generic/generic-lifetime-trait-impl.stderr rename src/test/{compile-fail => ui/generic}/generic-no-mangle.rs (100%) create mode 100644 src/test/ui/generic/generic-no-mangle.stderr rename src/test/{compile-fail => ui/generic}/generic-non-trailing-defaults.rs (100%) create mode 100644 src/test/ui/generic/generic-non-trailing-defaults.stderr rename src/test/ui/{ => generic}/generic-param-attrs.rs (100%) rename src/test/ui/{ => generic}/generic-type-less-params-with-defaults.rs (97%) create mode 100644 src/test/ui/generic/generic-type-less-params-with-defaults.stderr rename src/test/ui/{ => generic}/generic-type-more-params-with-defaults.rs (97%) create mode 100644 src/test/ui/generic/generic-type-more-params-with-defaults.stderr rename src/test/{compile-fail => ui/generic}/generic-type-params-forward-mention.rs (100%) create mode 100644 src/test/ui/generic/generic-type-params-forward-mention.stderr rename src/test/{compile-fail => ui/generic}/generic-type-params-name-repr.rs (100%) create mode 100644 src/test/ui/generic/generic-type-params-name-repr.stderr rename src/test/{compile-fail => ui}/glob-cycles.rs (100%) create mode 100644 src/test/ui/glob-cycles.stderr rename src/test/{compile-fail => ui}/glob-resolve1.rs (100%) create mode 100644 src/test/ui/glob-resolve1.stderr create mode 100644 src/test/ui/hashmap-iter-value-lifetime.nll.stderr rename src/test/{compile-fail => ui}/hashmap-iter-value-lifetime.rs (100%) create mode 100644 src/test/ui/hashmap-iter-value-lifetime.stderr create mode 100644 src/test/ui/hashmap-lifetimes.nll.stderr rename src/test/{compile-fail => ui}/hashmap-lifetimes.rs (98%) create mode 100644 src/test/ui/hashmap-lifetimes.stderr rename src/test/{compile-fail => ui}/hidden-rt-injection.rs (100%) create mode 100644 src/test/ui/hidden-rt-injection.stderr rename src/test/{compile-fail => ui}/hidden-rt-injection2.rs (100%) create mode 100644 src/test/ui/hidden-rt-injection2.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr create mode 100644 src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr rename src/test/{compile-fail => ui/hr-subtype}/hr-subtype.rs (100%) rename src/test/{compile-fail => ui/hrtb}/hrtb-conflate-regions.rs (100%) create mode 100644 src/test/ui/hrtb/hrtb-conflate-regions.stderr create mode 100644 src/test/ui/hrtb/hrtb-debruijn-in-receiver.nll.stderr rename src/test/{compile-fail => ui/hrtb}/hrtb-debruijn-in-receiver.rs (100%) create mode 100644 src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr rename src/test/{compile-fail => ui/hrtb}/hrtb-higher-ranker-supertraits-transitive.rs (100%) create mode 100644 src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr rename src/test/{compile-fail => ui/hrtb}/hrtb-higher-ranker-supertraits.rs (100%) create mode 100644 src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr create mode 100644 src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.nll.stderr create mode 100644 src/test/ui/hrtb/hrtb-identity-fn-borrows.ast.stderr create mode 100644 src/test/ui/hrtb/hrtb-identity-fn-borrows.mir.stderr rename src/test/{compile-fail => ui/hrtb}/hrtb-identity-fn-borrows.rs (100%) rename src/test/{compile-fail => ui/hrtb}/hrtb-just-for-static.rs (100%) create mode 100644 src/test/ui/hrtb/hrtb-just-for-static.stderr rename src/test/{compile-fail => ui/hrtb}/hrtb-perfect-forwarding.rs (100%) create mode 100644 src/test/ui/hrtb/hrtb-perfect-forwarding.stderr rename src/test/{compile-fail => ui}/huge-array-simple.rs (100%) rename src/test/{compile-fail => ui}/huge-array.rs (100%) create mode 100644 src/test/ui/huge-array.stderr rename src/test/{compile-fail => ui}/huge-enum.rs (92%) create mode 100644 src/test/ui/huge-enum.stderr rename src/test/{compile-fail => ui}/huge-struct.rs (92%) create mode 100644 src/test/ui/huge-struct.stderr create mode 100644 src/test/ui/hygiene/dollar-crate-modern.stderr rename src/test/{compile-fail => ui/hygiene}/hygienic-label-1.rs (100%) create mode 100644 src/test/ui/hygiene/hygienic-label-1.stderr rename src/test/{compile-fail => ui/hygiene}/hygienic-label-2.rs (100%) create mode 100644 src/test/ui/hygiene/hygienic-label-2.stderr rename src/test/{compile-fail => ui/hygiene}/hygienic-label-3.rs (100%) create mode 100644 src/test/ui/hygiene/hygienic-label-3.stderr rename src/test/{compile-fail => ui/hygiene}/hygienic-label-4.rs (100%) create mode 100644 src/test/ui/hygiene/hygienic-label-4.stderr delete mode 100644 src/test/ui/hygiene/local_inner_macros_disabled.rs delete mode 100644 src/test/ui/hygiene/local_inner_macros_disabled.stderr rename src/test/{compile-fail => ui/if}/if-branch-types.rs (100%) create mode 100644 src/test/ui/if/if-branch-types.stderr rename src/test/ui/{ => if}/if-let-arm-types.rs (100%) rename src/test/ui/{ => if}/if-let-arm-types.stderr (100%) rename src/test/{compile-fail => ui/if}/if-let.rs (100%) create mode 100644 src/test/ui/if/if-let.stderr rename src/test/{compile-fail => ui/if}/if-loop.rs (100%) create mode 100644 src/test/ui/if/if-loop.stderr rename src/test/{compile-fail => ui/if}/if-typeck.rs (100%) create mode 100644 src/test/ui/if/if-typeck.stderr rename src/test/ui/{ => if}/if-without-block.rs (100%) rename src/test/ui/{ => if}/if-without-block.stderr (100%) rename src/test/{compile-fail => ui/if}/if-without-else-result.rs (100%) create mode 100644 src/test/ui/if/if-without-else-result.stderr rename src/test/ui/{ => if}/ifmt-bad-arg.rs (100%) rename src/test/ui/{ => if}/ifmt-bad-arg.stderr (100%) rename src/test/{compile-fail => ui/if}/ifmt-bad-format-args.rs (100%) create mode 100644 src/test/ui/if/ifmt-bad-format-args.stderr rename src/test/{compile-fail => ui/if}/ifmt-unimpl.rs (100%) create mode 100644 src/test/ui/if/ifmt-unimpl.stderr rename src/test/{compile-fail => ui/if}/ifmt-unknown-trait.rs (100%) create mode 100644 src/test/ui/if/ifmt-unknown-trait.stderr rename src/test/{compile-fail => ui}/illegal-ufcs-drop.rs (100%) create mode 100644 src/test/ui/illegal-ufcs-drop.stderr create mode 100644 src/test/ui/immut-function-arguments.ast.nll.stderr create mode 100644 src/test/ui/immut-function-arguments.ast.stderr create mode 100644 src/test/ui/immut-function-arguments.mir.stderr rename src/test/{compile-fail => ui}/immut-function-arguments.rs (100%) rename src/test/{compile-fail => ui}/impl-bounds-checking.rs (100%) create mode 100644 src/test/ui/impl-bounds-checking.stderr rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/assoc-type.rs (92%) rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/assoc-type.stderr (100%) create mode 100644 src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr create mode 100644 src/test/ui/impl-header-lifetime-elision/dyn-trait.rs rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/dyn-trait.stderr (100%) rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/path-elided.rs (93%) rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/path-elided.stderr (100%) rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/path-underscore.rs (96%) rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/ref-underscore.rs (95%) rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/trait-elided.rs (93%) rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/trait-elided.stderr (100%) rename src/test/ui/{in-band-lifetimes/impl => impl-header-lifetime-elision}/trait-underscore.rs (96%) rename src/test/{compile-fail => ui}/impl-trait/impl-generic-mismatch-ab.rs (100%) create mode 100644 src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr rename src/test/ui/{ => impl-trait}/impl_trait_projections.rs (100%) rename src/test/ui/{ => impl-trait}/impl_trait_projections.stderr (100%) rename src/test/{compile-fail => ui}/impl-trait/infinite-impl-trait-issue-38064.rs (100%) create mode 100644 src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr create mode 100644 src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr rename src/test/{compile-fail => ui}/impl-trait/must_outlive_least_region_or_bound.rs (100%) create mode 100644 src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr rename src/test/{compile-fail => ui}/impl-trait/needs_least_region_or_bound.rs (100%) create mode 100644 src/test/ui/impl-trait/needs_least_region_or_bound.stderr rename src/test/{compile-fail => ui}/impl-trait/no-trait.rs (100%) create mode 100644 src/test/ui/impl-trait/no-trait.stderr create mode 100644 src/test/ui/impl-trait/type_parameters_captured.nll.stderr rename src/test/{compile-fail => ui}/impl-trait/type_parameters_captured.rs (100%) create mode 100644 src/test/ui/impl-trait/type_parameters_captured.stderr rename src/test/{compile-fail => ui}/impl-trait/where-allowed.rs (99%) create mode 100644 src/test/ui/impl-trait/where-allowed.stderr rename src/test/{compile-fail => ui}/impl-unused-tps-inherent.rs (100%) create mode 100644 src/test/ui/impl-unused-tps-inherent.stderr rename src/test/{compile-fail => ui}/impl-unused-tps.rs (100%) create mode 100644 src/test/ui/impl-unused-tps.stderr rename src/test/{compile-fail => ui}/implicit-method-bind.rs (100%) create mode 100644 src/test/ui/implicit-method-bind.stderr rename src/test/{compile-fail => ui}/import.rs (100%) create mode 100644 src/test/ui/import.stderr rename src/test/{compile-fail => ui}/import2.rs (100%) create mode 100644 src/test/ui/import2.stderr rename src/test/{compile-fail => ui}/import3.rs (100%) create mode 100644 src/test/ui/import3.stderr rename src/test/{compile-fail => ui}/import4.rs (100%) create mode 100644 src/test/ui/import4.stderr rename src/test/{compile-fail => ui/imports}/auxiliary/import_crate_var.rs (100%) rename src/test/{compile-fail => ui/imports}/import-crate-var.rs (76%) create mode 100644 src/test/ui/imports/import-crate-var.stderr rename src/test/{compile-fail => ui/imports}/import-from-missing.rs (100%) create mode 100644 src/test/ui/imports/import-from-missing.stderr rename src/test/{compile-fail => ui/imports}/import-glob-0.rs (100%) create mode 100644 src/test/ui/imports/import-glob-0.stderr rename src/test/{compile-fail => ui/imports}/import-glob-circular.rs (98%) create mode 100644 src/test/ui/imports/import-glob-circular.stderr rename src/test/{compile-fail => ui/imports}/import-loop-2.rs (97%) create mode 100644 src/test/ui/imports/import-loop-2.stderr rename src/test/{compile-fail => ui/imports}/import-loop.rs (100%) create mode 100644 src/test/ui/imports/import-loop.stderr rename src/test/{compile-fail => ui/imports}/import-prefix-macro-1.rs (100%) create mode 100644 src/test/ui/imports/import-prefix-macro-1.stderr rename src/test/{compile-fail => ui/imports}/import-prefix-macro-2.rs (100%) create mode 100644 src/test/ui/imports/import-prefix-macro-2.stderr rename src/test/{compile-fail => ui/imports}/import-trait-method.rs (100%) create mode 100644 src/test/ui/imports/import-trait-method.stderr create mode 100644 src/test/ui/imports/issue-53269.rs create mode 100644 src/test/ui/imports/issue-53269.stderr create mode 100644 src/test/ui/imports/issue-53512.rs create mode 100644 src/test/ui/imports/issue-53512.stderr create mode 100644 src/test/ui/imports/local-modularized-tricky-fail-1.rs create mode 100644 src/test/ui/imports/local-modularized-tricky-fail-1.stderr create mode 100644 src/test/ui/imports/local-modularized-tricky-fail-2.rs create mode 100644 src/test/ui/imports/local-modularized-tricky-fail-2.stderr create mode 100644 src/test/ui/imports/local-modularized-tricky-fail-3.rs create mode 100644 src/test/ui/imports/local-modularized-tricky-fail-3.stderr create mode 100644 src/test/ui/imports/local-modularized-tricky-pass.rs create mode 100644 src/test/ui/imports/local-modularized.rs rename src/test/{compile-fail => ui}/imports/reexports.rs (100%) create mode 100644 src/test/ui/imports/reexports.stderr rename src/test/{compile-fail => ui}/imports/unused-macro-use.rs (100%) create mode 100644 src/test/ui/imports/unused-macro-use.stderr rename src/test/{compile-fail => ui}/imports/unused.rs (100%) create mode 100644 src/test/ui/imports/unused.stderr delete mode 100644 src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr delete mode 100644 src/test/ui/in-band-lifetimes/impl/dyn-trait.rs delete mode 100644 src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr rename src/test/{compile-fail => ui}/inaccessible-test-modules.rs (100%) create mode 100644 src/test/ui/inaccessible-test-modules.stderr rename src/test/{compile-fail => ui}/index-bot.rs (100%) create mode 100644 src/test/ui/index-bot.stderr rename src/test/{compile-fail => ui}/index_message.rs (100%) create mode 100644 src/test/ui/index_message.stderr rename src/test/{compile-fail => ui}/indexing-requires-a-uint.rs (100%) create mode 100644 src/test/ui/indexing-requires-a-uint.stderr rename src/test/ui/{ => inference}/auxiliary/inference_unstable_iterator.rs (100%) rename src/test/ui/{ => inference}/auxiliary/inference_unstable_itertools.rs (100%) rename src/test/ui/{ => inference}/inference-variable-behind-raw-pointer.rs (100%) rename src/test/ui/{ => inference}/inference-variable-behind-raw-pointer.stderr (100%) rename src/test/ui/{ => inference}/inference_unstable.rs (100%) rename src/test/ui/{ => inference}/inference_unstable.stderr (100%) rename src/test/ui/{ => inference}/inference_unstable_featured.rs (100%) rename src/test/ui/{ => inference}/inference_unstable_featured.stderr (100%) rename src/test/ui/{ => inference}/inference_unstable_forced.rs (100%) rename src/test/ui/{ => inference}/inference_unstable_forced.stderr (100%) rename src/test/{compile-fail => ui/infinite}/infinite-autoderef.rs (100%) create mode 100644 src/test/ui/infinite/infinite-autoderef.stderr rename src/test/{compile-fail => ui/infinite}/infinite-instantiation.rs (100%) create mode 100644 src/test/ui/infinite/infinite-instantiation.stderr rename src/test/{compile-fail => ui/infinite}/infinite-macro-expansion.rs (100%) create mode 100644 src/test/ui/infinite/infinite-macro-expansion.stderr rename src/test/ui/{ => infinite}/infinite-recursion-const-fn.rs (96%) rename src/test/ui/{ => infinite}/infinite-recursion-const-fn.stderr (100%) rename src/test/{compile-fail => ui/infinite}/infinite-tag-type-recursion.rs (100%) create mode 100644 src/test/ui/infinite/infinite-tag-type-recursion.stderr rename src/test/{compile-fail => ui/infinite}/infinite-vec-type-recursion.rs (100%) create mode 100644 src/test/ui/infinite/infinite-vec-type-recursion.stderr rename src/test/{compile-fail => ui}/inhabitedness-infinite-loop.rs (100%) create mode 100644 src/test/ui/inhabitedness-infinite-loop.stderr rename src/test/{compile-fail => ui}/init-unsafe.rs (100%) create mode 100644 src/test/ui/init-unsafe.stderr rename src/test/{compile-fail => ui}/inner-static-type-parameter.rs (100%) create mode 100644 src/test/ui/inner-static-type-parameter.stderr rename src/test/{compile-fail => ui}/integer-literal-suffix-inference.rs (100%) create mode 100644 src/test/ui/integer-literal-suffix-inference.stderr rename src/test/{compile-fail => ui}/integral-indexing.rs (100%) create mode 100644 src/test/ui/integral-indexing.stderr rename src/test/{compile-fail => ui}/integral-variable-unification-error.rs (100%) create mode 100644 src/test/ui/integral-variable-unification-error.stderr rename src/test/{compile-fail => ui/internal}/auxiliary/internal_unstable.rs (100%) rename src/test/{compile-fail => ui/internal}/internal-unstable-noallow.rs (100%) create mode 100644 src/test/ui/internal/internal-unstable-noallow.stderr rename src/test/{compile-fail => ui/internal}/internal-unstable-thread-local.rs (100%) create mode 100644 src/test/ui/internal/internal-unstable-thread-local.stderr rename src/test/{compile-fail => ui/internal}/internal-unstable.rs (100%) create mode 100644 src/test/ui/internal/internal-unstable.stderr rename src/test/{compile-fail => ui}/intrinsic-invalid-number-of-arguments.rs (100%) create mode 100644 src/test/ui/intrinsic-invalid-number-of-arguments.stderr create mode 100644 src/test/ui/invalid/invalid-crate-type.rs create mode 100644 src/test/ui/invalid/invalid-crate-type.stderr rename src/test/{compile-fail => ui/invalid}/invalid-inline.rs (100%) create mode 100644 src/test/ui/invalid/invalid-inline.stderr rename src/test/{compile-fail => ui/invalid}/invalid-macro-matcher.rs (100%) create mode 100644 src/test/ui/invalid/invalid-macro-matcher.stderr rename src/test/ui/{ => invalid}/invalid-path-in-const.rs (100%) rename src/test/ui/{ => invalid}/invalid-path-in-const.stderr (100%) rename src/test/{compile-fail => ui/invalid}/invalid-plugin-attr.rs (100%) create mode 100644 src/test/ui/invalid/invalid-plugin-attr.stderr rename src/test/ui/{ => invalid}/invalid-variadic-function.rs (100%) rename src/test/ui/{ => invalid}/invalid-variadic-function.stderr (100%) rename src/test/{compile-fail => ui}/invalid_crate_type_syntax.rs (97%) create mode 100644 src/test/ui/invalid_crate_type_syntax.stderr delete mode 100644 src/test/ui/issue-10291.nll.stderr rename src/test/{parse-fail => ui}/issue-10636-1.rs (79%) create mode 100644 src/test/ui/issue-10636-1.stderr delete mode 100644 src/test/ui/issue-11692-1.stderr delete mode 100644 src/test/ui/issue-11692-2.stderr delete mode 100644 src/test/ui/issue-12567.nll.stderr delete mode 100644 src/test/ui/issue-12796.stderr delete mode 100644 src/test/ui/issue-13058.nll.stderr delete mode 100644 src/test/ui/issue-14092.stderr delete mode 100644 src/test/ui/issue-14285.nll.stderr delete mode 100644 src/test/ui/issue-15034.nll.stderr delete mode 100644 src/test/ui/issue-16683.nll.stderr delete mode 100644 src/test/ui/issue-16922.nll.stderr delete mode 100644 src/test/ui/issue-17458.stderr delete mode 100644 src/test/ui/issue-17718-const-bad-values.stderr delete mode 100644 src/test/ui/issue-17758.nll.stderr delete mode 100644 src/test/ui/issue-17954.ast.nll.stderr delete mode 100644 src/test/ui/issue-17954.ast.stderr delete mode 100644 src/test/ui/issue-17954.mir.stderr delete mode 100644 src/test/ui/issue-17954.rs delete mode 100644 src/test/ui/issue-18294.stderr delete mode 100644 src/test/ui/issue-18423.stderr delete mode 100644 src/test/ui/issue-22034.stderr rename src/test/{parse-fail => ui}/issue-2354.rs (81%) create mode 100644 src/test/ui/issue-2354.stderr delete mode 100644 src/test/ui/issue-23966.stderr delete mode 100644 src/test/ui/issue-25826.stderr delete mode 100644 src/test/ui/issue-26217.nll.stderr delete mode 100644 src/test/ui/issue-27282-move-match-input-into-guard.stderr delete mode 100644 src/test/ui/issue-3154.nll.stderr delete mode 100644 src/test/ui/issue-3214.stderr delete mode 100644 src/test/ui/issue-32829.stderr delete mode 100644 src/test/ui/issue-37323.stderr delete mode 100644 src/test/ui/issue-38715.rs delete mode 100644 src/test/ui/issue-38715.stderr delete mode 100644 src/test/ui/issue-40288-2.nll.stderr delete mode 100644 src/test/ui/issue-40288-2.stderr delete mode 100644 src/test/ui/issue-40402-ref-hints/issue-40402-2.nll.stderr delete mode 100644 src/test/ui/issue-40510-1.nll.stderr delete mode 100644 src/test/ui/issue-40510-3.nll.stderr delete mode 100644 src/test/ui/issue-41726.nll.stderr delete mode 100644 src/test/ui/issue-41726.stderr delete mode 100644 src/test/ui/issue-42755.stderr delete mode 100644 src/test/ui/issue-4335.nll.stderr delete mode 100644 src/test/ui/issue-43784-associated-type.stderr delete mode 100644 src/test/ui/issue-43784-supertrait.stderr delete mode 100644 src/test/ui/issue-45199.ast.nll.stderr delete mode 100644 src/test/ui/issue-45199.mir.stderr delete mode 100644 src/test/ui/issue-46471-1.stderr delete mode 100644 src/test/ui/issue-49074.stderr create mode 100644 src/test/ui/issue-51602.rs create mode 100644 src/test/ui/issue-51602.stderr delete mode 100644 src/test/ui/issue-52023-array-size-pointer-cast.stderr delete mode 100644 src/test/ui/issue-52213.nll.stderr delete mode 100644 src/test/ui/issue-5239-1.stderr delete mode 100644 src/test/ui/issue-52533-1.nll.stderr delete mode 100644 src/test/ui/issue-52533.nll.stderr create mode 100644 src/test/ui/issue-52992.rs create mode 100644 src/test/ui/issue-53251.rs create mode 100644 src/test/ui/issue-53251.stderr create mode 100644 src/test/ui/issue-53300.rs create mode 100644 src/test/ui/issue-53300.stderr create mode 100644 src/test/ui/issue-53419.rs create mode 100644 src/test/ui/issue-53565.rs create mode 100644 src/test/ui/issue-53565.stderr create mode 100644 src/test/ui/issue-53568.rs create mode 100644 src/test/ui/issue-53692.rs create mode 100644 src/test/ui/issue-53692.stderr create mode 100644 src/test/ui/issues/auxiliary/empty-struct.rs rename src/test/{compile-fail => ui/issues}/auxiliary/issue-19163.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue-21146-inc.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue-29181.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue-30535.rs (100%) rename src/test/ui/{ => issues}/auxiliary/issue-36708.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue-36881-aux.rs (100%) create mode 100644 src/test/ui/issues/auxiliary/issue-52489.rs rename src/test/{compile-fail => ui/issues}/auxiliary/issue_11680.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue_16725.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue_17718_const_privacy.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue_1920.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue_21202.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue_30123_aux.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue_41549.rs (100%) rename src/test/{compile-fail => ui/issues}/auxiliary/issue_5844_aux.rs (100%) create mode 100644 src/test/ui/issues/auxiliary/lint_stability.rs rename src/test/{compile-fail => ui/issues}/auxiliary/private_trait_xc.rs (100%) rename src/test/ui/{ => issues}/auxiliary/xcrate_issue_43189_a.rs (100%) rename src/test/ui/{ => issues}/auxiliary/xcrate_issue_43189_b.rs (100%) rename src/test/ui/{ => issues}/auxiliary/xcrate_issue_46112_rexport_core.rs (100%) rename src/test/ui/{ => issues}/issue-10176.rs (100%) rename src/test/ui/{ => issues}/issue-10176.stderr (100%) rename src/test/ui/{ => issues}/issue-10200.rs (100%) rename src/test/ui/{ => issues}/issue-10200.stderr (100%) create mode 100644 src/test/ui/issues/issue-10291.nll.stderr rename src/test/ui/{ => issues}/issue-10291.rs (100%) rename src/test/ui/{ => issues}/issue-10291.stderr (100%) rename src/test/ui/{ => issues}/issue-10398.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-10398.rs (100%) rename src/test/ui/{ => issues}/issue-10398.stderr (100%) rename src/test/ui/{ => issues}/issue-10401.rs (100%) rename src/test/ui/{ => issues}/issue-10401.stderr (100%) rename src/test/ui/{ => issues}/issue-10412.rs (100%) rename src/test/ui/{ => issues}/issue-10412.stderr (100%) rename src/test/ui/{ => issues}/issue-10465.rs (100%) rename src/test/ui/{ => issues}/issue-10465.stderr (100%) rename src/test/ui/{ => issues}/issue-10536.rs (100%) rename src/test/ui/{ => issues}/issue-10536.stderr (100%) rename src/test/ui/{ => issues}/issue-10545.rs (100%) rename src/test/ui/{ => issues}/issue-10545.stderr (100%) rename src/test/ui/{ => issues}/issue-10656.rs (100%) rename src/test/ui/{ => issues}/issue-10656.stderr (100%) rename src/test/ui/{ => issues}/issue-10764.rs (100%) rename src/test/ui/{ => issues}/issue-10764.stderr (100%) rename src/test/ui/{ => issues}/issue-10877.rs (100%) rename src/test/ui/{ => issues}/issue-10877.stderr (100%) rename src/test/ui/{ => issues}/issue-10969.rs (100%) rename src/test/ui/{ => issues}/issue-10969.stderr (100%) rename src/test/ui/{ => issues}/issue-10991.rs (100%) rename src/test/ui/{ => issues}/issue-10991.stderr (100%) rename src/test/ui/{ => issues}/issue-11004.rs (100%) rename src/test/ui/{ => issues}/issue-11004.stderr (100%) rename src/test/ui/{ => issues}/issue-11154.rs (100%) rename src/test/ui/{ => issues}/issue-11154.stderr (100%) rename src/test/ui/{ => issues}/issue-11192.nll.stderr (88%) rename src/test/ui/{ => issues}/issue-11192.rs (100%) rename src/test/ui/{ => issues}/issue-11192.stderr (100%) rename src/test/ui/{ => issues}/issue-11319.rs (100%) rename src/test/ui/{ => issues}/issue-11319.stderr (100%) rename src/test/ui/{ => issues}/issue-11374.rs (100%) rename src/test/ui/{ => issues}/issue-11374.stderr (100%) rename src/test/ui/{ => issues}/issue-11493.ast.stderr (100%) rename src/test/ui/{ => issues}/issue-11493.mir.stderr (100%) rename src/test/ui/{ => issues}/issue-11493.rs (100%) rename src/test/ui/{ => issues}/issue-11515.rs (100%) rename src/test/ui/{ => issues}/issue-11515.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-11593.rs (100%) create mode 100644 src/test/ui/issues/issue-11593.stderr rename src/test/{compile-fail => ui/issues}/issue-11680.rs (100%) create mode 100644 src/test/ui/issues/issue-11680.stderr rename src/test/ui/{ => issues}/issue-11681.rs (100%) rename src/test/ui/{ => issues}/issue-11681.stderr (100%) rename src/test/ui/{ => issues}/issue-11692-1.rs (96%) create mode 100644 src/test/ui/issues/issue-11692-1.stderr rename src/test/ui/{ => issues}/issue-11692-2.rs (86%) create mode 100644 src/test/ui/issues/issue-11692-2.stderr rename src/test/ui/{ => issues}/issue-11740.rs (100%) rename src/test/ui/{ => issues}/issue-11740.stderr (100%) rename src/test/ui/{ => issues}/issue-11771.rs (100%) rename src/test/ui/{ => issues}/issue-11771.stderr (100%) rename src/test/ui/{ => issues}/issue-11844.rs (100%) rename src/test/ui/{ => issues}/issue-11844.stderr (100%) rename src/test/ui/{ => issues}/issue-11873.nll.stderr (75%) rename src/test/ui/{ => issues}/issue-11873.rs (100%) rename src/test/ui/{ => issues}/issue-11873.stderr (100%) rename src/test/ui/{ => issues}/issue-12028.rs (100%) rename src/test/ui/{ => issues}/issue-12028.stderr (100%) rename src/test/ui/{ => issues}/issue-12041.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-12041.rs (100%) rename src/test/ui/{ => issues}/issue-12041.stderr (100%) rename src/test/ui/{ => issues}/issue-12116.rs (100%) rename src/test/ui/{ => issues}/issue-12116.stderr (100%) rename src/test/ui/{ => issues}/issue-12127.rs (100%) rename src/test/ui/{ => issues}/issue-12127.stderr (100%) rename src/test/ui/{ => issues}/issue-12187-1.rs (100%) rename src/test/ui/{ => issues}/issue-12187-1.stderr (100%) rename src/test/ui/{ => issues}/issue-12187-2.rs (100%) rename src/test/ui/{ => issues}/issue-12187-2.stderr (100%) rename src/test/ui/{ => issues}/issue-12369.rs (100%) rename src/test/ui/{ => issues}/issue-12369.stderr (100%) rename src/test/ui/{ => issues}/issue-12470.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-12470.rs (100%) rename src/test/ui/{ => issues}/issue-12470.stderr (100%) rename src/test/ui/{ => issues}/issue-12511.rs (100%) rename src/test/ui/{ => issues}/issue-12511.stderr (100%) rename src/test/ui/{ => issues}/issue-12552.rs (100%) rename src/test/ui/{ => issues}/issue-12552.stderr (100%) create mode 100644 src/test/ui/issues/issue-12567.nll.stderr rename src/test/ui/{ => issues}/issue-12567.rs (100%) rename src/test/ui/{ => issues}/issue-12567.stderr (100%) rename src/test/ui/{ => issues}/issue-12796.rs (100%) create mode 100644 src/test/ui/issues/issue-12796.stderr rename src/test/ui/{ => issues}/issue-12863.rs (100%) rename src/test/ui/{ => issues}/issue-12863.stderr (100%) rename src/test/ui/{ => issues}/issue-12997-1.rs (100%) rename src/test/ui/{ => issues}/issue-12997-1.stderr (100%) rename src/test/ui/{ => issues}/issue-12997-2.rs (100%) rename src/test/ui/{ => issues}/issue-12997-2.stderr (85%) rename src/test/ui/{ => issues}/issue-13033.rs (100%) rename src/test/ui/{ => issues}/issue-13033.stderr (100%) create mode 100644 src/test/ui/issues/issue-13058.nll.stderr rename src/test/ui/{ => issues}/issue-13058.rs (100%) rename src/test/ui/{ => issues}/issue-13058.stderr (91%) rename src/test/ui/{ => issues}/issue-13352.rs (100%) rename src/test/ui/{ => issues}/issue-13352.stderr (100%) rename src/test/ui/{ => issues}/issue-13359.rs (100%) rename src/test/ui/{ => issues}/issue-13359.stderr (100%) rename src/test/ui/{ => issues}/issue-13404.rs (100%) rename src/test/ui/{ => issues}/issue-13404.stderr (100%) rename src/test/ui/{ => issues}/issue-13407.rs (100%) rename src/test/ui/{ => issues}/issue-13407.stderr (100%) rename src/test/ui/{ => issues}/issue-13446.rs (100%) rename src/test/ui/{ => issues}/issue-13446.stderr (100%) rename src/test/ui/{ => issues}/issue-13466.rs (100%) rename src/test/ui/{ => issues}/issue-13466.stderr (100%) rename src/test/ui/{ => issues}/issue-13482-2.rs (100%) rename src/test/ui/{ => issues}/issue-13482-2.stderr (100%) rename src/test/ui/{ => issues}/issue-13482.rs (100%) rename src/test/ui/{ => issues}/issue-13482.stderr (100%) rename src/test/ui/{ => issues}/issue-13483.rs (100%) rename src/test/ui/{ => issues}/issue-13483.stderr (100%) rename src/test/ui/{ => issues}/issue-13497-2.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-13497-2.rs (100%) rename src/test/ui/{ => issues}/issue-13497-2.stderr (100%) rename src/test/ui/{ => issues}/issue-13497.rs (100%) rename src/test/ui/{ => issues}/issue-13497.stderr (100%) rename src/test/ui/{ => issues}/issue-1362.rs (100%) rename src/test/ui/{ => issues}/issue-1362.stderr (100%) rename src/test/ui/{ => issues}/issue-13641.rs (100%) rename src/test/ui/{ => issues}/issue-13641.stderr (100%) rename src/test/ui/{ => issues}/issue-13727.rs (100%) rename src/test/ui/{ => issues}/issue-13727.stderr (100%) rename src/test/ui/{ => issues}/issue-13847.rs (100%) rename src/test/ui/{ => issues}/issue-13847.stderr (100%) rename src/test/ui/{ => issues}/issue-13853-2.rs (100%) rename src/test/ui/{ => issues}/issue-13853-2.stderr (100%) rename src/test/ui/{ => issues}/issue-13853-5.rs (100%) rename src/test/ui/{ => issues}/issue-13853-5.stderr (100%) rename src/test/ui/{ => issues}/issue-13853.rs (100%) rename src/test/ui/{ => issues}/issue-13853.stderr (100%) rename src/test/ui/{ => issues}/issue-14091-2.rs (100%) rename src/test/ui/{ => issues}/issue-14091-2.stderr (100%) rename src/test/ui/{ => issues}/issue-14091.rs (100%) rename src/test/ui/{ => issues}/issue-14091.stderr (100%) rename src/test/ui/{ => issues}/issue-14092.rs (97%) create mode 100644 src/test/ui/issues/issue-14092.stderr rename src/test/ui/{ => issues}/issue-14221.rs (100%) rename src/test/ui/{ => issues}/issue-14221.stderr (100%) rename src/test/ui/{ => issues}/issue-14227.rs (100%) rename src/test/ui/{ => issues}/issue-14227.stderr (100%) rename src/test/ui/{ => issues}/issue-14285.rs (100%) rename src/test/ui/{ => issues}/issue-14285.stderr (79%) rename src/test/ui/{ => issues}/issue-14309.rs (100%) rename src/test/ui/{ => issues}/issue-14309.stderr (100%) rename src/test/ui/{ => issues}/issue-14366.rs (100%) rename src/test/ui/{ => issues}/issue-14366.stderr (96%) rename src/test/ui/{ => issues}/issue-1448-2.rs (100%) rename src/test/ui/{ => issues}/issue-1448-2.stderr (100%) rename src/test/ui/{ => issues}/issue-14541.rs (100%) rename src/test/ui/{ => issues}/issue-14541.stderr (100%) rename src/test/ui/{ => issues}/issue-14721.rs (100%) rename src/test/ui/{ => issues}/issue-14721.stderr (100%) rename src/test/ui/{ => issues}/issue-1476.rs (100%) rename src/test/ui/{ => issues}/issue-1476.stderr (100%) rename src/test/ui/{ => issues}/issue-14772.rs (100%) rename src/test/ui/{ => issues}/issue-14772.stderr (100%) rename src/test/ui/{ => issues}/issue-14845.rs (100%) rename src/test/ui/{ => issues}/issue-14845.stderr (100%) rename src/test/ui/{ => issues}/issue-14853.rs (100%) rename src/test/ui/{ => issues}/issue-14853.stderr (100%) rename src/test/ui/{ => issues}/issue-14915.rs (100%) rename src/test/ui/{ => issues}/issue-14915.stderr (100%) create mode 100644 src/test/ui/issues/issue-15034.nll.stderr rename src/test/ui/{ => issues}/issue-15034.rs (100%) rename src/test/ui/{ => issues}/issue-15034.stderr (75%) rename src/test/ui/{ => issues}/issue-15094.rs (100%) rename src/test/ui/{ => issues}/issue-15094.stderr (100%) rename src/test/ui/{ => issues}/issue-15129.rs (100%) rename src/test/ui/{ => issues}/issue-15129.stderr (100%) rename src/test/ui/{ => issues}/issue-15167.rs (100%) rename src/test/ui/{ => issues}/issue-15167.stderr (100%) rename src/test/ui/{ => issues}/issue-15207.rs (100%) rename src/test/ui/{ => issues}/issue-15207.stderr (100%) rename src/test/ui/{ => issues}/issue-15260.rs (100%) rename src/test/ui/{ => issues}/issue-15260.stderr (100%) rename src/test/ui/{ => issues}/issue-15381.rs (100%) rename src/test/ui/{ => issues}/issue-15381.stderr (100%) rename src/test/ui/{ => issues}/issue-15524.rs (100%) rename src/test/ui/{ => issues}/issue-15524.stderr (100%) rename src/test/ui/{ => issues}/issue-15756.rs (100%) rename src/test/ui/{ => issues}/issue-15756.stderr (87%) rename src/test/ui/{ => issues}/issue-15783.rs (100%) rename src/test/ui/{ => issues}/issue-15783.stderr (100%) rename src/test/ui/{ => issues}/issue-15896.rs (100%) rename src/test/ui/{ => issues}/issue-15896.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-15919.rs (92%) create mode 100644 src/test/ui/issues/issue-15919.stderr rename src/test/ui/{ => issues}/issue-15965.rs (100%) rename src/test/ui/{ => issues}/issue-15965.stderr (100%) rename src/test/ui/{ => issues}/issue-16048.rs (100%) rename src/test/ui/{ => issues}/issue-16048.stderr (100%) rename src/test/ui/{ => issues}/issue-16098.rs (100%) rename src/test/ui/{ => issues}/issue-16098.stderr (100%) rename src/test/ui/{ => issues}/issue-16149.rs (100%) rename src/test/ui/{ => issues}/issue-16149.stderr (100%) rename src/test/ui/{ => issues}/issue-16250.rs (100%) rename src/test/ui/{ => issues}/issue-16250.stderr (100%) rename src/test/ui/{ => issues}/issue-16338.rs (100%) rename src/test/ui/{ => issues}/issue-16338.stderr (100%) rename src/test/ui/{ => issues}/issue-16401.rs (100%) rename src/test/ui/{ => issues}/issue-16401.stderr (100%) rename src/test/ui/{ => issues}/issue-16538.rs (100%) rename src/test/ui/{ => issues}/issue-16538.stderr (100%) rename src/test/ui/{ => issues}/issue-16562.rs (100%) rename src/test/ui/{ => issues}/issue-16562.stderr (100%) create mode 100644 src/test/ui/issues/issue-16683.nll.stderr rename src/test/ui/{ => issues}/issue-16683.rs (100%) rename src/test/ui/{ => issues}/issue-16683.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-16725.rs (100%) create mode 100644 src/test/ui/issues/issue-16725.stderr create mode 100644 src/test/ui/issues/issue-16922.nll.stderr rename src/test/ui/{ => issues}/issue-16922.rs (100%) rename src/test/ui/{ => issues}/issue-16922.stderr (77%) rename src/test/ui/{ => issues}/issue-16939.rs (100%) rename src/test/ui/{ => issues}/issue-16939.stderr (100%) rename src/test/ui/{ => issues}/issue-16966.rs (100%) rename src/test/ui/{ => issues}/issue-16966.stderr (100%) rename src/test/ui/{ => issues}/issue-1697.rs (100%) rename src/test/ui/{ => issues}/issue-1697.stderr (100%) rename src/test/ui/{ => issues}/issue-16994.rs (100%) rename src/test/ui/{ => issues}/issue-16994.stderr (100%) rename src/test/ui/{ => issues}/issue-17001.rs (100%) rename src/test/ui/{ => issues}/issue-17001.stderr (100%) rename src/test/ui/{ => issues}/issue-17025.rs (100%) rename src/test/ui/{ => issues}/issue-17033.rs (100%) rename src/test/ui/{ => issues}/issue-17033.stderr (100%) rename src/test/ui/{ => issues}/issue-17252.rs (100%) rename src/test/ui/{ => issues}/issue-17252.stderr (100%) rename src/test/ui/{ => issues}/issue-17263.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-17263.rs (100%) rename src/test/ui/{ => issues}/issue-17263.stderr (100%) rename src/test/ui/{ => issues}/issue-17337.rs (84%) rename src/test/ui/{ => issues}/issue-17337.stderr (100%) rename src/test/ui/{ => issues}/issue-17373.rs (100%) rename src/test/ui/{ => issues}/issue-17373.stderr (100%) rename src/test/ui/{ => issues}/issue-17385.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-17385.rs (100%) rename src/test/ui/{ => issues}/issue-17385.stderr (100%) rename src/test/ui/{ => issues}/issue-17405.rs (100%) rename src/test/ui/{ => issues}/issue-17405.stderr (100%) rename src/test/ui/{ => issues}/issue-17431-1.rs (100%) rename src/test/ui/{ => issues}/issue-17431-1.stderr (100%) rename src/test/ui/{ => issues}/issue-17431-2.rs (100%) rename src/test/ui/{ => issues}/issue-17431-2.stderr (100%) rename src/test/ui/{ => issues}/issue-17431-3.rs (100%) rename src/test/ui/{ => issues}/issue-17431-3.stderr (100%) rename src/test/ui/{ => issues}/issue-17431-4.rs (100%) rename src/test/ui/{ => issues}/issue-17431-4.stderr (100%) rename src/test/ui/{ => issues}/issue-17431-5.rs (100%) rename src/test/ui/{ => issues}/issue-17431-5.stderr (100%) rename src/test/ui/{ => issues}/issue-17431-6.rs (100%) rename src/test/ui/{ => issues}/issue-17431-6.stderr (100%) rename src/test/ui/{ => issues}/issue-17431-7.rs (100%) rename src/test/ui/{ => issues}/issue-17431-7.stderr (100%) rename src/test/ui/{ => issues}/issue-17441.rs (100%) rename src/test/ui/{ => issues}/issue-17441.stderr (100%) rename src/test/ui/{ => issues}/issue-17444.rs (100%) rename src/test/ui/{ => issues}/issue-17444.stderr (100%) rename src/test/ui/{ => issues}/issue-17458.rs (89%) create mode 100644 src/test/ui/issues/issue-17458.stderr rename src/test/ui/{ => issues}/issue-17545.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-17545.rs (100%) rename src/test/ui/{ => issues}/issue-17545.stderr (100%) rename src/test/ui/{ => issues}/issue-17546.rs (100%) rename src/test/ui/{ => issues}/issue-17546.stderr (100%) rename src/test/ui/{ => issues}/issue-17551.rs (100%) rename src/test/ui/{ => issues}/issue-17551.stderr (100%) rename src/test/ui/{ => issues}/issue-17651.rs (100%) rename src/test/ui/{ => issues}/issue-17651.stderr (96%) rename src/test/ui/{ => issues}/issue-17718-const-bad-values.rs (91%) create mode 100644 src/test/ui/issues/issue-17718-const-bad-values.stderr rename src/test/ui/{ => issues}/issue-17718-const-borrow.rs (100%) rename src/test/ui/{ => issues}/issue-17718-const-borrow.stderr (100%) rename src/test/ui/{ => issues}/issue-17718-const-naming.rs (100%) rename src/test/ui/{ => issues}/issue-17718-const-naming.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-17718-const-privacy.rs (100%) create mode 100644 src/test/ui/issues/issue-17718-const-privacy.stderr rename src/test/ui/{ => issues}/issue-17718-constants-not-static.rs (100%) rename src/test/ui/{ => issues}/issue-17718-constants-not-static.stderr (100%) rename src/test/ui/{ => issues}/issue-17718-patterns.rs (100%) rename src/test/ui/{ => issues}/issue-17718-patterns.stderr (100%) rename src/test/ui/{ => issues}/issue-17718-references.rs (100%) rename src/test/ui/{ => issues}/issue-17718-references.stderr (100%) create mode 100644 src/test/ui/issues/issue-17718-static-move.nll.stderr rename src/test/ui/{ => issues}/issue-17718-static-move.rs (100%) rename src/test/ui/{ => issues}/issue-17718-static-move.stderr (100%) rename src/test/ui/{ => issues}/issue-17718-static-sync.rs (100%) rename src/test/ui/{ => issues}/issue-17718-static-sync.stderr (100%) rename src/test/ui/{ => issues}/issue-17728.nll.stderr (76%) rename src/test/ui/{ => issues}/issue-17728.rs (100%) rename src/test/ui/{ => issues}/issue-17728.stderr (100%) rename src/test/ui/{ => issues}/issue-17740.rs (100%) rename src/test/ui/{ => issues}/issue-17740.stderr (100%) create mode 100644 src/test/ui/issues/issue-17758.nll.stderr rename src/test/ui/{ => issues}/issue-17758.rs (100%) rename src/test/ui/{ => issues}/issue-17758.stderr (100%) rename src/test/ui/{ => issues}/issue-17800.rs (100%) rename src/test/ui/{ => issues}/issue-17800.stderr (100%) rename src/test/ui/{ => issues}/issue-17904-2.rs (100%) rename src/test/ui/{ => issues}/issue-17904-2.stderr (100%) rename src/test/ui/{ => issues}/issue-17905.rs (100%) rename src/test/ui/{ => issues}/issue-17905.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-17913.rs (93%) create mode 100644 src/test/ui/issues/issue-17913.stderr rename src/test/ui/{ => issues}/issue-17933.rs (100%) rename src/test/ui/{ => issues}/issue-17933.stderr (100%) create mode 100644 src/test/ui/issues/issue-17954.nll.stderr create mode 100644 src/test/ui/issues/issue-17954.rs create mode 100644 src/test/ui/issues/issue-17954.stderr rename src/test/ui/{ => issues}/issue-17959.rs (100%) rename src/test/ui/{ => issues}/issue-17959.stderr (100%) rename src/test/ui/{ => issues}/issue-17994.rs (100%) rename src/test/ui/{ => issues}/issue-17994.stderr (100%) rename src/test/ui/{ => issues}/issue-17999.rs (100%) rename src/test/ui/{ => issues}/issue-17999.stderr (100%) rename src/test/ui/{ => issues}/issue-18058.rs (100%) rename src/test/ui/{ => issues}/issue-18058.stderr (100%) rename src/test/ui/{ => issues}/issue-18107.rs (100%) rename src/test/ui/{ => issues}/issue-18107.stderr (96%) rename src/test/ui/{ => issues}/issue-18118-2.rs (100%) rename src/test/ui/{ => issues}/issue-18118-2.stderr (100%) rename src/test/ui/{ => issues}/issue-18118.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-18118.rs (100%) rename src/test/ui/{ => issues}/issue-18118.stderr (100%) rename src/test/ui/{ => issues}/issue-18119.rs (100%) rename src/test/ui/{ => issues}/issue-18119.stderr (100%) rename src/test/ui/{ => issues}/issue-18159.rs (100%) rename src/test/ui/{ => issues}/issue-18159.stderr (100%) rename src/test/ui/{ => issues}/issue-18183.rs (100%) rename src/test/ui/{ => issues}/issue-18183.stderr (100%) rename src/test/ui/{ => issues}/issue-18294.rs (88%) create mode 100644 src/test/ui/issues/issue-18294.stderr rename src/test/ui/{ => issues}/issue-18389.rs (100%) rename src/test/ui/{ => issues}/issue-18389.stderr (100%) rename src/test/ui/{ => issues}/issue-18400.rs (100%) rename src/test/ui/{ => issues}/issue-18400.stderr (100%) rename src/test/ui/{ => issues}/issue-18423.rs (79%) create mode 100644 src/test/ui/issues/issue-18423.stderr rename src/test/ui/{ => issues}/issue-18446.rs (100%) rename src/test/ui/{ => issues}/issue-18446.stderr (100%) rename src/test/ui/{ => issues}/issue-18532.rs (100%) rename src/test/ui/{ => issues}/issue-18532.stderr (100%) rename src/test/ui/{ => issues}/issue-18566.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-18566.rs (100%) rename src/test/ui/{ => issues}/issue-18566.stderr (100%) rename src/test/ui/{ => issues}/issue-18611.rs (100%) rename src/test/ui/{ => issues}/issue-18611.stderr (100%) rename src/test/ui/{ => issues}/issue-1871.rs (100%) rename src/test/ui/{ => issues}/issue-1871.stderr (100%) rename src/test/ui/{ => issues}/issue-18783.nll.stderr (76%) rename src/test/ui/{ => issues}/issue-18783.rs (100%) rename src/test/ui/{ => issues}/issue-18783.stderr (100%) rename src/test/ui/{ => issues}/issue-18819.rs (100%) rename src/test/ui/{ => issues}/issue-18819.stderr (100%) rename src/test/ui/{ => issues}/issue-18919.rs (100%) rename src/test/ui/{ => issues}/issue-18919.stderr (96%) rename src/test/ui/{ => issues}/issue-18937.rs (100%) rename src/test/ui/{ => issues}/issue-18937.stderr (100%) rename src/test/ui/{ => issues}/issue-18959.rs (100%) rename src/test/ui/{ => issues}/issue-18959.stderr (100%) rename src/test/ui/{ => issues}/issue-1900.rs (100%) rename src/test/ui/{ => issues}/issue-1900.stderr (100%) rename src/test/ui/{ => issues}/issue-19086.rs (100%) rename src/test/ui/{ => issues}/issue-19086.stderr (100%) rename src/test/ui/{ => issues}/issue-19100.fixed (100%) rename src/test/ui/{ => issues}/issue-19100.rs (100%) rename src/test/ui/{ => issues}/issue-19100.stderr (100%) create mode 100644 src/test/ui/issues/issue-19163.nll.stderr rename src/test/{compile-fail => ui/issues}/issue-19163.rs (100%) create mode 100644 src/test/ui/issues/issue-19163.stderr rename src/test/{compile-fail => ui/issues}/issue-1920-1.rs (100%) create mode 100644 src/test/ui/issues/issue-1920-1.stderr rename src/test/{compile-fail => ui/issues}/issue-1920-2.rs (100%) create mode 100644 src/test/ui/issues/issue-1920-2.stderr rename src/test/{compile-fail => ui/issues}/issue-1920-3.rs (100%) create mode 100644 src/test/ui/issues/issue-1920-3.stderr rename src/test/ui/{ => issues}/issue-19244-1.rs (100%) rename src/test/ui/{ => issues}/issue-19244-1.stderr (100%) rename src/test/ui/{ => issues}/issue-19244-2.rs (100%) rename src/test/ui/{ => issues}/issue-19244-2.stderr (100%) rename src/test/ui/{ => issues}/issue-19380.rs (100%) rename src/test/ui/{ => issues}/issue-19380.stderr (100%) rename src/test/ui/{ => issues}/issue-19482.rs (100%) rename src/test/ui/{ => issues}/issue-19482.stderr (100%) rename src/test/ui/{ => issues}/issue-19498.rs (100%) rename src/test/ui/{ => issues}/issue-19498.stderr (100%) rename src/test/ui/{ => issues}/issue-19521.rs (100%) rename src/test/ui/{ => issues}/issue-19521.stderr (100%) rename src/test/ui/{ => issues}/issue-19538.rs (100%) rename src/test/ui/{ => issues}/issue-19538.stderr (100%) rename src/test/ui/{ => issues}/issue-19601.rs (100%) rename src/test/ui/{ => issues}/issue-19601.stderr (100%) rename src/test/ui/{ => issues}/issue-1962.rs (100%) rename src/test/ui/{ => issues}/issue-1962.stderr (100%) rename src/test/ui/{ => issues}/issue-19660.rs (100%) rename src/test/ui/{ => issues}/issue-19660.stderr (100%) rename src/test/ui/{ => issues}/issue-19692.rs (100%) rename src/test/ui/{ => issues}/issue-19692.stderr (100%) rename src/test/ui/{ => issues}/issue-19707.rs (100%) rename src/test/ui/{ => issues}/issue-19707.stderr (100%) rename src/test/ui/{ => issues}/issue-19734.rs (100%) rename src/test/ui/{ => issues}/issue-19734.stderr (100%) rename src/test/ui/{ => issues}/issue-19883.rs (100%) rename src/test/ui/{ => issues}/issue-19883.stderr (100%) rename src/test/ui/{ => issues}/issue-19922.rs (100%) rename src/test/ui/{ => issues}/issue-19922.stderr (100%) rename src/test/ui/{ => issues}/issue-19982.rs (100%) rename src/test/ui/{ => issues}/issue-19982.stderr (100%) rename src/test/ui/{ => issues}/issue-19991.rs (100%) rename src/test/ui/{ => issues}/issue-19991.stderr (100%) rename src/test/ui/{ => issues}/issue-20005.rs (100%) rename src/test/ui/{ => issues}/issue-20005.stderr (97%) rename src/test/ui/{ => issues}/issue-20162.rs (100%) rename src/test/ui/{ => issues}/issue-20162.stderr (100%) rename src/test/ui/{ => issues}/issue-20225.rs (100%) rename src/test/ui/{ => issues}/issue-20225.stderr (100%) rename src/test/ui/{ => issues}/issue-20261.rs (100%) rename src/test/ui/{ => issues}/issue-20261.stderr (100%) rename src/test/ui/{ => issues}/issue-20313.rs (100%) rename src/test/ui/{ => issues}/issue-20313.stderr (100%) rename src/test/ui/{ => issues}/issue-20413.rs (100%) rename src/test/ui/{ => issues}/issue-20413.stderr (100%) rename src/test/ui/{ => issues}/issue-20433.rs (100%) rename src/test/ui/{ => issues}/issue-20433.stderr (96%) rename src/test/ui/{ => issues}/issue-20605.rs (100%) rename src/test/ui/{ => issues}/issue-20605.stderr (96%) rename src/test/ui/{ => issues}/issue-20616-1.rs (100%) rename src/test/ui/{ => issues}/issue-20616-1.stderr (100%) rename src/test/ui/{ => issues}/issue-20616-2.rs (100%) rename src/test/ui/{ => issues}/issue-20616-2.stderr (100%) rename src/test/ui/{ => issues}/issue-20616-3.rs (100%) rename src/test/ui/{ => issues}/issue-20616-3.stderr (100%) rename src/test/ui/{ => issues}/issue-20616-4.rs (100%) rename src/test/ui/{ => issues}/issue-20616-4.stderr (100%) rename src/test/ui/{ => issues}/issue-20616-5.rs (100%) rename src/test/ui/{ => issues}/issue-20616-5.stderr (100%) rename src/test/ui/{ => issues}/issue-20616-6.rs (100%) rename src/test/ui/{ => issues}/issue-20616-6.stderr (100%) rename src/test/ui/{ => issues}/issue-20616-7.rs (100%) rename src/test/ui/{ => issues}/issue-20616-7.stderr (100%) rename src/test/ui/{ => issues}/issue-20616-8.rs (100%) rename src/test/ui/{ => issues}/issue-20616-8.stderr (100%) rename src/test/ui/{ => issues}/issue-20616-9.rs (100%) rename src/test/ui/{ => issues}/issue-20616-9.stderr (100%) rename src/test/ui/{ => issues}/issue-20692.rs (100%) rename src/test/ui/{ => issues}/issue-20692.stderr (100%) rename src/test/ui/{ => issues}/issue-20714.rs (100%) rename src/test/ui/{ => issues}/issue-20714.stderr (100%) rename src/test/ui/{ => issues}/issue-20772.rs (100%) rename src/test/ui/{ => issues}/issue-20772.stderr (100%) rename src/test/ui/{ => issues}/issue-20801.nll.stderr (77%) rename src/test/ui/{ => issues}/issue-20801.rs (100%) rename src/test/ui/{ => issues}/issue-20801.stderr (100%) rename src/test/ui/{ => issues}/issue-20825.rs (100%) rename src/test/ui/{ => issues}/issue-20825.stderr (100%) rename src/test/ui/{ => issues}/issue-20831-debruijn.rs (100%) rename src/test/ui/{ => issues}/issue-20831-debruijn.stderr (100%) rename src/test/ui/{ => issues}/issue-20939.rs (100%) rename src/test/ui/{ => issues}/issue-20939.stderr (100%) rename src/test/ui/{ => issues}/issue-2111.rs (100%) rename src/test/ui/{ => issues}/issue-2111.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-21146.rs (100%) create mode 100644 src/test/ui/issues/issue-21146.stderr rename src/test/ui/{ => issues}/issue-21160.rs (100%) rename src/test/ui/{ => issues}/issue-21160.stderr (100%) rename src/test/ui/{ => issues}/issue-21174.rs (100%) rename src/test/ui/{ => issues}/issue-21174.stderr (100%) rename src/test/ui/{ => issues}/issue-21177.rs (100%) rename src/test/ui/{ => issues}/issue-21177.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-21202.rs (100%) create mode 100644 src/test/ui/issues/issue-21202.stderr rename src/test/ui/{ => issues}/issue-21332.rs (100%) rename src/test/ui/{ => issues}/issue-21332.stderr (100%) rename src/test/ui/{ => issues}/issue-21356.rs (100%) rename src/test/ui/{ => issues}/issue-21356.stderr (100%) rename src/test/ui/{ => issues}/issue-21449.rs (100%) rename src/test/ui/{ => issues}/issue-21449.stderr (100%) rename src/test/ui/{ => issues}/issue-2149.rs (100%) rename src/test/ui/{ => issues}/issue-2149.stderr (100%) rename src/test/ui/{ => issues}/issue-2150.rs (100%) rename src/test/ui/{ => issues}/issue-2150.stderr (100%) rename src/test/ui/{ => issues}/issue-2151.rs (100%) rename src/test/ui/{ => issues}/issue-2151.stderr (100%) rename src/test/ui/{ => issues}/issue-21546.rs (100%) rename src/test/ui/{ => issues}/issue-21546.stderr (100%) rename src/test/ui/{ => issues}/issue-21554.rs (100%) rename src/test/ui/{ => issues}/issue-21554.stderr (100%) rename src/test/ui/{ => issues}/issue-21600.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-21600.rs (100%) rename src/test/ui/{ => issues}/issue-21600.stderr (100%) rename src/test/ui/{ => issues}/issue-21701.rs (100%) rename src/test/ui/{ => issues}/issue-21701.stderr (100%) rename src/test/ui/{ => issues}/issue-21763.rs (100%) rename src/test/ui/{ => issues}/issue-21763.stderr (100%) rename src/test/ui/{ => issues}/issue-21837.rs (100%) rename src/test/ui/{ => issues}/issue-21837.stderr (100%) rename src/test/ui/{ => issues}/issue-21946.rs (100%) rename src/test/ui/{ => issues}/issue-21946.stderr (100%) rename src/test/ui/{ => issues}/issue-21950.rs (100%) rename src/test/ui/{ => issues}/issue-21950.stderr (100%) rename src/test/ui/{ => issues}/issue-21974.rs (100%) rename src/test/ui/{ => issues}/issue-21974.stderr (100%) rename src/test/ui/{ => issues}/issue-22034.rs (90%) create mode 100644 src/test/ui/issues/issue-22034.stderr rename src/test/ui/{ => issues}/issue-22037.rs (100%) rename src/test/ui/{ => issues}/issue-22037.stderr (100%) rename src/test/ui/{ => issues}/issue-22289.rs (100%) rename src/test/ui/{ => issues}/issue-22289.stderr (100%) rename src/test/ui/{ => issues}/issue-22312.rs (100%) rename src/test/ui/{ => issues}/issue-22312.stderr (100%) rename src/test/ui/{ => issues}/issue-22370.rs (100%) rename src/test/ui/{ => issues}/issue-22370.stderr (100%) rename src/test/ui/{ => issues}/issue-22384.rs (100%) rename src/test/ui/{ => issues}/issue-22384.stderr (100%) rename src/test/ui/{ => issues}/issue-22434.rs (100%) rename src/test/ui/{ => issues}/issue-22434.stderr (100%) rename src/test/ui/{ => issues}/issue-22468.rs (100%) rename src/test/ui/{ => issues}/issue-22468.stderr (100%) rename src/test/ui/{ => issues}/issue-22560.rs (100%) rename src/test/ui/{ => issues}/issue-22560.stderr (100%) rename src/test/ui/{ => issues}/issue-22599.rs (100%) rename src/test/ui/{ => issues}/issue-22599.stderr (100%) rename src/test/ui/{ => issues}/issue-22603.rs (100%) rename src/test/ui/{ => issues}/issue-22603.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-22638.rs (96%) create mode 100644 src/test/ui/issues/issue-22638.stderr rename src/test/ui/{ => issues}/issue-22644.rs (100%) rename src/test/ui/{ => issues}/issue-22644.stderr (100%) rename src/test/ui/{ => issues}/issue-22673.rs (100%) rename src/test/ui/{ => issues}/issue-22673.stderr (100%) rename src/test/ui/{ => issues}/issue-22684.rs (100%) rename src/test/ui/{ => issues}/issue-22684.stderr (100%) rename src/test/ui/{ => issues}/issue-22706.rs (100%) rename src/test/ui/{ => issues}/issue-22706.stderr (100%) rename src/test/ui/{ => issues}/issue-22789.rs (100%) rename src/test/ui/{ => issues}/issue-22789.stderr (100%) rename src/test/ui/{ => issues}/issue-2281-part1.rs (100%) rename src/test/ui/{ => issues}/issue-2281-part1.stderr (100%) rename src/test/ui/{ => issues}/issue-22874.rs (100%) rename src/test/ui/{ => issues}/issue-22874.stderr (96%) rename src/test/ui/{ => issues}/issue-22886.rs (100%) rename src/test/ui/{ => issues}/issue-22886.stderr (100%) rename src/test/ui/{ => issues}/issue-22933-1.rs (100%) rename src/test/ui/{ => issues}/issue-22933-1.stderr (100%) rename src/test/ui/{ => issues}/issue-22933-2.rs (100%) rename src/test/ui/{ => issues}/issue-22933-2.stderr (100%) rename src/test/ui/{ => issues}/issue-22933-3.rs (100%) rename src/test/ui/{ => issues}/issue-22933-3.stderr (100%) rename src/test/ui/{ => issues}/issue-23024.rs (98%) rename src/test/ui/{ => issues}/issue-23024.stderr (83%) rename src/test/ui/{ => issues}/issue-23041.rs (100%) rename src/test/ui/{ => issues}/issue-23041.stderr (100%) rename src/test/ui/{ => issues}/issue-23046.rs (100%) rename src/test/ui/{ => issues}/issue-23046.stderr (100%) rename src/test/ui/{ => issues}/issue-23073.rs (100%) rename src/test/ui/{ => issues}/issue-23073.stderr (100%) rename src/test/ui/{ => issues}/issue-23080-2.rs (100%) rename src/test/ui/{ => issues}/issue-23080-2.stderr (100%) rename src/test/ui/{ => issues}/issue-23080.rs (100%) rename src/test/ui/{ => issues}/issue-23080.stderr (100%) rename src/test/ui/{ => issues}/issue-23122-1.rs (100%) rename src/test/ui/{ => issues}/issue-23122-1.stderr (100%) rename src/test/ui/{ => issues}/issue-23122-2.rs (100%) rename src/test/ui/{ => issues}/issue-23122-2.stderr (100%) rename src/test/ui/{ => issues}/issue-23173.rs (100%) rename src/test/ui/{ => issues}/issue-23173.stderr (100%) rename src/test/ui/{ => issues}/issue-23217.rs (100%) rename src/test/ui/{ => issues}/issue-23217.stderr (100%) rename src/test/ui/{ => issues}/issue-23253.rs (100%) rename src/test/ui/{ => issues}/issue-23253.stderr (100%) rename src/test/ui/{ => issues}/issue-23281.rs (100%) rename src/test/ui/{ => issues}/issue-23281.stderr (96%) rename src/test/ui/{ => issues}/issue-2330.rs (100%) rename src/test/ui/{ => issues}/issue-2330.stderr (100%) rename src/test/ui/{ => issues}/issue-23302-1.rs (100%) rename src/test/ui/{ => issues}/issue-23302-1.stderr (100%) rename src/test/ui/{ => issues}/issue-23302-2.rs (100%) rename src/test/ui/{ => issues}/issue-23302-2.stderr (100%) rename src/test/ui/{ => issues}/issue-23302-3.rs (100%) rename src/test/ui/{ => issues}/issue-23302-3.stderr (100%) rename src/test/ui/{ => issues}/issue-23543.rs (100%) rename src/test/ui/{ => issues}/issue-23543.stderr (100%) rename src/test/ui/{ => issues}/issue-23544.rs (100%) rename src/test/ui/{ => issues}/issue-23544.stderr (100%) rename src/test/ui/{ => issues}/issue-23589.rs (100%) rename src/test/ui/{ => issues}/issue-23589.stderr (100%) rename src/test/ui/{ => issues}/issue-23595-2.rs (100%) rename src/test/ui/{ => issues}/issue-23595-2.stderr (100%) rename src/test/ui/{ => issues}/issue-23716.rs (100%) rename src/test/ui/{ => issues}/issue-23716.stderr (100%) rename src/test/ui/{ => issues}/issue-23966.rs (100%) create mode 100644 src/test/ui/issues/issue-23966.stderr rename src/test/ui/{ => issues}/issue-24013.rs (100%) rename src/test/ui/{ => issues}/issue-24013.stderr (100%) rename src/test/ui/{ => issues}/issue-24036.rs (100%) rename src/test/ui/{ => issues}/issue-24036.stderr (100%) rename src/test/ui/{ => issues}/issue-24081.rs (100%) rename src/test/ui/{ => issues}/issue-24081.stderr (100%) rename src/test/ui/{ => issues}/issue-24204.rs (100%) rename src/test/ui/{ => issues}/issue-24204.stderr (100%) rename src/test/ui/{ => issues}/issue-24267-flow-exit.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-24267-flow-exit.rs (100%) rename src/test/ui/{ => issues}/issue-24267-flow-exit.stderr (100%) rename src/test/ui/{ => issues}/issue-24322.rs (100%) rename src/test/ui/{ => issues}/issue-24322.stderr (100%) rename src/test/ui/{ => issues}/issue-24352.rs (100%) rename src/test/ui/{ => issues}/issue-24352.stderr (100%) rename src/test/ui/{ => issues}/issue-24357.nll.stderr (76%) rename src/test/ui/{ => issues}/issue-24357.rs (100%) rename src/test/ui/{ => issues}/issue-24357.stderr (100%) rename src/test/ui/{ => issues}/issue-24363.rs (100%) rename src/test/ui/{ => issues}/issue-24363.stderr (100%) rename src/test/ui/{ => issues}/issue-24365.rs (100%) rename src/test/ui/{ => issues}/issue-24365.stderr (100%) rename src/test/ui/{ => issues}/issue-24424.rs (100%) rename src/test/ui/{ => issues}/issue-24424.stderr (100%) rename src/test/ui/{ => issues}/issue-24446.rs (100%) rename src/test/ui/{ => issues}/issue-24446.stderr (98%) rename src/test/ui/{ => issues}/issue-24682.rs (100%) rename src/test/ui/{ => issues}/issue-24682.stderr (100%) rename src/test/ui/{ => issues}/issue-24819.rs (100%) rename src/test/ui/{ => issues}/issue-24819.stderr (100%) rename src/test/ui/{ => issues}/issue-24883.rs (100%) rename src/test/ui/{ => issues}/issue-24883.stderr (100%) rename src/test/ui/{ => issues}/issue-25076.rs (100%) rename src/test/ui/{ => issues}/issue-25076.stderr (100%) rename src/test/ui/{ => issues}/issue-25368.rs (100%) rename src/test/ui/{ => issues}/issue-25368.stderr (100%) rename src/test/ui/{ => issues}/issue-25385.rs (100%) rename src/test/ui/{ => issues}/issue-25385.stderr (100%) rename src/test/ui/{ => issues}/issue-25386.rs (100%) rename src/test/ui/{ => issues}/issue-25386.stderr (100%) rename src/test/ui/{ => issues}/issue-25396.rs (100%) rename src/test/ui/{ => issues}/issue-25396.stderr (100%) rename src/test/ui/{ => issues}/issue-25439.rs (100%) rename src/test/ui/{ => issues}/issue-25439.stderr (100%) rename src/test/ui/{ => issues}/issue-25579.ast.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-25579.ast.stderr (100%) rename src/test/ui/{ => issues}/issue-25579.mir.stderr (100%) rename src/test/ui/{ => issues}/issue-25579.rs (100%) rename src/test/ui/{ => issues}/issue-25700.rs (100%) rename src/test/ui/{ => issues}/issue-25700.stderr (100%) rename src/test/ui/{ => issues}/issue-25793.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-25793.rs (100%) rename src/test/ui/{ => issues}/issue-25793.stderr (100%) rename src/test/ui/{ => issues}/issue-25826.rs (89%) create mode 100644 src/test/ui/issues/issue-25826.stderr rename src/test/ui/{ => issues}/issue-2590.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-2590.rs (100%) rename src/test/ui/{ => issues}/issue-2590.stderr (100%) rename src/test/ui/{ => issues}/issue-25901.rs (100%) rename src/test/ui/{ => issues}/issue-25901.stderr (100%) rename src/test/ui/{ => issues}/issue-26056.rs (100%) rename src/test/ui/{ => issues}/issue-26056.stderr (100%) rename src/test/ui/{ => issues}/issue-26093.rs (100%) rename src/test/ui/{ => issues}/issue-26093.stderr (100%) rename src/test/ui/{ => issues}/issue-26094.rs (100%) rename src/test/ui/{ => issues}/issue-26094.stderr (100%) rename src/test/ui/{ => issues}/issue-26158.rs (100%) rename src/test/ui/{ => issues}/issue-26158.stderr (100%) create mode 100644 src/test/ui/issues/issue-26217.nll.stderr rename src/test/ui/{ => issues}/issue-26217.rs (100%) rename src/test/ui/{ => issues}/issue-26217.stderr (100%) rename src/test/ui/{ => issues}/issue-26237.rs (100%) rename src/test/ui/{ => issues}/issue-26237.stderr (100%) rename src/test/ui/{ => issues}/issue-26262.rs (100%) rename src/test/ui/{ => issues}/issue-26262.stderr (100%) rename src/test/ui/{ => issues}/issue-26459.rs (100%) rename src/test/ui/{ => issues}/issue-26459.stderr (100%) rename src/test/ui/{ => issues}/issue-26472.rs (100%) rename src/test/ui/{ => issues}/issue-26472.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-26548.rs (100%) create mode 100644 src/test/ui/issues/issue-26548.stderr rename src/test/ui/{ => issues}/issue-26614.rs (100%) rename src/test/ui/{ => issues}/issue-26614.stderr (100%) rename src/test/ui/{ => issues}/issue-26638.rs (100%) rename src/test/ui/{ => issues}/issue-26638.stderr (100%) rename src/test/ui/{ => issues}/issue-26812.rs (100%) rename src/test/ui/{ => issues}/issue-26812.stderr (100%) rename src/test/ui/{ => issues}/issue-26886.rs (100%) rename src/test/ui/{ => issues}/issue-26886.stderr (100%) rename src/test/ui/{ => issues}/issue-26905.rs (100%) rename src/test/ui/{ => issues}/issue-26905.stderr (100%) rename src/test/ui/{ => issues}/issue-26930.rs (100%) rename src/test/ui/{ => issues}/issue-26930.stderr (100%) rename src/test/ui/{ => issues}/issue-26948.rs (100%) rename src/test/ui/{ => issues}/issue-26948.stderr (100%) rename src/test/ui/{ => issues}/issue-27008.rs (100%) rename src/test/ui/{ => issues}/issue-27008.stderr (100%) rename src/test/ui/{ => issues}/issue-27033.rs (100%) rename src/test/ui/{ => issues}/issue-27033.stderr (100%) rename src/test/ui/{ => issues}/issue-27042.rs (100%) rename src/test/ui/{ => issues}/issue-27042.stderr (100%) rename src/test/ui/{ => issues}/issue-27060-2.rs (100%) rename src/test/ui/{ => issues}/issue-27060-2.stderr (81%) rename src/test/ui/{ => issues}/issue-27060.rs (100%) rename src/test/ui/{ => issues}/issue-27060.stderr (100%) rename src/test/ui/{ => issues}/issue-27078.rs (100%) rename src/test/ui/{ => issues}/issue-27078.stderr (88%) rename src/test/ui/{ => issues}/issue-2718-a.rs (100%) rename src/test/ui/{ => issues}/issue-2718-a.stderr (100%) rename src/test/ui/{ => issues}/issue-27282-move-match-input-into-guard.rs (100%) create mode 100644 src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr rename src/test/ui/{ => issues}/issue-27282-move-ref-mut-into-guard.rs (100%) rename src/test/ui/{ => issues}/issue-27282-move-ref-mut-into-guard.stderr (100%) rename src/test/ui/{ => issues}/issue-27282-mutate-before-diverging-arm-1.rs (100%) rename src/test/ui/{ => issues}/issue-27282-mutate-before-diverging-arm-1.stderr (88%) rename src/test/ui/{ => issues}/issue-27282-mutate-before-diverging-arm-2.rs (100%) rename src/test/ui/{ => issues}/issue-27282-mutate-before-diverging-arm-2.stderr (87%) rename src/test/ui/{ => issues}/issue-27282-reborrow-ref-mut-in-guard.rs (100%) rename src/test/ui/{ => issues}/issue-27282-reborrow-ref-mut-in-guard.stderr (100%) rename src/test/ui/{ => issues}/issue-27340.rs (100%) rename src/test/ui/{ => issues}/issue-27340.stderr (100%) rename src/test/ui/{ => issues}/issue-27433.rs (100%) rename src/test/ui/{ => issues}/issue-27433.stderr (100%) rename src/test/ui/{ => issues}/issue-27592.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-27592.rs (100%) rename src/test/ui/{ => issues}/issue-27592.stderr (100%) rename src/test/ui/{ => issues}/issue-27815.rs (100%) rename src/test/ui/{ => issues}/issue-27815.stderr (100%) rename src/test/ui/{ => issues}/issue-27842.rs (100%) rename src/test/ui/{ => issues}/issue-27842.stderr (100%) rename src/test/ui/{ => issues}/issue-27895.rs (100%) rename src/test/ui/{ => issues}/issue-27895.stderr (100%) rename src/test/ui/{ => issues}/issue-27942.rs (100%) rename src/test/ui/{ => issues}/issue-27942.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-28075.rs (84%) create mode 100644 src/test/ui/issues/issue-28075.stderr rename src/test/ui/{ => issues}/issue-28098.rs (100%) rename src/test/ui/{ => issues}/issue-28098.stderr (100%) rename src/test/ui/{ => issues}/issue-28105.rs (100%) rename src/test/ui/{ => issues}/issue-28105.stderr (100%) rename src/test/ui/{ => issues}/issue-28109.rs (100%) rename src/test/ui/{ => issues}/issue-28109.stderr (100%) rename src/test/ui/{ => issues}/issue-28113.rs (100%) rename src/test/ui/{ => issues}/issue-28113.stderr (100%) rename src/test/ui/{ => issues}/issue-2823.rs (100%) rename src/test/ui/{ => issues}/issue-2823.stderr (100%) rename src/test/ui/{ => issues}/issue-28324.rs (100%) rename src/test/ui/{ => issues}/issue-28324.stderr (100%) rename src/test/ui/{ => issues}/issue-28344.rs (100%) rename src/test/ui/{ => issues}/issue-28344.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-28388-1.rs (100%) create mode 100644 src/test/ui/issues/issue-28388-1.stderr rename src/test/{compile-fail => ui/issues}/issue-28388-2.rs (100%) create mode 100644 src/test/ui/issues/issue-28388-2.stderr rename src/test/{compile-fail => ui/issues}/issue-28388-3.rs (86%) create mode 100644 src/test/ui/issues/issue-28388-3.stderr rename src/test/ui/{ => issues}/issue-28433.rs (100%) rename src/test/ui/{ => issues}/issue-28433.stderr (100%) rename src/test/ui/{ => issues}/issue-28472.rs (100%) rename src/test/ui/{ => issues}/issue-28472.stderr (100%) rename src/test/ui/{ => issues}/issue-2848.rs (100%) rename src/test/ui/{ => issues}/issue-2848.stderr (100%) rename src/test/ui/{ => issues}/issue-2849.rs (100%) rename src/test/ui/{ => issues}/issue-2849.stderr (100%) rename src/test/ui/{ => issues}/issue-28568.rs (100%) rename src/test/ui/{ => issues}/issue-28568.stderr (100%) rename src/test/ui/{ => issues}/issue-28576.rs (100%) rename src/test/ui/{ => issues}/issue-28576.stderr (100%) rename src/test/ui/{ => issues}/issue-28586.rs (100%) rename src/test/ui/{ => issues}/issue-28586.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-28625.rs (94%) create mode 100644 src/test/ui/issues/issue-28625.stderr rename src/test/ui/{ => issues}/issue-28776.rs (100%) rename src/test/ui/{ => issues}/issue-28776.stderr (100%) rename src/test/ui/{ => issues}/issue-28837.rs (100%) rename src/test/ui/{ => issues}/issue-28837.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-28848.rs (96%) create mode 100644 src/test/ui/issues/issue-28848.stderr rename src/test/ui/{ => issues}/issue-28971.rs (100%) rename src/test/ui/{ => issues}/issue-28971.stderr (100%) rename src/test/ui/{ => issues}/issue-28992-empty.rs (100%) rename src/test/ui/{ => issues}/issue-28992-empty.stderr (100%) rename src/test/ui/{ => issues}/issue-29084.rs (100%) rename src/test/ui/{ => issues}/issue-29084.stderr (100%) rename src/test/ui/{ => issues}/issue-29124.rs (100%) rename src/test/ui/{ => issues}/issue-29124.stderr (100%) rename src/test/ui/{ => issues}/issue-29147.rs (100%) rename src/test/ui/{ => issues}/issue-29147.stderr (100%) rename src/test/ui/{ => issues}/issue-29161.rs (100%) rename src/test/ui/{ => issues}/issue-29161.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-29181.rs (100%) create mode 100644 src/test/ui/issues/issue-29181.stderr rename src/test/ui/{ => issues}/issue-29184.rs (100%) rename src/test/ui/{ => issues}/issue-29184.stderr (100%) rename src/test/ui/{ => issues}/issue-2937.rs (100%) rename src/test/ui/{ => issues}/issue-2937.stderr (100%) rename src/test/ui/{ => issues}/issue-2951.rs (100%) rename src/test/ui/{ => issues}/issue-2951.stderr (100%) rename src/test/ui/{ => issues}/issue-29723.rs (100%) rename src/test/ui/{ => issues}/issue-29723.stderr (100%) rename src/test/ui/{ => issues}/issue-29857.rs (100%) rename src/test/ui/{ => issues}/issue-29857.stderr (100%) rename src/test/ui/{ => issues}/issue-29861.rs (100%) rename src/test/ui/{ => issues}/issue-29861.stderr (100%) rename src/test/ui/{ => issues}/issue-2995.rs (100%) rename src/test/ui/{ => issues}/issue-2995.stderr (100%) rename src/test/ui/{ => issues}/issue-30007.rs (100%) rename src/test/ui/{ => issues}/issue-30007.stderr (100%) rename src/test/ui/{ => issues}/issue-30079.rs (100%) rename src/test/ui/{ => issues}/issue-30079.stderr (100%) rename src/test/ui/{ => issues}/issue-3008-1.rs (100%) rename src/test/ui/{ => issues}/issue-3008-1.stderr (100%) rename src/test/ui/{ => issues}/issue-3008-2.rs (100%) rename src/test/ui/{ => issues}/issue-3008-2.stderr (100%) rename src/test/ui/{ => issues}/issue-3008-3.rs (100%) rename src/test/ui/{ => issues}/issue-3008-3.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-30123.rs (100%) create mode 100644 src/test/ui/issues/issue-30123.stderr rename src/test/ui/{ => issues}/issue-3021-b.rs (100%) rename src/test/ui/{ => issues}/issue-3021-b.stderr (100%) rename src/test/ui/{ => issues}/issue-3021-c.rs (100%) rename src/test/ui/{ => issues}/issue-3021-c.stderr (100%) rename src/test/ui/{ => issues}/issue-3021-d.rs (100%) rename src/test/ui/{ => issues}/issue-3021-d.stderr (100%) rename src/test/ui/{ => issues}/issue-3021.rs (100%) rename src/test/ui/{ => issues}/issue-3021.stderr (100%) rename src/test/ui/{ => issues}/issue-30225.rs (100%) rename src/test/ui/{ => issues}/issue-30225.stderr (100%) rename src/test/ui/{ => issues}/issue-30236.rs (100%) rename src/test/ui/{ => issues}/issue-30236.stderr (100%) rename src/test/ui/{ => issues}/issue-30240-b.rs (100%) rename src/test/ui/{ => issues}/issue-30240-b.stderr (100%) rename src/test/ui/{ => issues}/issue-30240.rs (100%) rename src/test/ui/{ => issues}/issue-30240.stderr (100%) rename src/test/ui/{ => issues}/issue-30255.rs (100%) rename src/test/ui/{ => issues}/issue-30255.stderr (100%) rename src/test/ui/{ => issues}/issue-30302.rs (100%) rename src/test/ui/{ => issues}/issue-30302.stderr (100%) rename src/test/ui/{ => issues}/issue-30355.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-30355.rs (100%) rename src/test/ui/{ => issues}/issue-30355.stderr (100%) rename src/test/ui/{ => issues}/issue-3038.rs (100%) rename src/test/ui/{ => issues}/issue-3038.stderr (100%) rename src/test/ui/{ => issues}/issue-30438-a.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-30438-a.rs (100%) rename src/test/ui/{ => issues}/issue-30438-a.stderr (100%) rename src/test/ui/{ => issues}/issue-30438-b.rs (100%) rename src/test/ui/{ => issues}/issue-30438-b.stderr (100%) rename src/test/ui/{ => issues}/issue-30438-c.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-30438-c.rs (100%) rename src/test/ui/{ => issues}/issue-30438-c.stderr (100%) rename src/test/ui/{ => issues}/issue-3044.rs (100%) rename src/test/ui/{ => issues}/issue-3044.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-30535.rs (100%) create mode 100644 src/test/ui/issues/issue-30535.stderr rename src/test/ui/{ => issues}/issue-30560.rs (100%) rename src/test/ui/{ => issues}/issue-30560.stderr (100%) rename src/test/ui/{ => issues}/issue-30589.rs (100%) rename src/test/ui/{ => issues}/issue-30589.stderr (100%) rename src/test/ui/{ => issues}/issue-30730.rs (100%) rename src/test/ui/{ => issues}/issue-30730.stderr (100%) rename src/test/ui/{ => issues}/issue-3080.rs (100%) rename src/test/ui/{ => issues}/issue-3080.stderr (100%) rename src/test/ui/{ => issues}/issue-3096-1.rs (100%) rename src/test/ui/{ => issues}/issue-3096-1.stderr (100%) rename src/test/ui/{ => issues}/issue-3096-2.rs (100%) rename src/test/ui/{ => issues}/issue-3096-2.stderr (100%) rename src/test/ui/{ => issues}/issue-3099-a.rs (100%) rename src/test/ui/{ => issues}/issue-3099-a.stderr (100%) rename src/test/ui/{ => issues}/issue-3099-b.rs (100%) rename src/test/ui/{ => issues}/issue-3099-b.stderr (100%) rename src/test/ui/{ => issues}/issue-3099.rs (100%) rename src/test/ui/{ => issues}/issue-3099.stderr (100%) rename src/test/ui/{ => issues}/issue-31011.rs (100%) rename src/test/ui/{ => issues}/issue-31011.stderr (100%) rename src/test/ui/{ => issues}/issue-31109.rs (100%) rename src/test/ui/{ => issues}/issue-31109.stderr (100%) rename src/test/ui/{ => issues}/issue-31173.rs (100%) rename src/test/ui/{ => issues}/issue-31173.stderr (100%) rename src/test/ui/{ => issues}/issue-31212.rs (100%) rename src/test/ui/{ => issues}/issue-31212.stderr (100%) rename src/test/ui/{ => issues}/issue-31221.rs (100%) rename src/test/ui/{ => issues}/issue-31221.stderr (100%) rename src/test/ui/{ => issues}/issue-31511.rs (100%) rename src/test/ui/{ => issues}/issue-31511.stderr (100%) rename src/test/ui/{ => issues}/issue-3154.rs (100%) rename src/test/ui/{ => issues}/issue-3154.stderr (81%) rename src/test/ui/{ => issues}/issue-31561.rs (100%) rename src/test/ui/{ => issues}/issue-31561.stderr (100%) rename src/test/ui/{ => issues}/issue-31769.rs (100%) rename src/test/ui/{ => issues}/issue-31769.stderr (100%) rename src/test/ui/{ => issues}/issue-31804.rs (100%) rename src/test/ui/{ => issues}/issue-31804.stderr (100%) rename src/test/ui/{ => issues}/issue-31845.rs (89%) rename src/test/ui/{ => issues}/issue-31845.stderr (100%) rename src/test/ui/{ => issues}/issue-31910.rs (100%) rename src/test/ui/{ => issues}/issue-31910.stderr (100%) rename src/test/ui/{ => issues}/issue-31924-non-snake-ffi.rs (100%) rename src/test/ui/{ => issues}/issue-31924-non-snake-ffi.stderr (100%) rename src/test/ui/{ => issues}/issue-32004.rs (100%) rename src/test/ui/{ => issues}/issue-32004.stderr (100%) rename src/test/ui/{ => issues}/issue-32086.rs (100%) rename src/test/ui/{ => issues}/issue-32086.stderr (100%) rename src/test/ui/{ => issues}/issue-32119.rs (100%) rename src/test/ui/{ => issues}/issue-32119.stderr (100%) rename src/test/ui/{ => issues}/issue-3214.rs (100%) create mode 100644 src/test/ui/issues/issue-3214.stderr rename src/test/ui/{ => issues}/issue-32201.rs (100%) rename src/test/ui/{ => issues}/issue-32201.stderr (100%) rename src/test/ui/{ => issues}/issue-32222.rs (100%) rename src/test/ui/{ => issues}/issue-32222.stderr (100%) rename src/test/ui/{ => issues}/issue-32323.rs (100%) rename src/test/ui/{ => issues}/issue-32323.stderr (100%) rename src/test/ui/{ => issues}/issue-32326.rs (100%) rename src/test/ui/{ => issues}/issue-32326.stderr (100%) rename src/test/ui/{ => issues}/issue-32354-suggest-import-rename.fixed (100%) rename src/test/ui/{ => issues}/issue-32354-suggest-import-rename.rs (100%) rename src/test/ui/{ => issues}/issue-32354-suggest-import-rename.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-32377.rs (93%) create mode 100644 src/test/ui/issues/issue-32377.stderr rename src/test/ui/{ => issues}/issue-32655.rs (100%) rename src/test/ui/{ => issues}/issue-32655.stderr (85%) rename src/test/ui/{ => issues}/issue-32709.rs (100%) rename src/test/ui/{ => issues}/issue-32709.stderr (100%) rename src/test/ui/{ => issues}/issue-32782.rs (100%) rename src/test/ui/{ => issues}/issue-32782.stderr (100%) rename src/test/ui/{ => issues}/issue-32797.rs (100%) rename src/test/ui/{ => issues}/issue-32797.stderr (100%) rename src/test/ui/{ => issues}/issue-32829.rs (92%) create mode 100644 src/test/ui/issues/issue-32829.stderr rename src/test/ui/{ => issues}/issue-32833.rs (100%) rename src/test/ui/{ => issues}/issue-32833.stderr (100%) rename src/test/ui/{ => issues}/issue-32922.rs (100%) rename src/test/ui/{ => issues}/issue-32922.stderr (100%) rename src/test/ui/{ => issues}/issue-32950.rs (100%) rename src/test/ui/{ => issues}/issue-32950.stderr (100%) rename src/test/ui/{ => issues}/issue-32963.rs (100%) rename src/test/ui/{ => issues}/issue-32963.stderr (100%) rename src/test/ui/{ => issues}/issue-32995-2.rs (100%) rename src/test/ui/{ => issues}/issue-32995-2.stderr (100%) rename src/test/ui/{ => issues}/issue-32995.rs (100%) rename src/test/ui/{ => issues}/issue-32995.stderr (100%) rename src/test/ui/{ => issues}/issue-33241.rs (100%) rename src/test/ui/{ => issues}/issue-33241.stderr (100%) rename src/test/ui/{ => issues}/issue-33293.rs (100%) rename src/test/ui/{ => issues}/issue-33293.stderr (100%) rename src/test/ui/{ => issues}/issue-3344.rs (100%) rename src/test/ui/{ => issues}/issue-3344.stderr (100%) rename src/test/ui/{ => issues}/issue-33464.rs (100%) rename src/test/ui/{ => issues}/issue-33464.stderr (100%) rename src/test/ui/{ => issues}/issue-33504.rs (100%) rename src/test/ui/{ => issues}/issue-33504.stderr (100%) rename src/test/ui/{ => issues}/issue-33525.rs (100%) rename src/test/ui/{ => issues}/issue-33525.stderr (100%) rename src/test/ui/{ => issues}/issue-33571.rs (100%) rename src/test/ui/{ => issues}/issue-33571.stderr (100%) rename src/test/ui/{ => issues}/issue-33819.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-33819.rs (100%) rename src/test/ui/{ => issues}/issue-33819.stderr (100%) rename src/test/ui/{ => issues}/issue-33941.rs (100%) rename src/test/ui/{ => issues}/issue-33941.stderr (100%) rename src/test/ui/{ => issues}/issue-34028.rs (100%) rename src/test/ui/{ => issues}/issue-34028.stderr (100%) rename src/test/ui/{ => issues}/issue-34047.rs (100%) rename src/test/ui/{ => issues}/issue-34047.stderr (100%) rename src/test/ui/{ => issues}/issue-34171.rs (100%) rename src/test/ui/{ => issues}/issue-34171.stderr (100%) rename src/test/ui/{ => issues}/issue-34209.rs (100%) rename src/test/ui/{ => issues}/issue-34209.stderr (100%) rename src/test/ui/{ => issues}/issue-34222-1.rs (100%) rename src/test/ui/{ => issues}/issue-34222-1.stderr (100%) rename src/test/ui/{ => issues}/issue-34334.rs (100%) rename src/test/ui/{ => issues}/issue-34334.stderr (100%) rename src/test/ui/{ => issues}/issue-34349.rs (100%) rename src/test/ui/{ => issues}/issue-34349.stderr (100%) rename src/test/ui/{ => issues}/issue-34373.rs (100%) rename src/test/ui/{ => issues}/issue-34373.stderr (100%) rename src/test/ui/{ => issues}/issue-34418.rs (100%) rename src/test/ui/{ => issues}/issue-34418.stderr (100%) rename src/test/ui/{ => issues}/issue-3477.rs (100%) rename src/test/ui/{ => issues}/issue-3477.stderr (100%) rename src/test/ui/{ => issues}/issue-34839.rs (100%) rename src/test/ui/{ => issues}/issue-34839.stderr (100%) rename src/test/ui/{ => issues}/issue-35075.rs (100%) rename src/test/ui/{ => issues}/issue-35075.stderr (100%) rename src/test/ui/{ => issues}/issue-35139.rs (100%) rename src/test/ui/{ => issues}/issue-35139.stderr (100%) rename src/test/ui/{ => issues}/issue-3521-2.rs (100%) rename src/test/ui/{ => issues}/issue-3521-2.stderr (100%) rename src/test/ui/{ => issues}/issue-3521.rs (100%) rename src/test/ui/{ => issues}/issue-3521.stderr (100%) rename src/test/ui/{ => issues}/issue-35241.rs (100%) rename src/test/ui/{ => issues}/issue-35241.stderr (100%) rename src/test/ui/{ => issues}/issue-35450.rs (100%) rename src/test/ui/{ => issues}/issue-35450.stderr (100%) rename src/test/ui/{ => issues}/issue-35570.rs (100%) rename src/test/ui/{ => issues}/issue-35570.stderr (100%) rename src/test/ui/{ => issues}/issue-35668.rs (100%) rename src/test/ui/{ => issues}/issue-35668.stderr (100%) rename src/test/ui/{ => issues}/issue-35675.rs (100%) rename src/test/ui/{ => issues}/issue-35675.stderr (100%) rename src/test/ui/{ => issues}/issue-35869.rs (100%) rename src/test/ui/{ => issues}/issue-35869.stderr (100%) rename src/test/ui/{ => issues}/issue-35976.rs (100%) rename src/test/ui/{ => issues}/issue-35976.stderr (100%) rename src/test/ui/{ => issues}/issue-35988.rs (100%) rename src/test/ui/{ => issues}/issue-35988.stderr (96%) rename src/test/ui/{ => issues}/issue-3601.rs (100%) rename src/test/ui/{ => issues}/issue-3601.stderr (100%) rename src/test/ui/{ => issues}/issue-36082.ast.nll.stderr (86%) rename src/test/ui/{ => issues}/issue-36082.ast.stderr (100%) rename src/test/ui/{ => issues}/issue-36082.mir.stderr (86%) rename src/test/ui/{ => issues}/issue-36082.rs (94%) rename src/test/ui/{ => issues}/issue-36116.rs (100%) rename src/test/ui/{ => issues}/issue-36116.stderr (100%) rename src/test/ui/{ => issues}/issue-36163.rs (100%) rename src/test/ui/{ => issues}/issue-36163.stderr (100%) rename src/test/ui/{ => issues}/issue-36299.rs (100%) rename src/test/ui/{ => issues}/issue-36299.stderr (100%) rename src/test/ui/{ => issues}/issue-36379.rs (100%) rename src/test/ui/{ => issues}/issue-36379.stderr (100%) rename src/test/ui/{ => issues}/issue-36400.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-36400.rs (100%) rename src/test/ui/{ => issues}/issue-36400.stderr (85%) rename src/test/ui/{ => issues}/issue-36617.rs (100%) rename src/test/ui/{ => issues}/issue-36617.stderr (100%) rename src/test/ui/{ => issues}/issue-36638.rs (100%) rename src/test/ui/{ => issues}/issue-36638.stderr (100%) rename src/test/ui/{ => issues}/issue-3668-2.rs (100%) rename src/test/ui/{ => issues}/issue-3668-2.stderr (100%) rename src/test/ui/{ => issues}/issue-3668.rs (100%) rename src/test/ui/{ => issues}/issue-3668.stderr (100%) rename src/test/ui/{ => issues}/issue-36708.rs (100%) rename src/test/ui/{ => issues}/issue-36708.stderr (100%) rename src/test/ui/{ => issues}/issue-3680.rs (100%) rename src/test/ui/{ => issues}/issue-3680.stderr (100%) rename src/test/ui/{ => issues}/issue-36839.rs (100%) rename src/test/ui/{ => issues}/issue-36839.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-36881.rs (100%) create mode 100644 src/test/ui/issues/issue-36881.stderr rename src/test/ui/{ => issues}/issue-3702-2.rs (100%) rename src/test/ui/{ => issues}/issue-3702-2.stderr (100%) rename src/test/ui/{ => issues}/issue-37026.rs (100%) rename src/test/ui/{ => issues}/issue-37026.stderr (100%) rename src/test/ui/{ => issues}/issue-37051.rs (100%) rename src/test/ui/{ => issues}/issue-37051.stderr (100%) rename src/test/ui/{ => issues}/issue-3707.rs (100%) rename src/test/ui/{ => issues}/issue-3707.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-37131.rs (100%) create mode 100644 src/test/ui/issues/issue-37131.stderr rename src/test/ui/{ => issues}/issue-37311-type-length-limit/issue-37311.rs (100%) rename src/test/ui/{ => issues}/issue-37311-type-length-limit/issue-37311.stderr (100%) rename src/test/ui/{ => issues}/issue-37323.rs (96%) rename src/test/ui/{ => issues}/issue-37366.rs (100%) rename src/test/ui/{ => issues}/issue-37366.stderr (100%) rename src/test/ui/{ => issues}/issue-37510.rs (100%) rename src/test/ui/{ => issues}/issue-37510.stderr (100%) rename src/test/ui/{ => issues}/issue-37515.rs (100%) rename src/test/ui/{ => issues}/issue-37515.stderr (100%) rename src/test/ui/{ => issues}/issue-37534.rs (100%) rename src/test/ui/{ => issues}/issue-37534.stderr (100%) rename src/test/ui/{ => issues}/issue-37550.rs (100%) rename src/test/ui/{ => issues}/issue-37550.stderr (100%) rename src/test/ui/{ => issues}/issue-37576.rs (100%) rename src/test/ui/{ => issues}/issue-37576.stderr (100%) rename src/test/ui/{ => issues}/issue-3763.rs (100%) rename src/test/ui/{ => issues}/issue-3763.stderr (100%) rename src/test/ui/{ => issues}/issue-37665.rs (100%) rename src/test/ui/{ => issues}/issue-37665.stderr (100%) rename src/test/ui/{ => issues}/issue-3779.rs (100%) rename src/test/ui/{ => issues}/issue-3779.stderr (100%) rename src/test/ui/{ => issues}/issue-37884.rs (100%) rename src/test/ui/{ => issues}/issue-37884.stderr (100%) rename src/test/ui/{ => issues}/issue-37887.rs (100%) rename src/test/ui/{ => issues}/issue-37887.stderr (100%) rename src/test/ui/{ => issues}/issue-38160.rs (100%) rename src/test/ui/{ => issues}/issue-38160.stderr (100%) rename src/test/ui/{ => issues}/issue-3820.rs (100%) rename src/test/ui/{ => issues}/issue-3820.stderr (100%) rename src/test/ui/{ => issues}/issue-38293.rs (100%) rename src/test/ui/{ => issues}/issue-38293.stderr (100%) rename src/test/ui/{ => issues}/issue-38381.rs (100%) rename src/test/ui/{ => issues}/issue-38381.stderr (100%) rename src/test/ui/{ => issues}/issue-38404.rs (100%) rename src/test/ui/{ => issues}/issue-38404.stderr (100%) rename src/test/ui/{ => issues}/issue-38412.rs (100%) rename src/test/ui/{ => issues}/issue-38412.stderr (100%) rename src/test/ui/{ => issues}/issue-38458.rs (100%) rename src/test/ui/{ => issues}/issue-38458.stderr (100%) rename src/test/ui/{ => issues}/issue-38604.rs (100%) rename src/test/ui/{ => issues}/issue-38604.stderr (100%) create mode 100644 src/test/ui/issues/issue-38715.rs create mode 100644 src/test/ui/issues/issue-38715.stderr rename src/test/{compile-fail/isssue-38821.rs => ui/issues/issue-38821.rs} (100%) create mode 100644 src/test/ui/issues/issue-38821.stderr rename src/test/ui/{ => issues}/issue-38857.rs (100%) rename src/test/ui/{ => issues}/issue-38857.stderr (100%) rename src/test/ui/{ => issues}/issue-38868.rs (100%) rename src/test/ui/{ => issues}/issue-38868.stderr (100%) rename src/test/ui/{ => issues}/issue-38875/auxiliary/issue_38875_b.rs (100%) rename src/test/ui/{ => issues}/issue-38875/issue_38875.rs (100%) rename src/test/ui/{ => issues}/issue-38919.rs (100%) rename src/test/ui/{ => issues}/issue-38919.stderr (100%) rename src/test/ui/{ => issues}/issue-38954.rs (100%) rename src/test/ui/{ => issues}/issue-38954.stderr (77%) rename src/test/ui/{ => issues}/issue-39211.rs (100%) rename src/test/ui/{ => issues}/issue-39211.stderr (100%) rename src/test/ui/{ => issues}/issue-39362.rs (100%) rename src/test/ui/{ => issues}/issue-39362.stderr (100%) rename src/test/ui/{ => issues}/issue-39388.rs (100%) rename src/test/ui/{ => issues}/issue-39388.stderr (100%) rename src/test/ui/{ => issues}/issue-39404.rs (100%) rename src/test/ui/{ => issues}/issue-39404.stderr (100%) rename src/test/ui/{ => issues}/issue-39559-2.rs (100%) rename src/test/ui/{ => issues}/issue-39559-2.stderr (100%) rename src/test/ui/{ => issues}/issue-39559.rs (100%) rename src/test/ui/{ => issues}/issue-39559.stderr (100%) rename src/test/ui/{ => issues}/issue-39616.rs (100%) rename src/test/ui/{ => issues}/issue-39616.stderr (100%) rename src/test/ui/{ => issues}/issue-39687.rs (100%) rename src/test/ui/{ => issues}/issue-39687.stderr (100%) rename src/test/ui/{ => issues}/issue-3973.rs (100%) rename src/test/ui/{ => issues}/issue-3973.stderr (100%) rename src/test/ui/{ => issues}/issue-39848.rs (100%) rename src/test/ui/{ => issues}/issue-39848.stderr (100%) rename src/test/ui/{ => issues}/issue-3993.rs (100%) rename src/test/ui/{ => issues}/issue-3993.stderr (100%) rename src/test/ui/{ => issues}/issue-39970.rs (100%) rename src/test/ui/{ => issues}/issue-39970.stderr (100%) rename src/test/ui/{ => issues}/issue-39974.rs (100%) rename src/test/ui/{ => issues}/issue-39974.stderr (100%) rename src/test/ui/{ => issues}/issue-40000.rs (100%) rename src/test/ui/{ => issues}/issue-40000.stderr (100%) create mode 100644 src/test/ui/issues/issue-40288-2.nll.stderr rename src/test/ui/{ => issues}/issue-40288-2.rs (100%) create mode 100644 src/test/ui/issues/issue-40288-2.stderr rename src/test/ui/{ => issues}/issue-40288.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-40288.rs (100%) rename src/test/ui/{ => issues}/issue-40288.stderr (100%) rename src/test/ui/{ => issues}/issue-40350.rs (100%) rename src/test/ui/{ => issues}/issue-40350.stderr (100%) rename src/test/ui/{ => issues}/issue-40402-ref-hints/issue-40402-1.nll.stderr (84%) rename src/test/ui/{ => issues}/issue-40402-ref-hints/issue-40402-1.rs (100%) rename src/test/ui/{ => issues}/issue-40402-ref-hints/issue-40402-1.stderr (100%) create mode 100644 src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.nll.stderr rename src/test/ui/{ => issues}/issue-40402-ref-hints/issue-40402-2.rs (100%) rename src/test/ui/{ => issues}/issue-40402-ref-hints/issue-40402-2.stderr (100%) create mode 100644 src/test/ui/issues/issue-40510-1.nll.stderr rename src/test/ui/{ => issues}/issue-40510-1.rs (100%) rename src/test/ui/{ => issues}/issue-40510-1.stderr (100%) rename src/test/ui/{ => issues}/issue-40510-2.rs (100%) rename src/test/ui/{ => issues}/issue-40510-2.stderr (100%) create mode 100644 src/test/ui/issues/issue-40510-3.nll.stderr rename src/test/ui/{ => issues}/issue-40510-3.rs (100%) rename src/test/ui/{ => issues}/issue-40510-3.stderr (100%) rename src/test/ui/{ => issues}/issue-40510-4.rs (100%) rename src/test/ui/{ => issues}/issue-40510-4.stderr (100%) rename src/test/ui/{ => issues}/issue-40610.rs (100%) rename src/test/ui/{ => issues}/issue-40610.stderr (100%) rename src/test/ui/{ => issues}/issue-40749.rs (100%) rename src/test/ui/{ => issues}/issue-40749.stderr (100%) rename src/test/ui/{ => issues}/issue-40782.rs (100%) rename src/test/ui/{ => issues}/issue-40782.stderr (100%) rename src/test/ui/{ => issues}/issue-40845.rs (100%) rename src/test/ui/{ => issues}/issue-40845.stderr (100%) rename src/test/ui/{ => issues}/issue-40861.rs (100%) rename src/test/ui/{ => issues}/issue-40861.stderr (100%) rename src/test/ui/{ => issues}/issue-41139.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-41139.rs (100%) rename src/test/ui/{ => issues}/issue-41139.stderr (100%) rename src/test/ui/{ => issues}/issue-41229-ref-str.rs (100%) rename src/test/ui/{ => issues}/issue-41229-ref-str.stderr (78%) rename src/test/ui/{ => issues}/issue-41255.rs (100%) rename src/test/ui/{ => issues}/issue-41255.stderr (100%) rename src/test/ui/{ => issues}/issue-41394.rs (100%) rename src/test/ui/{ => issues}/issue-41394.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue-41549.rs (100%) create mode 100644 src/test/ui/issues/issue-41549.stderr rename src/test/ui/{ => issues}/issue-41652/auxiliary/issue_41652_b.rs (100%) rename src/test/ui/{ => issues}/issue-41652/issue_41652.rs (100%) rename src/test/ui/{ => issues}/issue-41652/issue_41652.stderr (100%) create mode 100644 src/test/ui/issues/issue-41726.nll.stderr rename src/test/ui/{ => issues}/issue-41726.rs (100%) create mode 100644 src/test/ui/issues/issue-41726.stderr rename src/test/ui/{ => issues}/issue-41742.rs (100%) rename src/test/ui/{ => issues}/issue-41742.stderr (100%) rename src/test/ui/{ => issues}/issue-41776.rs (100%) rename src/test/ui/{ => issues}/issue-41776.stderr (100%) rename src/test/ui/{ => issues}/issue-41880.rs (100%) rename src/test/ui/{ => issues}/issue-41880.stderr (100%) rename src/test/ui/{ => issues}/issue-41974.rs (100%) rename src/test/ui/{ => issues}/issue-41974.stderr (100%) rename src/test/ui/{ => issues}/issue-41998.rs (100%) rename src/test/ui/{ => issues}/issue-41998.stderr (100%) rename src/test/ui/{ => issues}/issue-4201.rs (100%) rename src/test/ui/{ => issues}/issue-4201.stderr (100%) rename src/test/ui/{ => issues}/issue-42060.rs (100%) rename src/test/ui/{ => issues}/issue-42060.stderr (100%) rename src/test/ui/{ => issues}/issue-42106.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-42106.rs (100%) rename src/test/ui/{ => issues}/issue-42106.stderr (100%) rename src/test/ui/{ => issues}/issue-42312.rs (100%) rename src/test/ui/{ => issues}/issue-42312.stderr (80%) rename src/test/ui/{ => issues}/issue-42344.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-42344.rs (100%) rename src/test/ui/{ => issues}/issue-42344.stderr (100%) rename src/test/ui/{ => issues}/issue-4265.rs (100%) rename src/test/ui/{ => issues}/issue-4265.stderr (100%) rename src/test/ui/{ => issues}/issue-42755.rs (90%) create mode 100644 src/test/ui/issues/issue-42755.stderr rename src/test/ui/{ => issues}/issue-42796.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-42796.rs (100%) rename src/test/ui/{ => issues}/issue-42796.stderr (100%) rename src/test/ui/{ => issues}/issue-42880.rs (100%) rename src/test/ui/{ => issues}/issue-42880.stderr (100%) rename src/test/ui/{ => issues}/issue-42954.fixed (100%) rename src/test/ui/{ => issues}/issue-42954.rs (100%) rename src/test/ui/{ => issues}/issue-42954.stderr (100%) rename src/test/ui/{ => issues}/issue-43023.rs (100%) rename src/test/ui/{ => issues}/issue-43023.stderr (100%) rename src/test/ui/{ => issues}/issue-43105.rs (100%) rename src/test/ui/{ => issues}/issue-43105.stderr (100%) rename src/test/ui/{ => issues}/issue-43162.rs (100%) rename src/test/ui/{ => issues}/issue-43162.stderr (100%) rename src/test/ui/{ => issues}/issue-43189.rs (100%) rename src/test/ui/{ => issues}/issue-43189.stderr (100%) rename src/test/ui/{ => issues}/issue-43196.rs (100%) rename src/test/ui/{ => issues}/issue-43196.stderr (100%) rename src/test/ui/{ => issues}/issue-4321.rs (100%) rename src/test/ui/{ => issues}/issue-4321.stderr (100%) rename src/test/ui/{ => issues}/issue-43250.rs (100%) rename src/test/ui/{ => issues}/issue-43250.stderr (100%) create mode 100644 src/test/ui/issues/issue-4335.nll.stderr rename src/test/ui/{ => issues}/issue-4335.rs (100%) rename src/test/ui/{ => issues}/issue-4335.stderr (100%) rename src/test/ui/{ => issues}/issue-43355.rs (100%) rename src/test/ui/{ => issues}/issue-43355.stderr (100%) rename src/test/ui/{ => issues}/issue-43420-no-over-suggest.rs (100%) rename src/test/ui/{ => issues}/issue-43420-no-over-suggest.stderr (100%) rename src/test/ui/{ => issues}/issue-43424.rs (100%) rename src/test/ui/{ => issues}/issue-43424.stderr (100%) rename src/test/ui/{ => issues}/issue-43431.rs (100%) rename src/test/ui/{ => issues}/issue-43431.stderr (100%) rename src/test/ui/{ => issues}/issue-4366-2.rs (100%) rename src/test/ui/{ => issues}/issue-4366-2.stderr (100%) rename src/test/ui/{ => issues}/issue-4366.rs (100%) rename src/test/ui/{ => issues}/issue-4366.stderr (100%) rename src/test/ui/{ => issues}/issue-43733.rs (100%) rename src/test/ui/{ => issues}/issue-43733.stderr (100%) rename src/test/ui/{ => issues}/issue-43784-associated-type.rs (98%) create mode 100644 src/test/ui/issues/issue-43784-associated-type.stderr rename src/test/ui/{ => issues}/issue-43784-supertrait.rs (97%) create mode 100644 src/test/ui/issues/issue-43784-supertrait.stderr rename src/test/ui/{ => issues}/issue-43806.rs (100%) rename src/test/ui/{ => issues}/issue-43925.rs (95%) rename src/test/ui/{ => issues}/issue-43925.stderr (86%) rename src/test/ui/{ => issues}/issue-43926.rs (100%) rename src/test/ui/{ => issues}/issue-43926.stderr (100%) rename src/test/ui/{ => issues}/issue-43988.rs (100%) rename src/test/ui/{ => issues}/issue-43988.stderr (100%) rename src/test/ui/{ => issues}/issue-44021.rs (100%) rename src/test/ui/{ => issues}/issue-44021.stderr (100%) rename src/test/ui/{ => issues}/issue-44023.rs (100%) rename src/test/ui/{ => issues}/issue-44023.stderr (100%) rename src/test/ui/{ => issues}/issue-44078.rs (100%) rename src/test/ui/{ => issues}/issue-44078.stderr (100%) rename src/test/ui/{ => issues}/issue-44239.rs (100%) rename src/test/ui/{ => issues}/issue-44239.stderr (100%) rename src/test/ui/{ => issues}/issue-44373.rs (100%) rename src/test/ui/{ => issues}/issue-44373.stderr (100%) rename src/test/ui/{ => issues}/issue-44406.rs (100%) rename src/test/ui/{ => issues}/issue-44406.stderr (100%) rename src/test/ui/{ => issues}/issue-44415.rs (96%) rename src/test/ui/{ => issues}/issue-44415.stderr (100%) rename src/test/ui/{ => issues}/issue-45087-unreachable-unsafe.rs (100%) rename src/test/ui/{ => issues}/issue-45087-unreachable-unsafe.stderr (100%) rename src/test/ui/{ => issues}/issue-45107-unnecessary-unsafe-in-closure.rs (100%) rename src/test/ui/{ => issues}/issue-45107-unnecessary-unsafe-in-closure.stderr (100%) rename src/test/ui/{ => issues}/issue-45157.rs (100%) rename src/test/ui/{ => issues}/issue-45157.stderr (100%) rename src/test/ui/{ => issues}/issue-4517.rs (100%) rename src/test/ui/{ => issues}/issue-4517.stderr (100%) create mode 100644 src/test/ui/issues/issue-45199.ast.nll.stderr rename src/test/ui/{ => issues}/issue-45199.ast.stderr (86%) create mode 100644 src/test/ui/issues/issue-45199.mir.stderr rename src/test/ui/{ => issues}/issue-45199.rs (85%) rename src/test/ui/{ => issues}/issue-45296.rs (100%) rename src/test/ui/{ => issues}/issue-45296.stderr (100%) rename src/test/ui/{ => issues}/issue-45562.fixed (100%) rename src/test/ui/{ => issues}/issue-45562.rs (100%) rename src/test/ui/{ => issues}/issue-45562.stderr (100%) create mode 100644 src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs create mode 100644 src/test/ui/issues/issue-45696-no-variant-box-recur.rs create mode 100644 src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.ast.stderr create mode 100644 src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr create mode 100644 src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.nll.stderr create mode 100644 src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.rs rename src/test/ui/{ => issues}/issue-45697-1.rs (100%) rename src/test/ui/{ => issues}/issue-45697-1.stderr (100%) rename src/test/ui/{ => issues}/issue-45697.rs (100%) rename src/test/ui/{ => issues}/issue-45697.stderr (100%) rename src/test/ui/{ => issues}/issue-45729-unsafe-in-generator.rs (100%) rename src/test/ui/{ => issues}/issue-45729-unsafe-in-generator.stderr (100%) rename src/test/ui/{ => issues}/issue-45730.rs (100%) rename src/test/ui/{ => issues}/issue-45730.stderr (100%) rename src/test/ui/{ => issues}/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed (100%) rename src/test/ui/{ => issues}/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs (100%) rename src/test/ui/{ => issues}/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr (100%) rename src/test/ui/{ => issues}/issue-45801.rs (100%) rename src/test/ui/{ => issues}/issue-45801.stderr (100%) rename src/test/ui/{ => issues}/issue-45965.rs (100%) rename src/test/ui/{ => issues}/issue-45965.stderr (100%) rename src/test/ui/{ => issues}/issue-46023.ast.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-46023.ast.stderr (100%) rename src/test/ui/{ => issues}/issue-46023.mir.stderr (100%) rename src/test/ui/{ => issues}/issue-46023.rs (100%) rename src/test/ui/{ => issues}/issue-46036.rs (100%) rename src/test/ui/{ => issues}/issue-46036.stderr (100%) rename src/test/ui/{ => issues}/issue-46112.rs (100%) rename src/test/ui/{ => issues}/issue-46112.stderr (100%) rename src/test/ui/{ => issues}/issue-46186.rs (100%) rename src/test/ui/{ => issues}/issue-46186.stderr (100%) rename src/test/ui/{ => issues}/issue-46302.rs (100%) rename src/test/ui/{ => issues}/issue-46302.stderr (100%) rename src/test/ui/{ => issues}/issue-46311.rs (100%) rename src/test/ui/{ => issues}/issue-46311.stderr (100%) rename src/test/ui/{ => issues}/issue-46332.rs (100%) rename src/test/ui/{ => issues}/issue-46332.stderr (100%) rename src/test/ui/{ => issues}/issue-46438.rs (100%) rename src/test/ui/{ => issues}/issue-46438.stderr (100%) rename src/test/ui/{ => issues}/issue-46471-1.rs (100%) create mode 100644 src/test/ui/issues/issue-46471-1.stderr rename src/test/ui/{ => issues}/issue-46471.rs (100%) rename src/test/ui/{ => issues}/issue-46471.stderr (100%) rename src/test/ui/{ => issues}/issue-46472.rs (100%) rename src/test/ui/{ => issues}/issue-46472.stderr (100%) rename src/test/ui/{ => issues}/issue-46576.rs (100%) rename src/test/ui/{ => issues}/issue-46576.stderr (100%) rename src/test/ui/{ => issues}/issue-46604.ast.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-46604.ast.stderr (100%) rename src/test/ui/{ => issues}/issue-46604.mir.stderr (100%) rename src/test/ui/{ => issues}/issue-46604.rs (100%) rename src/test/ui/{ => issues}/issue-46756-consider-borrowing-cast-or-binexpr.fixed (100%) rename src/test/ui/{ => issues}/issue-46756-consider-borrowing-cast-or-binexpr.rs (100%) rename src/test/ui/{ => issues}/issue-46756-consider-borrowing-cast-or-binexpr.stderr (100%) rename src/test/ui/{ => issues}/issue-46771.rs (100%) rename src/test/ui/{ => issues}/issue-46771.stderr (100%) rename src/test/ui/{ => issues}/issue-46843.rs (100%) rename src/test/ui/{ => issues}/issue-46843.stderr (100%) rename src/test/ui/{ => issues}/issue-46983.rs (100%) rename src/test/ui/{ => issues}/issue-46983.stderr (76%) rename src/test/ui/{ => issues}/issue-47073-zero-padded-tuple-struct-indices.rs (100%) rename src/test/ui/{ => issues}/issue-47073-zero-padded-tuple-struct-indices.stderr (100%) rename src/test/ui/{ => issues}/issue-47094.rs (100%) rename src/test/ui/{ => issues}/issue-47094.stderr (100%) rename src/test/ui/{ => issues}/issue-47184.rs (100%) rename src/test/ui/{ => issues}/issue-47184.stderr (100%) rename src/test/ui/{ => issues}/issue-47309.rs (100%) rename src/test/ui/{ => issues}/issue-4736.rs (100%) rename src/test/ui/{ => issues}/issue-4736.stderr (100%) rename src/test/ui/{ => issues}/issue-47377.rs (100%) rename src/test/ui/{ => issues}/issue-47377.stderr (100%) rename src/test/ui/{ => issues}/issue-47380.rs (100%) rename src/test/ui/{ => issues}/issue-47380.stderr (100%) rename src/test/ui/{ => issues}/issue-47412.rs (100%) rename src/test/ui/{ => issues}/issue-47412.stderr (100%) rename src/test/ui/{ => issues}/issue-47511.rs (100%) rename src/test/ui/{ => issues}/issue-47511.stderr (100%) rename src/test/ui/{ => issues}/issue-47623.rs (100%) rename src/test/ui/{ => issues}/issue-47623.stderr (100%) rename src/test/ui/{ => issues}/issue-47646.rs (100%) rename src/test/ui/{ => issues}/issue-47646.stderr (100%) rename src/test/ui/{ => issues}/issue-47706-trait.rs (100%) rename src/test/ui/{ => issues}/issue-47706-trait.stderr (100%) rename src/test/ui/{ => issues}/issue-47706.rs (100%) rename src/test/ui/{ => issues}/issue-47706.stderr (100%) rename src/test/ui/{ => issues}/issue-47715.rs (100%) rename src/test/ui/{ => issues}/issue-47715.stderr (100%) rename src/test/ui/{ => issues}/issue-48131.rs (100%) rename src/test/ui/{ => issues}/issue-48131.stderr (100%) rename src/test/ui/{ => issues}/issue-48132.rs (100%) rename src/test/ui/{ => issues}/issue-48179.rs (100%) rename src/test/ui/{ => issues}/issue-48276.rs (100%) rename src/test/ui/{ => issues}/issue-48276.stderr (100%) rename src/test/ui/{ => issues}/issue-48364.rs (100%) rename src/test/ui/{ => issues}/issue-48364.stderr (100%) rename src/test/ui/{ => issues}/issue-48636.fixed (100%) rename src/test/ui/{ => issues}/issue-48636.rs (100%) rename src/test/ui/{ => issues}/issue-48636.stderr (100%) rename src/test/ui/{ => issues}/issue-48728.rs (100%) rename src/test/ui/{ => issues}/issue-48728.stderr (100%) rename src/test/ui/{ => issues}/issue-48803.rs (100%) rename src/test/ui/{ => issues}/issue-48803.stderr (100%) rename src/test/ui/{ => issues}/issue-48838.rs (100%) rename src/test/ui/{ => issues}/issue-48838.stderr (100%) rename src/test/ui/{ => issues}/issue-49040.rs (100%) rename src/test/ui/{ => issues}/issue-49040.stderr (100%) rename src/test/ui/{ => issues}/issue-49074.rs (94%) create mode 100644 src/test/ui/issues/issue-49074.stderr rename src/test/ui/{ => issues}/issue-49257.rs (100%) rename src/test/ui/{ => issues}/issue-49257.stderr (100%) rename src/test/ui/{ => issues}/issue-4935.rs (100%) rename src/test/ui/{ => issues}/issue-4935.stderr (100%) create mode 100644 src/test/ui/issues/issue-49579.rs rename src/test/ui/{ => issues}/issue-4968.rs (100%) rename src/test/ui/{ => issues}/issue-4968.stderr (100%) rename src/test/ui/{ => issues}/issue-4972.rs (100%) rename src/test/ui/{ => issues}/issue-4972.stderr (100%) create mode 100644 src/test/ui/issues/issue-49824.nll.stderr create mode 100644 src/test/ui/issues/issue-49824.rs create mode 100644 src/test/ui/issues/issue-49824.stderr rename src/test/ui/{ => issues}/issue-49851/compiler-builtins-error.rs (100%) rename src/test/ui/{ => issues}/issue-49851/compiler-builtins-error.stderr (100%) rename src/test/ui/{ => issues}/issue-49934.rs (100%) rename src/test/ui/{ => issues}/issue-49934.stderr (100%) rename src/test/ui/{ => issues}/issue-50187.rs (95%) create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/option_deref.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/option_deref.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result_deref.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result_deref.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result_deref_err.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result_deref_err.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result_deref_ok.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result_deref_ok.stderr rename src/test/ui/{ => issues}/issue-50403.rs (100%) rename src/test/ui/{ => issues}/issue-50403.stderr (100%) rename src/test/ui/{ => issues}/issue-50471.rs (100%) rename src/test/ui/{ => issues}/issue-50480.rs (100%) rename src/test/ui/{ => issues}/issue-50480.stderr (100%) rename src/test/ui/{ => issues}/issue-50576.rs (100%) rename src/test/ui/{ => issues}/issue-50576.stderr (100%) rename src/test/ui/{ => issues}/issue-50577.rs (100%) rename src/test/ui/{ => issues}/issue-50577.stderr (100%) rename src/test/ui/{ => issues}/issue-50581.rs (100%) rename src/test/ui/{ => issues}/issue-50581.stderr (100%) rename src/test/ui/{ => issues}/issue-50585.rs (100%) rename src/test/ui/{ => issues}/issue-50585.stderr (100%) rename src/test/ui/{ => issues}/issue-50599.rs (100%) rename src/test/ui/{ => issues}/issue-50599.stderr (100%) rename src/test/ui/{ => issues}/issue-50600.rs (100%) rename src/test/ui/{ => issues}/issue-50600.stderr (100%) rename src/test/ui/{ => issues}/issue-50618.rs (100%) rename src/test/ui/{ => issues}/issue-50618.stderr (100%) rename src/test/ui/{ => issues}/issue-5062.rs (100%) rename src/test/ui/{ => issues}/issue-5062.stderr (100%) rename src/test/ui/{ => issues}/issue-5067.rs (100%) rename src/test/ui/{ => issues}/issue-5067.stderr (100%) rename src/test/ui/{ => issues}/issue-50688.rs (100%) rename src/test/ui/{ => issues}/issue-50688.stderr (100%) rename src/test/ui/{ => issues}/issue-50714-1.rs (100%) rename src/test/ui/{ => issues}/issue-50714-1.stderr (100%) rename src/test/ui/{ => issues}/issue-50714.rs (100%) rename src/test/ui/{ => issues}/issue-50714.stderr (100%) rename src/test/ui/{ => issues}/issue-50761.rs (90%) rename src/test/ui/{ => issues}/issue-50781.rs (100%) rename src/test/ui/{ => issues}/issue-50781.stderr (100%) rename src/test/ui/{ => issues}/issue-50802.rs (100%) rename src/test/ui/{ => issues}/issue-50802.stderr (100%) rename src/test/ui/{ => issues}/issue-50825-1.rs (100%) rename src/test/ui/{ => issues}/issue-50825.rs (100%) rename src/test/ui/{ => issues}/issue-5099.rs (100%) rename src/test/ui/{ => issues}/issue-5099.stderr (100%) rename src/test/ui/{ => issues}/issue-50993.rs (100%) rename src/test/ui/{ => issues}/issue-50993.stderr (100%) rename src/test/ui/{ => issues}/issue-5100.rs (100%) rename src/test/ui/{ => issues}/issue-5100.stderr (100%) rename src/test/ui/{ => issues}/issue-51022.rs (100%) rename src/test/ui/{ => issues}/issue-51022.stderr (100%) rename src/test/ui/{ => issues}/issue-51044.rs (100%) rename src/test/ui/{ => issues}/issue-51102.rs (100%) rename src/test/ui/{ => issues}/issue-51102.stderr (100%) rename src/test/ui/{ => issues}/issue-51116.rs (100%) rename src/test/ui/{ => issues}/issue-51116.stderr (100%) rename src/test/ui/{ => issues}/issue-51244.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-51244.rs (100%) rename src/test/ui/{ => issues}/issue-51244.stderr (100%) rename src/test/ui/{ => issues}/issue-51279.rs (100%) rename src/test/ui/{ => issues}/issue-51279.stderr (100%) rename src/test/ui/{ => issues}/issue-51515.rs (100%) rename src/test/ui/{ => issues}/issue-51515.stderr (100%) rename src/test/ui/{ => issues}/issue-5153.rs (100%) rename src/test/ui/{ => issues}/issue-5153.stderr (100%) rename src/test/ui/{ => issues}/issue-51632-try-desugar-incompatible-types.fixed (100%) rename src/test/ui/{ => issues}/issue-51632-try-desugar-incompatible-types.rs (100%) rename src/test/ui/{ => issues}/issue-51632-try-desugar-incompatible-types.stderr (100%) rename src/test/ui/{ => issues}/issue-51714.rs (100%) rename src/test/ui/{ => issues}/issue-51714.stderr (100%) rename src/test/ui/{ => issues}/issue-51848.rs (100%) rename src/test/ui/{ => issues}/issue-51848.stderr (100%) rename src/test/ui/{ => issues}/issue-51874.rs (100%) rename src/test/ui/{ => issues}/issue-51874.stderr (100%) rename src/test/ui/{ => issues}/issue-52023-array-size-pointer-cast.rs (83%) create mode 100644 src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr rename src/test/ui/{ => issues}/issue-52049.nll.stderr (100%) rename src/test/ui/{ => issues}/issue-52049.rs (100%) rename src/test/ui/{ => issues}/issue-52049.stderr (100%) rename src/test/ui/{ => issues}/issue-52057.rs (100%) create mode 100644 src/test/ui/issues/issue-52060.rs create mode 100644 src/test/ui/issues/issue-52060.stderr rename src/test/ui/{ => issues}/issue-52126-assign-op-invariance.nll.stderr (92%) rename src/test/ui/{ => issues}/issue-52126-assign-op-invariance.rs (100%) rename src/test/ui/{ => issues}/issue-52126-assign-op-invariance.stderr (100%) rename src/test/ui/{ => issues}/issue-5216.rs (100%) rename src/test/ui/{ => issues}/issue-5216.stderr (100%) create mode 100644 src/test/ui/issues/issue-52213.nll.stderr rename src/test/ui/{ => issues}/issue-52213.rs (100%) rename src/test/ui/{ => issues}/issue-52213.stderr (100%) rename src/test/ui/{ => issues}/issue-5239-1.rs (100%) create mode 100644 src/test/ui/issues/issue-5239-1.stderr create mode 100644 src/test/ui/issues/issue-52489.rs create mode 100644 src/test/ui/issues/issue-52489.stderr create mode 100644 src/test/ui/issues/issue-52533-1.nll.stderr rename src/test/ui/{ => issues}/issue-52533-1.rs (100%) rename src/test/ui/{ => issues}/issue-52533-1.stderr (100%) create mode 100644 src/test/ui/issues/issue-52533.nll.stderr rename src/test/ui/{ => issues}/issue-52533.rs (100%) rename src/test/ui/{ => issues}/issue-52533.stderr (100%) create mode 100644 src/test/ui/issues/issue-53348.rs create mode 100644 src/test/ui/issues/issue-53348.stderr rename src/test/ui/{ => issues}/issue-5358-1.rs (100%) rename src/test/ui/{ => issues}/issue-5358-1.stderr (100%) rename src/test/ui/{ => issues}/issue-5439.rs (100%) rename src/test/ui/{ => issues}/issue-5439.stderr (100%) create mode 100644 src/test/ui/issues/issue-5500-1.ast.stderr create mode 100644 src/test/ui/issues/issue-5500-1.mir.stderr rename src/test/{compile-fail => ui/issues}/issue-5500-1.rs (97%) rename src/test/{compile-fail => ui/issues}/issue-5844.rs (100%) create mode 100644 src/test/ui/issues/issue-5844.stderr rename src/test/ui/{ => issues}/issue-5883.rs (100%) rename src/test/ui/{ => issues}/issue-5883.stderr (92%) rename src/test/ui/{ => issues}/issue-5927.rs (100%) rename src/test/ui/{ => issues}/issue-5927.stderr (100%) rename src/test/ui/{ => issues}/issue-5997-enum.rs (100%) rename src/test/ui/{ => issues}/issue-5997-enum.stderr (100%) rename src/test/ui/{ => issues}/issue-5997-struct.rs (100%) rename src/test/ui/{ => issues}/issue-5997-struct.stderr (100%) rename src/test/ui/{ => issues}/issue-6458-2.rs (100%) rename src/test/ui/{ => issues}/issue-6458-2.stderr (100%) rename src/test/ui/{ => issues}/issue-6458-3.rs (100%) rename src/test/ui/{ => issues}/issue-6458-3.stderr (100%) rename src/test/ui/{ => issues}/issue-6458-4.rs (100%) rename src/test/ui/{ => issues}/issue-6458-4.stderr (100%) rename src/test/ui/{ => issues}/issue-6458.rs (100%) rename src/test/ui/{ => issues}/issue-6458.stderr (100%) rename src/test/ui/{ => issues}/issue-6596-1.rs (100%) rename src/test/ui/{ => issues}/issue-6596-1.stderr (100%) rename src/test/ui/{ => issues}/issue-6596-2.rs (100%) rename src/test/ui/{ => issues}/issue-6596-2.stderr (100%) rename src/test/ui/{ => issues}/issue-6642.rs (100%) rename src/test/ui/{ => issues}/issue-6642.stderr (100%) rename src/test/ui/{ => issues}/issue-6738.rs (100%) rename src/test/ui/{ => issues}/issue-6738.stderr (100%) rename src/test/ui/{ => issues}/issue-6801.nll.stderr (75%) rename src/test/ui/{ => issues}/issue-6801.rs (100%) rename src/test/ui/{ => issues}/issue-6801.stderr (100%) rename src/test/ui/{ => issues}/issue-6804.rs (100%) rename src/test/ui/{ => issues}/issue-6804.stderr (100%) rename src/test/ui/{ => issues}/issue-6936.rs (100%) rename src/test/ui/{ => issues}/issue-6936.stderr (100%) rename src/test/ui/{ => issues}/issue-7013.rs (100%) rename src/test/ui/{ => issues}/issue-7013.stderr (100%) rename src/test/ui/{ => issues}/issue-7044.rs (100%) rename src/test/ui/{ => issues}/issue-7044.stderr (100%) rename src/test/ui/{ => issues}/issue-7061.rs (100%) rename src/test/ui/{ => issues}/issue-7061.stderr (100%) rename src/test/ui/{ => issues}/issue-7092.rs (100%) rename src/test/ui/{ => issues}/issue-7092.stderr (100%) rename src/test/ui/{ => issues}/issue-7246.rs (100%) rename src/test/ui/{ => issues}/issue-7246.stderr (100%) rename src/test/ui/{ => issues}/issue-7364.rs (100%) rename src/test/ui/{ => issues}/issue-7364.stderr (100%) rename src/test/ui/{ => issues}/issue-7607-1.rs (100%) rename src/test/ui/{ => issues}/issue-7607-1.stderr (100%) rename src/test/ui/{ => issues}/issue-7813.rs (100%) rename src/test/ui/{ => issues}/issue-7813.stderr (100%) rename src/test/ui/{ => issues}/issue-7867.rs (100%) rename src/test/ui/{ => issues}/issue-7867.stderr (100%) rename src/test/ui/{ => issues}/issue-7950.rs (100%) rename src/test/ui/{ => issues}/issue-7950.stderr (100%) rename src/test/ui/{ => issues}/issue-7970a.rs (100%) rename src/test/ui/{ => issues}/issue-7970a.stderr (100%) rename src/test/ui/{ => issues}/issue-7970b.rs (100%) rename src/test/ui/{ => issues}/issue-7970b.stderr (100%) rename src/test/ui/{ => issues}/issue-8153.rs (100%) rename src/test/ui/{ => issues}/issue-8153.stderr (100%) rename src/test/ui/{ => issues}/issue-8208.rs (100%) rename src/test/ui/{ => issues}/issue-8208.stderr (100%) rename src/test/ui/{ => issues}/issue-8460-const.rs (100%) rename src/test/ui/{ => issues}/issue-8460-const.stderr (100%) rename src/test/ui/{ => issues}/issue-8640.rs (100%) rename src/test/ui/{ => issues}/issue-8640.stderr (100%) rename src/test/ui/{ => issues}/issue-8727.rs (93%) rename src/test/ui/{ => issues}/issue-8727.stderr (94%) rename src/test/ui/{ => issues}/issue-8761.rs (100%) rename src/test/ui/{ => issues}/issue-8761.stderr (100%) rename src/test/ui/{ => issues}/issue-8767.rs (100%) rename src/test/ui/{ => issues}/issue-8767.stderr (100%) rename src/test/ui/{ => issues}/issue-9575.rs (100%) rename src/test/ui/{ => issues}/issue-9575.stderr (100%) rename src/test/ui/{ => issues}/issue-9725.rs (100%) rename src/test/ui/{ => issues}/issue-9725.stderr (100%) rename src/test/ui/{ => issues}/issue-9814.rs (100%) rename src/test/ui/{ => issues}/issue-9814.stderr (100%) rename src/test/ui/{ => issues}/issue-pr29383.rs (100%) rename src/test/ui/{ => issues}/issue-pr29383.stderr (100%) rename src/test/{compile-fail => ui/issues}/issue32829.rs (100%) create mode 100644 src/test/ui/issues/issue32829.stderr rename src/test/{compile-fail => ui/keyword}/keyword-extern-as-identifier.rs (84%) create mode 100644 src/test/ui/keyword/keyword-extern-as-identifier.stderr rename src/test/{compile-fail => ui/keyword}/keyword-false-as-identifier.rs (100%) create mode 100644 src/test/ui/keyword/keyword-false-as-identifier.stderr rename src/test/{compile-fail => ui/keyword}/keyword-self-as-identifier.rs (88%) create mode 100644 src/test/ui/keyword/keyword-self-as-identifier.stderr rename src/test/{compile-fail => ui/keyword}/keyword-super-as-identifier.rs (100%) create mode 100644 src/test/ui/keyword/keyword-super-as-identifier.stderr rename src/test/{compile-fail => ui/keyword}/keyword-super.rs (100%) create mode 100644 src/test/ui/keyword/keyword-super.stderr rename src/test/{compile-fail => ui/keyword}/keyword-true-as-identifier.rs (100%) create mode 100644 src/test/ui/keyword/keyword-true-as-identifier.stderr rename src/test/{compile-fail => ui/kindck}/kindck-copy.rs (100%) create mode 100644 src/test/ui/kindck/kindck-copy.stderr rename src/test/{compile-fail => ui/kindck}/kindck-impl-type-params-2.rs (100%) create mode 100644 src/test/ui/kindck/kindck-impl-type-params-2.stderr create mode 100644 src/test/ui/kindck/kindck-impl-type-params.nll.stderr rename src/test/{compile-fail => ui/kindck}/kindck-impl-type-params.rs (100%) create mode 100644 src/test/ui/kindck/kindck-impl-type-params.stderr rename src/test/{compile-fail => ui/kindck}/kindck-inherited-copy-bound.rs (100%) create mode 100644 src/test/ui/kindck/kindck-inherited-copy-bound.stderr rename src/test/{compile-fail => ui/kindck}/kindck-nonsendable-1.rs (100%) create mode 100644 src/test/ui/kindck/kindck-nonsendable-1.stderr rename src/test/{compile-fail => ui/kindck}/kindck-send-object.rs (100%) create mode 100644 src/test/ui/kindck/kindck-send-object.stderr create mode 100644 src/test/ui/kindck/kindck-send-object1.nll.stderr rename src/test/{compile-fail => ui/kindck}/kindck-send-object1.rs (100%) create mode 100644 src/test/ui/kindck/kindck-send-object1.stderr rename src/test/{compile-fail => ui/kindck}/kindck-send-object2.rs (100%) create mode 100644 src/test/ui/kindck/kindck-send-object2.stderr rename src/test/{compile-fail => ui/kindck}/kindck-send-owned.rs (100%) create mode 100644 src/test/ui/kindck/kindck-send-owned.stderr rename src/test/{compile-fail => ui/kindck}/kindck-send-unsafe.rs (100%) rename src/test/{compile-fail => ui/kindck}/kindck-send-unsafe.rs~rust-lang_master (100%) create mode 100644 src/test/ui/kindck/kindck-send-unsafe.stderr rename src/test/{compile-fail => ui/label}/label-static.rs (100%) create mode 100644 src/test/ui/label/label-static.stderr rename src/test/{compile-fail => ui/label}/label-underscore.rs (100%) create mode 100644 src/test/ui/label/label-underscore.stderr rename src/test/ui/{ => label}/label_break_value_continue.rs (100%) rename src/test/ui/{ => label}/label_break_value_continue.stderr (100%) rename src/test/ui/{ => label}/label_break_value_illegal_uses.rs (93%) rename src/test/ui/{ => label}/label_break_value_illegal_uses.stderr (100%) rename src/test/ui/{ => label}/label_break_value_unlabeled_break.rs (100%) rename src/test/ui/{ => label}/label_break_value_unlabeled_break.stderr (100%) rename src/test/{compile-fail => ui}/lang-item-missing.rs (100%) create mode 100644 src/test/ui/lang-item-missing.stderr rename src/test/{compile-fail => ui}/lexical-scopes.rs (100%) create mode 100644 src/test/ui/lexical-scopes.stderr delete mode 100644 src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr delete mode 100644 src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr delete mode 100644 src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr rename src/test/{compile-fail => ui/lifetimes}/auxiliary/lifetime_bound_will_change_warning_lib.rs (100%) create mode 100644 src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr rename src/test/{compile-fail => ui/lifetimes}/lifetime-bound-will-change-warning.rs (100%) create mode 100644 src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr rename src/test/ui/{ => lifetimes}/lifetime-elision-return-type-requires-explicit-lifetime.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-elision-return-type-requires-explicit-lifetime.stderr (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/42701_one_named_and_one_anonymous.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/42701_one_named_and_one_anonymous.stderr (78%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr (80%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr (81%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr (79%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr (82%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr (81%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-if-else.stderr (80%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1b-return-no-names-if-else.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex1b-return-no-names-if-else.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2a-push-one-existing-name-2.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2a-push-one-existing-name-2.stderr (79%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs (98%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr (77%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2a-push-one-existing-name.rs (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2b-push-no-existing-names.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2b-push-no-existing-names.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2c-push-inference-variable.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2c-push-inference-variable.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2d-push-inference-variable-2.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2d-push-inference-variable-2.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2e-push-inference-variable-3.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex2e-push-inference-variable-3.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-2.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-2.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-3.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-3.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-latebound-regions.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-using-fn-items.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-using-trait-objects.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr (100%) create mode 100644 src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.nll.stderr rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions.rs (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/ex3-both-anon-regions.stderr (100%) rename src/test/ui/{ => lifetimes}/lifetime-errors/liveness-assign-imm-local-notes.rs (93%) rename src/test/ui/{ => lifetimes}/lifetime-errors/liveness-assign-imm-local-notes.stderr (91%) rename src/test/{compile-fail => ui/lifetimes}/lifetime-no-keyword.rs (100%) create mode 100644 src/test/ui/lifetimes/lifetime-no-keyword.stderr rename src/test/{compile-fail => ui}/linkage2.rs (100%) create mode 100644 src/test/ui/linkage2.stderr rename src/test/{compile-fail => ui}/linkage3.rs (100%) create mode 100644 src/test/ui/linkage3.stderr rename src/test/{compile-fail => ui}/linkage4.rs (100%) create mode 100644 src/test/ui/linkage4.stderr delete mode 100644 src/test/ui/lint-anon-param-edition.fixed delete mode 100644 src/test/ui/lint-anon-param-edition.rs delete mode 100644 src/test/ui/lint-anon-param-edition.stderr delete mode 100644 src/test/ui/lint-unconditional-recursion.stderr rename src/test/{compile-fail => ui/lint}/auxiliary/inherited_stability.rs (80%) create mode 100644 src/test/ui/lint/auxiliary/lint_output_format.rs create mode 100644 src/test/ui/lint/auxiliary/lint_stability.rs create mode 100644 src/test/ui/lint/auxiliary/lint_stability_fields.rs rename src/test/{compile-fail => ui/lint}/auxiliary/lint_unused_extern_crate.rs (100%) rename src/test/{compile-fail => ui/lint}/auxiliary/lint_unused_extern_crate2.rs (100%) rename src/test/{compile-fail => ui/lint}/auxiliary/lint_unused_extern_crate3.rs (100%) rename src/test/{compile-fail => ui/lint}/auxiliary/lint_unused_extern_crate4.rs (100%) rename src/test/{compile-fail => ui/lint}/auxiliary/lint_unused_extern_crate5.rs (100%) rename src/test/{compile-fail => ui/lint}/auxiliary/stability_cfg1.rs (100%) create mode 100644 src/test/ui/lint/auxiliary/stability_cfg2.rs rename src/test/{compile-fail => ui/lint}/lint-attr-non-item-node.rs (100%) create mode 100644 src/test/ui/lint/lint-attr-non-item-node.stderr rename src/test/{compile-fail => ui/lint}/lint-change-warnings.rs (100%) create mode 100644 src/test/ui/lint/lint-change-warnings.stderr rename src/test/{compile-fail => ui/lint}/lint-ctypes-enum.rs (100%) create mode 100644 src/test/ui/lint/lint-ctypes-enum.stderr rename src/test/ui/{ => lint}/lint-ctypes.rs (96%) rename src/test/ui/{ => lint}/lint-ctypes.stderr (89%) rename src/test/{compile-fail => ui/lint}/lint-dead-code-1.rs (96%) create mode 100644 src/test/ui/lint/lint-dead-code-1.stderr rename src/test/{compile-fail => ui/lint}/lint-dead-code-2.rs (100%) create mode 100644 src/test/ui/lint/lint-dead-code-2.stderr rename src/test/{compile-fail => ui/lint}/lint-dead-code-3.rs (97%) create mode 100644 src/test/ui/lint/lint-dead-code-3.stderr rename src/test/{compile-fail => ui/lint}/lint-dead-code-4.rs (100%) create mode 100644 src/test/ui/lint/lint-dead-code-4.stderr rename src/test/{compile-fail => ui/lint}/lint-dead-code-5.rs (100%) create mode 100644 src/test/ui/lint/lint-dead-code-5.stderr rename src/test/{compile-fail => ui/lint}/lint-dead-code-type-alias.rs (100%) create mode 100644 src/test/ui/lint/lint-dead-code-type-alias.stderr rename src/test/{compile-fail => ui/lint}/lint-dead-code-variant.rs (100%) create mode 100644 src/test/ui/lint/lint-dead-code-variant.stderr rename src/test/{compile-fail => ui/lint}/lint-directives-on-use-items-issue-10534.rs (100%) create mode 100644 src/test/ui/lint/lint-directives-on-use-items-issue-10534.stderr rename src/test/{compile-fail => ui/lint}/lint-exceeding-bitshifts.rs (100%) create mode 100644 src/test/ui/lint/lint-exceeding-bitshifts.stderr rename src/test/{compile-fail => ui/lint}/lint-exceeding-bitshifts2.rs (100%) create mode 100644 src/test/ui/lint/lint-exceeding-bitshifts2.stderr rename src/test/ui/{ => lint}/lint-forbid-attr.rs (100%) rename src/test/ui/{ => lint}/lint-forbid-attr.stderr (100%) rename src/test/{compile-fail => ui/lint}/lint-forbid-cmdline.rs (100%) create mode 100644 src/test/ui/lint/lint-forbid-cmdline.stderr rename src/test/{compile-fail => ui/lint}/lint-impl-fn.rs (100%) create mode 100644 src/test/ui/lint/lint-impl-fn.stderr rename src/test/{compile-fail => ui/lint}/lint-malformed.rs (100%) create mode 100644 src/test/ui/lint/lint-malformed.stderr rename src/test/{compile-fail => ui/lint}/lint-misplaced-attr.rs (100%) create mode 100644 src/test/ui/lint/lint-misplaced-attr.stderr rename src/test/{compile-fail => ui/lint}/lint-missing-copy-implementations.rs (100%) create mode 100644 src/test/ui/lint/lint-missing-copy-implementations.stderr rename src/test/{compile-fail => ui/lint}/lint-missing-doc.rs (100%) create mode 100644 src/test/ui/lint/lint-missing-doc.stderr rename src/test/{compile-fail => ui/lint}/lint-non-camel-case-types.rs (100%) create mode 100644 src/test/ui/lint/lint-non-camel-case-types.stderr rename src/test/{compile-fail => ui/lint}/lint-non-snake-case-crate-2.rs (100%) create mode 100644 src/test/ui/lint/lint-non-snake-case-crate-2.stderr rename src/test/{compile-fail => ui/lint}/lint-non-snake-case-crate.rs (100%) create mode 100644 src/test/ui/lint/lint-non-snake-case-crate.stderr rename src/test/{compile-fail => ui/lint}/lint-non-snake-case-functions.rs (100%) create mode 100644 src/test/ui/lint/lint-non-snake-case-functions.stderr rename src/test/{compile-fail => ui/lint}/lint-non-snake-case-lifetimes.rs (100%) create mode 100644 src/test/ui/lint/lint-non-snake-case-lifetimes.stderr rename src/test/{compile-fail => ui/lint}/lint-non-snake-case-modules.rs (100%) create mode 100644 src/test/ui/lint/lint-non-snake-case-modules.stderr rename src/test/{compile-fail => ui/lint}/lint-non-uppercase-statics.rs (100%) create mode 100644 src/test/ui/lint/lint-non-uppercase-statics.stderr rename src/test/{compile-fail => ui/lint}/lint-obsolete-attr.rs (100%) create mode 100644 src/test/ui/lint/lint-obsolete-attr.stderr rename src/test/ui/{ => lint}/lint-output-format-2.rs (89%) rename src/test/ui/{ => lint}/lint-output-format-2.stderr (82%) rename src/test/{compile-fail => ui/lint}/lint-output-format.rs (100%) create mode 100644 src/test/ui/lint/lint-output-format.stderr rename src/test/{compile-fail => ui/lint}/lint-owned-heap-memory.rs (100%) create mode 100644 src/test/ui/lint/lint-owned-heap-memory.stderr rename src/test/{compile-fail => ui/lint}/lint-qualification.rs (100%) create mode 100644 src/test/ui/lint/lint-qualification.stderr rename src/test/{compile-fail => ui/lint}/lint-removed-allow.rs (100%) create mode 100644 src/test/ui/lint/lint-removed-allow.stderr rename src/test/{compile-fail => ui/lint}/lint-removed-cmdline.rs (100%) create mode 100644 src/test/ui/lint/lint-removed-cmdline.stderr rename src/test/{compile-fail => ui/lint}/lint-removed.rs (100%) create mode 100644 src/test/ui/lint/lint-removed.stderr rename src/test/{compile-fail => ui/lint}/lint-renamed-allow.rs (95%) create mode 100644 src/test/ui/lint/lint-renamed-allow.stderr create mode 100644 src/test/ui/lint/lint-renamed-cmdline.rs create mode 100644 src/test/ui/lint/lint-renamed-cmdline.stderr rename src/test/{compile-fail => ui/lint}/lint-renamed.rs (83%) create mode 100644 src/test/ui/lint/lint-renamed.stderr rename src/test/{compile-fail => ui/lint}/lint-shorthand-field.rs (96%) create mode 100644 src/test/ui/lint/lint-shorthand-field.stderr rename src/test/{compile-fail => ui/lint}/lint-stability-2.rs (83%) create mode 100644 src/test/ui/lint/lint-stability-2.stderr rename src/test/{compile-fail => ui/lint}/lint-stability-deprecated.rs (92%) create mode 100644 src/test/ui/lint/lint-stability-deprecated.stderr rename src/test/{compile-fail => ui/lint}/lint-stability-fields-deprecated.rs (91%) create mode 100644 src/test/ui/lint/lint-stability-fields-deprecated.stderr rename src/test/{compile-fail => ui/lint}/lint-stability-fields.rs (90%) create mode 100644 src/test/ui/lint/lint-stability-fields.stderr rename src/test/{compile-fail => ui/lint}/lint-stability.rs (86%) create mode 100644 src/test/ui/lint/lint-stability.stderr rename src/test/{compile-fail => ui/lint}/lint-stability2.rs (100%) create mode 100644 src/test/ui/lint/lint-stability2.stderr rename src/test/{compile-fail => ui/lint}/lint-stability3.rs (100%) create mode 100644 src/test/ui/lint/lint-stability3.stderr rename src/test/{compile-fail => ui/lint}/lint-type-limits.rs (100%) create mode 100644 src/test/ui/lint/lint-type-limits.stderr rename src/test/{compile-fail => ui/lint}/lint-type-limits2.rs (100%) create mode 100644 src/test/ui/lint/lint-type-limits2.stderr rename src/test/{compile-fail => ui/lint}/lint-type-limits3.rs (100%) create mode 100644 src/test/ui/lint/lint-type-limits3.stderr rename src/test/{compile-fail => ui/lint}/lint-type-overflow.rs (100%) create mode 100644 src/test/ui/lint/lint-type-overflow.stderr rename src/test/{compile-fail => ui/lint}/lint-type-overflow2.rs (100%) create mode 100644 src/test/ui/lint/lint-type-overflow2.stderr rename src/test/ui/{ => lint}/lint-unconditional-recursion.rs (91%) create mode 100644 src/test/ui/lint/lint-unconditional-recursion.stderr rename src/test/{compile-fail => ui/lint}/lint-unexported-no-mangle.rs (100%) create mode 100644 src/test/ui/lint/lint-unexported-no-mangle.stderr rename src/test/{compile-fail => ui/lint}/lint-unknown-attr.rs (100%) create mode 100644 src/test/ui/lint/lint-unknown-attr.stderr rename src/test/{compile-fail => ui/lint}/lint-unknown-feature-default.rs (93%) create mode 100644 src/test/ui/lint/lint-unknown-feature-default.stderr rename src/test/{compile-fail => ui/lint}/lint-unknown-feature.rs (93%) create mode 100644 src/test/ui/lint/lint-unknown-feature.stderr rename src/test/{compile-fail => ui/lint}/lint-unknown-lint-cmdline.rs (100%) create mode 100644 src/test/ui/lint/lint-unknown-lint-cmdline.stderr rename src/test/{compile-fail => ui/lint}/lint-unknown-lint.rs (100%) create mode 100644 src/test/ui/lint/lint-unknown-lint.stderr rename src/test/{compile-fail => ui/lint}/lint-unnecessary-import-braces.rs (100%) create mode 100644 src/test/ui/lint/lint-unnecessary-import-braces.stderr rename src/test/{compile-fail => ui/lint}/lint-unnecessary-parens.rs (100%) create mode 100644 src/test/ui/lint/lint-unnecessary-parens.stderr rename src/test/{compile-fail => ui/lint}/lint-unsafe-code.rs (100%) create mode 100644 src/test/ui/lint/lint-unsafe-code.stderr rename src/test/{compile-fail => ui/lint}/lint-unused-extern-crate.rs (94%) create mode 100644 src/test/ui/lint/lint-unused-extern-crate.stderr rename src/test/{compile-fail => ui/lint}/lint-unused-imports.rs (100%) create mode 100644 src/test/ui/lint/lint-unused-imports.stderr rename src/test/{compile-fail => ui/lint}/lint-unused-mut-self.rs (100%) create mode 100644 src/test/ui/lint/lint-unused-mut-self.stderr create mode 100644 src/test/ui/lint/lint-unused-mut-variables.lexical.stderr create mode 100644 src/test/ui/lint/lint-unused-mut-variables.nll.stderr rename src/test/{compile-fail => ui/lint}/lint-unused-mut-variables.rs (100%) rename src/test/{compile-fail => ui/lint}/lint-uppercase-variables.rs (100%) create mode 100644 src/test/ui/lint/lint-uppercase-variables.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.nll.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.ast.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.mir.stderr rename src/test/{compile-fail => ui/liveness/liveness-assign}/liveness-assign-imm-local-in-loop.rs (92%) create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.nll.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.ast.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.mir.stderr rename src/test/{compile-fail => ui/liveness/liveness-assign}/liveness-assign-imm-local-in-op-eq.rs (92%) create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.nll.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.ast.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.mir.stderr rename src/test/{compile-fail => ui/liveness/liveness-assign}/liveness-assign-imm-local-with-drop.rs (89%) create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.nll.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.ast.stderr create mode 100644 src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.mir.stderr rename src/test/{compile-fail => ui/liveness/liveness-assign}/liveness-assign-imm-local-with-init.rs (89%) rename src/test/{compile-fail => ui/liveness}/liveness-closure-require-ret.rs (100%) create mode 100644 src/test/ui/liveness/liveness-closure-require-ret.stderr rename src/test/{compile-fail => ui/liveness}/liveness-dead.rs (100%) create mode 100644 src/test/ui/liveness/liveness-dead.stderr rename src/test/{compile-fail => ui/liveness}/liveness-forgot-ret.rs (100%) create mode 100644 src/test/ui/liveness/liveness-forgot-ret.stderr rename src/test/{compile-fail => ui/liveness}/liveness-issue-2163.rs (100%) create mode 100644 src/test/ui/liveness/liveness-issue-2163.stderr rename src/test/{compile-fail => ui/liveness}/liveness-missing-ret2.rs (100%) create mode 100644 src/test/ui/liveness/liveness-missing-ret2.stderr rename src/test/{compile-fail => ui/liveness}/liveness-move-call-arg.rs (100%) create mode 100644 src/test/ui/liveness/liveness-move-call-arg.stderr rename src/test/{compile-fail => ui/liveness}/liveness-move-in-loop.rs (100%) create mode 100644 src/test/ui/liveness/liveness-move-in-loop.stderr create mode 100644 src/test/ui/liveness/liveness-move-in-while.nll.stderr rename src/test/{compile-fail => ui/liveness}/liveness-move-in-while.rs (100%) create mode 100644 src/test/ui/liveness/liveness-move-in-while.stderr rename src/test/ui/{ => liveness}/liveness-return-last-stmt-semi.rs (100%) rename src/test/ui/{ => liveness}/liveness-return-last-stmt-semi.stderr (100%) rename src/test/{compile-fail => ui/liveness}/liveness-unused.rs (100%) create mode 100644 src/test/ui/liveness/liveness-unused.stderr create mode 100644 src/test/ui/liveness/liveness-use-after-move.nll.stderr rename src/test/{compile-fail => ui/liveness}/liveness-use-after-move.rs (100%) create mode 100644 src/test/ui/liveness/liveness-use-after-move.stderr create mode 100644 src/test/ui/liveness/liveness-use-after-send.nll.stderr rename src/test/{compile-fail => ui/liveness}/liveness-use-after-send.rs (100%) create mode 100644 src/test/ui/liveness/liveness-use-after-send.stderr rename src/test/ui/{ => loops}/loop-break-value-no-repeat.rs (100%) rename src/test/ui/{ => loops}/loop-break-value-no-repeat.stderr (100%) rename src/test/{compile-fail => ui/loops}/loop-break-value.rs (100%) create mode 100644 src/test/ui/loops/loop-break-value.stderr rename src/test/{compile-fail => ui/loops}/loop-labeled-break-value.rs (100%) create mode 100644 src/test/ui/loops/loop-labeled-break-value.stderr create mode 100644 src/test/ui/loops/loop-proper-liveness.nll.stderr rename src/test/{compile-fail => ui/loops}/loop-proper-liveness.rs (100%) create mode 100644 src/test/ui/loops/loop-proper-liveness.stderr rename src/test/{compile-fail => ui/loops}/loop-properly-diverging-2.rs (100%) create mode 100644 src/test/ui/loops/loop-properly-diverging-2.stderr rename src/test/ui/{ => loops}/loops-reject-duplicate-labels-2.rs (100%) rename src/test/ui/{ => loops}/loops-reject-duplicate-labels-2.stderr (100%) rename src/test/ui/{ => loops}/loops-reject-duplicate-labels.rs (100%) rename src/test/ui/{ => loops}/loops-reject-duplicate-labels.stderr (100%) rename src/test/ui/{ => loops}/loops-reject-labels-shadowing-lifetimes.rs (100%) rename src/test/ui/{ => loops}/loops-reject-labels-shadowing-lifetimes.stderr (100%) rename src/test/ui/{ => loops}/loops-reject-lifetime-shadowing-label.rs (100%) rename src/test/ui/{ => loops}/loops-reject-lifetime-shadowing-label.stderr (100%) create mode 100644 src/test/ui/lto-duplicate-symbols.rs create mode 100644 src/test/ui/lto-duplicate-symbols.stderr create mode 100644 src/test/ui/lub-if.nll.stderr rename src/test/{compile-fail => ui}/lub-if.rs (100%) create mode 100644 src/test/ui/lub-if.stderr create mode 100644 src/test/ui/lub-match.nll.stderr rename src/test/{compile-fail => ui}/lub-match.rs (100%) create mode 100644 src/test/ui/lub-match.stderr delete mode 100644 src/test/ui/macro-shadowing.stderr create mode 100644 src/test/ui/macros/auxiliary/macro-in-other-crate.rs rename src/test/{compile-fail => ui/macros}/auxiliary/macro_crate_nonterminal.rs (100%) rename src/test/ui/{ => macros}/auxiliary/two_macros.rs (100%) create mode 100644 src/test/ui/macros/auxiliary/unstable-macros.rs create mode 100644 src/test/ui/macros/issue-30143.rs create mode 100644 src/test/ui/macros/issue-30143.stderr rename src/test/{compile-fail => ui/macros}/macro-attribute.rs (81%) create mode 100644 src/test/ui/macros/macro-attribute.stderr create mode 100644 src/test/ui/macros/macro-comma-behavior.core.stderr rename src/test/{compile-fail => ui/macros}/macro-comma-behavior.rs (100%) create mode 100644 src/test/ui/macros/macro-comma-behavior.std.stderr rename src/test/{compile-fail => ui/macros}/macro-comma-support.rs (100%) create mode 100644 src/test/ui/macros/macro-comma-support.stderr rename src/test/ui/{ => macros}/macro-context.rs (100%) rename src/test/ui/{ => macros}/macro-context.stderr (100%) rename src/test/{compile-fail => ui/macros}/macro-crate-nonterminal-non-root.rs (100%) create mode 100644 src/test/ui/macros/macro-crate-nonterminal-non-root.stderr rename src/test/{compile-fail => ui/macros}/macro-error.rs (100%) create mode 100644 src/test/ui/macros/macro-error.stderr rename src/test/{compile-fail => ui/macros}/macro-expanded-include/file.txt (100%) rename src/test/{compile-fail => ui/macros}/macro-expanded-include/foo/mod.rs (100%) rename src/test/{compile-fail => ui/macros}/macro-expanded-include/test.rs (100%) create mode 100644 src/test/ui/macros/macro-expanded-include/test.stderr rename src/test/{compile-fail => ui/macros}/macro-expansion-tests.rs (100%) create mode 100644 src/test/ui/macros/macro-expansion-tests.stderr rename src/test/{compile-fail => ui/macros}/macro-follow.rs (100%) create mode 100644 src/test/ui/macros/macro-follow.stderr rename src/test/{compile-fail => ui/macros}/macro-followed-by-seq-bad.rs (100%) create mode 100644 src/test/ui/macros/macro-followed-by-seq-bad.stderr rename src/test/{compile-fail => ui/macros}/macro-inner-attributes.rs (100%) create mode 100644 src/test/ui/macros/macro-inner-attributes.stderr rename src/test/{compile-fail => ui/macros}/macro-input-future-proofing.rs (100%) create mode 100644 src/test/ui/macros/macro-input-future-proofing.stderr rename src/test/ui/{ => macros}/macro-invalid-fragment-spec.rs (100%) rename src/test/ui/{ => macros}/macro-invalid-fragment-spec.stderr (100%) rename src/test/{compile-fail => ui/macros}/macro-local-data-key-priv.rs (100%) create mode 100644 src/test/ui/macros/macro-local-data-key-priv.stderr rename src/test/{compile-fail => ui/macros}/macro-match-nonterminal.rs (100%) create mode 100644 src/test/ui/macros/macro-match-nonterminal.stderr rename src/test/{compile-fail => ui/macros}/macro-missing-delimiters.rs (100%) create mode 100644 src/test/ui/macros/macro-missing-delimiters.stderr rename src/test/{compile-fail => ui/macros}/macro-missing-fragment.rs (100%) create mode 100644 src/test/ui/macros/macro-missing-fragment.stderr rename src/test/{compile-fail => ui/macros}/macro-non-lifetime.rs (100%) create mode 100644 src/test/ui/macros/macro-non-lifetime.stderr rename src/test/{compile-fail => ui/macros}/macro-outer-attributes.rs (100%) create mode 100644 src/test/ui/macros/macro-outer-attributes.stderr rename src/test/{compile-fail => ui/macros}/macro-parameter-span.rs (100%) create mode 100644 src/test/ui/macros/macro-parameter-span.stderr create mode 100644 src/test/ui/macros/macro-path-prelude-fail-1.rs create mode 100644 src/test/ui/macros/macro-path-prelude-fail-1.stderr create mode 100644 src/test/ui/macros/macro-path-prelude-fail-2.rs create mode 100644 src/test/ui/macros/macro-path-prelude-fail-2.stderr create mode 100644 src/test/ui/macros/macro-path-prelude-fail-3.rs create mode 100644 src/test/ui/macros/macro-path-prelude-fail-3.stderr create mode 100644 src/test/ui/macros/macro-path-prelude-fail-4.rs create mode 100644 src/test/ui/macros/macro-path-prelude-fail-4.stderr create mode 100644 src/test/ui/macros/macro-path-prelude-pass.rs create mode 100644 src/test/ui/macros/macro-path-prelude-pass.stderr create mode 100644 src/test/ui/macros/macro-path-prelude-shadowing.rs create mode 100644 src/test/ui/macros/macro-path-prelude-shadowing.stderr rename src/test/ui/{ => macros}/macro-reexport-removed.rs (100%) rename src/test/ui/{ => macros}/macro-reexport-removed.stderr (85%) create mode 100644 src/test/ui/macros/macro-shadowing-relaxed.rs rename src/test/ui/{ => macros}/macro-shadowing.rs (92%) create mode 100644 src/test/ui/macros/macro-shadowing.stderr rename src/test/{compile-fail => ui/macros}/macro-stability.rs (100%) create mode 100644 src/test/ui/macros/macro-stability.stderr rename src/test/{compile-fail => ui/macros}/macro-stmt-matchers.rs (100%) create mode 100644 src/test/ui/macros/macro-stmt-matchers.stderr rename src/test/{compile-fail => ui/macros}/macro-tt-matchers.rs (100%) create mode 100644 src/test/ui/macros/macro-tt-matchers.stderr rename src/test/{compile-fail => ui/macros}/macro-use-bad-args-1.rs (97%) create mode 100644 src/test/ui/macros/macro-use-bad-args-1.stderr rename src/test/{compile-fail => ui/macros}/macro-use-bad-args-2.rs (97%) create mode 100644 src/test/ui/macros/macro-use-bad-args-2.stderr rename src/test/{compile-fail => ui/macros}/macro-use-scope.rs (100%) create mode 100644 src/test/ui/macros/macro-use-scope.stderr rename src/test/{compile-fail => ui/macros}/macro-use-undef.rs (100%) create mode 100644 src/test/ui/macros/macro-use-undef.stderr rename src/test/{compile-fail => ui/macros}/macro-use-wrong-name.rs (100%) create mode 100644 src/test/ui/macros/macro-use-wrong-name.stderr create mode 100644 src/test/ui/macros/macros-in-extern.rs create mode 100644 src/test/ui/macros/macros-in-extern.stderr rename src/test/{compile-fail => ui/macros}/macros-nonfatal-errors.rs (91%) create mode 100644 src/test/ui/macros/macros-nonfatal-errors.stderr create mode 100644 src/test/ui/macros/missing-comma.rs create mode 100644 src/test/ui/macros/missing-comma.stderr create mode 100644 src/test/ui/macros/restricted-shadowing-legacy.rs create mode 100644 src/test/ui/macros/restricted-shadowing-legacy.stderr create mode 100644 src/test/ui/macros/restricted-shadowing-modern.rs create mode 100644 src/test/ui/macros/restricted-shadowing-modern.stderr rename src/test/{compile-fail => ui}/main-wrong-type.rs (100%) create mode 100644 src/test/ui/main-wrong-type.stderr rename src/test/{compile-fail => ui/malformed}/malformed-derive-entry.rs (100%) create mode 100644 src/test/ui/malformed/malformed-derive-entry.stderr rename src/test/{compile-fail => ui/malformed}/malformed-plugin-1.rs (100%) create mode 100644 src/test/ui/malformed/malformed-plugin-1.stderr rename src/test/{compile-fail => ui/malformed}/malformed-plugin-2.rs (100%) create mode 100644 src/test/ui/malformed/malformed-plugin-2.stderr rename src/test/{compile-fail => ui/malformed}/malformed-plugin-3.rs (100%) create mode 100644 src/test/ui/malformed/malformed-plugin-3.stderr rename src/test/{compile-fail => ui}/malformed_macro_lhs.rs (100%) create mode 100644 src/test/ui/malformed_macro_lhs.stderr rename src/test/{compile-fail => ui/manual}/manual-link-bad-form.rs (100%) create mode 100644 src/test/ui/manual/manual-link-bad-form.stderr rename src/test/{compile-fail => ui/manual}/manual-link-bad-kind.rs (100%) create mode 100644 src/test/ui/manual/manual-link-bad-kind.stderr rename src/test/{compile-fail => ui/manual}/manual-link-bad-search-path.rs (100%) create mode 100644 src/test/ui/manual/manual-link-bad-search-path.stderr rename src/test/{compile-fail => ui/manual}/manual-link-framework.rs (100%) create mode 100644 src/test/ui/manual/manual-link-framework.stderr rename src/test/{compile-fail => ui}/map-types.rs (100%) create mode 100644 src/test/ui/map-types.stderr rename src/test/{compile-fail => ui/match}/match-argm-statics-2.rs (100%) create mode 100644 src/test/ui/match/match-argm-statics-2.stderr rename src/test/{compile-fail => ui/match}/match-arm-statics.rs (100%) create mode 100644 src/test/ui/match/match-arm-statics.stderr rename src/test/{compile-fail => ui/match}/match-byte-array-patterns-2.rs (100%) create mode 100644 src/test/ui/match/match-byte-array-patterns-2.stderr rename src/test/{compile-fail => ui/match}/match-byte-array-patterns.rs (100%) create mode 100644 src/test/ui/match/match-byte-array-patterns.stderr rename src/test/{compile-fail => ui/match}/match-ill-type2.rs (100%) create mode 100644 src/test/ui/match/match-ill-type2.stderr rename src/test/{compile-fail => ui/match}/match-join.rs (100%) create mode 100644 src/test/ui/match/match-join.stderr rename src/test/{compile-fail => ui/match}/match-no-arms-unreachable-after.rs (100%) create mode 100644 src/test/ui/match/match-no-arms-unreachable-after.stderr rename src/test/{compile-fail => ui/match}/match-non-exhaustive.rs (100%) create mode 100644 src/test/ui/match/match-non-exhaustive.stderr rename src/test/{compile-fail => ui/match}/match-pattern-field-mismatch-2.rs (100%) create mode 100644 src/test/ui/match/match-pattern-field-mismatch-2.stderr rename src/test/{compile-fail => ui/match}/match-pattern-field-mismatch.rs (100%) create mode 100644 src/test/ui/match/match-pattern-field-mismatch.stderr rename src/test/{compile-fail => ui/match}/match-privately-empty.rs (100%) create mode 100644 src/test/ui/match/match-privately-empty.stderr rename src/test/{compile-fail => ui/match}/match-range-fail-2.rs (100%) create mode 100644 src/test/ui/match/match-range-fail-2.stderr rename src/test/{compile-fail => ui/match}/match-range-fail-dominate.rs (100%) create mode 100644 src/test/ui/match/match-range-fail-dominate.stderr rename src/test/{compile-fail => ui/match}/match-range-fail.rs (100%) create mode 100644 src/test/ui/match/match-range-fail.stderr rename src/test/{compile-fail => ui/match}/match-ref-ice.rs (100%) create mode 100644 src/test/ui/match/match-ref-ice.stderr create mode 100644 src/test/ui/match/match-ref-mut-invariance.nll.stderr rename src/test/{compile-fail => ui/match}/match-ref-mut-invariance.rs (100%) create mode 100644 src/test/ui/match/match-ref-mut-invariance.stderr create mode 100644 src/test/ui/match/match-ref-mut-let-invariance.nll.stderr rename src/test/{compile-fail => ui/match}/match-ref-mut-let-invariance.rs (100%) create mode 100644 src/test/ui/match/match-ref-mut-let-invariance.stderr rename src/test/{compile-fail => ui/match}/match-slice-patterns.rs (100%) create mode 100644 src/test/ui/match/match-slice-patterns.stderr rename src/test/{compile-fail => ui/match}/match-static-const-lc.rs (100%) create mode 100644 src/test/ui/match/match-static-const-lc.stderr rename src/test/{compile-fail => ui/match}/match-struct.rs (100%) create mode 100644 src/test/ui/match/match-struct.stderr rename src/test/{compile-fail => ui/match}/match-tag-nullary.rs (100%) create mode 100644 src/test/ui/match/match-tag-nullary.stderr rename src/test/{compile-fail => ui/match}/match-tag-unary.rs (100%) create mode 100644 src/test/ui/match/match-tag-unary.stderr rename src/test/{compile-fail => ui/match}/match-unreachable-warning-with-diverging-discrim.rs (100%) create mode 100644 src/test/ui/match/match-unreachable-warning-with-diverging-discrim.stderr rename src/test/{compile-fail => ui/match}/match-unresolved-one-arm.rs (100%) create mode 100644 src/test/ui/match/match-unresolved-one-arm.stderr rename src/test/{compile-fail => ui/match}/match-vec-fixed.rs (100%) create mode 100644 src/test/ui/match/match-vec-fixed.stderr rename src/test/{compile-fail => ui/match}/match-vec-mismatch-2.rs (100%) create mode 100644 src/test/ui/match/match-vec-mismatch-2.stderr rename src/test/{compile-fail => ui/match}/match-vec-mismatch.rs (100%) create mode 100644 src/test/ui/match/match-vec-mismatch.stderr rename src/test/{compile-fail => ui/match}/match-vec-unreachable.rs (100%) create mode 100644 src/test/ui/match/match-vec-unreachable.stderr rename src/test/{compile-fail => ui}/maybe-bounds-where-cpass.rs (100%) create mode 100644 src/test/ui/maybe-bounds-where-cpass.stderr rename src/test/{compile-fail => ui}/maybe-bounds-where.rs (100%) create mode 100644 src/test/ui/maybe-bounds-where.stderr create mode 100644 src/test/ui/meta-expected-error-correct-rev.a.stderr rename src/test/{compile-fail => ui}/meta-expected-error-correct-rev.rs (100%) rename src/test/{compile-fail => ui/methods}/auxiliary/ambig_impl_2_lib.rs (100%) create mode 100644 src/test/ui/methods/auxiliary/macro-in-other-crate.rs rename src/test/{compile-fail => ui/methods}/method-ambig-one-trait-unknown-int-type.rs (100%) create mode 100644 src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr rename src/test/{compile-fail => ui/methods}/method-ambig-two-traits-cross-crate.rs (100%) create mode 100644 src/test/ui/methods/method-ambig-two-traits-cross-crate.stderr rename src/test/{compile-fail => ui/methods}/method-ambig-two-traits-from-bounds.rs (100%) create mode 100644 src/test/ui/methods/method-ambig-two-traits-from-bounds.stderr rename src/test/{compile-fail => ui/methods}/method-ambig-two-traits-with-default-method.rs (100%) create mode 100644 src/test/ui/methods/method-ambig-two-traits-with-default-method.stderr rename src/test/ui/{ => methods}/method-call-err-msg.rs (100%) rename src/test/ui/{ => methods}/method-call-err-msg.stderr (100%) create mode 100644 src/test/ui/methods/method-call-lifetime-args-fail.rs create mode 100644 src/test/ui/methods/method-call-lifetime-args-fail.stderr rename src/test/{compile-fail/method-call-lifetime-args-lint.rs => ui/methods/method-call-lifetime-args-lint-fail.rs} (100%) create mode 100644 src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr rename src/test/ui/{ => methods}/method-call-lifetime-args-lint.rs (100%) rename src/test/ui/{ => methods}/method-call-lifetime-args-lint.stderr (100%) rename src/test/{compile-fail => ui/methods}/method-call-lifetime-args-subst-index.rs (100%) create mode 100644 src/test/ui/methods/method-call-lifetime-args-subst-index.stderr rename src/test/{compile-fail => ui/methods}/method-call-lifetime-args-unresolved.rs (100%) create mode 100644 src/test/ui/methods/method-call-lifetime-args-unresolved.stderr rename src/test/ui/{ => methods}/method-call-lifetime-args.rs (100%) rename src/test/ui/{ => methods}/method-call-lifetime-args.stderr (100%) rename src/test/{compile-fail => ui/methods}/method-call-type-binding.rs (100%) create mode 100644 src/test/ui/methods/method-call-type-binding.stderr rename src/test/{compile-fail => ui/methods}/method-macro-backtrace.rs (100%) create mode 100644 src/test/ui/methods/method-macro-backtrace.stderr rename src/test/ui/{ => methods}/method-missing-call.rs (100%) rename src/test/ui/{ => methods}/method-missing-call.stderr (100%) rename src/test/ui/{ => methods}/method-on-ambiguous-numeric-type.rs (100%) rename src/test/ui/{ => methods}/method-on-ambiguous-numeric-type.stderr (100%) rename src/test/{compile-fail => ui/methods}/method-path-in-pattern.rs (100%) create mode 100644 src/test/ui/methods/method-path-in-pattern.stderr rename src/test/{compile-fail => ui/methods}/method-resolvable-path-in-pattern.rs (100%) create mode 100644 src/test/ui/methods/method-resolvable-path-in-pattern.stderr rename src/test/{compile-fail => ui/methods}/method-self-arg-1.rs (100%) create mode 100644 src/test/ui/methods/method-self-arg-1.stderr create mode 100644 src/test/ui/methods/method-self-arg-2.nll.stderr rename src/test/{compile-fail => ui/methods}/method-self-arg-2.rs (86%) create mode 100644 src/test/ui/methods/method-self-arg-2.stderr rename src/test/{compile-fail => ui}/minus-string.rs (100%) create mode 100644 src/test/ui/minus-string.stderr rename src/test/{compile-fail => ui}/mir-dataflow/README.md (100%) rename src/test/{compile-fail => ui}/mir-dataflow/def-inits-1.rs (100%) create mode 100644 src/test/ui/mir-dataflow/def-inits-1.stderr rename src/test/{compile-fail => ui}/mir-dataflow/inits-1.rs (100%) create mode 100644 src/test/ui/mir-dataflow/inits-1.stderr rename src/test/{compile-fail => ui}/mir-dataflow/uninits-1.rs (100%) create mode 100644 src/test/ui/mir-dataflow/uninits-1.stderr rename src/test/{compile-fail => ui}/mir-dataflow/uninits-2.rs (100%) create mode 100644 src/test/ui/mir-dataflow/uninits-2.stderr rename src/test/{compile-fail => ui}/mir-unpretty.rs (100%) create mode 100644 src/test/ui/mir-unpretty.stderr create mode 100644 src/test/ui/missing/auxiliary/two_macros.rs rename src/test/ui/{ => missing}/missing-alloc_error_handler.rs (91%) rename src/test/ui/{ => missing}/missing-alloc_error_handler.stderr (100%) rename src/test/ui/{ => missing}/missing-allocator.rs (89%) rename src/test/ui/{ => missing}/missing-allocator.stderr (100%) rename src/test/ui/{ => missing}/missing-block-hint.rs (100%) rename src/test/ui/{ => missing}/missing-block-hint.stderr (100%) rename src/test/ui/{ => missing}/missing-comma-in-match.fixed (100%) rename src/test/ui/{ => missing}/missing-comma-in-match.rs (100%) rename src/test/ui/{ => missing}/missing-comma-in-match.stderr (100%) rename src/test/{compile-fail => ui/missing}/missing-derivable-attr.rs (100%) create mode 100644 src/test/ui/missing/missing-derivable-attr.stderr rename src/test/ui/{ => missing}/missing-fields-in-struct-pattern.rs (100%) rename src/test/ui/{ => missing}/missing-fields-in-struct-pattern.stderr (100%) rename src/test/ui/{ => missing}/missing-items/auxiliary/m1.rs (100%) rename src/test/ui/{ => missing}/missing-items/issue-40221.rs (100%) rename src/test/ui/{ => missing}/missing-items/issue-40221.stderr (100%) rename src/test/ui/{ => missing}/missing-items/m2.rs (100%) rename src/test/ui/{ => missing}/missing-items/m2.stderr (100%) rename src/test/ui/{ => missing}/missing-items/missing-type-parameter.rs (100%) rename src/test/ui/{ => missing}/missing-items/missing-type-parameter.stderr (100%) rename src/test/{compile-fail => ui/missing}/missing-macro-use.rs (100%) create mode 100644 src/test/ui/missing/missing-macro-use.stderr rename src/test/{compile-fail => ui/missing}/missing-main.rs (100%) create mode 100644 src/test/ui/missing/missing-main.stderr rename src/test/{compile-fail => ui/missing}/missing-return.rs (100%) create mode 100644 src/test/ui/missing/missing-return.stderr rename src/test/{compile-fail => ui/missing}/missing-semicolon-warning.rs (100%) create mode 100644 src/test/ui/missing/missing-semicolon-warning.stderr rename src/test/{compile-fail => ui/missing}/missing-stability.rs (83%) create mode 100644 src/test/ui/missing/missing-stability.stderr rename src/test/{compile-fail => ui}/missing_debug_impls.rs (100%) create mode 100644 src/test/ui/missing_debug_impls.stderr rename src/test/{compile-fail => ui/mod}/mod_file_aux.rs (100%) rename src/test/{compile-fail => ui/mod}/mod_file_correct_spans.rs (86%) create mode 100644 src/test/ui/mod/mod_file_correct_spans.stderr rename src/test/{compile-fail => ui/mod}/mod_file_disambig.rs (100%) create mode 100644 src/test/ui/mod/mod_file_disambig.stderr rename src/test/{compile-fail => ui/mod}/mod_file_disambig_aux.rs (100%) rename src/test/{compile-fail => ui/mod}/mod_file_disambig_aux/mod.rs (100%) rename src/test/{compile-fail => ui}/module-macro_use-arguments.rs (100%) create mode 100644 src/test/ui/module-macro_use-arguments.stderr delete mode 100644 src/test/ui/moves-based-on-type-block-bad.nll.stderr rename src/test/{compile-fail => ui/moves}/move-guard-same-consts.rs (100%) create mode 100644 src/test/ui/moves/move-guard-same-consts.stderr rename src/test/{compile-fail => ui/moves}/move-in-guard-1.rs (100%) create mode 100644 src/test/ui/moves/move-in-guard-1.stderr rename src/test/{compile-fail => ui/moves}/move-in-guard-2.rs (100%) create mode 100644 src/test/ui/moves/move-in-guard-2.stderr create mode 100644 src/test/ui/moves/move-into-dead-array-1.nll.stderr rename src/test/{compile-fail => ui/moves}/move-into-dead-array-1.rs (100%) create mode 100644 src/test/ui/moves/move-into-dead-array-1.stderr create mode 100644 src/test/ui/moves/move-into-dead-array-2.nll.stderr rename src/test/{compile-fail => ui/moves}/move-into-dead-array-2.rs (100%) create mode 100644 src/test/ui/moves/move-into-dead-array-2.stderr rename src/test/{compile-fail => ui/moves}/move-out-of-array-1.rs (100%) create mode 100644 src/test/ui/moves/move-out-of-array-1.stderr create mode 100644 src/test/ui/moves/move-out-of-slice-1.nll.stderr rename src/test/{compile-fail => ui/moves}/move-out-of-slice-1.rs (100%) create mode 100644 src/test/ui/moves/move-out-of-slice-1.stderr create mode 100644 src/test/ui/moves/move-out-of-tuple-field.nll.stderr rename src/test/{compile-fail => ui/moves}/move-out-of-tuple-field.rs (100%) create mode 100644 src/test/ui/moves/move-out-of-tuple-field.stderr create mode 100644 src/test/ui/moves/moves-based-on-type-access-to-field.nll.stderr rename src/test/{compile-fail => ui/moves}/moves-based-on-type-access-to-field.rs (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-access-to-field.stderr create mode 100644 src/test/ui/moves/moves-based-on-type-block-bad.nll.stderr rename src/test/ui/{ => moves}/moves-based-on-type-block-bad.rs (100%) rename src/test/ui/{ => moves}/moves-based-on-type-block-bad.stderr (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-capture-clause-bad.nll.stderr rename src/test/{compile-fail => ui/moves}/moves-based-on-type-capture-clause-bad.rs (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-capture-clause-bad.stderr create mode 100644 src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.nll.stderr rename src/test/{compile-fail => ui/moves}/moves-based-on-type-cyclic-types-issue-4821.rs (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr create mode 100644 src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.nll.stderr rename src/test/{compile-fail => ui/moves}/moves-based-on-type-distribute-copy-over-paren.rs (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr create mode 100644 src/test/ui/moves/moves-based-on-type-exprs.nll.stderr rename src/test/{compile-fail => ui/moves}/moves-based-on-type-exprs.rs (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-exprs.stderr rename src/test/ui/{ => moves}/moves-based-on-type-match-bindings.nll.stderr (100%) rename src/test/ui/{ => moves}/moves-based-on-type-match-bindings.rs (100%) rename src/test/ui/{ => moves}/moves-based-on-type-match-bindings.stderr (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.nll.stderr rename src/test/{compile-fail => ui/moves}/moves-based-on-type-move-out-of-closure-env-issue-1965.rs (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr create mode 100644 src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr rename src/test/{compile-fail => ui/moves}/moves-based-on-type-no-recursive-stack-closure.rs (100%) create mode 100644 src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr rename src/test/ui/{ => moves}/moves-based-on-type-tuple.rs (100%) rename src/test/ui/{ => moves}/moves-based-on-type-tuple.stderr (100%) create mode 100644 src/test/ui/moves/moves-sru-moved-field.nll.stderr rename src/test/{compile-fail => ui/moves}/moves-sru-moved-field.rs (100%) create mode 100644 src/test/ui/moves/moves-sru-moved-field.stderr rename src/test/{compile-fail => ui}/multiple-main-2.rs (100%) create mode 100644 src/test/ui/multiple-main-2.stderr rename src/test/{compile-fail => ui}/multiple-main-3.rs (100%) create mode 100644 src/test/ui/multiple-main-3.stderr rename src/test/{compile-fail => ui}/multiple-plugin-registrars.rs (100%) create mode 100644 src/test/ui/multiple-plugin-registrars.stderr create mode 100644 src/test/ui/mut/mut-cant-alias.nll.stderr rename src/test/{compile-fail => ui/mut}/mut-cant-alias.rs (85%) create mode 100644 src/test/ui/mut/mut-cant-alias.stderr rename src/test/{compile-fail => ui/mut}/mut-cross-borrowing.rs (100%) create mode 100644 src/test/ui/mut/mut-cross-borrowing.stderr create mode 100644 src/test/ui/mut/mut-pattern-internal-mutability.ast.nll.stderr create mode 100644 src/test/ui/mut/mut-pattern-internal-mutability.ast.stderr create mode 100644 src/test/ui/mut/mut-pattern-internal-mutability.mir.stderr rename src/test/{compile-fail => ui/mut}/mut-pattern-internal-mutability.rs (100%) rename src/test/{compile-fail => ui/mut}/mut-pattern-mismatched.rs (100%) create mode 100644 src/test/ui/mut/mut-pattern-mismatched.stderr rename src/test/ui/{ => mut}/mut-ref.rs (100%) rename src/test/ui/{ => mut}/mut-ref.stderr (100%) create mode 100644 src/test/ui/mut/mut-suggestion.nll.stderr rename src/test/{compile-fail => ui/mut}/mut-suggestion.rs (85%) create mode 100644 src/test/ui/mut/mut-suggestion.stderr create mode 100644 src/test/ui/mut/mutable-class-fields-2.nll.stderr rename src/test/{compile-fail => ui/mut}/mutable-class-fields-2.rs (100%) create mode 100644 src/test/ui/mut/mutable-class-fields-2.stderr create mode 100644 src/test/ui/mut/mutable-class-fields.ast.nll.stderr create mode 100644 src/test/ui/mut/mutable-class-fields.ast.stderr create mode 100644 src/test/ui/mut/mutable-class-fields.mir.stderr rename src/test/{compile-fail => ui/mut}/mutable-class-fields.rs (100%) rename src/test/{compile-fail => ui/mut}/mutable-enum-indirect.rs (100%) create mode 100644 src/test/ui/mut/mutable-enum-indirect.stderr rename src/test/{compile-fail => ui}/mutexguard-sync.rs (100%) create mode 100644 src/test/ui/mutexguard-sync.stderr rename src/test/{compile-fail => ui/namespace}/auxiliary/namespace-mix.rs (100%) rename src/test/{run-pass => ui/namespace}/auxiliary/namespaced_enums.rs (100%) rename src/test/{compile-fail => ui/namespace}/namespace-mix.rs (100%) create mode 100644 src/test/ui/namespace/namespace-mix.stderr rename src/test/{compile-fail => ui/namespace}/namespaced-enum-glob-import-no-impls-xcrate.rs (100%) create mode 100644 src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr rename src/test/{compile-fail => ui/namespace}/namespaced-enum-glob-import-no-impls.rs (100%) create mode 100644 src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr rename src/test/{compile-fail => ui}/nested-cfg-attrs.rs (100%) create mode 100644 src/test/ui/nested-cfg-attrs.stderr rename src/test/{compile-fail => ui}/nested-ty-params.rs (97%) create mode 100644 src/test/ui/nested-ty-params.stderr rename src/test/{compile-fail => ui}/never-assign-dead-code.rs (100%) create mode 100644 src/test/ui/never-assign-dead-code.stderr rename src/test/{compile-fail => ui}/never-assign-wrong-type.rs (100%) create mode 100644 src/test/ui/never-assign-wrong-type.stderr rename src/test/{compile-fail => ui}/never_transmute_never.rs (100%) create mode 100644 src/test/ui/nll/closure-access-spans.rs create mode 100644 src/test/ui/nll/closure-access-spans.stderr create mode 100644 src/test/ui/nll/closure-borrow-spans.rs create mode 100644 src/test/ui/nll/closure-borrow-spans.stderr create mode 100644 src/test/ui/nll/closure-move-spans.rs create mode 100644 src/test/ui/nll/closure-move-spans.stderr create mode 100644 src/test/ui/nll/closure-use-spans.rs create mode 100644 src/test/ui/nll/closure-use-spans.stderr create mode 100644 src/test/ui/nll/closures-in-loops.rs create mode 100644 src/test/ui/nll/closures-in-loops.stderr rename src/test/{compile-fail => ui}/nll/constant-thread-locals-issue-47053.rs (100%) create mode 100644 src/test/ui/nll/constant-thread-locals-issue-47053.stderr rename src/test/{compile-fail => ui}/nll/do-not-ignore-lifetime-bounds-in-copy.rs (100%) create mode 100644 src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr create mode 100644 src/test/ui/nll/issue-27868.rs create mode 100644 src/test/ui/nll/issue-27868.stderr create mode 100644 src/test/ui/nll/issue-30104.rs create mode 100644 src/test/ui/nll/issue-48697.rs create mode 100644 src/test/ui/nll/issue-52113.rs create mode 100644 src/test/ui/nll/issue-52113.stderr delete mode 100644 src/test/ui/nll/issue-52133.rs delete mode 100644 src/test/ui/nll/issue-52133.stderr create mode 100644 src/test/ui/nll/issue-52663-span-decl-captured-variable.rs create mode 100644 src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr create mode 100644 src/test/ui/nll/issue-52742.rs create mode 100644 src/test/ui/nll/issue-52742.stderr create mode 100644 src/test/ui/nll/issue-53119.rs create mode 100644 src/test/ui/nll/issue-53570.rs rename src/test/{compile-fail => ui}/nll/loan_ends_mid_block_pair.rs (100%) create mode 100644 src/test/ui/nll/loan_ends_mid_block_pair.stderr rename src/test/{compile-fail => ui}/nll/loan_ends_mid_block_vec.rs (100%) create mode 100644 src/test/ui/nll/loan_ends_mid_block_vec.stderr create mode 100644 src/test/ui/nll/match-guards-always-borrow.ast.nll.stderr create mode 100644 src/test/ui/nll/match-guards-always-borrow.ast.stderr create mode 100644 src/test/ui/nll/match-guards-always-borrow.mir.stderr rename src/test/{compile-fail => ui}/nll/match-guards-always-borrow.rs (100%) create mode 100644 src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs create mode 100644 src/test/ui/nll/reference-carried-through-struct-field.ast.nll.stderr create mode 100644 src/test/ui/nll/reference-carried-through-struct-field.ast.stderr create mode 100644 src/test/ui/nll/reference-carried-through-struct-field.mir.stderr rename src/test/{compile-fail => ui}/nll/reference-carried-through-struct-field.rs (100%) create mode 100644 src/test/ui/nll/region-ends-after-if-condition.nll.stderr rename src/test/{compile-fail => ui}/nll/region-ends-after-if-condition.rs (100%) create mode 100644 src/test/ui/nll/region-ends-after-if-condition.stderr delete mode 100644 src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.stderr create mode 100644 src/test/ui/nll/relate_tys/universe-violation.rs create mode 100644 src/test/ui/nll/relate_tys/universe-violation.stderr create mode 100644 src/test/ui/nll/relate_tys/var-appears-twice.rs create mode 100644 src/test/ui/nll/relate_tys/var-appears-twice.stderr rename src/test/{compile-fail => ui}/nll/return_from_loop.rs (100%) create mode 100644 src/test/ui/nll/return_from_loop.stderr rename src/test/{compile-fail => ui}/nll/unused-mut-issue-50343.rs (100%) create mode 100644 src/test/ui/nll/unused-mut-issue-50343.stderr create mode 100644 src/test/ui/nll/user-annotations/adt-brace-enums.rs create mode 100644 src/test/ui/nll/user-annotations/adt-brace-enums.stderr create mode 100644 src/test/ui/nll/user-annotations/adt-brace-structs.rs create mode 100644 src/test/ui/nll/user-annotations/adt-brace-structs.stderr create mode 100644 src/test/ui/nll/user-annotations/adt-nullary-enums.rs create mode 100644 src/test/ui/nll/user-annotations/adt-nullary-enums.stderr create mode 100644 src/test/ui/nll/user-annotations/adt-tuple-enums.rs create mode 100644 src/test/ui/nll/user-annotations/adt-tuple-enums.stderr create mode 100644 src/test/ui/nll/user-annotations/adt-tuple-struct.rs create mode 100644 src/test/ui/nll/user-annotations/adt-tuple-struct.stderr create mode 100644 src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs create mode 100644 src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr create mode 100644 src/test/ui/nll/user-annotations/dump-fn-method.rs create mode 100644 src/test/ui/nll/user-annotations/dump-fn-method.stderr create mode 100644 src/test/ui/nll/user-annotations/fns.rs create mode 100644 src/test/ui/nll/user-annotations/fns.stderr create mode 100644 src/test/ui/nll/user-annotations/method-call.rs create mode 100644 src/test/ui/nll/user-annotations/method-call.stderr create mode 100644 src/test/ui/nll/user-annotations/method-ufcs-1.rs create mode 100644 src/test/ui/nll/user-annotations/method-ufcs-1.stderr create mode 100644 src/test/ui/nll/user-annotations/method-ufcs-2.rs create mode 100644 src/test/ui/nll/user-annotations/method-ufcs-2.stderr create mode 100644 src/test/ui/nll/user-annotations/method-ufcs-3.rs create mode 100644 src/test/ui/nll/user-annotations/method-ufcs-3.stderr create mode 100644 src/test/ui/nll/user-annotations/patterns.rs create mode 100644 src/test/ui/nll/user-annotations/patterns.stderr rename src/test/{compile-fail => ui}/nll/where_clauses_in_functions.rs (88%) create mode 100644 src/test/ui/nll/where_clauses_in_functions.stderr rename src/test/{compile-fail => ui}/nll/where_clauses_in_structs.rs (88%) create mode 100644 src/test/ui/nll/where_clauses_in_structs.stderr create mode 100644 src/test/ui/no-capture-arc.nll.stderr rename src/test/{compile-fail => ui}/no-capture-arc.rs (100%) create mode 100644 src/test/ui/no-capture-arc.stderr rename src/test/{compile-fail => ui}/no-implicit-prelude-nested.rs (100%) create mode 100644 src/test/ui/no-implicit-prelude-nested.stderr rename src/test/{compile-fail => ui}/no-implicit-prelude.rs (100%) create mode 100644 src/test/ui/no-implicit-prelude.stderr rename src/test/{compile-fail => ui}/no-link.rs (87%) create mode 100644 src/test/ui/no-link.stderr rename src/test/{compile-fail => ui}/no-patterns-in-args-2.rs (100%) create mode 100644 src/test/ui/no-patterns-in-args-2.stderr rename src/test/{compile-fail => ui}/no-patterns-in-args-macro.rs (100%) create mode 100644 src/test/ui/no-patterns-in-args-macro.stderr create mode 100644 src/test/ui/no-reuse-move-arc.nll.stderr rename src/test/{compile-fail => ui}/no-reuse-move-arc.rs (100%) create mode 100644 src/test/ui/no-reuse-move-arc.stderr rename src/test/{compile-fail => ui}/no-send-res-ports.rs (100%) create mode 100644 src/test/ui/no-send-res-ports.stderr rename src/test/{compile-fail => ui}/no-std-inject.rs (100%) create mode 100644 src/test/ui/no-std-inject.stderr rename src/test/{compile-fail => ui}/no-type-for-node-ice.rs (100%) create mode 100644 src/test/ui/no-type-for-node-ice.stderr rename src/test/{compile-fail => ui}/no-warn-on-field-replace-issue-34101.rs (100%) create mode 100644 src/test/ui/no-warn-on-field-replace-issue-34101.stderr rename src/test/{compile-fail => ui}/no_crate_type.rs (100%) create mode 100644 src/test/ui/no_crate_type.stderr rename src/test/{compile-fail => ui}/no_owned_box_lang_item.rs (88%) create mode 100644 src/test/ui/no_owned_box_lang_item.stderr rename src/test/{compile-fail => ui}/no_send-enum.rs (100%) create mode 100644 src/test/ui/no_send-enum.stderr rename src/test/{compile-fail => ui}/no_send-rc.rs (100%) create mode 100644 src/test/ui/no_send-rc.stderr rename src/test/{compile-fail => ui}/no_send-struct.rs (100%) create mode 100644 src/test/ui/no_send-struct.stderr rename src/test/{compile-fail => ui}/no_share-enum.rs (100%) create mode 100644 src/test/ui/no_share-enum.stderr rename src/test/{compile-fail => ui}/no_share-struct.rs (100%) create mode 100644 src/test/ui/no_share-struct.stderr rename src/test/{compile-fail => ui}/noexporttypeexe.rs (100%) create mode 100644 src/test/ui/noexporttypeexe.stderr rename src/test/{compile-fail => ui}/non-constant-in-const-path.rs (100%) create mode 100644 src/test/ui/non-constant-in-const-path.stderr rename src/test/{compile-fail => ui}/non-copyable-void.rs (100%) create mode 100644 src/test/ui/non-copyable-void.stderr rename src/test/{compile-fail => ui/non-exhaustive}/non-exhaustive-match-nested.rs (100%) create mode 100644 src/test/ui/non-exhaustive/non-exhaustive-match-nested.stderr rename src/test/{compile-fail => ui/non-exhaustive}/non-exhaustive-match.rs (100%) create mode 100644 src/test/ui/non-exhaustive/non-exhaustive-match.stderr rename src/test/ui/{ => non-exhaustive}/non-exhaustive-pattern-witness.rs (100%) rename src/test/ui/{ => non-exhaustive}/non-exhaustive-pattern-witness.stderr (100%) rename src/test/{compile-fail => ui}/non-interger-atomic.rs (100%) create mode 100644 src/test/ui/non-interger-atomic.stderr delete mode 100644 src/test/ui/non_modrs_mods/non_modrs_mods.rs delete mode 100644 src/test/ui/non_modrs_mods/non_modrs_mods.stderr rename src/test/{compile-fail => ui}/noncopyable-class.rs (100%) create mode 100644 src/test/ui/noncopyable-class.stderr rename src/test/{compile-fail => ui}/nonscalar-cast.rs (100%) create mode 100644 src/test/ui/nonscalar-cast.stderr rename src/test/{compile-fail => ui}/not-clone-closure.rs (100%) create mode 100644 src/test/ui/not-clone-closure.stderr create mode 100644 src/test/ui/not-copy-closure.nll.stderr rename src/test/{compile-fail => ui}/not-copy-closure.rs (100%) create mode 100644 src/test/ui/not-copy-closure.stderr rename src/test/{compile-fail => ui/not-panic}/not-panic-safe-2.rs (100%) create mode 100644 src/test/ui/not-panic/not-panic-safe-2.stderr rename src/test/{compile-fail => ui/not-panic}/not-panic-safe-3.rs (100%) create mode 100644 src/test/ui/not-panic/not-panic-safe-3.stderr rename src/test/{compile-fail => ui/not-panic}/not-panic-safe-4.rs (100%) create mode 100644 src/test/ui/not-panic/not-panic-safe-4.stderr rename src/test/{compile-fail => ui/not-panic}/not-panic-safe-5.rs (100%) create mode 100644 src/test/ui/not-panic/not-panic-safe-5.stderr rename src/test/{compile-fail => ui/not-panic}/not-panic-safe-6.rs (100%) create mode 100644 src/test/ui/not-panic/not-panic-safe-6.stderr rename src/test/{compile-fail => ui/not-panic}/not-panic-safe.rs (100%) create mode 100644 src/test/ui/not-panic/not-panic-safe.stderr rename src/test/{compile-fail => ui}/not-sync.rs (100%) create mode 100644 src/test/ui/not-sync.stderr rename src/test/ui/{ => numeric}/numeric-cast-2.rs (100%) rename src/test/ui/{ => numeric}/numeric-cast-2.stderr (100%) rename src/test/ui/{ => numeric}/numeric-cast.rs (100%) rename src/test/ui/{ => numeric}/numeric-cast.stderr (100%) rename src/test/ui/{ => numeric}/numeric-fields.rs (100%) rename src/test/ui/{ => numeric}/numeric-fields.stderr (100%) rename src/test/{compile-fail => ui}/object-does-not-impl-trait.rs (100%) create mode 100644 src/test/ui/object-does-not-impl-trait.stderr rename src/test/{compile-fail => ui/object-lifetime}/object-lifetime-default-ambiguous.rs (100%) create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-elision.nll.stderr rename src/test/{compile-fail => ui/object-lifetime}/object-lifetime-default-elision.rs (100%) create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-elision.stderr create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr rename src/test/{compile-fail => ui/object-lifetime}/object-lifetime-default-from-box-error.rs (100%) create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr rename src/test/{compile-fail => ui/object-lifetime}/object-lifetime-default-from-rptr-box-error.rs (100%) create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr rename src/test/{compile-fail => ui/object-lifetime}/object-lifetime-default-from-rptr-struct-error.rs (100%) create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr rename src/test/{compile-fail => ui/object-lifetime}/object-lifetime-default-mybox.rs (100%) create mode 100644 src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr rename src/test/{compile-fail => ui/object-lifetime}/object-lifetime-default.rs (97%) create mode 100644 src/test/ui/object-lifetime/object-lifetime-default.stderr rename src/test/{compile-fail => ui}/object-pointer-types.rs (100%) create mode 100644 src/test/ui/object-pointer-types.stderr rename src/test/ui/{ => object-safety}/object-safety-associated-consts.rs (100%) rename src/test/ui/{ => object-safety}/object-safety-associated-consts.stderr (100%) create mode 100644 src/test/ui/object-safety/object-safety-by-value-self-use.nll.stderr rename src/test/{compile-fail => ui/object-safety}/object-safety-by-value-self-use.rs (100%) create mode 100644 src/test/ui/object-safety/object-safety-by-value-self-use.stderr rename src/test/{compile-fail => ui/object-safety}/object-safety-by-value-self.rs (100%) create mode 100644 src/test/ui/object-safety/object-safety-by-value-self.stderr rename src/test/ui/{ => object-safety}/object-safety-generics.rs (100%) rename src/test/ui/{ => object-safety}/object-safety-generics.stderr (100%) rename src/test/{compile-fail => ui/object-safety}/object-safety-issue-22040.rs (100%) create mode 100644 src/test/ui/object-safety/object-safety-issue-22040.stderr rename src/test/ui/{ => object-safety}/object-safety-mentions-Self.rs (100%) rename src/test/ui/{ => object-safety}/object-safety-mentions-Self.stderr (100%) rename src/test/{compile-fail => ui/object-safety}/object-safety-no-static.rs (100%) create mode 100644 src/test/ui/object-safety/object-safety-no-static.stderr rename src/test/{compile-fail => ui/object-safety}/object-safety-phantom-fn.rs (100%) create mode 100644 src/test/ui/object-safety/object-safety-phantom-fn.stderr rename src/test/{compile-fail => ui/object-safety}/object-safety-sized-2.rs (100%) create mode 100644 src/test/ui/object-safety/object-safety-sized-2.stderr rename src/test/ui/{ => object-safety}/object-safety-sized.rs (100%) rename src/test/ui/{ => object-safety}/object-safety-sized.stderr (100%) rename src/test/ui/{ => object-safety}/object-safety-supertrait-mentions-Self.rs (100%) rename src/test/ui/{ => object-safety}/object-safety-supertrait-mentions-Self.stderr (100%) rename src/test/{compile-fail => ui}/occurs-check-2.rs (100%) create mode 100644 src/test/ui/occurs-check-2.stderr rename src/test/{compile-fail => ui}/occurs-check-3.rs (100%) create mode 100644 src/test/ui/occurs-check-3.stderr rename src/test/{compile-fail => ui}/occurs-check.rs (100%) create mode 100644 src/test/ui/occurs-check.stderr rename src/test/{compile-fail => ui}/old-suffixes-are-really-forbidden.rs (100%) create mode 100644 src/test/ui/old-suffixes-are-really-forbidden.stderr rename src/test/{compile-fail => ui}/once-cant-call-twice-on-heap.rs (100%) create mode 100644 src/test/ui/once-cant-call-twice-on-heap.stderr rename src/test/{compile-fail => ui}/opt-in-copy.rs (100%) create mode 100644 src/test/ui/opt-in-copy.stderr rename src/test/{compile-fail => ui}/or-patter-mismatch.rs (100%) create mode 100644 src/test/ui/or-patter-mismatch.stderr rename src/test/{compile-fail => ui}/orphan-check-diagnostics.rs (100%) create mode 100644 src/test/ui/orphan-check-diagnostics.stderr rename src/test/{compile-fail => ui}/osx-frameworks.rs (100%) create mode 100644 src/test/ui/osx-frameworks.stderr rename src/test/{compile-fail => ui}/out-of-order-shadowing.rs (92%) create mode 100644 src/test/ui/out-of-order-shadowing.stderr rename src/test/{compile-fail => ui}/output-type-mismatch.rs (100%) create mode 100644 src/test/ui/output-type-mismatch.stderr rename src/test/{compile-fail => ui}/overlap-marker-trait.rs (100%) create mode 100644 src/test/ui/overlap-marker-trait.stderr rename src/test/{compile-fail => ui}/overloaded-calls-nontuple.rs (100%) create mode 100644 src/test/ui/overloaded-calls-nontuple.stderr rename src/test/{compile-fail => ui/packed-struct}/packed-struct-generic-transmute.rs (100%) create mode 100644 src/test/ui/packed-struct/packed-struct-generic-transmute.stderr rename src/test/{compile-fail => ui/packed-struct}/packed-struct-transmute.rs (95%) create mode 100644 src/test/ui/packed-struct/packed-struct-transmute.stderr create mode 100644 src/test/ui/panic-handler/auxiliary/some-panic-impl.rs create mode 100644 src/test/ui/panic-handler/panic-handler-bad-signature-1.rs create mode 100644 src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr create mode 100644 src/test/ui/panic-handler/panic-handler-bad-signature-2.rs create mode 100644 src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr create mode 100644 src/test/ui/panic-handler/panic-handler-bad-signature-3.rs create mode 100644 src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr create mode 100644 src/test/ui/panic-handler/panic-handler-bad-signature-4.rs create mode 100644 src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr create mode 100644 src/test/ui/panic-handler/panic-handler-duplicate.rs create mode 100644 src/test/ui/panic-handler/panic-handler-duplicate.stderr create mode 100644 src/test/ui/panic-handler/panic-handler-requires-panic-info.rs create mode 100644 src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr create mode 100644 src/test/ui/panic-handler/panic-handler-std.rs create mode 100644 src/test/ui/panic-handler/panic-handler-std.stderr create mode 100644 src/test/ui/panic-implementation/panic-implementation-deprecated.rs create mode 100644 src/test/ui/panic-implementation/panic-implementation-deprecated.stderr rename src/test/{compile-fail => ui}/panic-runtime/abort-link-to-unwind-dylib.rs (100%) create mode 100644 src/test/ui/panic-runtime/abort-link-to-unwind-dylib.stderr rename src/test/{compile-fail => ui}/panic-runtime/auxiliary/depends.rs (100%) rename src/test/{compile-fail => ui}/panic-runtime/auxiliary/needs-panic-runtime.rs (100%) rename src/test/{compile-fail => ui}/panic-runtime/auxiliary/panic-runtime-abort.rs (100%) create mode 100644 src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs create mode 100644 src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs create mode 100644 src/test/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs rename src/test/{compile-fail => ui}/panic-runtime/auxiliary/wants-panic-runtime-abort.rs (100%) create mode 100644 src/test/ui/panic-runtime/auxiliary/wants-panic-runtime-unwind.rs rename src/test/{compile-fail => ui}/panic-runtime/bad-panic-flag1.rs (100%) create mode 100644 src/test/ui/panic-runtime/bad-panic-flag1.stderr rename src/test/{compile-fail => ui}/panic-runtime/bad-panic-flag2.rs (100%) create mode 100644 src/test/ui/panic-runtime/bad-panic-flag2.stderr rename src/test/{compile-fail => ui}/panic-runtime/libtest-unwinds.rs (100%) create mode 100644 src/test/ui/panic-runtime/libtest-unwinds.stderr rename src/test/{compile-fail => ui}/panic-runtime/needs-gate.rs (100%) create mode 100644 src/test/ui/panic-runtime/needs-gate.stderr rename src/test/{compile-fail => ui}/panic-runtime/runtime-depend-on-needs-runtime.rs (100%) create mode 100644 src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.stderr rename src/test/{compile-fail => ui}/panic-runtime/transitive-link-a-bunch.rs (100%) create mode 100644 src/test/ui/panic-runtime/transitive-link-a-bunch.stderr rename src/test/{compile-fail => ui}/panic-runtime/want-unwind-got-abort.rs (100%) create mode 100644 src/test/ui/panic-runtime/want-unwind-got-abort.stderr rename src/test/{compile-fail => ui}/panic-runtime/want-unwind-got-abort2.rs (100%) create mode 100644 src/test/ui/panic-runtime/want-unwind-got-abort2.stderr rename src/test/{compile-fail => ui}/panic_implementation-closures.rs (91%) rename src/test/{compile-fail => ui}/paren-span.rs (100%) create mode 100644 src/test/ui/paren-span.stderr rename src/test/{compile-fail => ui}/parse-error-correct.rs (100%) create mode 100644 src/test/ui/parse-error-correct.stderr rename src/test/{compile-fail => ui}/parser-recovery-1.rs (78%) create mode 100644 src/test/ui/parser-recovery-1.stderr rename src/test/{compile-fail => ui}/parser-recovery-2.rs (100%) create mode 100644 src/test/ui/parser-recovery-2.stderr create mode 100644 src/test/ui/parser/unclosed-braces.rs create mode 100644 src/test/ui/parser/unclosed-braces.stderr rename src/test/{compile-fail => ui/pattern}/pat-shadow-in-nested-binding.rs (100%) create mode 100644 src/test/ui/pattern/pat-shadow-in-nested-binding.stderr rename src/test/{compile-fail => ui/pattern}/pat-tuple-bad-type.rs (100%) create mode 100644 src/test/ui/pattern/pat-tuple-bad-type.stderr rename src/test/{compile-fail => ui/pattern}/pat-tuple-overfield.rs (100%) create mode 100644 src/test/ui/pattern/pat-tuple-overfield.stderr rename src/test/{compile-fail => ui/pattern}/patkind-litrange-no-expr.rs (100%) create mode 100644 src/test/ui/pattern/patkind-litrange-no-expr.stderr rename src/test/{compile-fail => ui/pattern}/pattern-binding-disambiguation.rs (100%) create mode 100644 src/test/ui/pattern/pattern-binding-disambiguation.stderr rename src/test/{compile-fail => ui/pattern}/pattern-bindings-after-at.rs (100%) create mode 100644 src/test/ui/pattern/pattern-bindings-after-at.stderr rename src/test/{compile-fail => ui/pattern}/pattern-error-continue.rs (100%) create mode 100644 src/test/ui/pattern/pattern-error-continue.stderr rename src/test/{compile-fail => ui/pattern}/pattern-ident-path-generics.rs (100%) create mode 100644 src/test/ui/pattern/pattern-ident-path-generics.stderr rename src/test/{compile-fail => ui/pattern}/pattern-tyvar-2.rs (100%) create mode 100644 src/test/ui/pattern/pattern-tyvar-2.stderr rename src/test/{compile-fail => ui/pattern}/pattern-tyvar.rs (100%) create mode 100644 src/test/ui/pattern/pattern-tyvar.stderr rename src/test/{compile-fail => ui}/phantom-oibit.rs (100%) create mode 100644 src/test/ui/phantom-oibit.stderr rename src/test/{compile-fail => ui}/platform-intrinsic-params.rs (100%) create mode 100644 src/test/ui/platform-intrinsic-params.stderr rename src/test/{compile-fail => ui}/pptypedef.rs (100%) create mode 100644 src/test/ui/pptypedef.stderr rename src/test/{compile-fail => ui}/prim-with-args.rs (100%) create mode 100644 src/test/ui/prim-with-args.stderr rename src/test/{compile-fail => ui}/priv-in-bad-locations.rs (100%) create mode 100644 src/test/ui/priv-in-bad-locations.stderr rename src/test/{compile-fail => ui}/privacy/associated-item-privacy-inherent.rs (100%) create mode 100644 src/test/ui/privacy/associated-item-privacy-inherent.stderr rename src/test/{compile-fail => ui}/privacy/associated-item-privacy-trait.rs (100%) create mode 100644 src/test/ui/privacy/associated-item-privacy-trait.stderr rename src/test/{compile-fail => ui}/privacy/associated-item-privacy-type-binding.rs (100%) create mode 100644 src/test/ui/privacy/associated-item-privacy-type-binding.stderr rename src/test/{compile-fail => ui/privacy}/auxiliary/cci_class.rs (100%) rename src/test/{compile-fail => ui/privacy}/auxiliary/cci_class_5.rs (100%) rename src/test/{compile-fail => ui/privacy}/auxiliary/privacy_tuple_struct.rs (100%) rename src/test/{compile-fail => ui/privacy}/auxiliary/private-inferred-type.rs (100%) rename src/test/{compile-fail => ui}/privacy/legacy-ctor-visibility.rs (100%) create mode 100644 src/test/ui/privacy/legacy-ctor-visibility.stderr rename src/test/{compile-fail => ui/privacy}/privacy-in-paths.rs (100%) create mode 100644 src/test/ui/privacy/privacy-in-paths.stderr rename src/test/{compile-fail => ui/privacy}/privacy-ns1.rs (100%) create mode 100644 src/test/ui/privacy/privacy-ns1.stderr rename src/test/{compile-fail => ui/privacy}/privacy-ns2.rs (100%) create mode 100644 src/test/ui/privacy/privacy-ns2.stderr rename src/test/{compile-fail => ui/privacy}/privacy-sanity.rs (100%) create mode 100644 src/test/ui/privacy/privacy-sanity.stderr rename src/test/{compile-fail => ui/privacy}/privacy-ufcs.rs (100%) create mode 100644 src/test/ui/privacy/privacy-ufcs.stderr rename src/test/{compile-fail => ui/privacy}/privacy1.rs (100%) create mode 100644 src/test/ui/privacy/privacy1.stderr rename src/test/{compile-fail => ui/privacy}/privacy2.rs (100%) create mode 100644 src/test/ui/privacy/privacy2.stderr rename src/test/{compile-fail => ui/privacy}/privacy3.rs (100%) create mode 100644 src/test/ui/privacy/privacy3.stderr rename src/test/{compile-fail => ui/privacy}/privacy4.rs (100%) create mode 100644 src/test/ui/privacy/privacy4.stderr rename src/test/{compile-fail => ui/privacy}/privacy5.rs (100%) create mode 100644 src/test/ui/privacy/privacy5.stderr rename src/test/{compile-fail => ui/privacy}/private-impl-method.rs (100%) create mode 100644 src/test/ui/privacy/private-impl-method.stderr rename src/test/{compile-fail => ui/privacy}/private-in-public-assoc-ty.rs (100%) create mode 100644 src/test/ui/privacy/private-in-public-assoc-ty.stderr rename src/test/{compile-fail => ui/privacy}/private-in-public-ill-formed.rs (100%) create mode 100644 src/test/ui/privacy/private-in-public-ill-formed.stderr rename src/test/{compile-fail => ui/privacy}/private-in-public-lint.rs (100%) create mode 100644 src/test/ui/privacy/private-in-public-lint.stderr rename src/test/{compile-fail => ui/privacy}/private-in-public-warn.rs (100%) create mode 100644 src/test/ui/privacy/private-in-public-warn.stderr rename src/test/{compile-fail => ui/privacy}/private-in-public.rs (100%) create mode 100644 src/test/ui/privacy/private-in-public.stderr rename src/test/{compile-fail => ui/privacy}/private-inferred-type-1.rs (100%) create mode 100644 src/test/ui/privacy/private-inferred-type-1.stderr rename src/test/{compile-fail => ui/privacy}/private-inferred-type-2.rs (100%) create mode 100644 src/test/ui/privacy/private-inferred-type-2.stderr rename src/test/{compile-fail => ui/privacy}/private-inferred-type-3.rs (100%) create mode 100644 src/test/ui/privacy/private-inferred-type-3.stderr rename src/test/{compile-fail => ui/privacy}/private-inferred-type.rs (100%) create mode 100644 src/test/ui/privacy/private-inferred-type.stderr rename src/test/{compile-fail => ui/privacy}/private-item-simple.rs (100%) create mode 100644 src/test/ui/privacy/private-item-simple.stderr rename src/test/{compile-fail => ui/privacy}/private-method-cross-crate.rs (100%) create mode 100644 src/test/ui/privacy/private-method-cross-crate.stderr rename src/test/{compile-fail => ui/privacy}/private-method-inherited.rs (100%) create mode 100644 src/test/ui/privacy/private-method-inherited.stderr rename src/test/{compile-fail => ui/privacy}/private-method.rs (100%) create mode 100644 src/test/ui/privacy/private-method.stderr rename src/test/{compile-fail => ui/privacy}/private-struct-field-cross-crate.rs (100%) create mode 100644 src/test/ui/privacy/private-struct-field-cross-crate.stderr rename src/test/{compile-fail => ui/privacy}/private-struct-field-ctor.rs (100%) create mode 100644 src/test/ui/privacy/private-struct-field-ctor.stderr rename src/test/{compile-fail => ui/privacy}/private-struct-field-pattern.rs (100%) create mode 100644 src/test/ui/privacy/private-struct-field-pattern.stderr rename src/test/{compile-fail => ui/privacy}/private-struct-field.rs (100%) create mode 100644 src/test/ui/privacy/private-struct-field.stderr rename src/test/{compile-fail => ui/privacy}/private-type-in-interface.rs (100%) create mode 100644 src/test/ui/privacy/private-type-in-interface.stderr rename src/test/{compile-fail => ui/privacy}/private-variant-reexport.rs (100%) create mode 100644 src/test/ui/privacy/private-variant-reexport.stderr rename src/test/{compile-fail => ui}/privacy/restricted/auxiliary/pub_restricted.rs (100%) rename src/test/{compile-fail => ui}/privacy/restricted/lookup-ignores-private.rs (100%) create mode 100644 src/test/ui/privacy/restricted/lookup-ignores-private.stderr rename src/test/{compile-fail => ui}/privacy/restricted/private-in-public.rs (100%) create mode 100644 src/test/ui/privacy/restricted/private-in-public.stderr rename src/test/{compile-fail => ui}/privacy/restricted/struct-literal-field.rs (100%) create mode 100644 src/test/ui/privacy/restricted/struct-literal-field.stderr rename src/test/{compile-fail => ui}/privacy/restricted/test.rs (100%) create mode 100644 src/test/ui/privacy/restricted/test.stderr rename src/test/{compile-fail => ui}/privacy/union-field-privacy-1.rs (100%) create mode 100644 src/test/ui/privacy/union-field-privacy-1.stderr rename src/test/{compile-fail => ui}/privacy/union-field-privacy-2.rs (100%) create mode 100644 src/test/ui/privacy/union-field-privacy-2.stderr rename src/test/{compile-fail => ui}/ptr-coercion.rs (100%) create mode 100644 src/test/ui/ptr-coercion.stderr rename src/test/ui/{ => pub}/pub-ident-fn-2.rs (100%) rename src/test/ui/{ => pub}/pub-ident-fn-2.stderr (100%) rename src/test/ui/{ => pub}/pub-ident-fn-or-struct-2.rs (100%) rename src/test/ui/{ => pub}/pub-ident-fn-or-struct-2.stderr (100%) rename src/test/ui/{ => pub}/pub-ident-fn-or-struct.rs (100%) rename src/test/ui/{ => pub}/pub-ident-fn-or-struct.stderr (100%) rename src/test/ui/{ => pub}/pub-ident-fn.fixed (100%) rename src/test/ui/{ => pub}/pub-ident-fn.rs (100%) rename src/test/ui/{ => pub}/pub-ident-fn.stderr (100%) rename src/test/ui/{ => pub}/pub-ident-struct.rs (100%) rename src/test/ui/{ => pub}/pub-ident-struct.stderr (100%) rename src/test/{compile-fail => ui/pub}/pub-reexport-priv-extern-crate.rs (100%) create mode 100644 src/test/ui/pub/pub-reexport-priv-extern-crate.stderr rename src/test/ui/{ => qualified}/qualified-path-params-2.rs (100%) rename src/test/ui/{ => qualified}/qualified-path-params-2.stderr (100%) rename src/test/{compile-fail => ui/qualified}/qualified-path-params.rs (100%) create mode 100644 src/test/ui/qualified/qualified-path-params.stderr rename src/test/{compile-fail => ui}/question-mark-type-infer.rs (100%) create mode 100644 src/test/ui/question-mark-type-infer.stderr rename src/test/{compile-fail => ui}/quote-with-interpolated.rs (100%) create mode 100644 src/test/ui/quote-with-interpolated.stderr rename src/test/{compile-fail => ui/range}/range-1.rs (100%) create mode 100644 src/test/ui/range/range-1.stderr rename src/test/ui/{ => range}/range-inclusive-pattern-precedence.rs (100%) rename src/test/ui/{ => range}/range-inclusive-pattern-precedence.stderr (100%) rename src/test/{compile-fail => ui/range}/range_traits-1.rs (100%) create mode 100644 src/test/ui/range/range_traits-1.stderr rename src/test/{compile-fail => ui/range}/range_traits-2.rs (100%) create mode 100644 src/test/ui/range/range_traits-2.stderr rename src/test/{compile-fail => ui/range}/range_traits-3.rs (100%) create mode 100644 src/test/ui/range/range_traits-3.stderr rename src/test/{compile-fail => ui/range}/range_traits-4.rs (100%) create mode 100644 src/test/ui/range/range_traits-4.stderr rename src/test/{compile-fail => ui/range}/range_traits-5.rs (100%) create mode 100644 src/test/ui/range/range_traits-5.stderr rename src/test/{compile-fail => ui/range}/range_traits-6.rs (100%) create mode 100644 src/test/ui/range/range_traits-6.stderr rename src/test/{compile-fail => ui/range}/range_traits-7.rs (100%) create mode 100644 src/test/ui/range/range_traits-7.stderr rename src/test/ui/{ => raw}/raw-literal-keywords.rs (95%) rename src/test/ui/{ => raw}/raw-literal-keywords.stderr (83%) rename src/test/ui/{ => raw}/raw-literal-self.rs (95%) rename src/test/ui/{ => raw}/raw-literal-self.stderr (79%) rename src/test/ui/{ => raw}/raw-literal-underscore.rs (100%) rename src/test/ui/{ => raw}/raw-literal-underscore.stderr (100%) rename src/test/ui/{ => raw}/raw_string.rs (100%) rename src/test/ui/{ => raw}/raw_string.stderr (100%) rename src/test/{compile-fail => ui/recursion}/auxiliary/recursive_reexports.rs (100%) rename src/test/{compile-fail => ui/recursion}/recursion.rs (100%) create mode 100644 src/test/ui/recursion/recursion.stderr rename src/test/{compile-fail => ui/recursion}/recursive-enum.rs (100%) create mode 100644 src/test/ui/recursion/recursive-enum.stderr rename src/test/{compile-fail => ui/recursion}/recursive-reexports.rs (100%) create mode 100644 src/test/ui/recursion/recursive-reexports.stderr rename src/test/ui/{ => recursion}/recursive-requirements.rs (100%) rename src/test/ui/{ => recursion}/recursive-requirements.stderr (100%) rename src/test/{compile-fail => ui/recursion}/recursive-static-definition.rs (100%) create mode 100644 src/test/ui/recursion/recursive-static-definition.stderr rename src/test/{compile-fail => ui/recursion}/recursive-types-are-not-uninhabited.rs (100%) create mode 100644 src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr create mode 100644 src/test/ui/ref-suggestion.nll.stderr rename src/test/{compile-fail => ui}/ref-suggestion.rs (100%) create mode 100644 src/test/ui/ref-suggestion.stderr rename src/test/{compile-fail => ui}/refutable-pattern-errors.rs (100%) create mode 100644 src/test/ui/refutable-pattern-errors.stderr rename src/test/{compile-fail => ui}/refutable-pattern-in-fn-arg.rs (100%) create mode 100644 src/test/ui/refutable-pattern-in-fn-arg.stderr delete mode 100644 src/test/ui/region-borrow-params-issue-29793-small.nll.stderr rename src/test/{compile-fail/regions-fn-subtyping-return-static.rs => ui/regions-fn-subtyping-return-static-fail.rs} (100%) create mode 100644 src/test/ui/regions-fn-subtyping-return-static-fail.stderr delete mode 100644 src/test/ui/regions-nested-fns-2.nll.stderr rename src/test/{compile-fail => ui/regions}/auxiliary/rbmtp_cross_crate_lib.rs (100%) create mode 100644 src/test/ui/regions/region-borrow-params-issue-29793-big.ast.nll.stderr create mode 100644 src/test/ui/regions/region-borrow-params-issue-29793-big.ast.stderr create mode 100644 src/test/ui/regions/region-borrow-params-issue-29793-big.mir.stderr rename src/test/{compile-fail => ui/regions}/region-borrow-params-issue-29793-big.rs (100%) create mode 100644 src/test/ui/regions/region-borrow-params-issue-29793-small.nll.stderr rename src/test/ui/{ => regions}/region-borrow-params-issue-29793-small.rs (100%) rename src/test/ui/{ => regions}/region-borrow-params-issue-29793-small.stderr (100%) rename src/test/{compile-fail => ui/regions}/region-bound-extra-bound-in-inherent-impl.rs (100%) create mode 100644 src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.stderr create mode 100644 src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr rename src/test/{compile-fail => ui/regions}/region-bound-on-closure-outlives-call.rs (100%) create mode 100644 src/test/ui/regions/region-bound-on-closure-outlives-call.stderr rename src/test/{compile-fail => ui/regions}/region-bound-same-bounds-in-trait-and-impl.rs (100%) create mode 100644 src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.stderr rename src/test/{compile-fail => ui/regions}/region-bounds-on-objects-and-type-parameters.rs (100%) create mode 100644 src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr create mode 100644 src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr rename src/test/{compile-fail => ui/regions}/region-invariant-static-error-reporting.rs (100%) create mode 100644 src/test/ui/regions/region-invariant-static-error-reporting.stderr create mode 100644 src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr rename src/test/{compile-fail => ui/regions}/region-lifetime-bounds-on-fns-where-clause.rs (100%) create mode 100644 src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr create mode 100644 src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr rename src/test/{compile-fail => ui/regions}/region-multiple-lifetime-bounds-on-fns-where-clause.rs (100%) create mode 100644 src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr rename src/test/{compile-fail => ui/regions}/region-object-lifetime-1.rs (100%) create mode 100644 src/test/ui/regions/region-object-lifetime-1.stderr create mode 100644 src/test/ui/regions/region-object-lifetime-2.nll.stderr rename src/test/{compile-fail => ui/regions}/region-object-lifetime-2.rs (100%) create mode 100644 src/test/ui/regions/region-object-lifetime-2.stderr rename src/test/{compile-fail => ui/regions}/region-object-lifetime-3.rs (100%) create mode 100644 src/test/ui/regions/region-object-lifetime-3.stderr create mode 100644 src/test/ui/regions/region-object-lifetime-4.nll.stderr rename src/test/{compile-fail => ui/regions}/region-object-lifetime-4.rs (100%) create mode 100644 src/test/ui/regions/region-object-lifetime-4.stderr create mode 100644 src/test/ui/regions/region-object-lifetime-5.nll.stderr rename src/test/{compile-fail => ui/regions}/region-object-lifetime-5.rs (100%) create mode 100644 src/test/ui/regions/region-object-lifetime-5.stderr create mode 100644 src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr rename src/test/{compile-fail => ui/regions}/region-object-lifetime-in-coercion.rs (100%) create mode 100644 src/test/ui/regions/region-object-lifetime-in-coercion.stderr create mode 100644 src/test/ui/regions/regions-addr-of-arg.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-addr-of-arg.rs (100%) create mode 100644 src/test/ui/regions/regions-addr-of-arg.stderr create mode 100644 src/test/ui/regions/regions-addr-of-self.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-addr-of-self.rs (100%) create mode 100644 src/test/ui/regions/regions-addr-of-self.stderr create mode 100644 src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-addr-of-upvar-self.rs (100%) create mode 100644 src/test/ui/regions/regions-addr-of-upvar-self.stderr create mode 100644 src/test/ui/regions/regions-adjusted-lvalue-op.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-adjusted-lvalue-op.rs (100%) create mode 100644 src/test/ui/regions/regions-adjusted-lvalue-op.stderr rename src/test/{compile-fail => ui/regions}/regions-assoc-type-in-supertrait-outlives-container.rs (98%) create mode 100644 src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr rename src/test/{compile-fail => ui/regions}/regions-assoc-type-region-bound-in-trait-not-met.rs (100%) create mode 100644 src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr rename src/test/{compile-fail => ui/regions}/regions-assoc-type-static-bound-in-trait-not-met.rs (100%) create mode 100644 src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr rename src/test/{compile-fail => ui/regions}/regions-bounded-by-trait-requiring-static.rs (98%) create mode 100644 src/test/ui/regions/regions-bounded-by-trait-requiring-static.stderr create mode 100644 src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-bounded-method-type-parameters-cross-crate.rs (100%) create mode 100644 src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr create mode 100644 src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-bounded-method-type-parameters-trait-bound.rs (100%) create mode 100644 src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr rename src/test/{compile-fail => ui/regions}/regions-bounded-method-type-parameters.rs (96%) create mode 100644 src/test/ui/regions/regions-bounded-method-type-parameters.stderr create mode 100644 src/test/ui/regions/regions-bounds.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-bounds.rs (100%) create mode 100644 src/test/ui/regions/regions-bounds.stderr create mode 100644 src/test/ui/regions/regions-close-associated-type-into-object.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-associated-type-into-object.rs (100%) create mode 100644 src/test/ui/regions/regions-close-associated-type-into-object.stderr create mode 100644 src/test/ui/regions/regions-close-object-into-object-1.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-object-into-object-1.rs (100%) create mode 100644 src/test/ui/regions/regions-close-object-into-object-1.stderr create mode 100644 src/test/ui/regions/regions-close-object-into-object-2.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-object-into-object-2.rs (100%) create mode 100644 src/test/ui/regions/regions-close-object-into-object-2.stderr create mode 100644 src/test/ui/regions/regions-close-object-into-object-3.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-object-into-object-3.rs (100%) create mode 100644 src/test/ui/regions/regions-close-object-into-object-3.stderr create mode 100644 src/test/ui/regions/regions-close-object-into-object-4.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-object-into-object-4.rs (100%) create mode 100644 src/test/ui/regions/regions-close-object-into-object-4.stderr create mode 100644 src/test/ui/regions/regions-close-object-into-object-5.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-object-into-object-5.rs (100%) create mode 100644 src/test/ui/regions/regions-close-object-into-object-5.stderr create mode 100644 src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-over-type-parameter-1.rs (100%) create mode 100644 src/test/ui/regions/regions-close-over-type-parameter-1.stderr create mode 100644 src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-over-type-parameter-multiple.rs (100%) create mode 100644 src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr create mode 100644 src/test/ui/regions/regions-close-param-into-object.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-close-param-into-object.rs (100%) create mode 100644 src/test/ui/regions/regions-close-param-into-object.stderr create mode 100644 src/test/ui/regions/regions-creating-enums.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-creating-enums.rs (100%) create mode 100644 src/test/ui/regions/regions-creating-enums.stderr create mode 100644 src/test/ui/regions/regions-creating-enums3.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-creating-enums3.rs (100%) create mode 100644 src/test/ui/regions/regions-creating-enums3.stderr create mode 100644 src/test/ui/regions/regions-creating-enums4.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-creating-enums4.rs (100%) create mode 100644 src/test/ui/regions/regions-creating-enums4.stderr create mode 100644 src/test/ui/regions/regions-early-bound-error-method.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-early-bound-error-method.rs (100%) create mode 100644 src/test/ui/regions/regions-early-bound-error-method.stderr create mode 100644 src/test/ui/regions/regions-early-bound-error.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-early-bound-error.rs (100%) create mode 100644 src/test/ui/regions/regions-early-bound-error.stderr create mode 100644 src/test/ui/regions/regions-enum-not-wf.rs create mode 100644 src/test/ui/regions/regions-enum-not-wf.stderr create mode 100644 src/test/ui/regions/regions-escape-method.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-escape-method.rs (100%) create mode 100644 src/test/ui/regions/regions-escape-method.stderr create mode 100644 src/test/ui/regions/regions-escape-via-trait-or-not.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-escape-via-trait-or-not.rs (100%) create mode 100644 src/test/ui/regions/regions-escape-via-trait-or-not.stderr rename src/test/ui/{ => regions}/regions-fn-subtyping-return-static.rs (100%) rename src/test/ui/{ => regions}/regions-fn-subtyping-return-static.stderr (100%) rename src/test/{compile-fail => ui/regions}/regions-free-region-ordering-callee-4.rs (100%) create mode 100644 src/test/ui/regions/regions-free-region-ordering-callee-4.stderr create mode 100644 src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-free-region-ordering-callee.rs (100%) create mode 100644 src/test/ui/regions/regions-free-region-ordering-callee.stderr rename src/test/{compile-fail => ui/regions}/regions-free-region-ordering-caller.rs (97%) create mode 100644 src/test/ui/regions/regions-free-region-ordering-caller.stderr create mode 100644 src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-free-region-ordering-caller1.rs (100%) create mode 100644 src/test/ui/regions/regions-free-region-ordering-caller1.stderr create mode 100644 src/test/ui/regions/regions-free-region-ordering-incorrect.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-free-region-ordering-incorrect.rs (100%) create mode 100644 src/test/ui/regions/regions-free-region-ordering-incorrect.stderr rename src/test/{compile-fail => ui/regions}/regions-glb-free-free.rs (100%) create mode 100644 src/test/ui/regions/regions-glb-free-free.stderr rename src/test/{compile-fail => ui/regions}/regions-implied-bounds-projection-gap-1.rs (97%) create mode 100644 src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr rename src/test/{compile-fail => ui/regions}/regions-implied-bounds-projection-gap-2.rs (100%) create mode 100644 src/test/ui/regions/regions-implied-bounds-projection-gap-2.stderr rename src/test/{compile-fail => ui/regions}/regions-implied-bounds-projection-gap-3.rs (100%) create mode 100644 src/test/ui/regions/regions-implied-bounds-projection-gap-3.stderr rename src/test/{compile-fail => ui/regions}/regions-implied-bounds-projection-gap-4.rs (100%) create mode 100644 src/test/ui/regions/regions-implied-bounds-projection-gap-4.stderr rename src/test/{compile-fail => ui/regions}/regions-implied-bounds-projection-gap-hr-1.rs (100%) create mode 100644 src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr rename src/test/{compile-fail => ui/regions}/regions-in-enums-anon.rs (100%) create mode 100644 src/test/ui/regions/regions-in-enums-anon.stderr rename src/test/{compile-fail => ui/regions}/regions-in-enums.rs (100%) create mode 100644 src/test/ui/regions/regions-in-enums.stderr rename src/test/{compile-fail => ui/regions}/regions-in-structs-anon.rs (100%) create mode 100644 src/test/ui/regions/regions-in-structs-anon.stderr rename src/test/{compile-fail => ui/regions}/regions-in-structs.rs (100%) create mode 100644 src/test/ui/regions/regions-in-structs.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-at-fn-not-param.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-at-fn-not-param.stderr create mode 100644 src/test/ui/regions/regions-infer-borrow-scope-too-big.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-borrow-scope-too-big.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-borrow-scope-too-big.stderr create mode 100644 src/test/ui/regions/regions-infer-bound-from-trait-self.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-bound-from-trait-self.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-bound-from-trait-self.stderr create mode 100644 src/test/ui/regions/regions-infer-bound-from-trait.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-bound-from-trait.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-bound-from-trait.stderr create mode 100644 src/test/ui/regions/regions-infer-call-3.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-call-3.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-call-3.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-contravariance-due-to-decl.rs (98%) create mode 100644 src/test/ui/regions/regions-infer-contravariance-due-to-decl.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-covariance-due-to-decl.rs (97%) create mode 100644 src/test/ui/regions/regions-infer-covariance-due-to-decl.stderr create mode 100644 src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-invariance-due-to-decl.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr create mode 100644 src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-invariance-due-to-mutability-3.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr create mode 100644 src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-invariance-due-to-mutability-4.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr create mode 100644 src/test/ui/regions/regions-infer-not-param.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-not-param.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-not-param.stderr create mode 100644 src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-paramd-indirect.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-paramd-indirect.stderr create mode 100644 src/test/ui/regions/regions-infer-proc-static-upvar.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-infer-proc-static-upvar.rs (100%) create mode 100644 src/test/ui/regions/regions-infer-proc-static-upvar.stderr create mode 100644 src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-lifetime-bounds-on-fns.rs (100%) create mode 100644 src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr rename src/test/{compile-fail => ui/regions}/regions-lifetime-of-struct-or-enum-variant.rs (100%) create mode 100644 src/test/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr rename src/test/{compile-fail => ui/regions}/regions-name-duplicated.rs (100%) create mode 100644 src/test/ui/regions/regions-name-duplicated.stderr rename src/test/{compile-fail => ui/regions}/regions-name-static.rs (100%) create mode 100644 src/test/ui/regions/regions-name-static.stderr rename src/test/{compile-fail => ui/regions}/regions-name-undeclared.rs (100%) create mode 100644 src/test/ui/regions/regions-name-undeclared.stderr create mode 100644 src/test/ui/regions/regions-nested-fns-2.nll.stderr rename src/test/ui/{ => regions}/regions-nested-fns-2.rs (100%) rename src/test/ui/{ => regions}/regions-nested-fns-2.stderr (100%) create mode 100644 src/test/ui/regions/regions-nested-fns.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-nested-fns.rs (100%) create mode 100644 src/test/ui/regions/regions-nested-fns.stderr rename src/test/{compile-fail => ui/regions}/regions-normalize-in-where-clause-list.rs (100%) create mode 100644 src/test/ui/regions/regions-normalize-in-where-clause-list.stderr rename src/test/{compile-fail => ui/regions}/regions-outlives-nominal-type-enum-region-rev.rs (90%) rename src/test/{compile-fail => ui/regions}/regions-outlives-nominal-type-enum-region.rs (90%) rename src/test/{compile-fail => ui/regions}/regions-outlives-nominal-type-enum-type-rev.rs (86%) rename src/test/{compile-fail => ui/regions}/regions-outlives-nominal-type-enum-type.rs (90%) rename src/test/{compile-fail => ui/regions}/regions-outlives-nominal-type-struct-region-rev.rs (90%) rename src/test/{compile-fail => ui/regions}/regions-outlives-nominal-type-struct-region.rs (98%) rename src/test/{compile-fail => ui/regions}/regions-outlives-nominal-type-struct-type-rev.rs (98%) rename src/test/{compile-fail => ui/regions}/regions-outlives-nominal-type-struct-type.rs (98%) create mode 100644 src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-outlives-projection-container-hrtb.rs (100%) create mode 100644 src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr rename src/test/{compile-fail => ui/regions}/regions-outlives-projection-container-wc.rs (98%) create mode 100644 src/test/ui/regions/regions-outlives-projection-container-wc.stderr rename src/test/{compile-fail => ui/regions}/regions-outlives-projection-container.rs (97%) create mode 100644 src/test/ui/regions/regions-outlives-projection-container.stderr rename src/test/{compile-fail => ui/regions}/regions-outlives-projection-hrtype.rs (100%) create mode 100644 src/test/ui/regions/regions-outlives-projection-hrtype.stderr rename src/test/{compile-fail => ui/regions}/regions-outlives-projection-trait-def.rs (100%) create mode 100644 src/test/ui/regions/regions-outlives-projection-trait-def.stderr rename src/test/{compile-fail => ui/regions}/regions-outlives-scalar.rs (100%) create mode 100644 src/test/ui/regions/regions-outlives-scalar.stderr create mode 100644 src/test/ui/regions/regions-pattern-typing-issue-19552.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-pattern-typing-issue-19552.rs (100%) create mode 100644 src/test/ui/regions/regions-pattern-typing-issue-19552.stderr create mode 100644 src/test/ui/regions/regions-pattern-typing-issue-19997.ast.nll.stderr create mode 100644 src/test/ui/regions/regions-pattern-typing-issue-19997.ast.stderr create mode 100644 src/test/ui/regions/regions-pattern-typing-issue-19997.mir.stderr rename src/test/{compile-fail => ui/regions}/regions-pattern-typing-issue-19997.rs (100%) rename src/test/{compile-fail => ui/regions}/regions-proc-bound-capture.rs (100%) create mode 100644 src/test/ui/regions/regions-proc-bound-capture.stderr create mode 100644 src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-reborrow-from-shorter-mut-ref-mut-ref.rs (100%) create mode 100644 src/test/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr create mode 100644 src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-reborrow-from-shorter-mut-ref.rs (100%) create mode 100644 src/test/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr create mode 100644 src/test/ui/regions/regions-ref-in-fn-arg.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-ref-in-fn-arg.rs (100%) create mode 100644 src/test/ui/regions/regions-ref-in-fn-arg.stderr create mode 100644 src/test/ui/regions/regions-ret-borrowed-1.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-ret-borrowed-1.rs (100%) create mode 100644 src/test/ui/regions/regions-ret-borrowed-1.stderr create mode 100644 src/test/ui/regions/regions-ret-borrowed.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-ret-borrowed.rs (100%) create mode 100644 src/test/ui/regions/regions-ret-borrowed.stderr create mode 100644 src/test/ui/regions/regions-ret.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-ret.rs (100%) create mode 100644 src/test/ui/regions/regions-ret.stderr create mode 100644 src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-return-ref-to-upvar-issue-17403.rs (100%) create mode 100644 src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr rename src/test/{compile-fail => ui/regions}/regions-return-stack-allocated-vec.rs (100%) create mode 100644 src/test/ui/regions/regions-return-stack-allocated-vec.stderr create mode 100644 src/test/ui/regions/regions-static-bound.ll.nll.stderr create mode 100644 src/test/ui/regions/regions-static-bound.ll.stderr create mode 100644 src/test/ui/regions/regions-static-bound.nll.stderr create mode 100644 src/test/ui/regions/regions-static-bound.rs create mode 100644 src/test/ui/regions/regions-steal-closure.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-steal-closure.rs (100%) create mode 100644 src/test/ui/regions/regions-steal-closure.stderr create mode 100644 src/test/ui/regions/regions-struct-not-wf.rs create mode 100644 src/test/ui/regions/regions-struct-not-wf.stderr rename src/test/{compile-fail => ui/regions}/regions-trait-1.rs (100%) create mode 100644 src/test/ui/regions/regions-trait-1.stderr create mode 100644 src/test/ui/regions/regions-trait-object-subtyping.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-trait-object-subtyping.rs (100%) create mode 100644 src/test/ui/regions/regions-trait-object-subtyping.stderr create mode 100644 src/test/ui/regions/regions-trait-variance.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-trait-variance.rs (100%) create mode 100644 src/test/ui/regions/regions-trait-variance.stderr rename src/test/{compile-fail => ui/regions}/regions-undeclared.rs (100%) create mode 100644 src/test/ui/regions/regions-undeclared.stderr create mode 100644 src/test/ui/regions/regions-var-type-out-of-scope.nll.stderr rename src/test/{compile-fail => ui/regions}/regions-var-type-out-of-scope.rs (100%) create mode 100644 src/test/ui/regions/regions-var-type-out-of-scope.stderr rename src/test/{compile-fail => ui/regions}/regions-variance-contravariant-use-covariant-in-second-position.rs (97%) create mode 100644 src/test/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr rename src/test/{compile-fail => ui/regions}/regions-variance-contravariant-use-covariant.rs (97%) create mode 100644 src/test/ui/regions/regions-variance-contravariant-use-covariant.stderr rename src/test/{compile-fail => ui/regions}/regions-variance-covariant-use-contravariant.rs (97%) create mode 100644 src/test/ui/regions/regions-variance-covariant-use-contravariant.stderr rename src/test/{compile-fail => ui/regions}/regions-variance-invariant-use-contravariant.rs (97%) create mode 100644 src/test/ui/regions/regions-variance-invariant-use-contravariant.stderr rename src/test/{compile-fail => ui/regions}/regions-variance-invariant-use-covariant.rs (97%) create mode 100644 src/test/ui/regions/regions-variance-invariant-use-covariant.stderr rename src/test/{compile-fail => ui/regions}/regions-wf-trait-object.rs (100%) create mode 100644 src/test/ui/regions/regions-wf-trait-object.stderr rename src/test/{compile-fail => ui}/reject-specialized-drops-8142.rs (100%) create mode 100644 src/test/ui/reject-specialized-drops-8142.stderr rename src/test/{compile-fail => ui}/repeat-to-run-dtor-twice.rs (100%) create mode 100644 src/test/ui/repeat-to-run-dtor-twice.stderr rename src/test/{compile-fail => ui}/repeat_count.rs (100%) create mode 100644 src/test/ui/repeat_count.stderr rename src/test/ui/{ => repr}/repr-align-assign.fixed (100%) rename src/test/ui/{ => repr}/repr-align-assign.rs (100%) rename src/test/ui/{ => repr}/repr-align-assign.stderr (100%) rename src/test/{compile-fail => ui/repr}/repr-align.rs (100%) create mode 100644 src/test/ui/repr/repr-align.stderr rename src/test/{compile-fail => ui/repr}/repr-packed-contains-align.rs (100%) create mode 100644 src/test/ui/repr/repr-packed-contains-align.stderr rename src/test/{compile-fail => ui/repr}/repr-transparent-other-items.rs (98%) create mode 100644 src/test/ui/repr/repr-transparent-other-items.stderr rename src/test/{compile-fail => ui/repr}/repr-transparent-other-reprs.rs (95%) create mode 100644 src/test/ui/repr/repr-transparent-other-reprs.stderr rename src/test/{compile-fail => ui/repr}/repr-transparent.rs (97%) create mode 100644 src/test/ui/repr/repr-transparent.stderr rename src/test/{compile-fail => ui}/required-lang-item.rs (100%) create mode 100644 src/test/ui/required-lang-item.stderr rename src/test/{compile-fail => ui/reserved}/reserved-attr-on-macro.rs (100%) create mode 100644 src/test/ui/reserved/reserved-attr-on-macro.stderr rename src/test/{compile-fail => ui/reserved}/reserved-become.rs (100%) create mode 100644 src/test/ui/reserved/reserved-become.stderr rename src/test/{compile-fail => ui/resolve}/resolve-bad-import-prefix.rs (100%) create mode 100644 src/test/ui/resolve/resolve-bad-import-prefix.stderr rename src/test/{compile-fail => ui/resolve}/resolve-bad-visibility.rs (100%) create mode 100644 src/test/ui/resolve/resolve-bad-visibility.stderr rename src/test/{compile-fail => ui/resolve}/resolve-conflict-extern-crate-vs-extern-crate.rs (100%) create mode 100644 src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr rename src/test/{compile-fail => ui/resolve}/resolve-conflict-import-vs-extern-crate.rs (100%) create mode 100644 src/test/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr rename src/test/{compile-fail => ui/resolve}/resolve-conflict-import-vs-import.rs (100%) create mode 100644 src/test/ui/resolve/resolve-conflict-import-vs-import.stderr rename src/test/{compile-fail => ui/resolve}/resolve-conflict-item-vs-extern-crate.rs (100%) create mode 100644 src/test/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr rename src/test/ui/{ => resolve}/resolve-conflict-item-vs-import.rs (100%) rename src/test/ui/{ => resolve}/resolve-conflict-item-vs-import.stderr (100%) rename src/test/{compile-fail => ui/resolve}/resolve-conflict-type-vs-import.rs (100%) create mode 100644 src/test/ui/resolve/resolve-conflict-type-vs-import.stderr rename src/test/{compile-fail => ui/resolve}/resolve-inconsistent-binding-mode.rs (100%) create mode 100644 src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr rename src/test/ui/{ => resolve}/resolve-inconsistent-names.rs (100%) rename src/test/ui/{ => resolve}/resolve-inconsistent-names.stderr (100%) rename src/test/{compile-fail => ui/resolve}/resolve-label.rs (100%) create mode 100644 src/test/ui/resolve/resolve-label.stderr rename src/test/{compile-fail => ui/resolve}/resolve-primitive-fallback.rs (100%) create mode 100644 src/test/ui/resolve/resolve-primitive-fallback.stderr rename src/test/{compile-fail => ui/resolve}/resolve-self-in-impl-2.rs (100%) create mode 100644 src/test/ui/resolve/resolve-self-in-impl-2.stderr rename src/test/{compile-fail => ui/resolve}/resolve-self-in-impl.rs (100%) create mode 100644 src/test/ui/resolve/resolve-self-in-impl.stderr rename src/test/{compile-fail => ui/resolve}/resolve-type-param-in-item-in-trait.rs (100%) create mode 100644 src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr rename src/test/{compile-fail => ui/resolve}/resolve-unknown-trait.rs (98%) create mode 100644 src/test/ui/resolve/resolve-unknown-trait.stderr rename src/test/{compile-fail => ui/resolve}/resolve-variant-assoc-item.rs (100%) create mode 100644 src/test/ui/resolve/resolve-variant-assoc-item.stderr rename src/test/{compile-fail => ui}/resolve_self_super_hint.rs (98%) create mode 100644 src/test/ui/resolve_self_super_hint.stderr rename src/test/{compile-fail => ui}/ret-non-nil.rs (100%) create mode 100644 src/test/ui/ret-non-nil.stderr rename src/test/{compile-fail => ui}/retslot-cast.rs (100%) create mode 100644 src/test/ui/retslot-cast.stderr rename src/test/{compile-fail => ui/return}/return-from-diverging.rs (100%) create mode 100644 src/test/ui/return/return-from-diverging.stderr rename src/test/ui/{ => return}/return-match-array-const.rs (100%) rename src/test/ui/{ => return}/return-match-array-const.stderr (100%) rename src/test/ui/{ => return}/return-type.rs (100%) rename src/test/ui/{ => return}/return-type.stderr (100%) rename src/test/{compile-fail => ui/return}/return-unit-from-diverging.rs (100%) create mode 100644 src/test/ui/return/return-unit-from-diverging.stderr rename src/test/{compile-fail => ui}/rfc-1937-termination-trait/termination-trait-main-i32.rs (100%) create mode 100644 src/test/ui/rfc-1937-termination-trait/termination-trait-main-i32.stderr rename src/test/{compile-fail => ui}/rfc-1937-termination-trait/termination-trait-not-satisfied.rs (100%) create mode 100644 src/test/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr rename src/test/{compile-fail => ui}/rfc-2008-non-exhaustive/auxiliary/enums.rs (100%) rename src/test/{compile-fail => ui}/rfc-2008-non-exhaustive/auxiliary/structs.rs (100%) rename src/test/{compile-fail => ui}/rfc-2008-non-exhaustive/auxiliary/variants.rs (100%) rename src/test/{compile-fail => ui}/rfc-2008-non-exhaustive/enum.rs (100%) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/enum.stderr rename src/test/{compile-fail => ui}/rfc-2008-non-exhaustive/invalid-attribute.rs (100%) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr rename src/test/{compile-fail => ui}/rfc-2008-non-exhaustive/structs.rs (100%) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/structs.stderr rename src/test/{compile-fail => ui}/rfc-2008-non-exhaustive/variants.rs (100%) rename src/test/{compile-fail => ui}/rfc-2008-non-exhaustive/variants_create.rs (100%) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/variants_create.stderr create mode 100644 src/test/ui/rfc-2093-infer-outlives/privacy.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr rename src/test/{compile-fail => ui}/rfc-2126-crate-paths/crate-path-non-absolute.rs (91%) create mode 100644 src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr rename src/test/{compile-fail => ui}/rfc-2126-crate-paths/keyword-crate-as-identifier.rs (83%) create mode 100644 src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr rename src/test/{compile-fail => ui}/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs (100%) create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/meta.rs create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr rename src/test/{compile-fail => ui}/rfc-2126-extern-in-paths/auxiliary/xcrate.rs (100%) create mode 100644 src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs create mode 100644 src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr create mode 100644 src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs create mode 100644 src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr create mode 100644 src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs create mode 100644 src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr create mode 100644 src/test/ui/rfc-2126-extern-in-paths/single-segment.rs create mode 100644 src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr create mode 100644 src/test/ui/rfc-2306/convert-id-const-no-gate.rs create mode 100644 src/test/ui/rfc-2306/convert-id-const-no-gate.stderr create mode 100644 src/test/ui/rfc-2306/convert-id-const-with-gate.rs create mode 100644 src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs create mode 100644 src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr create mode 100644 src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs create mode 100644 src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr create mode 100644 src/test/ui/rfc1445/feature-gate.no_gate.stderr rename src/test/{compile-fail => ui}/rfc1445/feature-gate.rs (100%) create mode 100644 src/test/ui/rfc1445/feature-gate.with_gate.stderr rename src/test/{compile-fail => ui}/rfc1445/match-forbidden-without-eq.rs (100%) create mode 100644 src/test/ui/rfc1445/match-forbidden-without-eq.stderr rename src/test/{compile-fail => ui}/rfc1445/match-requires-both-partialeq-and-eq.rs (100%) create mode 100644 src/test/ui/rfc1445/match-requires-both-partialeq-and-eq.stderr create mode 100644 src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs create mode 100644 src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr create mode 100644 src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr create mode 100644 src/test/ui/rfc1598-generic-associated-types/shadowing.stderr rename src/test/{compile-fail => ui}/rfc1623.rs (100%) create mode 100644 src/test/ui/rfc1623.stderr rename src/test/{compile-fail => ui}/rfc1717/missing-link-attr.rs (100%) create mode 100644 src/test/ui/rfc1717/missing-link-attr.stderr rename src/test/{compile-fail => ui}/rfc1717/multiple-renames.rs (100%) create mode 100644 src/test/ui/rfc1717/multiple-renames.stderr rename src/test/{compile-fail => ui}/rfc1717/rename-to-empty.rs (100%) create mode 100644 src/test/ui/rfc1717/rename-to-empty.stderr rename src/test/{compile-fail => ui}/rmeta-lib-pass.rs (100%) rename src/test/{compile-fail => ui}/rmeta-pass.rs (100%) rename src/test/{compile-fail => ui}/rmeta-priv-warn.rs (100%) rename src/test/{compile-fail => ui}/rmeta.rs (100%) create mode 100644 src/test/ui/rmeta.stderr rename src/test/{compile-fail => ui}/rmeta_lib.rs (100%) create mode 100644 src/test/ui/rmeta_lib.stderr rename src/test/{compile-fail => ui}/rmeta_meta_main.rs (100%) create mode 100644 src/test/ui/rmeta_meta_main.stderr rename src/test/{ => ui}/run-pass/allocator/auxiliary/custom-as-global.rs (100%) create mode 100644 src/test/ui/run-pass/allocator/auxiliary/custom.rs rename src/test/{ => ui}/run-pass/allocator/auxiliary/helper.rs (100%) create mode 100644 src/test/ui/run-pass/allocator/custom.rs rename src/test/{ => ui}/run-pass/allocator/xcrate-use.rs (99%) rename src/test/{ => ui}/run-pass/allocator/xcrate-use2.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/arr_cycle.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/array_const_index-1.rs (94%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/box-of-array-of-drop-1.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/box-of-array-of-drop-2.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/cast-in-array-size.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/check-static-mut-slices.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/check-static-slice.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/copy-out-of-array-1.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/destructure-array-1.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/empty-mutable-vec.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/estr-slice.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/evec-slice.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/fixed_length_copy.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/huge-largest-array.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/ivec-pass-by-value.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/mutability-inherits-through-fixed-length-vec.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/mutable-alias-vec.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/nested-vec-1.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/nested-vec-2.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/nested-vec-3.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/new-style-fixed-length-vec.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/rcvr-borrowed-to-slice.rs (95%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/repeated-vector-syntax.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/show-boxed-slice.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/slice-2.rs (99%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/slice-of-zero-size-elements.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/slice-panic-1.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/slice-panic-2.rs (98%) create mode 100644 src/test/ui/run-pass/array-slice-vec/slice.rs rename src/test/{run-pass => ui/run-pass/array-slice-vec}/slice_binary_search.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/variance-vec-covariant.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-concat.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-dst.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-fixed-length.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-growth.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-late-init.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-macro-no-std.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-macro-repeat.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-macro-rvalue-scope.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-macro-with-brackets.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-macro-with-trailing-comma.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-matching-autoslice.rs (92%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-matching-fixed.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-matching-fold.rs (99%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-matching-legal-tail-element-borrow.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-matching.rs (99%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-push.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-repeat-with-cast.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-slice-drop.rs (95%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-slice.rs (97%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-tail-matching.rs (99%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec-to_str.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec_cycle.rs (98%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vec_cycle_wrapped.rs (99%) rename src/test/{run-pass => ui/run-pass/array-slice-vec}/vector-no-ann-2.rs (95%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-const-eval.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-cross-crate-const-eval.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-cross-crate-defaults.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-in-global-const.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-inherent-impl.rs (97%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-marks-live-code.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-match-patterns.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-outer-ty-refs.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-overwrite-default.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-public-impl.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-range-match-patterns.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-resolution-order.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-self-type.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-type-parameters.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-ufcs-infer-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-use-default.rs (97%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const-use-impl-of-same-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/associated-const.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-consts}/auxiliary/associated-const-cc-lib.rs (100%) rename src/test/{run-pass => ui/run-pass/associated-consts}/auxiliary/empty-struct.rs (100%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-basic.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-binding-in-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-binding-in-where-clause.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-cc.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-conditional-dispatch.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-constant-type.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-doubleendediterator-object.rs (96%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-duplicate-binding-in-env-hrtb.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-duplicate-binding-in-env.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-enum-field-named.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-enum-field-numbered.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-eq-obj.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-impl-redirect.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-in-bound-type-arg.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-in-default-method.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-in-fn.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-in-impl-generics.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-in-inherent-method.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-issue-20220.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-issue-20371.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-issue-21212.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-iterator-binding.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-method.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-nested-projections.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-normalize-in-bounds-binding.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-normalize-in-bounds-ufcs.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-normalize-in-bounds.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-normalize-unifield-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-project-from-type-param-via-bound-in-where.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-projection-bound-in-supertraits.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-projection-from-known-type-in-impl.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-projection-in-object-type.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-projection-in-supertrait.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-projection-in-where-clause.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-projection-to-unrelated-trait.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-qualified-path-with-trait-with-type-parameters.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-ref-from-struct.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-ref-in-struct-literal.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-region-erasure-issue-20582.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-resolve-lifetime.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-return.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-simple.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-stream.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-struct-field-named.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-struct-field-numbered.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-sugar-path.rs (98%) rename src/test/{run-pass => ui/run-pass/associated-types}/associated-types-where-clause-impl-ambiguity.rs (99%) rename src/test/{run-pass => ui/run-pass/associated-types}/auxiliary/associated-types-cc-lib.rs (100%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/auto-ref-bounded-ty-param.rs (98%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/auto-ref-sliceable.rs (98%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/auto-ref.rs (98%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/autoderef-and-borrow-method-receiver.rs (98%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/autoderef-method-on-trait.rs (94%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/autoderef-method-priority.rs (94%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/autoderef-method-twice-but-not-thrice.rs (94%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/autoderef-method-twice.rs (94%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/autoderef-method.rs (94%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/autoderef-privacy.rs (99%) rename src/test/{run-pass => ui/run-pass/autoref-autoderef}/autoref-intermediate-types-issue-3585.rs (96%) rename src/test/{ => ui}/run-pass/bench/issue-32062.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/allow_irrefutable_let_patterns.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/bind-field-short-with-modifiers.rs (94%) rename src/test/{run-pass => ui/run-pass/binding}/borrowed-ptr-pattern-2.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/borrowed-ptr-pattern-3.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/borrowed-ptr-pattern-infallible.rs (97%) rename src/test/{run-pass => ui/run-pass/binding}/borrowed-ptr-pattern-option.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/borrowed-ptr-pattern.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/empty-types-in-patterns.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/exhaustive-bool-match-sanity.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/expr-match-generic-unique1.rs (96%) rename src/test/{run-pass => ui/run-pass/binding}/expr-match-generic-unique2.rs (96%) rename src/test/{run-pass => ui/run-pass/binding}/expr-match-generic.rs (96%) rename src/test/{run-pass => ui/run-pass/binding}/expr-match-panic-all.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/expr-match-panic.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/expr-match-unique.rs (96%) rename src/test/{run-pass => ui/run-pass/binding}/expr-match.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/fat-arrow-match.rs (93%) rename src/test/{run-pass => ui/run-pass/binding}/fn-pattern-expected-type-2.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/fn-pattern-expected-type.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/func-arg-incomplete-pattern.rs (96%) rename src/test/{run-pass => ui/run-pass/binding}/func-arg-ref-pattern.rs (97%) rename src/test/{run-pass => ui/run-pass/binding}/func-arg-wild-pattern.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/if-let.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/inconsistent-lifetime-mismatch.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/inferred-suffix-in-pattern-range.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/irrefutable-slice-patterns.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/let-assignability.rs (95%) rename src/test/{run-pass => ui/run-pass/binding}/let-destruct-ref.rs (97%) rename src/test/{run-pass => ui/run-pass/binding}/let-var-hygiene.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-arm-statics.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/match-beginning-vert.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-borrowed_str.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-bot-2.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-bot.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-byte-array-patterns.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/match-enum-struct-0.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-enum-struct-1.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-implicit-copy-unique.rs (93%) rename src/test/{run-pass => ui/run-pass/binding}/match-in-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-join.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-larger-const.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-naked-record-expr.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-naked-record.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-path.rs (93%) rename src/test/{run-pass => ui/run-pass/binding}/match-pattern-bindings.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-pattern-lit.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-pattern-no-type-params.rs (93%) rename src/test/{run-pass => ui/run-pass/binding}/match-pattern-simple.rs (97%) rename src/test/{run-pass => ui/run-pass/binding}/match-phi.rs (94%) rename src/test/{run-pass => ui/run-pass/binding}/match-pipe-binding.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/match-range-infer.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-range-static.rs (93%) rename src/test/{run-pass => ui/run-pass/binding}/match-range.rs (92%) rename src/test/{run-pass => ui/run-pass/binding}/match-reassign.rs (94%) rename src/test/{run-pass => ui/run-pass/binding}/match-ref-binding-in-guard-3256.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-ref-binding-mut-option.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-ref-binding-mut.rs (92%) rename src/test/{run-pass => ui/run-pass/binding}/match-ref-binding.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-ref-unsized.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-static-const-rename.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/match-str.rs (95%) rename src/test/{run-pass => ui/run-pass/binding}/match-struct-0.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-tag.rs (96%) rename src/test/{run-pass => ui/run-pass/binding}/match-unique-bind.rs (95%) rename src/test/{run-pass => ui/run-pass/binding}/match-unsized.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-value-binding-in-guard-3291.rs (96%) rename src/test/{run-pass => ui/run-pass/binding}/match-var-hygiene.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-vec-alternatives.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/match-vec-rvalue.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/match-with-ret-arm.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/multi-let.rs (97%) rename src/test/{run-pass => ui/run-pass/binding}/mut-in-ident-patterns.rs (95%) rename src/test/{run-pass => ui/run-pass/binding}/nested-exhaustive-match.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/nested-matchs.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/nested-pattern.rs (94%) rename src/test/{run-pass => ui/run-pass/binding}/nil-pattern.rs (97%) rename src/test/{run-pass => ui/run-pass/binding}/nullary-or-pattern.rs (93%) rename src/test/{run-pass => ui/run-pass/binding}/optional_comma_in_match_arm.rs (97%) rename src/test/{run-pass => ui/run-pass/binding}/or-pattern.rs (94%) rename src/test/{run-pass => ui/run-pass/binding}/order-drop-with-match.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/pat-ranges.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/pat-tuple-1.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/pat-tuple-2.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/pat-tuple-3.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/pat-tuple-4.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/pat-tuple-5.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/pat-tuple-6.rs (99%) rename src/test/{run-pass => ui/run-pass/binding}/pat-tuple-7.rs (97%) rename src/test/{run-pass => ui/run-pass/binding}/pattern-bound-var-in-for-each.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/pattern-in-closure.rs (92%) rename src/test/{run-pass => ui/run-pass/binding}/range-inclusive-pattern-precedence.rs (98%) rename src/test/{run-pass => ui/run-pass/binding}/simple-generic-match.rs (93%) rename src/test/{run-pass => ui/run-pass/binding}/use-uninit-match.rs (94%) rename src/test/{run-pass => ui/run-pass/binding}/use-uninit-match2.rs (94%) rename src/test/{run-pass => ui/run-pass/binding}/zero_sized_subslice_match.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-assign-to-subfield.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-assignment-to-static-mut.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-binding-mutbl.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-borrow-from-expr-block.rs (96%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-closures-two-imm.rs (99%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-field-sensitivity.rs (99%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-fixed-length-vecs.rs (97%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-freeze-frozen-mut.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-lend-args.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-macro-interaction-issue-6304.rs (95%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-move-by-capture-ok.rs (95%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-multiple-borrows-interior-boxes.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-mut-uniq.rs (97%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-mut-vec-as-imm-slice.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-pat-enum.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-pat-reassign-no-binding.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-rvalues-mutable.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-scope-of-deref-issue-4666.rs (99%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-slice-pattern-element-loan.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-static-item-in-fn.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-trait-lifetime.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-uniq-via-ref.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-univariant-enum.rs (95%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-unsafe-static-mutable-borrows.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-unused-mut-locals.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/borrowck-use-mut-borrow.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/two-phase-baseline.rs (98%) rename src/test/{ => ui}/run-pass/borrowck/two-phase-bin-ops.rs (99%) rename src/test/{ => ui}/run-pass/borrowck/two-phase-control-flow-split-before-activation.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/auxiliary/cfg_inner_static.rs (100%) rename src/test/{run-pass => ui/run-pass/cfg}/auxiliary/crate-attributes-using-cfg_attr.rs (100%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-attr-cfg.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-attr-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-family.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-in-crate-1.rs (97%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-macros-foo.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-macros-notfoo.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-match-arm.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-target-family.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg-target-vendor.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg_attr.rs (99%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg_inner_static.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/cfg_stmt_expr.rs (99%) rename src/test/{run-pass => ui/run-pass/cfg}/cfgs-on-items.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/conditional-compile-arch.rs (98%) rename src/test/{run-pass => ui/run-pass/cfg}/conditional-compile.rs (96%) rename src/test/{run-pass => ui/run-pass/cfg}/crate-attributes-using-cfg_attr.rs (97%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-expect-unsized.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-overloaded-autoderef.rs (99%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-reborrow-imm-ptr-arg.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-reborrow-imm-ptr-rcvr.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-reborrow-imm-vec-arg.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-reborrow-imm-vec-rcvr.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-reborrow-mut-ptr-arg.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-reborrow-mut-ptr-rcvr.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-reborrow-mut-vec-arg.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-reborrow-mut-vec-rcvr.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-unify-return.rs (98%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-unify.rs (99%) rename src/test/{run-pass => ui/run-pass/coerce}/coerce-unsize-subtype.rs (99%) rename src/test/{run-pass => ui/run-pass/coherence}/auxiliary/coherence_copy_like_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/coherence}/auxiliary/coherence_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-bigint-int.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-bigint-vecint.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-blanket.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-covered-type-parameter.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-impl-in-fn.rs (94%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-iterator-vec-any-elem.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-iterator-vec.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-multidispatch-tuple.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-negative-impls-safe.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-rfc447-constrained.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-subtyping.rs (99%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence-where-clause.rs (98%) rename src/test/{run-pass => ui/run-pass/coherence}/coherence_copy_like.rs (98%) create mode 100644 src/test/ui/run-pass/consts/auxiliary/anon-extern-mod-cross-crate-1.rs rename src/test/{run-pass => ui/run-pass/consts}/auxiliary/cci_borrow_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/consts}/auxiliary/cci_const.rs (100%) rename src/test/{run-pass => ui/run-pass/consts}/auxiliary/cci_const_block.rs (100%) create mode 100644 src/test/ui/run-pass/consts/auxiliary/const_fn_lib.rs rename src/test/{run-pass => ui/run-pass/consts}/const-adt-align-mismatch.rs (96%) rename src/test/{run-pass => ui/run-pass/consts}/const-autoderef.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-big-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-binops.rs (99%) rename src/test/{run-pass => ui/run-pass/consts}/const-bitshift-rhs-inference.rs (99%) rename src/test/{run-pass => ui/run-pass/consts}/const-block-cross-crate-fn.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-block-item-macro-codegen.rs (99%) rename src/test/{run-pass => ui/run-pass/consts}/const-block-item.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-block.rs (99%) rename src/test/{run-pass => ui/run-pass/consts}/const-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-byte-str-cast.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-cast-ptr-int.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-cast.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-const.rs (92%) rename src/test/{run-pass => ui/run-pass/consts}/const-contents.rs (94%) rename src/test/{run-pass => ui/run-pass/consts}/const-cross-crate-const.rs (94%) rename src/test/{run-pass => ui/run-pass/consts}/const-cross-crate-extern.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-deref.rs (97%) rename src/test/{run-pass => ui/run-pass/consts}/const-endianess.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-byref-self.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-byref.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-cast.rs (94%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-ptr.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-struct2.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-structlike.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-tuple.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-tuple2.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-tuplestruct.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-tuplestruct2.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-vec-index.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-vec-ptr.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-enum-vector.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-err.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-expr-in-fixed-length-vec.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-expr-in-vec-repeat.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-extern-function.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-fields-and-indexing.rs (95%) rename src/test/{run-pass => ui/run-pass/consts}/const-fn-const-eval.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-fn-feature-flags.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-fn-method.rs (94%) rename src/test/{run-pass => ui/run-pass/consts}/const-fn-nested.rs (94%) rename src/test/{run-pass => ui/run-pass/consts}/const-fn-stability-calls.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-fn-val.rs (89%) rename src/test/{run-pass => ui/run-pass/consts}/const-fn.rs (96%) rename src/test/{run-pass => ui/run-pass/consts}/const-index-feature-gate.rs (97%) rename src/test/{run-pass => ui/run-pass/consts}/const-meth-pattern.rs (94%) rename src/test/{run-pass => ui/run-pass/consts}/const-negation.rs (97%) rename src/test/{run-pass => ui/run-pass/consts}/const-negative.rs (92%) rename src/test/{run-pass => ui/run-pass/consts}/const-nullary-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-nullary-univariant-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-pattern-variant.rs (95%) rename src/test/{run-pass => ui/run-pass/consts}/const-rec-and-tup.rs (92%) rename src/test/{run-pass => ui/run-pass/consts}/const-region-ptrs-noncopy.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-region-ptrs.rs (94%) rename src/test/{run-pass => ui/run-pass/consts}/const-repeated-values.rs (97%) rename src/test/{run-pass => ui/run-pass/consts}/const-size_of-align_of.rs (97%) rename src/test/{run-pass => ui/run-pass/consts}/const-str-ptr.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-struct-offsets.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-struct.rs (93%) rename src/test/{run-pass => ui/run-pass/consts}/const-trait-to-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-tuple-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-typeid-of.rs (99%) rename src/test/{run-pass => ui/run-pass/consts}/const-unit-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/consts}/const-unsafe-fn.rs (95%) rename src/test/{run-pass => ui/run-pass/consts}/const-vec-of-fns.rs (96%) rename src/test/{run-pass => ui/run-pass/consts}/const-vec-syntax.rs (97%) rename src/test/{run-pass => ui/run-pass/consts}/const-vecs-and-slices.rs (95%) rename src/test/{run-pass => ui/run-pass/consts}/const.rs (91%) rename src/test/{run-pass => ui/run-pass/consts}/consts-in-patterns.rs (95%) rename src/test/{run-pass => ui/run-pass/cross-crate}/anon-extern-mod-cross-crate-2.rs (98%) create mode 100644 src/test/ui/run-pass/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/anon_trait_static_method_lib.rs (100%) create mode 100644 src/test/ui/run-pass/cross-crate/auxiliary/cci_borrow_lib.rs rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/cci_capture_clause.rs (100%) create mode 100644 src/test/ui/run-pass/cross-crate/auxiliary/cci_const.rs rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/cci_impl_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/cci_iter_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/cci_nested_lib.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/cci_no_inline_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/moves_based_on_type_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/newtype_struct_xc.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/pub_static_array.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/reexported_static_methods.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/xcrate-trait-lifetime-param.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/xcrate_address_insignificant.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/xcrate_associated_type_defaults.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/xcrate_generic_fn_nested_return.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/auxiliary/xcrate_static_addresses.rs (100%) rename src/test/{compile-fail => ui/run-pass/cross-crate}/auxiliary/xcrate_unit_struct.rs (100%) rename src/test/{run-pass => ui/run-pass/cross-crate}/cci_borrow.rs (96%) rename src/test/{run-pass => ui/run-pass/cross-crate}/cci_capture_clause.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/cci_impl_exe.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/cci_iter_exe.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/cci_nested_exe.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/cci_no_inline_exe.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/cross-crate-const-pat.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/cross-crate-newtype-struct-pat.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/moves-based-on-type-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/reexported-static-methods-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/static-array-across-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/xcrate-address-insignificant.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/xcrate-associated-type-defaults.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/xcrate-static-addresses.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/xcrate-trait-lifetime-param.rs (98%) rename src/test/{run-pass => ui/run-pass/cross-crate}/xcrate-unit-struct.rs (96%) rename src/test/{run-pass => ui/run-pass/cross-crate}/xcrate_generic_fn_nested_return.rs (98%) rename src/test/{ => ui}/run-pass/ctfe/assoc-const.rs (98%) rename src/test/{ => ui}/run-pass/ctfe/bswap-const.rs (98%) rename src/test/{ => ui}/run-pass/ctfe/chained-constants-stackoverflow.rs (99%) rename src/test/{ => ui}/run-pass/ctfe/const-block-non-item-statement-3.rs (97%) rename src/test/{ => ui}/run-pass/ctfe/const-block-non-item-statement.rs (97%) rename src/test/{ => ui}/run-pass/ctfe/const-fn-destructuring-arg.rs (98%) rename src/test/{ => ui}/run-pass/ctfe/deref_in_pattern.rs (97%) rename src/test/{ => ui}/run-pass/ctfe/ice-48279.rs (95%) rename src/test/{ => ui}/run-pass/ctfe/issue-37550.rs (97%) rename src/test/{ => ui}/run-pass/ctfe/issue-broken-mir.rs (97%) rename src/test/{ => ui}/run-pass/ctfe/locals-in-const-fn.rs (98%) rename src/test/{ => ui}/run-pass/ctfe/match-const-fn-structs.rs (95%) rename src/test/{ => ui}/run-pass/ctfe/mozjs-error.rs (95%) rename src/test/{ => ui}/run-pass/ctfe/non-scalar-cast.rs (97%) create mode 100644 src/test/ui/run-pass/ctfe/promotion.rs rename src/test/{ => ui}/run-pass/ctfe/references.rs (98%) rename src/test/{ => ui}/run-pass/ctfe/repeat_match.rs (98%) rename src/test/{ => ui}/run-pass/ctfe/return-in-const-fn.rs (93%) rename src/test/{ => ui}/run-pass/ctfe/signed_enum_discr.rs (98%) create mode 100644 src/test/ui/run-pass/ctfe/transmute-const.rs rename src/test/{ => ui}/run-pass/ctfe/tuple-struct-constructors.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/auxiliary/derive-no-std.rs (100%) rename src/test/{run-pass => ui/run-pass/deriving}/derive-no-std.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/derive-partialord-correctness.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-associated-types.rs (99%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-bounds.rs (97%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-clone-array.rs (97%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-clone-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-clone-generic-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-clone-generic-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-clone-generic-tuple-struct.rs (97%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-clone-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-clone-tuple-struct.rs (97%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-cmp-generic-enum.rs (99%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-cmp-generic-struct-enum.rs (99%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-cmp-generic-struct.rs (99%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-cmp-generic-tuple-struct.rs (99%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-cmp-shortcircuit.rs (99%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-copyclone.rs (99%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-default-box.rs (96%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-enum-single-variant.rs (93%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-eq-ord-boxed-slice.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-hash.rs (93%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-in-fn.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-in-macro.rs (93%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-meta-multiple.rs (96%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-meta.rs (96%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-self-lifetime-totalord-totaleq.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-show-2.rs (99%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-show.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-c-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-hash-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-hash-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-struct-empty.rs (97%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-struct-like-enum-variant.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-struct-tuple.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-via-extension-type-params.rs (98%) rename src/test/{run-pass => ui/run-pass/deriving}/deriving-with-repr-packed.rs (98%) rename src/test/{run-pass => ui/run-pass/drop}/auxiliary/dropck_eyepatch_extern_crate.rs (100%) rename src/test/{run-pass => ui/run-pass/drop}/drop-on-empty-block-exit.rs (93%) rename src/test/{run-pass => ui/run-pass/drop}/drop-on-ret.rs (98%) rename src/test/{run-pass => ui/run-pass/drop}/drop-struct-as-object.rs (95%) rename src/test/{run-pass => ui/run-pass/drop}/drop-trait-enum.rs (99%) rename src/test/{run-pass => ui/run-pass/drop}/drop-trait-generic.rs (98%) rename src/test/{run-pass => ui/run-pass/drop}/drop-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/drop}/drop-uninhabited-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/drop}/drop-with-type-ascription-1.rs (98%) rename src/test/{run-pass => ui/run-pass/drop}/drop-with-type-ascription-2.rs (98%) rename src/test/{run-pass => ui/run-pass/drop}/dropck-eyepatch-extern-crate.rs (99%) rename src/test/{run-pass => ui/run-pass/drop}/dropck-eyepatch-reorder.rs (99%) rename src/test/{run-pass => ui/run-pass/drop}/dropck-eyepatch.rs (99%) rename src/test/{run-pass => ui/run-pass/drop}/dropck_legal_cycles.rs (99%) rename src/test/{run-pass => ui/run-pass/drop}/dynamic-drop.rs (99%) rename src/test/{run-pass => ui/run-pass/drop}/no-drop-flag-size.rs (98%) rename src/test/{run-pass => ui/run-pass/drop}/nondrop-cycle.rs (98%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-coerce-custom.rs (99%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-coerce-rc.rs (97%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-coercions.rs (98%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-deref-mut.rs (98%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-deref.rs (98%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-field-align.rs (99%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-index.rs (98%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-irrefutable-bind.rs (98%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-raw.rs (99%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-struct-sole.rs (99%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-struct.rs (99%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-trait-tuple.rs (98%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-tuple-sole.rs (96%) rename src/test/{run-pass => ui/run-pass/dynamically-sized-types}/dst-tuple.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/auxiliary/extern-crosscrate-source.rs (100%) rename src/test/{run-pass => ui/run-pass/extern}/auxiliary/extern-take-value.rs (100%) rename src/test/{run-pass => ui/run-pass/extern}/auxiliary/extern_calling_convention.rs (100%) rename src/test/{run-pass => ui/run-pass/extern}/auxiliary/extern_mod_ordering_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/extern}/auxiliary/fat_drop.rs (100%) rename src/test/{run-pass => ui/run-pass/extern}/extern-1.rs (97%) rename src/test/{run-pass => ui/run-pass/extern}/extern-call-deep.rs (99%) rename src/test/{run-pass => ui/run-pass/extern}/extern-call-deep2.rs (99%) rename src/test/{run-pass => ui/run-pass/extern}/extern-call-direct.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-call-indirect.rs (99%) rename src/test/{run-pass => ui/run-pass/extern}/extern-call-scrub.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-calling-convention-test.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-compare-with-return-type.rs (96%) rename src/test/{run-pass => ui/run-pass/extern}/extern-crosscrate.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-foreign-crate.rs (97%) rename src/test/{run-pass => ui/run-pass/extern}/extern-methods.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-mod-abi.rs (97%) rename src/test/{run-pass => ui/run-pass/extern}/extern-mod-ordering-exe.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-TwoU16s.rs (96%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-TwoU32s.rs (96%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-TwoU64s.rs (96%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-TwoU8s.rs (96%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-char.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-double.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-empty.rs (94%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-u32.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-pass-u64.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-prelude-core.rs (98%) create mode 100644 src/test/ui/run-pass/extern/extern-prelude-core.stderr rename src/test/{run-pass => ui/run-pass/extern}/extern-prelude-no-speculative.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-prelude-std.rs (98%) create mode 100644 src/test/ui/run-pass/extern/extern-prelude-std.stderr rename src/test/{run-pass => ui/run-pass/extern}/extern-pub.rs (97%) rename src/test/{run-pass => ui/run-pass/extern}/extern-return-TwoU16s.rs (95%) rename src/test/{run-pass => ui/run-pass/extern}/extern-return-TwoU32s.rs (95%) rename src/test/{run-pass => ui/run-pass/extern}/extern-return-TwoU64s.rs (95%) rename src/test/{run-pass => ui/run-pass/extern}/extern-return-TwoU8s.rs (95%) rename src/test/{run-pass => ui/run-pass/extern}/extern-rust.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-take-value.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-thiscall.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-types-inherent-impl.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-types-manual-sync-send.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-types-pointer-cast.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-types-size_of_val.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-types-thin-pointer.rs (99%) rename src/test/{run-pass => ui/run-pass/extern}/extern-types-trait-impl.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern-vectorcall.rs (98%) rename src/test/{run-pass => ui/run-pass/extern}/extern_fat_drop.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/auto-loop.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/break-value.rs (97%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/break.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-destruct.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-goofiness.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-has-unit-body.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-into-iterator.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-lifetime-of-unbound-values.rs (99%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-mut-ref-element.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-no-std.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-panic.rs (97%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/for-loop-unconstrained-element-type-i32-fallback.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-external-iterators-break.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-external-iterators-hashmap-break-restart.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-external-iterators-hashmap.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-external-iterators-loop.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-external-iterators-nested.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-external-iterators.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-nested.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-put-structured.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/foreach-simple-outer-slot.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/label_break_value.rs (99%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/labeled-break.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/linear-for-loop.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/liveness-assign-imm-local-after-loop.rs (96%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/liveness-loop-break.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/liveness-move-in-loop.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/loop-break-cont-1.rs (97%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/loop-break-cont.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/loop-break-value.rs (99%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/loop-diverges.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/loop-label-shadowing.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/loop-labeled-break-value.rs (87%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/loop-no-reinit-needed-post-bot.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/loop-scope.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/while-cont.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/while-flow-graph.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/while-label.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/while-let.rs (94%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/while-loop-constraints-2.rs (96%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/while-prelude-drop.rs (95%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/while-with-break.rs (98%) rename src/test/{run-pass => ui/run-pass/for-loop-while}/while.rs (98%) rename src/test/{run-pass => ui/run-pass/foreign}/auxiliary/fn-abi.rs (100%) create mode 100644 src/test/ui/run-pass/foreign/auxiliary/foreign_lib.rs rename src/test/{run-pass => ui/run-pass/foreign}/foreign-call-no-runtime.rs (99%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-dupe.rs (98%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-fn-linkname.rs (97%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-fn-with-byval.rs (96%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-int-types.rs (98%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-mod-src/compiletest-ignore-dir (100%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-mod-src/inner.rs (98%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-mod-unused-const.rs (97%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-no-abi.rs (98%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-src/compiletest-ignore-dir (100%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-src/foreign.rs (98%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign-truncated-arguments.rs (98%) rename src/test/{run-pass => ui/run-pass/foreign}/foreign2.rs (98%) create mode 100644 src/test/ui/run-pass/functions-closures/auxiliary/fn-abi.rs rename src/test/{run-pass => ui/run-pass/functions-closures}/call-closure-from-overloaded-op.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/capture-clauses-boxed-closures.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/capture-clauses-unboxed-closures.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/clone-closure.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-bounds-can-capture-chan.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-expected-type/README.md (100%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-expected-type/expect-infer-supply-two-infers.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-expected-type/issue-38714.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-expected-type/supply-just-return-type.rs (99%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-expected-type/supply-nothing.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-immediate.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-inference.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-inference2.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-reform.rs (99%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-returning-closure.rs (97%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure-to-fn-coercion.rs (99%) rename src/test/{run-pass => ui/run-pass/functions-closures}/closure_to_fn_coercion-expected-types.rs (97%) rename src/test/{run-pass => ui/run-pass/functions-closures}/copy-closure.rs (98%) create mode 100644 src/test/ui/run-pass/functions-closures/fn-abi.rs rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-bare-assign.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-bare-coerce-to-block.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-bare-item.rs (97%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-bare-size.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-bare-spawn.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-coerce-field.rs (93%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-item-type-cast.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-item-type-coerce.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-item-type-zero-sized.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-lval.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/fn-type-infer.rs (98%) rename src/test/{run-pass => ui/run-pass/functions-closures}/implied-bounds-closure-arg-outlives.rs (99%) rename src/test/{run-pass => ui/run-pass/functions-closures}/nullable-pointer-opt-closures.rs (99%) rename src/test/{run-pass => ui/run-pass/functions-closures}/parallel-codegen-closures.rs (95%) rename src/test/{run-pass => ui/run-pass/functions-closures}/return-from-closure.rs (95%) rename src/test/{ => ui}/run-pass/generator/auxiliary/xcrate-reachable.rs (100%) rename src/test/{ => ui}/run-pass/generator/auxiliary/xcrate.rs (100%) rename src/test/{ => ui}/run-pass/generator/borrow-in-tail-expr.rs (97%) rename src/test/{ => ui}/run-pass/generator/conditional-drop.rs (99%) rename src/test/{ => ui}/run-pass/generator/control-flow.rs (99%) rename src/test/{ => ui}/run-pass/generator/drop-env.rs (99%) rename src/test/{ => ui}/run-pass/generator/issue-44197.rs (98%) create mode 100644 src/test/ui/run-pass/generator/issue-52398.rs rename src/test/{ => ui}/run-pass/generator/iterator-count.rs (99%) rename src/test/{ => ui}/run-pass/generator/live-upvar-across-yield.rs (98%) rename src/test/{ => ui}/run-pass/generator/match-bindings.rs (98%) rename src/test/{ => ui}/run-pass/generator/nested_generators.rs (98%) rename src/test/{ => ui}/run-pass/generator/panic-drops.rs (99%) create mode 100644 src/test/ui/run-pass/generator/panic-safe.rs rename src/test/{ => ui}/run-pass/generator/reborrow-mut-upvar.rs (98%) rename src/test/{ => ui}/run-pass/generator/resume-after-return.rs (98%) rename src/test/{ => ui}/run-pass/generator/smoke.rs (99%) rename src/test/{ => ui}/run-pass/generator/static-generators.rs (98%) rename src/test/{ => ui}/run-pass/generator/too-live-local-in-immovable-gen.rs (98%) rename src/test/{ => ui}/run-pass/generator/xcrate-reachable.rs (98%) create mode 100644 src/test/ui/run-pass/generator/xcrate.rs rename src/test/{ => ui}/run-pass/generator/yield-in-args-rev.rs (98%) rename src/test/{ => ui}/run-pass/generator/yield-in-box.rs (98%) create mode 100644 src/test/ui/run-pass/generator/yield-in-initializer.rs rename src/test/{ => ui}/run-pass/generator/yield-subtype.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/auxiliary/default_type_params_xc.rs (100%) rename src/test/{run-pass => ui/run-pass/generics}/generic-alias-unique.rs (96%) rename src/test/{run-pass => ui/run-pass/generics}/generic-default-type-params-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/generic-default-type-params.rs (99%) rename src/test/{run-pass => ui/run-pass/generics}/generic-derived-type.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/generic-exterior-unique.rs (96%) rename src/test/{run-pass => ui/run-pass/generics}/generic-extern-mangle.rs (96%) rename src/test/{run-pass => ui/run-pass/generics}/generic-fn-infer.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/generic-fn-twice.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/generic-fn-unique.rs (95%) rename src/test/{run-pass => ui/run-pass/generics}/generic-fn.rs (97%) rename src/test/{run-pass => ui/run-pass/generics}/generic-ivec-leak.rs (92%) rename src/test/{run-pass => ui/run-pass/generics}/generic-newtype-struct.rs (97%) rename src/test/{run-pass => ui/run-pass/generics}/generic-object.rs (96%) rename src/test/{run-pass => ui/run-pass/generics}/generic-recursive-tag.rs (94%) rename src/test/{run-pass => ui/run-pass/generics}/generic-static-methods.rs (95%) rename src/test/{run-pass => ui/run-pass/generics}/generic-tag-corruption.rs (93%) rename src/test/{run-pass => ui/run-pass/generics}/generic-tag-local.rs (92%) rename src/test/{run-pass => ui/run-pass/generics}/generic-tag-match.rs (94%) rename src/test/{run-pass => ui/run-pass/generics}/generic-tag-values.rs (95%) rename src/test/{run-pass => ui/run-pass/generics}/generic-tag.rs (92%) rename src/test/{run-pass => ui/run-pass/generics}/generic-temporary.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/generic-tup.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/generic-type-synonym.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/generic-type.rs (98%) rename src/test/{run-pass => ui/run-pass/generics}/generic-unique.rs (96%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-binder-levels-in-object-types.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-debruijn-object-types-in-closures.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-fn-like-trait-object.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-fn-like-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-opt-in-copy.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-parse.rs (99%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-precedence-of-plus-where-clause.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-precedence-of-plus.rs (96%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-resolve-lifetime.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-trait-object-paren-notation.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-trait-object-passed-to-closure.rs (98%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-type-outlives.rs (99%) rename src/test/{run-pass => ui/run-pass/higher-rank-trait-bounds}/hrtb-unboxed-closure-trait.rs (98%) create mode 100644 src/test/ui/run-pass/hygiene/auxiliary/legacy_interaction.rs rename src/test/{ => ui}/run-pass/hygiene/auxiliary/my_crate.rs (97%) rename src/test/{ => ui}/run-pass/hygiene/auxiliary/unhygienic_example.rs (98%) create mode 100644 src/test/ui/run-pass/hygiene/auxiliary/xcrate.rs rename src/test/{run-pass => ui/run-pass/hygiene}/hygiene-dodging-1.rs (98%) rename src/test/{run-pass => ui/run-pass/hygiene}/hygiene.rs (99%) rename src/test/{run-pass => ui/run-pass/hygiene}/hygienic-labels-in-let.rs (99%) create mode 100644 src/test/ui/run-pass/hygiene/hygienic-labels-in-let.stderr rename src/test/{run-pass => ui/run-pass/hygiene}/hygienic-labels.rs (99%) create mode 100644 src/test/ui/run-pass/hygiene/hygienic-labels.stderr rename src/test/{ => ui}/run-pass/hygiene/issue-44128.rs (98%) rename src/test/{ => ui}/run-pass/hygiene/issue-47311.rs (98%) rename src/test/{ => ui}/run-pass/hygiene/issue-47312.rs (98%) create mode 100644 src/test/ui/run-pass/hygiene/items.rs create mode 100644 src/test/ui/run-pass/hygiene/legacy_interaction.rs rename src/test/{ => ui}/run-pass/hygiene/lexical.rs (98%) rename src/test/{ => ui}/run-pass/hygiene/specialization.rs (98%) rename src/test/{ => ui}/run-pass/hygiene/trait_items.rs (98%) rename src/test/{ => ui}/run-pass/hygiene/ty_params.rs (98%) rename src/test/{ => ui}/run-pass/hygiene/wrap_unhygienic_example.rs (99%) create mode 100644 src/test/ui/run-pass/hygiene/xcrate.rs rename src/test/{ => ui}/run-pass/impl-trait/auto-trait-leak.rs (98%) rename src/test/{ => ui}/run-pass/impl-trait/auxiliary/xcrate.rs (100%) rename src/test/{ => ui}/run-pass/impl-trait/bounds_regression.rs (98%) rename src/test/{ => ui}/run-pass/impl-trait/equality.rs (99%) rename src/test/{ => ui}/run-pass/impl-trait/example-calendar.rs (99%) rename src/test/{ => ui}/run-pass/impl-trait/example-st.rs (98%) rename src/test/{ => ui}/run-pass/impl-trait/existential-minimal.rs (97%) rename src/test/{ => ui}/run-pass/impl-trait/issue-42479.rs (98%) rename src/test/{ => ui}/run-pass/impl-trait/issue-49376.rs (98%) rename src/test/{ => ui}/run-pass/impl-trait/lifetimes.rs (99%) rename src/test/{ => ui}/run-pass/impl-trait/nesting.rs (98%) rename src/test/{ => ui}/run-pass/impl-trait/universal_hrtb_anon.rs (97%) rename src/test/{ => ui}/run-pass/impl-trait/universal_hrtb_named.rs (97%) rename src/test/{ => ui}/run-pass/impl-trait/universal_in_adt_in_parameters.rs (98%) rename src/test/{ => ui}/run-pass/impl-trait/universal_in_impl_trait_in_parameters.rs (99%) rename src/test/{ => ui}/run-pass/impl-trait/universal_in_trait_defn_parameters.rs (98%) rename src/test/{ => ui}/run-pass/impl-trait/universal_multiple_bounds.rs (98%) create mode 100644 src/test/ui/run-pass/impl-trait/xcrate.rs rename src/test/{ => ui}/run-pass/impl-trait/xcrate_simple.rs (97%) rename src/test/{run-pass => ui/run-pass/imports}/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans.rs (100%) rename src/test/{run-pass => ui/run-pass/imports}/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans_macros.rs (100%) create mode 100644 src/test/ui/run-pass/imports/import-crate-with-invalid-spans/main.rs rename src/test/{run-pass => ui/run-pass/imports}/import-from.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import-glob-0.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import-glob-1.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import-glob-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import-in-block.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import-prefix-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import-rename.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import-trailing-comma.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import2.rs (97%) rename src/test/{run-pass => ui/run-pass/imports}/import3.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import4.rs (97%) rename src/test/{run-pass => ui/run-pass/imports}/import5.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import6.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import7.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/import8.rs (98%) rename src/test/{run-pass => ui/run-pass/imports}/imports.rs (99%) rename src/test/{run-pass => ui/run-pass/intrinsics}/auxiliary/cci_intrinsic.rs (100%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsic-alignment.rs (99%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsic-assume.rs (98%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsic-atomics-cc.rs (98%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsic-atomics.rs (99%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsic-move-val-cleanups.rs (99%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsic-move-val.rs (99%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsic-uninit.rs (98%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsic-unreachable.rs (98%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsics-integer.rs (99%) rename src/test/{run-pass => ui/run-pass/intrinsics}/intrinsics-math.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/cgu_test.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/cgu_test_a.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/cgu_test_b.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/i8.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/iss.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-10028.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-11224.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-11225-1.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-11225-2.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-11225-3.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-11508.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-11529.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-12133-dylib.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-12133-dylib2.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-12133-rlib.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-12660-aux.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-13620-1.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-13620-2.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-13872-1.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-13872-2.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-13872-3.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-14344-1.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-14344-2.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-14421.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-14422.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-15562.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-16643.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-17662.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-17718-aux.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-18501.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-18514.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-18711.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-18913-1.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-18913-2.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-19340-1.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-2380.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-2414-a.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-2414-b.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-25185-1.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-25185-2.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-2526.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-25467.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-2631-a.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-29485.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-3012-1.rs (100%) create mode 100644 src/test/ui/run-pass/issues/auxiliary/issue-36954.rs rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-41394.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-4208-cc.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-4545.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-48984-aux.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-5518.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-5521.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-7178.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-7899.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-8044.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-8259.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-9906.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue-9968.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue13507.rs (80%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue2170lib.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue34796aux.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_10031_aux.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_12612_1.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_12612_2.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_19293.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_20389.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_2316_a.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_2316_b.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_2472_b.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_2723_a.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_3136_a.rc (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_3136_a.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_38190.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_38226_aux.rs (100%) create mode 100644 src/test/ui/run-pass/issues/auxiliary/issue_38715-modern.rs rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_38715.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_3979_traits.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_39823.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_40469.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_41053.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_42007_s.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_8401.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_9123.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_9155.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/auxiliary/issue_9188.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10025.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10028.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10031.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10228.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10392.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10396.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10436.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10456.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10626.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10638.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10682.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10683.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10718.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10734.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10763.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10764.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10767.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10802.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10806.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10853.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-10902.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11047.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11085.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1112.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11205.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11224.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11225-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11225-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11225-3.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11267.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11382.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11384.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11508.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11529.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11552.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11577.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11592.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11612.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11677.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11709.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11820.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11869.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11940.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-11958.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12033.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12133-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12133-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12133-3.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12285.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1251.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1257.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12582.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12612.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12660.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12677.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12699.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12729.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12744.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12860.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-12909.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13027.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13105.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13167.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13204.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13214.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13259-windows-tcb-trash.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13264.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13304.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13323.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13405.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13434.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13494.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13507-2.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13620.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13655.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13665.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13703.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13763.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13775.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13808.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13837.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13867.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13872.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-13902.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14082.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14229.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14254.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14308.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14330.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14344.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14382.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14393.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14399.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14421.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14422.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14456.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1451.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14589.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1460.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14821.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14837.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14865.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14875.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14901.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14919.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14933.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14936.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14940.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14958.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-14959.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15043.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15063.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15080.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15104.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15108.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15129.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15155.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15189.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15221.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15261.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15444.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15487.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15523-big.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15523.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15562.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15571.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15673.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15689-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15689-2.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15730.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15734.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15735.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15763.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15774.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15793.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15858.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-15881-model-lexer-dotdotdot.rs (90%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16151.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16256.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16272.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16278.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16441.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16452.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16492.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16530.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16560.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16596.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16597-empty.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16597.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1660.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16602-1.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16602-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16602-3.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16643.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16648.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16668.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16671.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16739.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16745.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16774.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16783.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16819.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-16922.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1696.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1701.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17068.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17074.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17121.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17170.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17216.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17233.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17302.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17322.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17336.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17351.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17361.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17450.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17503.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17662.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17718-borrow-interior.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17718-const-destructors.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17718-parse-const.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17718-static-unsafe-interior.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17718.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17732.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17734.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17746.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17756.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17771.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17816.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17877.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17897.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-17904.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18060.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18075.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18083.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18088.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18110.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18173.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18188.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1821.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18232.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18352.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18353.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18412.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18425.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18446.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18464.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18501.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18514.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18539.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18652.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18655.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1866.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18661.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18685.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18711.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18738.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18767.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18804/auxiliary/lib.rs (100%) create mode 100644 src/test/ui/run-pass/issues/issue-18804/main.rs rename src/test/{run-pass => ui/run-pass/issues}/issue-18809.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18845.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18859.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18906.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18913.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18937-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-18988.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19001.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19037.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19081.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19097.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19098.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19102.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19127.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19129-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19129-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19135.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19244.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19293.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19340-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19340-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19358.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19367.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19398.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19404.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19479.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19499.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19631.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19632.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-1974.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19811-escape-unicode.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19850.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-19982.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20009.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20055-box-trait.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20055-box-unsized-array.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20091.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20174.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20186.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20313.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20343.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20389.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20396.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20414.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20427.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20454.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20544.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20575.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20616.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2063-resource.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2063.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20644.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20676.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2074.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20763-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20763-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20797.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20803.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20823.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20825.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20847.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-20953.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21033.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21058.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21140.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21174.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21245.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21291.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21306.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21361.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21363.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21384.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21400.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21402.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21475.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21486.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21520.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21562.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21622.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21634.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21655.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21721.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21726.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21891.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2190-1.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21909.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-21922.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22008.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22036.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22066.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2214.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2216.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22258.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22346.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22356.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22375.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22403.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22426.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22463.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22471.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22536-copy-mustnt-zero.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22546.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22577.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22629.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22777.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22781.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22814.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22828.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2284.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22864-1.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22864-2.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2288.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22894.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22992-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-22992.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23036.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2311-2.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2311.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2312.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2316-c.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23208.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23261.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23304-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23304-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23311.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23336.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23338-ensure-param-drop-order.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23338-params-outlive-temps-of-body.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23406.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23433.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23442.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23477.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23485.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23491.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23550.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23611-enum-swap-in-drop.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23649-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23649-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23649-3.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23699.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23781.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2380-b.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23808.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23825.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2383.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23833.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23891.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23898.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23958.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23968-const-not-overflow.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-23992.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24085.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24086.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2414-c.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24161.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24227.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2428.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24308.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24313.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24353.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24389.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24434.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2445-b.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2445.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24533.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24535-allow-mutable-borrow-in-match-guard.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24589.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2463.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2472.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24779.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24805-dropck-itemless.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2487-a.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24945-repeat-dash-opts.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24947.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-24954.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2502.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25089.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25145.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25180.rs (91%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25185.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2526-a.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25279.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25339.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25343.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25394.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25467.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25497.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2550.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25515.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25549-multiple-drop.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25679.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25693.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25700-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25700-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25746-bool-transmute.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25757.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25810.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-25916.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26095.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2611-3.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26127.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26205.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26251.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2631-b.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26322.rs (80%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2633-2.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2633.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2642.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26468.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26484.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26641.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26646.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26655.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26709.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26802.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26805.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26873-multifile.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26873-onefile.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26905.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26996.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-26997.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27021.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27054-primitive-binary-ops.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27060.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2708.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27105.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2718.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2723-b.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27240.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27268.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27281.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27320.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2734.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2735-2.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2735-3.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2735.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27401-dropflag-reinit.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2748-a.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2748-b.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27583.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27639.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27859.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27889.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27890.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27901.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-27997.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2804-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28181.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28279.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28550.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28561.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28600.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28676.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28777.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28822.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28828.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28839.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28871.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28936.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2895.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28950.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28983.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-28999.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29030.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29037.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2904.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29048.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29053.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29071-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29071.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29092.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29147.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29166.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29227.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29276.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2935.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2936.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29466.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29485.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29488.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29516.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29522.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29540.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29663.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29668.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29710.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29740.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29746.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29844.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-2989.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29914-2.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29914-3.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29914.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29927.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-29948.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30018-nopanic.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30018-panic.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30081.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3012-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30240.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3026.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3037.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30371.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30490.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3052.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30530.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30615.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30756.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-30891.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3091.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3109.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3121.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-31260.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-31267-additional.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-31267.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-31299.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3149.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-31597.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-31702.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-31776.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-32008.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3211.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3220.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-32292.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-32324.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-32389.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-32518.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-32805.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3290.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-32947.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33096.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33185.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33187.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33202.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33264.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33287.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-333.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33387.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33461.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33498.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33537.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33687.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33770.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3389.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33903.rs (89%) rename src/test/{run-pass => ui/run-pass/issues}/issue-33992.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34053.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34074.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34194.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3424.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3429.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34427.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3447.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34503.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34569.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34571.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34751.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34780.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34784.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34796.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34798.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-34932.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3500.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-35376.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-35423.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-35546.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3556.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3559.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-35600.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3563-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3563-3.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3574.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-35815.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36023.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36036-associated-type-layout.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36053.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36075.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3609.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36139-normalize-closure-sig.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36260.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36278-prefix-nesting.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36381.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36401.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36474.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3656.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36744-bitcast-args-if-needed.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36744-without-calls.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36768.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36786-resolve-call.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36792.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36816.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3683.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36856.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-36936.rs (98%) create mode 100644 src/test/ui/run-pass/issues/issue-36954.rs rename src/test/{run-pass => ui/run-pass/issues}/issue-3702.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37109.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37175.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37222.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37291/auxiliary/lib.rs (100%) create mode 100644 src/test/ui/run-pass/issues/issue-37291/main.rs rename src/test/{run-pass => ui/run-pass/issues}/issue-3743.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3753.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37598.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37655.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37686.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37725.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37733.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3794.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-37991.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38002.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38033.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38074.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38091.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38190.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38226.rs (91%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38437.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3847.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38556.rs (98%) create mode 100644 src/test/ui/run-pass/issues/issue-38715.rs rename src/test/{run-pass => ui/run-pass/issues}/issue-38727.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3874.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38763.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3878.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3888-2.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38942.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3895.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-38987.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3904.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39089.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39292.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3935.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39367.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39467.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39548.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39709.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39720.rs (95%) create mode 100644 src/test/ui/run-pass/issues/issue-39720.stderr rename src/test/{run-pass => ui/run-pass/issues}/issue-3979-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3979-generics.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3979-xcrate.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3979.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39808.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39823.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39827.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-3991.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-39984.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40003.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40085.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40136.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40235.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4025.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40408.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40469.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40770.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40847.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40883.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40951.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-40962.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41053.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4107.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41213.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41272.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41298.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41394.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41479.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41498.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41604.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41628.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41677.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41696.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41744.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41803.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41849-variance-req.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41888.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-41936-variance-coerce-unsized-cycle.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42007.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4208.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42148.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42210.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4228.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42453.rs (91%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42463.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42467.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4252.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42552.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42679.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42747.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-42956.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43057.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43132.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43205.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43291.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4333.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43357.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43483.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43692.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43853.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4387.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43910.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-43923.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-44005.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4401.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-44056.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-44247.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-44333.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-44373.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-44402.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4446.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4448.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4464.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-44730.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-44851.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-45124.rs (85%) rename src/test/{run-pass => ui/run-pass/issues}/issue-45152.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4541.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4542.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-45425.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4545.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-45731.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46069.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46095.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46519.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46553.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46845.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46855.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46920-byte-array-patterns.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46959.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-46964.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47139-1.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47139-2.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4734.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4735.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47364.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4759-1.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4759.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47638.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47673.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47703-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47703-tuple.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47703.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47722.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-47789.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-48159.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4830.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-48508-aux.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-48508.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-48551.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4865-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4865-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4865-3.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-4875.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-48962.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-48984.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49298.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49556.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49632.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49685.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49854.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49955-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49955.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-49973.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5008-borrowed-traitobject-method-call.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-50415.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-50442.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5060.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-50689.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-50731.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-50811.rs (99%) create mode 100644 src/test/ui/run-pass/issues/issue-50865-private-impl-trait/auxiliary/lib.rs create mode 100644 src/test/ui/run-pass/issues/issue-50865-private-impl-trait/main.rs rename src/test/{run-pass => ui/run-pass/issues}/issue-51185.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-51345.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-51582.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-51655.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-51907.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5192.rs (97%) create mode 100644 src/test/ui/run-pass/issues/issue-52140/auxiliary/some_crate.rs create mode 100644 src/test/ui/run-pass/issues/issue-52140/main.rs create mode 100644 src/test/ui/run-pass/issues/issue-52141/auxiliary/some_crate.rs create mode 100644 src/test/ui/run-pass/issues/issue-52141/main.rs create mode 100644 src/test/ui/run-pass/issues/issue-52169.rs rename src/test/{run-pass => ui/run-pass/issues}/issue-5239-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5243.rs (98%) create mode 100644 src/test/ui/run-pass/issues/issue-52557.rs create mode 100644 src/test/ui/run-pass/issues/issue-52705/auxiliary/png2.rs create mode 100644 src/test/ui/run-pass/issues/issue-52705/main.rs rename src/test/{run-pass => ui/run-pass/issues}/issue-5280.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5315.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5321-immediates-with-bare-self.rs (97%) create mode 100644 src/test/ui/run-pass/issues/issue-53333.rs rename src/test/{run-pass => ui/run-pass/issues}/issue-5353.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5518.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5521.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5530.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5550.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5554.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5572.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5666.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5688.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5708.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5718.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5741.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5754.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5791.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5884.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5900.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5917.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5950.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5988.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-5997.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6117.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6128.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6130.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6153.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6157.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6318.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6334.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6341.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6344-let.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6344-match.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6449.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6470.rs (90%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6557.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6892.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6898.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6919.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-6991.rs (91%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7012.rs (92%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7178.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7222.rs (88%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7268.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7344.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7519-match-unit-in-arg.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7563.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7575.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7607-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7660.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7663.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7673-cast-generically-implemented-trait.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7784.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7899.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-7911.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8044.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8171-default-method-self-inherit-builtin-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8248.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8249.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8259.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8351-1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8351-2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8391.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8398.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8401.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8460.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8498.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8506.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8521.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8578.rs (91%) rename src/test/{run-pass => ui/run-pass/issues}/issue-868.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8709.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8783.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8827.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8851.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8860.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-8898.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9047.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9110.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9123.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9129.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9188.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9243.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9249.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9259.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9382.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9394-inherited-trait-calls.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9396.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9446.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9719.rs (99%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9737.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-979.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9837.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9906.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9918.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9942.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9951.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue-9968.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue2170exe.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue24687-embed-debuginfo/auxiliary/issue24687_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/issues}/issue24687-embed-debuginfo/auxiliary/issue24687_mbcs_in_comments.rs (100%) create mode 100644 src/test/ui/run-pass/issues/issue24687-embed-debuginfo/main.rs rename src/test/{run-pass => ui/run-pass/issues}/issue28498-must-work-ex1.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue28498-must-work-ex2.rs (98%) rename src/test/{run-pass => ui/run-pass/issues}/issue28498-ugeh-ex1.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue28498-ugeh-with-lifetime-param.rs (94%) rename src/test/{run-pass => ui/run-pass/issues}/issue28498-ugeh-with-passed-to-fn.rs (96%) rename src/test/{run-pass => ui/run-pass/issues}/issue28498-ugeh-with-trait-bound.rs (95%) rename src/test/{run-pass => ui/run-pass/issues}/issue29927-1.rs (93%) rename src/test/{run-pass => ui/run-pass/issues}/issue_26873_multifile/A/B.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue_26873_multifile/A/C.rs (97%) create mode 100644 src/test/ui/run-pass/issues/issue_26873_multifile/A/mod.rs rename src/test/{run-pass => ui/run-pass/issues}/issue_26873_multifile/compiletest-ignore-dir (100%) create mode 100644 src/test/ui/run-pass/issues/issue_26873_multifile/mod.rs rename src/test/{run-pass => ui/run-pass/issues}/issue_3136_b.rs (97%) rename src/test/{run-pass => ui/run-pass/issues}/issue_9155.rs (98%) rename src/test/{run-pass => ui/run-pass/iterators}/into-iterator-type-inference-shift.rs (98%) rename src/test/{run-pass => ui/run-pass/iterators}/iter-cloned-type-inference.rs (95%) rename src/test/{run-pass => ui/run-pass/iterators}/iter-range.rs (98%) rename src/test/{run-pass => ui/run-pass/iterators}/iter-step-overflow-debug.rs (98%) rename src/test/{run-pass => ui/run-pass/iterators}/iter-step-overflow-ndebug.rs (98%) rename src/test/{run-pass => ui/run-pass/iterators}/iter-sum-overflow-debug.rs (98%) rename src/test/{run-pass => ui/run-pass/iterators}/iter-sum-overflow-ndebug.rs (98%) rename src/test/{run-pass => ui/run-pass/iterators}/iter-sum-overflow-overflow-checks.rs (98%) rename src/test/{run-pass => ui/run-pass/iterators}/iter-zip.rs (99%) rename src/test/{run-pass => ui/run-pass/macros}/assert-eq-macro-success.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/assert-eq-macro-unsized.rs (97%) rename src/test/{run-pass => ui/run-pass/macros}/assert-ne-macro-success.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/assert-ne-macro-unsized.rs (97%) rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/macro-comma-support.rs (100%) rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/macro-include-items-expr.rs (100%) rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/macro-include-items-item.rs (100%) rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/macro_crate_def_only.rs (100%) rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/macro_crate_nonterminal.rs (100%) rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/macro_export_inner_module.rs (100%) rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/macro_with_super_1.rs (100%) rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/two_macros.rs (100%) create mode 100644 src/test/ui/run-pass/macros/auxiliary/unstable-macros.rs rename src/test/{run-pass => ui/run-pass/macros}/auxiliary/use-macro-self.rs (100%) rename src/test/{run-pass => ui/run-pass/macros}/colorful-write-macros.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/conditional-debug-macro-on.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/die-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/log_syntax-trace_macros-macro-locations.rs (98%) create mode 100644 src/test/ui/run-pass/macros/log_syntax-trace_macros-macro-locations.stdout rename src/test/{run-pass => ui/run-pass/macros}/macro-2.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-at-most-once-rep.rs (97%) rename src/test/{run-pass => ui/run-pass/macros}/macro-attribute-expansion.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-attributes.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-block-nonterminal.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-comma-behavior.rs (99%) rename src/test/{run-pass => ui/run-pass/macros}/macro-comma-support.rs (99%) rename src/test/{run-pass => ui/run-pass/macros}/macro-crate-def-only.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-crate-nonterminal-renamed.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-crate-nonterminal.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-crate-use.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-deep_expansion.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-delimiter-significance.rs (97%) rename src/test/{run-pass => ui/run-pass/macros}/macro-doc-comments.rs (95%) rename src/test/{run-pass => ui/run-pass/macros}/macro-doc-escapes.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-doc-raw-str-hashes.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-export-inner-module.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-first-set.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-follow.rs (99%) rename src/test/{run-pass => ui/run-pass/macros}/macro-followed-by-seq.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-include-items.rs (93%) rename src/test/{run-pass => ui/run-pass/macros}/macro-interpolation.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-invocation-in-count-expr-fixed-array-type.rs (97%) rename src/test/{run-pass => ui/run-pass/macros}/macro-lifetime-used-with-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-lifetime-used-with-labels.rs (96%) create mode 100644 src/test/ui/run-pass/macros/macro-lifetime-used-with-labels.stderr rename src/test/{run-pass => ui/run-pass/macros}/macro-lifetime-used-with-static.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-lifetime.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-literal.rs (99%) rename src/test/{run-pass => ui/run-pass/macros}/macro-meta-items.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-method-issue-4621.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-multiple-items.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-named-default.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-nested_definition_issue-31946.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-nested_expr.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-nested_stmt_macros.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-nt-list.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-of-higher-order.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-pat-follow.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-pat-neg-lit.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-pat.rs (99%) rename src/test/{run-pass => ui/run-pass/macros}/macro-path.rs (93%) rename src/test/{run-pass => ui/run-pass/macros}/macro-pub-matcher.rs (97%) rename src/test/{run-pass => ui/run-pass/macros}/macro-seq-followed-by-seq.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-stability.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-stmt.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-stmt_macro_in_expr_macro.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-tt-followed-by-seq.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-use-all-and-none.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-use-all.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-use-both.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-use-one.rs (97%) rename src/test/{run-pass => ui/run-pass/macros}/macro-with-attrs1.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-with-attrs2.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro-with-braces-in-expr-position.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/macro_with_super_2.rs (98%) create mode 100644 src/test/ui/run-pass/macros/macros-in-extern.rs rename src/test/{run-pass => ui/run-pass/macros}/parse-complex-macro-invoc-op.rs (95%) rename src/test/{run-pass => ui/run-pass/macros}/paths-in-macro-invocations.rs (96%) rename src/test/{run-pass => ui/run-pass/macros}/pub-item-inside-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/pub-method-inside-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/semi-after-macro-ty.rs (97%) rename src/test/{run-pass => ui/run-pass/macros}/stmt_expr_attr_macro_parse.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/syntax-extension-cfg.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/syntax-extension-source-utils-files/includeme.fragment (100%) rename src/test/{run-pass => ui/run-pass/macros}/syntax-extension-source-utils.rs (89%) create mode 100644 src/test/ui/run-pass/macros/try-macro.rs rename src/test/{run-pass => ui/run-pass/macros}/two-macro-use.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/type-macros-hlist.rs (99%) rename src/test/{run-pass => ui/run-pass/macros}/type-macros-simple.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/typeck-macro-interaction-issue-8852.rs (98%) rename src/test/{run-pass => ui/run-pass/macros}/use-macro-self.rs (95%) rename src/test/{run-pass => ui/run-pass/methods}/auxiliary/method_self_arg1.rs (97%) rename src/test/{run-pass => ui/run-pass/methods}/auxiliary/method_self_arg2.rs (98%) rename src/test/{run-pass => ui/run-pass/methods}/method-argument-inference-associated-type.rs (98%) rename src/test/{run-pass => ui/run-pass/methods}/method-attributes.rs (95%) rename src/test/{run-pass => ui/run-pass/methods}/method-early-bound-lifetimes-on-self.rs (98%) rename src/test/{run-pass => ui/run-pass/methods}/method-mut-self-modifies-mut-slice-lvalue.rs (96%) rename src/test/{run-pass => ui/run-pass/methods}/method-normalize-bounds-issue-20604.rs (97%) rename src/test/{run-pass => ui/run-pass/methods}/method-projection.rs (99%) rename src/test/{run-pass => ui/run-pass/methods}/method-recursive-blanket-impl.rs (98%) rename src/test/{run-pass => ui/run-pass/methods}/method-self-arg-aux1.rs (96%) rename src/test/{run-pass => ui/run-pass/methods}/method-self-arg-aux2.rs (96%) rename src/test/{run-pass => ui/run-pass/methods}/method-self-arg-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/methods}/method-self-arg.rs (97%) rename src/test/{run-pass => ui/run-pass/methods}/method-two-trait-defer-resolution-1.rs (95%) rename src/test/{run-pass => ui/run-pass/methods}/method-two-trait-defer-resolution-2.rs (98%) rename src/test/{run-pass => ui/run-pass/methods}/method-two-traits-distinguished-via-where-clause.rs (97%) rename src/test/{run-pass => ui/run-pass/methods}/method-where-clause.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/auxiliary/mir_external_refs.rs (100%) rename src/test/{run-pass => ui/run-pass/mir}/mir-inlining/ice-issue-45493.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir-inlining/ice-issue-45885.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir-inlining/no-trait-method-issue-40473.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir-typeck-normalize-fn-sig.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_adt_construction.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_ascription_coercion.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_augmented_assignments.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_autoderef.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_boxing.rs (97%) rename src/test/{run-pass => ui/run-pass/mir}/mir_build_match_comparisons.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_call_with_associated_type.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_calls_to_shims.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_cast_fn_ret.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_array.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_array_2.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_call_converging.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_calls.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_calls_variadic.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_critical_edge.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_spike1.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_switch.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_codegen_switchint.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_coercion_casts.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_coercions.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_constval_adts.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_drop_order.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_early_return_scope.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_fat_ptr.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_fat_ptr_drop.rs (96%) rename src/test/{run-pass => ui/run-pass/mir}/mir_heavy_promoted.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_match_arm_guard.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_misc_casts.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_overflow_off.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_raw_fat_ptr.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_refs_correct.rs (99%) rename src/test/{run-pass => ui/run-pass/mir}/mir_small_agg_arg.rs (97%) rename src/test/{run-pass => ui/run-pass/mir}/mir_struct_with_assoc_ty.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_temp_promotions.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_void_return.rs (98%) rename src/test/{run-pass => ui/run-pass/mir}/mir_void_return_2.rs (97%) rename src/test/{run-pass => ui/run-pass/modules}/auxiliary/two_macros_2.rs (100%) rename src/test/{run-pass => ui/run-pass/modules}/mod-inside-fn.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod-view-items.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_implicit.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_implicit_aux/compiletest-ignore-dir (100%) create mode 100644 src/test/ui/run-pass/modules/mod_dir_implicit_aux/mod.rs rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_path.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_path2.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_path3.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_path_multi.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_recursive.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_simple.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_simple/compiletest-ignore-dir (100%) rename src/test/{run-pass => ui/run-pass/modules}/mod_dir_simple/load_another_mod.rs (97%) create mode 100644 src/test/ui/run-pass/modules/mod_dir_simple/test.rs rename src/test/{run-pass => ui/run-pass/modules}/mod_file.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/mod_file_aux.rs (97%) rename src/test/{run-pass => ui/run-pass/modules}/mod_file_with_path_attr.rs (98%) rename src/test/{run-pass => ui/run-pass/modules}/module-polymorphism3-files/compiletest-ignore-dir (100%) rename src/test/{run-pass => ui/run-pass/modules}/module-polymorphism3-files/float-template/inst_f32.rs (100%) rename src/test/{run-pass => ui/run-pass/modules}/module-polymorphism3-files/float-template/inst_f64.rs (100%) rename src/test/{run-pass => ui/run-pass/modules}/module-polymorphism3-files/float-template/inst_float.rs (100%) rename src/test/{run-pass => ui/run-pass/moves}/move-1-unique.rs (97%) rename src/test/{run-pass => ui/run-pass/moves}/move-2-unique.rs (95%) rename src/test/{run-pass => ui/run-pass/moves}/move-2.rs (95%) rename src/test/{run-pass => ui/run-pass/moves}/move-3-unique.rs (97%) rename src/test/{run-pass => ui/run-pass/moves}/move-4-unique.rs (96%) rename src/test/{run-pass => ui/run-pass/moves}/move-4.rs (96%) rename src/test/{run-pass => ui/run-pass/moves}/move-arg-2-unique.rs (96%) rename src/test/{run-pass => ui/run-pass/moves}/move-arg-2.rs (96%) rename src/test/{run-pass => ui/run-pass/moves}/move-arg.rs (97%) rename src/test/{run-pass => ui/run-pass/moves}/move-nullary-fn.rs (98%) rename src/test/{run-pass => ui/run-pass/moves}/move-out-of-field.rs (98%) rename src/test/{run-pass => ui/run-pass/moves}/move-scalar.rs (97%) rename src/test/{run-pass => ui/run-pass/moves}/moves-based-on-type-capture-clause.rs (96%) rename src/test/{ => ui}/run-pass/nll/issue-47153-generic-const.rs (98%) rename src/test/{ => ui}/run-pass/nll/issue-47589.rs (98%) rename src/test/{ => ui}/run-pass/nll/issue-48623-closure.rs (98%) rename src/test/{ => ui}/run-pass/nll/issue-48623-generator.rs (98%) rename src/test/{ => ui}/run-pass/nll/issue-50343.rs (97%) rename src/test/{ => ui}/run-pass/nll/issue-50461-used-mut-from-moves.rs (98%) create mode 100644 src/test/ui/run-pass/nll/issue-53123-raw-pointer-cast.rs rename src/test/{ => ui}/run-pass/nll/mutating_references.rs (98%) rename src/test/{ => ui}/run-pass/nll/process_or_insert_default.rs (98%) rename src/test/{ => ui}/run-pass/nll/rc-loop.rs (98%) rename src/test/{ => ui}/run-pass/non_modrs_mods/foors_mod.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/foors_mod/compiletest-ignore-dir (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/foors_mod/inner_foors_mod.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/foors_mod/inner_foors_mod/innest.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/foors_mod/inner_modrs_mod/innest.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/foors_mod/inner_modrs_mod/mod.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/modrs_mod/compiletest-ignore-dir (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/modrs_mod/inner_foors_mod.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/modrs_mod/inner_foors_mod/innest.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/modrs_mod/inner_modrs_mod/innest.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/modrs_mod/inner_modrs_mod/mod.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/modrs_mod/mod.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/arbitrary_name.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/compiletest-ignore-dir (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs (100%) rename src/test/{ => ui}/run-pass/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs (100%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/arith-0.rs (97%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/arith-1.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/arith-2.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/arith-unsigned.rs (96%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/div-mod.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/float-int-invalid-const-cast.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/float-literal-inference.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/float-nan.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/float-signature.rs (98%) create mode 100644 src/test/ui/run-pass/numbers-arithmetic/float.rs rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/float2.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/float_math.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/floatlits.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/i128-ffi.rs (96%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/i128.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/i32-sub.rs (97%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/i8-incr.rs (97%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/int-abs-overflow.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/int.rs (97%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/integer-literal-radix.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/integer-literal-suffix-inference-2.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/integer-literal-suffix-inference-3.rs (97%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/integer-literal-suffix-inference.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/next-power-of-two-overflow-debug.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/next-power-of-two-overflow-ndebug.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/num-wrapping.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/numeric-method-autoexport.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/promoted_overflow_opt.rs (97%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/saturating-float-casts.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/shift-near-oflo.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/shift-various-types.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/shift.rs (96%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/signed-shift-const-eval.rs (92%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/u128-as-f32.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/u128.rs (99%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/u32-decr.rs (97%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/u8-incr-decr.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/u8-incr.rs (98%) rename src/test/{run-pass => ui/run-pass/numbers-arithmetic}/uint.rs (97%) rename src/test/{run-pass => ui/run-pass/overloaded}/auxiliary/overloaded_autoderef_xc.rs (100%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-autoderef-count.rs (99%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-autoderef-indexing.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-autoderef-order.rs (99%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-autoderef-vtable.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-autoderef-xcrate.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-autoderef.rs (97%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-calls-object-one-arg.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-calls-object-two-args.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-calls-object-zero-args.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-calls-param-vtables.rs (99%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-calls-simple.rs (99%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-calls-zero-args.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-deref-count.rs (99%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-deref.rs (99%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-index-assoc-list.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-index-autoderef.rs (97%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-index-in-field.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded-index.rs (98%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded_deref_with_ref_pattern.rs (99%) rename src/test/{run-pass => ui/run-pass/overloaded}/overloaded_deref_with_ref_pattern_issue15609.rs (98%) rename src/test/{run-pass => ui/run-pass/packed}/auxiliary/packed.rs (100%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-borrow-element.rs (98%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-drop-aligned.rs (98%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-generic-layout.rs (96%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-generic-size.rs (94%) create mode 100644 src/test/ui/run-pass/packed/packed-struct-generic-size.stderr rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-layout.rs (98%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-match.rs (99%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-optimized-enum.rs (95%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-size-xc.rs (98%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-size.rs (97%) rename src/test/{run-pass => ui/run-pass/packed}/packed-struct-vec.rs (99%) rename src/test/{run-pass => ui/run-pass/packed}/packed-tuple-struct-layout.rs (98%) rename src/test/{run-pass => ui/run-pass/packed}/packed-tuple-struct-size.rs (97%) rename src/test/{ => ui}/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs (97%) rename src/test/{ => ui}/run-pass/panic-runtime/abort.rs (97%) rename src/test/{ => ui}/run-pass/panic-runtime/auxiliary/exit-success-if-unwind.rs (100%) rename src/test/{ => ui}/run-pass/panic-runtime/link-to-abort.rs (93%) rename src/test/{ => ui}/run-pass/panic-runtime/link-to-unwind.rs (97%) rename src/test/{ => ui}/run-pass/panic-runtime/lto-abort.rs (98%) rename src/test/{ => ui}/run-pass/panic-runtime/lto-unwind.rs (98%) rename src/test/{run-pass => ui/run-pass/panics}/panic-handler-chain.rs (94%) rename src/test/{run-pass => ui/run-pass/panics}/panic-handler-flail-wildly.rs (96%) rename src/test/{run-pass => ui/run-pass/panics}/panic-handler-set-twice.rs (93%) rename src/test/{run-pass => ui/run-pass/panics}/panic-in-dtor-drops-fields.rs (95%) rename src/test/{run-pass => ui/run-pass/panics}/panic-recover-propagate.rs (97%) create mode 100644 src/test/ui/run-pass/panics/panic-safe.rs rename src/test/{run-pass => ui/run-pass/privacy}/auxiliary/priv-impl-prim-ty.rs (100%) rename src/test/{run-pass => ui/run-pass/privacy}/auxiliary/privacy_reexport.rs (100%) rename src/test/{run-pass => ui/run-pass/privacy}/auxiliary/pub_use_mods_xcrate.rs (100%) rename src/test/{run-pass => ui/run-pass/privacy}/auxiliary/pub_use_xcrate1.rs (100%) rename src/test/{run-pass => ui/run-pass/privacy}/auxiliary/pub_use_xcrate2.rs (100%) rename src/test/{run-pass => ui/run-pass/privacy}/priv-impl-prim-ty.rs (98%) rename src/test/{run-pass => ui/run-pass/privacy}/privacy-ns.rs (97%) rename src/test/{run-pass => ui/run-pass/privacy}/privacy-reexport.rs (98%) rename src/test/{run-pass => ui/run-pass/privacy}/privacy1.rs (98%) rename src/test/{run-pass => ui/run-pass/privacy}/private-class-field.rs (94%) rename src/test/{run-pass => ui/run-pass/privacy}/private-method.rs (95%) rename src/test/{run-pass => ui/run-pass/privacy}/pub-extern-privacy.rs (98%) rename src/test/{run-pass => ui/run-pass/privacy}/pub-use-xcrate.rs (98%) rename src/test/{run-pass => ui/run-pass/privacy}/pub_use_mods_xcrate_exe.rs (98%) rename src/test/{run-pass => ui/run-pass/process}/process-envs.rs (99%) rename src/test/{run-pass => ui/run-pass/process}/process-exit.rs (98%) rename src/test/{run-pass => ui/run-pass/process}/process-remove-from-env.rs (99%) rename src/test/{run-pass => ui/run-pass/process}/process-sigpipe.rs (97%) rename src/test/{run-pass => ui/run-pass/process}/process-spawn-nonexistent.rs (98%) rename src/test/{run-pass => ui/run-pass/process}/process-spawn-with-unicode-params.rs (99%) rename src/test/{run-pass => ui/run-pass/process}/process-status-inherits-stdin.rs (99%) rename src/test/{run-pass => ui/run-pass/regions}/regions-addr-of-interior-of-unique-box.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-addr-of-ret.rs (97%) rename src/test/{run-pass => ui/run-pass/regions}/regions-assoc-type-region-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-assoc-type-static-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-borrow-at.rs (95%) rename src/test/{run-pass => ui/run-pass/regions}/regions-borrow-evec-fixed.rs (97%) rename src/test/{run-pass => ui/run-pass/regions}/regions-borrow-evec-uniq.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-borrow-uniq.rs (95%) rename src/test/{run-pass => ui/run-pass/regions}/regions-bot.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-bound-lists-feature-gate-2.rs (93%) rename src/test/{run-pass => ui/run-pass/regions}/regions-bound-lists-feature-gate.rs (93%) rename src/test/{run-pass => ui/run-pass/regions}/regions-close-over-type-parameter-successfully.rs (96%) rename src/test/{run-pass => ui/run-pass/regions}/regions-copy-closure.rs (94%) rename src/test/{run-pass => ui/run-pass/regions}/regions-creating-enums2.rs (93%) rename src/test/{run-pass => ui/run-pass/regions}/regions-creating-enums5.rs (93%) rename src/test/{run-pass => ui/run-pass/regions}/regions-debruijn-of-object.rs (94%) rename src/test/{run-pass => ui/run-pass/regions}/regions-dependent-addr-of.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-dependent-autofn.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-dependent-autoslice.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-dependent-let-ref.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-early-bound-lifetime-in-assoc-fn.rs (99%) rename src/test/{run-pass => ui/run-pass/regions}/regions-early-bound-trait-param.rs (99%) rename src/test/{run-pass => ui/run-pass/regions}/regions-early-bound-used-in-bound-method.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-early-bound-used-in-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-early-bound-used-in-type-param.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-escape-into-other-fn.rs (95%) rename src/test/{run-pass => ui/run-pass/regions}/regions-expl-self.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-fn-subtyping-2.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-fn-subtyping.rs (95%) rename src/test/{run-pass => ui/run-pass/regions}/regions-free-region-outlives-static-outlives-free-region.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-borrow-scope-addr-of.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-borrow-scope-view.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-borrow-scope-within-loop-ok.rs (95%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-borrow-scope.rs (95%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-call-2.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-call.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-contravariance-due-to-ret.rs (94%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-reborrow-ref-mut-recurse.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-region-in-fn-but-not-type.rs (94%) rename src/test/{run-pass => ui/run-pass/regions}/regions-infer-static-from-proc.rs (94%) rename src/test/{run-pass => ui/run-pass/regions}/regions-issue-21422.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-issue-22246.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-lifetime-nonfree-late-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-lifetime-static-items-enclosing-scopes.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-link-fn-args.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-lub-ref-ref-rc.rs (99%) rename src/test/{run-pass => ui/run-pass/regions}/regions-mock-codegen.rs (96%) rename src/test/{run-pass => ui/run-pass/regions}/regions-no-bound-in-argument-cleanup.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-no-variance-from-fn-generics.rs (99%) rename src/test/{run-pass => ui/run-pass/regions}/regions-nullary-variant.rs (93%) rename src/test/{run-pass => ui/run-pass/regions}/regions-params.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-reassign-let-bound-pointer.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-reassign-match-bound-pointer.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-refcell.rs (99%) rename src/test/{run-pass => ui/run-pass/regions}/regions-relate-bound-regions-on-closures-to-inference-variables.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-return-interior-of-option.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-scope-chain-example.rs (99%) rename src/test/{run-pass => ui/run-pass/regions}/regions-self-impls.rs (94%) rename src/test/{run-pass => ui/run-pass/regions}/regions-self-in-enums.rs (94%) rename src/test/{run-pass => ui/run-pass/regions}/regions-simple.rs (97%) create mode 100644 src/test/ui/run-pass/regions/regions-static-bound.rs rename src/test/{run-pass => ui/run-pass/regions}/regions-static-closure.rs (94%) rename src/test/{run-pass => ui/run-pass/regions}/regions-trait-object-1.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-variance-contravariant-use-contravariant.rs (98%) rename src/test/{run-pass => ui/run-pass/regions}/regions-variance-covariant-use-covariant.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1014-2.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1014.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1789-as-cell/from-mut.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs (97%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1937-termination-trait/termination-trait-for-empty.rs (97%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1937-termination-trait/termination-trait-for-exitcode.rs (97%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs (97%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs (97%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1937-termination-trait/termination-trait-for-result.rs (97%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-1937-termination-trait/termination-trait-for-str.rs (97%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/box.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/constref.rs (99%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/enum.rs (99%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/for.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/general.rs (99%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/lit.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/range.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/ref-region.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/reset-mode.rs (98%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2005-default-binding-mode/slice.rs rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/struct.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/tuple-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2005-default-binding-mode/tuple.rs (98%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/enums.rs create mode 100644 src/test/ui/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/structs.rs create mode 100644 src/test/ui/run-pass/rfcs/rfc-2008-non-exhaustive/auxiliary/variants.rs create mode 100644 src/test/ui/run-pass/rfcs/rfc-2008-non-exhaustive/enums.rs rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2008-non-exhaustive/enums_same_crate.rs (98%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2008-non-exhaustive/structs.rs rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2008-non-exhaustive/structs_same_crate.rs (98%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2008-non-exhaustive/variants.rs rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2008-non-exhaustive/variants_same_crate.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2126-crate-paths/crate-path-absolute.rs (75%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-absolute.stderr rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2126-crate-paths/crate-path-visibility-ambiguity.rs (88%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2126-crate-paths/crate-path-visibility-ambiguity.stderr rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs (100%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2126-extern-absolute-paths/extern.rs (95%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/test.rs create mode 100644 src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2151-raw-identifiers/attr.rs (95%) create mode 100644 src/test/ui/run-pass/rfcs/rfc-2151-raw-identifiers/basic.rs create mode 100644 src/test/ui/run-pass/rfcs/rfc-2151-raw-identifiers/items.rs create mode 100644 src/test/ui/run-pass/rfcs/rfc-2151-raw-identifiers/macros.rs create mode 100644 src/test/ui/run-pass/rfcs/rfc-2175-or-if-while-let/basic.rs create mode 100644 src/test/ui/run-pass/rfcs/rfc-2302-self-struct-ctor.rs rename src/test/{run-pass => ui/run-pass/rfcs}/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc1445/eq-allows-match-on-ty-in-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc1445/eq-allows-match.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc1623.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc1717/auxiliary/clibrary.rs (100%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc1717/library-override.rs (98%) rename src/test/{run-pass => ui/run-pass/rfcs}/rfc1857-drop-order.rs (99%) rename src/test/{run-pass => ui/run-pass/self}/arbitrary_self_types_raw_pointer_struct.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/arbitrary_self_types_raw_pointer_trait.rs (99%) rename src/test/{run-pass => ui/run-pass/self}/arbitrary_self_types_silly.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/arbitrary_self_types_struct.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/arbitrary_self_types_trait.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/arbitrary_self_types_unsized_struct.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/auxiliary/explicit_self_xcrate.rs (100%) rename src/test/{run-pass => ui/run-pass/self}/builtin-superkinds-self-type.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/by-value-self-in-mut-slot.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/explicit-self-closures.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/explicit-self-generic.rs (97%) rename src/test/{run-pass => ui/run-pass/self}/explicit-self-objects-uniq.rs (96%) rename src/test/{run-pass => ui/run-pass/self}/explicit-self.rs (96%) rename src/test/{run-pass => ui/run-pass/self}/explicit_self_xcrate_exe.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/move-self.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/object-safety-sized-self-by-value-self.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/object-safety-sized-self-generic-method.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/object-safety-sized-self-return-Self.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/self-impl.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/self-in-mut-slot-default-method.rs (97%) rename src/test/{run-pass => ui/run-pass/self}/self-in-mut-slot-immediate-value.rs (98%) create mode 100644 src/test/ui/run-pass/self/self-in-typedefs.rs rename src/test/{run-pass => ui/run-pass/self}/self-re-assign.rs (96%) rename src/test/{run-pass => ui/run-pass/self}/self-shadowing-import.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/self-type-param.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/string-self-append.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/ufcs-explicit-self.rs (98%) rename src/test/{run-pass => ui/run-pass/self}/uniq-self-in-mut-slot.rs (96%) rename src/test/{run-pass => ui/run-pass/self}/where-for-self.rs (99%) rename src/test/{run-pass => ui/run-pass/sepcomp}/auxiliary/sepcomp-extern-lib.rs (100%) rename src/test/{run-pass => ui/run-pass/sepcomp}/auxiliary/sepcomp_cci_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/sepcomp}/auxiliary/sepcomp_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/sepcomp}/sepcomp-cci.rs (98%) rename src/test/{run-pass => ui/run-pass/sepcomp}/sepcomp-extern.rs (97%) rename src/test/{run-pass => ui/run-pass/sepcomp}/sepcomp-fns-backwards.rs (98%) rename src/test/{run-pass => ui/run-pass/sepcomp}/sepcomp-fns.rs (98%) rename src/test/{run-pass => ui/run-pass/sepcomp}/sepcomp-lib-lto.rs (98%) rename src/test/{run-pass => ui/run-pass/sepcomp}/sepcomp-lib.rs (98%) rename src/test/{run-pass => ui/run-pass/sepcomp}/sepcomp-statics.rs (98%) rename src/test/{run-pass => ui/run-pass/sepcomp}/sepcomp-unwind.rs (99%) rename src/test/{run-pass => ui/run-pass/simd}/simd-generics.rs (96%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-float-math.rs (99%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-float-minmax.rs (83%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-generic-arithmetic.rs (99%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-generic-cast.rs (99%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-generic-comparison.rs (99%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-generic-elements.rs (99%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-generic-gather.rs (99%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-generic-reduction.rs (99%) rename src/test/{run-pass => ui/run-pass/simd}/simd-intrinsic-generic-select.rs (98%) rename src/test/{run-pass => ui/run-pass/simd}/simd-size-align.rs (98%) rename src/test/{run-pass => ui/run-pass/simd}/simd-target-feature-mixup.rs (98%) rename src/test/{run-pass => ui/run-pass/simd}/simd-type.rs (98%) rename src/test/{run-pass => ui/run-pass/simd}/simd-upgraded.rs (94%) rename src/test/{ => ui}/run-pass/specialization/README.md (100%) rename src/test/{ => ui}/run-pass/specialization/assoc-ty-graph-cycle.rs (98%) rename src/test/{ => ui}/run-pass/specialization/auxiliary/cross_crates_defaults.rs (100%) rename src/test/{run-pass => ui/run-pass/specialization}/auxiliary/go_trait.rs (100%) rename src/test/{ => ui}/run-pass/specialization/auxiliary/specialization_cross_crate.rs (100%) rename src/test/{ => ui}/run-pass/specialization/cross-crate-defaults.rs (98%) rename src/test/{ => ui}/run-pass/specialization/defaultimpl/allowed-cross-crate.rs (98%) rename src/test/{ => ui}/run-pass/specialization/defaultimpl/auxiliary/go_trait.rs (100%) rename src/test/{ => ui}/run-pass/specialization/defaultimpl/out-of-order.rs (98%) rename src/test/{ => ui}/run-pass/specialization/defaultimpl/overlap-projection.rs (98%) rename src/test/{ => ui}/run-pass/specialization/defaultimpl/projection.rs (98%) rename src/test/{ => ui}/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-allowed-cross-crate.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-assoc-fns.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-basics.rs (99%) rename src/test/{ => ui}/run-pass/specialization/specialization-cross-crate-no-gate.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-cross-crate.rs (99%) rename src/test/{ => ui}/run-pass/specialization/specialization-default-methods.rs (99%) rename src/test/{ => ui}/run-pass/specialization/specialization-on-projection.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-out-of-order.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-overlap-projection.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-projection-alias.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-projection.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-super-traits.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-translate-projections-with-lifetimes.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-translate-projections-with-params.rs (98%) rename src/test/{ => ui}/run-pass/specialization/specialization-translate-projections.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/auxiliary/static-function-pointer-aux.rs (100%) rename src/test/{run-pass => ui/run-pass/statics}/auxiliary/static-methods-crate.rs (100%) rename src/test/{run-pass => ui/run-pass/statics}/auxiliary/static_fn_inline_xc_aux.rs (100%) rename src/test/{run-pass => ui/run-pass/statics}/auxiliary/static_fn_trait_xc_aux.rs (100%) rename src/test/{run-pass => ui/run-pass/statics}/auxiliary/static_mut_xc.rs (100%) rename src/test/{run-pass => ui/run-pass/statics}/static-fn-inline-xc.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/static-fn-trait-xc.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/static-function-pointer-xc.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/static-function-pointer.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/static-impl.rs (97%) rename src/test/{run-pass => ui/run-pass/statics}/static-method-in-trait-with-tps-intracrate.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/static-method-xcrate.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/static-methods-in-traits.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/static-methods-in-traits2.rs (98%) rename src/test/{run-pass => ui/run-pass/statics}/static-mut-foreign.rs (99%) rename src/test/{run-pass => ui/run-pass/statics}/static-mut-xc.rs (96%) rename src/test/{run-pass => ui/run-pass/statics}/static-recursive.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/align-struct.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/cci_class.rs (100%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/cci_class_2.rs (100%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/cci_class_3.rs (100%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/cci_class_4.rs (100%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/cci_class_6.rs (100%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/cci_class_cast.rs (100%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/cci_class_trait.rs (100%) create mode 100644 src/test/ui/run-pass/structs-enums/auxiliary/empty-struct.rs rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/namespaced_enum_emulate_flat.rs (100%) create mode 100644 src/test/ui/run-pass/structs-enums/auxiliary/namespaced_enums.rs create mode 100644 src/test/ui/run-pass/structs-enums/auxiliary/newtype_struct_xc.rs rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/struct_destructuring_cross_crate.rs (100%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/struct_variant_xc_aux.rs (100%) rename src/test/{run-pass => ui/run-pass/structs-enums}/auxiliary/xcrate_struct_aliases.rs (100%) create mode 100644 src/test/ui/run-pass/structs-enums/borrow-tuple-fields.rs rename src/test/{run-pass => ui/run-pass/structs-enums}/class-attributes-1.rs (94%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-attributes-2.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-cast-to-trait-cross-crate-2.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-cast-to-trait-multiple-types.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-cast-to-trait.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-dtor.rs (94%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-exports.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-impl-very-parameterized-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-implement-trait-cross-crate.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-implement-traits.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-method-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-methods-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-methods.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-poly-methods-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-poly-methods.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-separate-impl.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-str-field.rs (93%) rename src/test/{run-pass => ui/run-pass/structs-enums}/class-typarams.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/classes-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/classes-self-referential.rs (93%) rename src/test/{run-pass => ui/run-pass/structs-enums}/classes-simple-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/classes-simple-method.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/classes-simple.rs (94%) rename src/test/{run-pass => ui/run-pass/structs-enums}/classes.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/codegen-tag-static-padding.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/compare-generic-enums.rs (94%) rename src/test/{run-pass => ui/run-pass/structs-enums}/discrim-explicit-23030.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/empty-struct-braces.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/empty-tag.rs (94%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-alignment.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-clike-ffi-as-int.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-discr.rs (98%) create mode 100644 src/test/ui/run-pass/structs-enums/enum-discrim-autosizing.rs rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-discrim-manual-sizing.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-discrim-range-overflow.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-discrim-width-stuff.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-disr-val-pretty.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-export-inheritance.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-layout-optimization.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-non-c-like-repr-c-and-int.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-non-c-like-repr-c.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-non-c-like-repr-int.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-null-pointer-opt.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-nullable-const-null-with-fields.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-nullable-simplifycfg-misopt.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-univariant-repr.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-variants.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/enum-vec-initializer.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/export-abstract-tag.rs (94%) rename src/test/{run-pass => ui/run-pass/structs-enums}/export-tag-variant.rs (92%) rename src/test/{run-pass => ui/run-pass/structs-enums}/expr-if-struct.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/expr-match-struct.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/field-destruction-order.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/foreign-struct.rs (93%) rename src/test/{run-pass => ui/run-pass/structs-enums}/functional-struct-upd.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/ivec-tag.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/module-qualified-struct-destructure.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/namespaced-enum-emulate-flat-xc.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/namespaced-enum-emulate-flat.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/namespaced-enum-glob-import-xcrate.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/namespaced-enum-glob-import.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/namespaced-enums-xcrate.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/namespaced-enums.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/nested-enum-same-names.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/newtype-struct-drop-run.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/newtype-struct-with-dtor.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/newtype-struct-xc-2.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/newtype-struct-xc.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/nonzero-enum.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/numeric-fields.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/object-lifetime-default-from-ref-struct.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/object-lifetime-default-from-rptr-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/rec-align-u32.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/rec-align-u64.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/rec-auto.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/rec-extend.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/rec-tup.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/rec.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/record-pat.rs (91%) rename src/test/{run-pass => ui/run-pass/structs-enums}/resource-in-struct.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/simple-generic-tag.rs (92%) rename src/test/{run-pass => ui/run-pass/structs-enums}/simple-match-generic-tag.rs (93%) rename src/test/{run-pass => ui/run-pass/structs-enums}/small-enum-range-edge.rs (88%) rename src/test/{run-pass => ui/run-pass/structs-enums}/small-enums-with-fields.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-aliases-xcrate.rs (93%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-aliases.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-destructuring-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-field-shorthand.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-like-variant-construct.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-like-variant-match.rs (94%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-lit-functional-no-fields.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-literal-dtor.rs (93%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-new-as-field-name.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-order-of-eval-1.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-order-of-eval-2.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-order-of-eval-3.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-order-of-eval-4.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-partial-move-1.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-partial-move-2.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-path-associated-type.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-path-self.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-pattern-matching.rs (92%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-return.rs (99%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct-variant-field-visibility.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct_variant_xc.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/struct_variant_xc_match.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-align-dyn-u64.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-align-dyn-variants.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-align-shape.rs (94%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-align-u64.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-disr-val-shape.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-exports.rs (95%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-in-block.rs (93%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-variant-disr-type-mismatch.rs (92%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag-variant-disr-val.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tag.rs (96%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tuple-struct-construct.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tuple-struct-constructor-pointer.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tuple-struct-destructuring.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tuple-struct-matching.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/tuple-struct-trivial.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/uninstantiable-struct.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/unit-like-struct-drop-run.rs (98%) rename src/test/{run-pass => ui/run-pass/structs-enums}/unit-like-struct.rs (97%) rename src/test/{run-pass => ui/run-pass/structs-enums}/variant-structs-trivial.rs (97%) rename src/test/{ => ui}/run-pass/thinlto/all-crates.rs (97%) rename src/test/{ => ui}/run-pass/thinlto/auxiliary/dylib.rs (100%) rename src/test/{ => ui}/run-pass/thinlto/auxiliary/msvc-imp-present.rs (100%) rename src/test/{ => ui}/run-pass/thinlto/auxiliary/thin-lto-inlines-aux.rs (100%) rename src/test/{ => ui}/run-pass/thinlto/dylib-works.rs (97%) rename src/test/{ => ui}/run-pass/thinlto/msvc-imp-present.rs (99%) rename src/test/{ => ui}/run-pass/thinlto/thin-lto-inlines.rs (98%) rename src/test/{ => ui}/run-pass/thinlto/thin-lto-inlines2.rs (98%) rename src/test/{ => ui}/run-pass/thinlto/weak-works.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/auxiliary/thread-local-extern-static.rs (100%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/comm.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/send-is-not-static-par-for.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/send-resource.rs (95%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/send-type-inference.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/send_str_hashmap.rs (99%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/send_str_treemap.rs (99%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/sendable-class.rs (94%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/sendfn-is-a-block.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/sendfn-spawn-with-fn-arg.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/spawn-fn.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/spawn-types.rs (95%) create mode 100644 src/test/ui/run-pass/threads-sendsync/spawn.rs rename src/test/{run-pass => ui/run-pass/threads-sendsync}/spawn2.rs (99%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/spawning-with-debug.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/std-sync-right-kind-impls.rs (91%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/sync-send-atomics.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/sync-send-in-std.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/sync-send-iterators-in-libcollections.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/sync-send-iterators-in-libcore.rs (99%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-0.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-1.rs (96%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-10.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-11.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-12.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-13.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-14.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-15.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-16.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-17.rs (96%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-3.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-4.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-5.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-6.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-7.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-9.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-comm-chan-nil.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-life-0.rs (96%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-spawn-move-and-copy.rs (93%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/task-stderr.rs (99%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/thread-local-extern-static.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/thread-local-syntax.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/threads.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/tls-dtors-are-run-in-a-static-binary.rs (98%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/tls-init-on-init.rs (97%) rename src/test/{run-pass => ui/run-pass/threads-sendsync}/tls-try-with.rs (96%) rename src/test/{run-pass => ui/run-pass/traits}/anon-trait-static-method.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/anon_trait_static_method_exe.rs (93%) rename src/test/{run-pass => ui/run-pass/traits}/assignability-trait.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/astconv-cycle-between-trait-and-type.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/augmented-assignments-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/auto-traits.rs (98%) create mode 100644 src/test/ui/run-pass/traits/auxiliary/anon_trait_static_method_lib.rs rename src/test/{run-pass/specialization => ui/run-pass/traits}/auxiliary/go_trait.rs (100%) rename src/test/{run-pass => ui/run-pass/traits}/auxiliary/trait_default_method_xc_aux.rs (100%) rename src/test/{run-pass => ui/run-pass/traits}/auxiliary/trait_default_method_xc_aux_2.rs (100%) rename src/test/{run-pass => ui/run-pass/traits}/auxiliary/trait_inheritance_auto_xc_2_aux.rs (100%) rename src/test/{run-pass => ui/run-pass/traits}/auxiliary/trait_inheritance_auto_xc_aux.rs (100%) rename src/test/{run-pass => ui/run-pass/traits}/auxiliary/trait_inheritance_overloading_xc.rs (100%) rename src/test/{compile-fail => ui/run-pass/traits}/auxiliary/trait_safety_lib.rs (100%) rename src/test/{run-pass => ui/run-pass/traits}/auxiliary/trait_xc_call_aux.rs (100%) rename src/test/{run-pass => ui/run-pass/traits}/auxiliary/traitimpl.rs (100%) rename src/test/{run-pass => ui/run-pass/traits}/conservative_impl_trait.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/cycle-trait-type-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/default-method-supertrait-vtable.rs (98%) create mode 100644 src/test/ui/run-pass/traits/dyn-trait.rs rename src/test/{run-pass => ui/run-pass/traits}/fmt-pointer-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/impl-implicit-trait.rs (94%) rename src/test/{run-pass => ui/run-pass/traits}/impl-inherent-prefer-over-trait.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/infer-from-object-trait-issue-26952.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/inherent-trait-method-order.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/kindck-owned-trait-contains-1.rs (92%) rename src/test/{run-pass => ui/run-pass/traits}/multiple-trait-bounds.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/object-one-type-two-traits.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/overlap-permitted-for-marker-traits-neg.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/overlap-permitted-for-marker-traits.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/parameterized-trait-with-bounds.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/supertrait-default-generics.rs (96%) rename src/test/{run-pass => ui/run-pass/traits}/syntax-trait-polarity.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-bounds-basic.rs (93%) rename src/test/{run-pass => ui/run-pass/traits}/trait-bounds-impl-comparison-duplicates.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-bounds-in-arc.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-bounds-on-structs-and-enums.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/trait-bounds-recursion.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-bounds.rs (93%) rename src/test/{run-pass => ui/run-pass/traits}/trait-cache-issue-18209.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-coercion-generic.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-coercion.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-composition-trivial.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-copy-guessing.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/trait-default-method-bound-subst.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-default-method-bound-subst2.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-default-method-bound-subst3.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-default-method-bound-subst4.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-default-method-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-default-method-xc-2.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-default-method-xc.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/trait-false-ambiguity-where-clause-builtin-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-generic.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/trait-impl-2.rs (94%) rename src/test/{run-pass => ui/run-pass/traits}/trait-impl.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-auto-xc-2.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-auto-xc.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-auto.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-call-bound-inherited.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-call-bound-inherited2.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-cast-without-call-to-supertrait.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-cast.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-cross-trait-call-xc.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-cross-trait-call.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-diamond.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-multiple-inheritors.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-multiple-params.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-num.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-num0.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-num1.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-num2.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-num3.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-num5.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-overloading-simple.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-overloading-xc-exe.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-overloading.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-self-in-supertype.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-self.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-simple.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-static.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-static2.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-subst.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-subst2.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance-visibility.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-inheritance2.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-item-inside-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-object-auto-dedup.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/trait-object-exclusion.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-object-generics.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/trait-object-lifetime-first.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-object-with-lifetime-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-region-pointer-simple.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-safety-ok-cc.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-safety-ok.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-static-method-overwriting.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/trait-to-str.rs (96%) rename src/test/{run-pass => ui/run-pass/traits}/trait-where-clause-vs-impl.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/trait-with-bounds-default.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-assoc-type-in-supertrait.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-conditional-dispatch.rs (97%) rename src/test/{run-pass => ui/run-pass/traits}/traits-conditional-model-fn.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/traits-default-method-macro.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-default-method-mut.rs (95%) rename src/test/{run-pass => ui/run-pass/traits}/traits-default-method-self.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-default-method-trivial.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-elaborate-type-region.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/traits-impl-object-overlap-issue-23853.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-issue-22019.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/traits-issue-22110.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-issue-22655.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-issue-23003.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-issue-26339.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-multidispatch-infer-convert-target.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-negative-impls.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/traits-repeated-supertrait.rs (99%) rename src/test/{run-pass => ui/run-pass/traits}/ufcs-trait-object.rs (98%) rename src/test/{run-pass => ui/run-pass/traits}/use-trait-before-def.rs (93%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/auxiliary/unboxed-closures-cross-crate.rs (100%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-all-traits.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-blanket-fn-mut.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-blanket-fn.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-boxed.rs (96%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-by-ref.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-call-fn-autoderef.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-call-sugar-autoderef.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-call-sugar-object-autoderef.rs (96%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-call-sugar-object.rs (96%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-counter-not-moved.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-cross-crate.rs (94%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-direct-sugary-call.rs (97%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-drop.rs (99%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-extern-fn-hr.rs (99%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-extern-fn.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-fn-as-fnmut-and-fnonce.rs (99%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-fnmut-as-fnonce.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-generic.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-arg-types-from-expected-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-arg-types-from-expected-object-type.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-arg-types-w-bound-regs-from-expected-bound.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-explicit-call-early.rs (97%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-fnmut-calling-fnmut.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-fnmut-move.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-fnmut.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-fnonce-move.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-fnonce.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-kind.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-recursive-fn.rs (99%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-infer-upvar.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-manual-impl.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-monomorphization.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-move-from-projection-issue-30046.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-move-mutable.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-move-some-upvars-in-by-ref-closure.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-prelude.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-simple.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-single-word-env.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-static-call-fn-once.rs (97%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-sugar-object.rs (98%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-unique-type-id.rs (93%) rename src/test/{run-pass => ui/run-pass/unboxed-closures}/unboxed-closures-zero-args.rs (97%) create mode 100644 src/test/ui/run-pass/uniform-paths/basic-nested.rs create mode 100644 src/test/ui/run-pass/uniform-paths/basic.rs create mode 100644 src/test/ui/run-pass/uniform-paths/macros-nested.rs create mode 100644 src/test/ui/run-pass/uniform-paths/macros.rs create mode 100644 src/test/ui/run-pass/uniform-paths/same-crate.rs rename src/test/{ => ui}/run-pass/union/auxiliary/union.rs (100%) rename src/test/{ => ui}/run-pass/union/union-align.rs (99%) rename src/test/{ => ui}/run-pass/union/union-backcomp.rs (98%) rename src/test/{ => ui}/run-pass/union/union-basic.rs (99%) rename src/test/{ => ui}/run-pass/union/union-c-interop.rs (96%) rename src/test/{ => ui}/run-pass/union/union-const-codegen.rs (98%) create mode 100644 src/test/ui/run-pass/union/union-const-eval-field.rs rename src/test/{ => ui}/run-pass/union/union-derive.rs (95%) rename src/test/{ => ui}/run-pass/union/union-drop-assign.rs (95%) rename src/test/{ => ui}/run-pass/union/union-drop.rs (96%) rename src/test/{ => ui}/run-pass/union/union-generic.rs (95%) rename src/test/{ => ui}/run-pass/union/union-inherent-method.rs (97%) rename src/test/{ => ui}/run-pass/union/union-macro.rs (98%) rename src/test/{ => ui}/run-pass/union/union-nodrop.rs (99%) rename src/test/{ => ui}/run-pass/union/union-overwrite.rs (97%) rename src/test/{ => ui}/run-pass/union/union-packed.rs (99%) rename src/test/{ => ui}/run-pass/union/union-pat-refutability.rs (95%) rename src/test/{ => ui}/run-pass/union/union-trait-impl.rs (98%) rename src/test/{ => ui}/run-pass/union/union-transmute.rs (98%) rename src/test/{ => ui}/run-pass/union/union-with-drop-fields-lint.rs (98%) rename src/test/{run-pass => ui/run-pass/unique}/unique-assign-copy.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-assign-drop.rs (92%) rename src/test/{run-pass => ui/run-pass/unique}/unique-assign-generic.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-assign.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-autoderef-field.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-autoderef-index.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-cmp.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-containing-tag.rs (94%) rename src/test/{run-pass => ui/run-pass/unique}/unique-create.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-decl-init-copy.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-decl-init.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-decl-move.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-decl.rs (97%) rename src/test/{run-pass => ui/run-pass/unique}/unique-deref.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-destructure.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-drop-complex.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-ffi-symbols.rs (98%) rename src/test/{run-pass => ui/run-pass/unique}/unique-fn-arg-move.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-fn-arg-mut.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-fn-arg.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-fn-ret.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-generic-assign.rs (97%) rename src/test/{run-pass => ui/run-pass/unique}/unique-in-tag.rs (94%) rename src/test/{run-pass => ui/run-pass/unique}/unique-in-vec-copy.rs (96%) rename src/test/{run-pass => ui/run-pass/unique}/unique-in-vec.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-init.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-kinds.rs (98%) rename src/test/{run-pass => ui/run-pass/unique}/unique-log.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-match-discrim.rs (98%) rename src/test/{run-pass => ui/run-pass/unique}/unique-move-drop.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-move-temp.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-move.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-mutable.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-object-move.rs (96%) rename src/test/{run-pass => ui/run-pass/unique}/unique-pat-2.rs (90%) rename src/test/{run-pass => ui/run-pass/unique}/unique-pat-3.rs (93%) rename src/test/{run-pass => ui/run-pass/unique}/unique-pat.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-rec.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-send-2.rs (97%) rename src/test/{run-pass => ui/run-pass/unique}/unique-send.rs (95%) rename src/test/{run-pass => ui/run-pass/unique}/unique-swap.rs (95%) create mode 100644 src/test/ui/run-pass/unsized-locals/reference-unsized-locals.rs create mode 100644 src/test/ui/run-pass/unsized-locals/simple-unsized-locals.rs create mode 100644 src/test/ui/run-pass/unsized-locals/unsized-exprs.rs create mode 100644 src/test/ui/run-pass/unsized-locals/unsized-parameters.rs rename src/test/{run-pass => ui/run-pass/where-clauses}/auxiliary/where_clauses_xc.rs (100%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clause-bounds-inconsistency.rs (98%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clause-early-bound-lifetimes.rs (94%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clause-method-substituion.rs (98%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clause-region-outlives.rs (98%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clauses-cross-crate.rs (98%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clauses-lifetimes.rs (98%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clauses-method.rs (98%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clauses-unboxed-closures.rs (98%) rename src/test/{run-pass => ui/run-pass/where-clauses}/where-clauses.rs (98%) rename src/test/{run-pass => ui/run-pass/zero-sized}/zero-size-type-destructors.rs (94%) rename src/test/{run-pass => ui/run-pass/zero-sized}/zero-sized-binary-heap-push.rs (98%) rename src/test/{run-pass => ui/run-pass/zero-sized}/zero-sized-btreemap-insert.rs (98%) rename src/test/{run-pass => ui/run-pass/zero-sized}/zero-sized-linkedlist-push.rs (99%) rename src/test/{run-pass => ui/run-pass/zero-sized}/zero-sized-tuple-struct.rs (98%) rename src/test/{run-pass => ui/run-pass/zero-sized}/zero-sized-vec-deque-push.rs (99%) rename src/test/{run-pass => ui/run-pass/zero-sized}/zero-sized-vec-push.rs (98%) create mode 100644 src/test/ui/rust-2018/auxiliary/remove-extern-crate.rs create mode 100644 src/test/ui/rust-2018/issue-54006.rs create mode 100644 src/test/ui/rust-2018/issue-54006.stderr create mode 100644 src/test/ui/rust-2018/remove-extern-crate.fixed create mode 100644 src/test/ui/rust-2018/remove-extern-crate.rs create mode 100644 src/test/ui/rust-2018/remove-extern-crate.stderr create mode 100644 src/test/ui/rust-2018/try-ident.fixed create mode 100644 src/test/ui/rust-2018/try-ident.rs create mode 100644 src/test/ui/rust-2018/try-ident.stderr create mode 100644 src/test/ui/rust-2018/try-macro.fixed create mode 100644 src/test/ui/rust-2018/try-macro.rs create mode 100644 src/test/ui/rust-2018/try-macro.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths/ambiguity-macros.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths/ambiguity-nested.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths/ambiguity.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/ambiguity.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-54253.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-54253.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths/redundant.rs rename src/test/{compile-fail => ui}/rust-unstable-column-gated.rs (100%) create mode 100644 src/test/ui/rust-unstable-column-gated.stderr rename src/test/{compile-fail => ui}/rustc-args-required-const.rs (94%) create mode 100644 src/test/ui/rustc-args-required-const.stderr rename src/test/{compile-fail => ui}/rustc-args-required-const2.rs (92%) create mode 100644 src/test/ui/rustc-args-required-const2.stderr rename src/test/{compile-fail => ui}/rustc-error.rs (100%) create mode 100644 src/test/ui/rustc-error.stderr rename src/test/{compile-fail => ui}/safe-extern-statics-mut.rs (100%) create mode 100644 src/test/ui/safe-extern-statics-mut.stderr rename src/test/{compile-fail => ui}/safe-extern-statics.rs (100%) create mode 100644 src/test/ui/safe-extern-statics.stderr rename src/test/ui/{ => self}/self-impl.rs (100%) rename src/test/ui/{ => self}/self-impl.stderr (100%) rename src/test/{compile-fail => ui/self}/self-infer.rs (100%) create mode 100644 src/test/ui/self/self-infer.stderr rename src/test/{compile-fail => ui/self}/self-vs-path-ambiguity.rs (100%) create mode 100644 src/test/ui/self/self-vs-path-ambiguity.stderr rename src/test/{compile-fail => ui/self}/self_type_keyword-2.rs (79%) create mode 100644 src/test/ui/self/self_type_keyword-2.stderr rename src/test/{compile-fail => ui/self}/self_type_keyword.rs (100%) create mode 100644 src/test/ui/self/self_type_keyword.stderr rename src/test/{compile-fail => ui}/seq-args.rs (100%) create mode 100644 src/test/ui/seq-args.stderr rename src/test/ui/{ => shadowed}/shadowed-lifetime.rs (100%) rename src/test/ui/{ => shadowed}/shadowed-lifetime.stderr (100%) rename src/test/{compile-fail => ui/shadowed}/shadowed-trait-methods.rs (100%) create mode 100644 src/test/ui/shadowed/shadowed-trait-methods.stderr rename src/test/ui/{ => shadowed}/shadowed-type-parameter.rs (100%) rename src/test/ui/{ => shadowed}/shadowed-type-parameter.stderr (100%) rename src/test/{compile-fail => ui/shadowed}/shadowed-use-visibility.rs (100%) create mode 100644 src/test/ui/shadowed/shadowed-use-visibility.stderr rename src/test/{compile-fail => ui/shadowed}/shadowing-in-the-same-pattern.rs (100%) create mode 100644 src/test/ui/shadowed/shadowing-in-the-same-pattern.stderr rename src/test/{compile-fail => ui}/shift-various-bad-types.rs (100%) create mode 100644 src/test/ui/shift-various-bad-types.stderr rename src/test/{compile-fail => ui}/should-fail-no_gate_irrefutable_if_let_pattern.rs (100%) create mode 100644 src/test/ui/should-fail-no_gate_irrefutable_if_let_pattern.stderr rename src/test/{compile-fail => ui}/should-fail-with_gate_irrefutable_pattern_deny.rs (100%) create mode 100644 src/test/ui/should-fail-with_gate_irrefutable_pattern_deny.stderr rename src/test/{compile-fail => ui/simd-intrinsic}/simd-intrinsic-declaration-type.rs (100%) create mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-declaration-type.stderr rename src/test/{compile-fail => ui/simd-intrinsic}/simd-intrinsic-generic-arithmetic.rs (100%) create mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr rename src/test/{compile-fail => ui/simd-intrinsic}/simd-intrinsic-generic-cast.rs (100%) create mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr rename src/test/{compile-fail => ui/simd-intrinsic}/simd-intrinsic-generic-comparison.rs (100%) create mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr rename src/test/{compile-fail => ui/simd-intrinsic}/simd-intrinsic-generic-elements.rs (100%) create mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr rename src/test/{compile-fail => ui/simd-intrinsic}/simd-intrinsic-generic-reduction.rs (100%) create mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr rename src/test/{compile-fail => ui/simd-intrinsic}/simd-intrinsic-generic-select.rs (100%) create mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr rename src/test/{compile-fail => ui/simd-intrinsic}/simd-intrinsic-single-nominal-type.rs (100%) create mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-single-nominal-type.stderr rename src/test/{compile-fail => ui}/simd-type-generic-monomorphisation.rs (100%) create mode 100644 src/test/ui/simd-type-generic-monomorphisation.stderr rename src/test/{compile-fail => ui}/simd-type.rs (100%) create mode 100644 src/test/ui/simd-type.stderr rename src/test/{compile-fail => ui}/single-primitive-inherent-impl.rs (100%) create mode 100644 src/test/ui/single-primitive-inherent-impl.stderr rename src/test/{compile-fail => ui}/sized-cycle-note.rs (100%) create mode 100644 src/test/ui/sized-cycle-note.stderr rename src/test/{compile-fail => ui}/slice-2.rs (100%) create mode 100644 src/test/ui/slice-2.stderr create mode 100644 src/test/ui/slice-mut-2.nll.stderr rename src/test/{compile-fail => ui}/slice-mut-2.rs (100%) create mode 100644 src/test/ui/slice-mut-2.stderr rename src/test/{compile-fail => ui}/slice-mut.rs (100%) create mode 100644 src/test/ui/slice-mut.stderr rename src/test/{compile-fail => ui}/slightly-nice-generic-literal-messages.rs (100%) create mode 100644 src/test/ui/slightly-nice-generic-literal-messages.stderr rename src/test/{compile-fail => ui}/specialization/README.md (100%) rename src/test/{compile-fail => ui}/specialization/defaultimpl/specialization-feature-gate-default.rs (100%) create mode 100644 src/test/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr rename src/test/{compile-fail => ui}/specialization/defaultimpl/specialization-no-default.rs (100%) create mode 100644 src/test/ui/specialization/defaultimpl/specialization-no-default.stderr rename src/test/{compile-fail => ui}/specialization/defaultimpl/specialization-trait-item-not-implemented.rs (100%) create mode 100644 src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr rename src/test/{compile-fail => ui}/specialization/defaultimpl/specialization-trait-not-implemented.rs (100%) create mode 100644 src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr rename src/test/{compile-fail => ui}/specialization/defaultimpl/specialization-wfcheck.rs (100%) create mode 100644 src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr rename src/test/{compile-fail => ui}/specialization/defaultimpl/validation.rs (98%) create mode 100644 src/test/ui/specialization/defaultimpl/validation.stderr rename src/test/{compile-fail => ui}/specialization/issue-52050.rs (100%) create mode 100644 src/test/ui/specialization/issue-52050.stderr rename src/test/{compile-fail => ui}/specialization/specialization-default-projection.rs (100%) create mode 100644 src/test/ui/specialization/specialization-default-projection.stderr rename src/test/{compile-fail => ui}/specialization/specialization-default-types.rs (100%) create mode 100644 src/test/ui/specialization/specialization-default-types.stderr rename src/test/ui/{ => specialization}/specialization-feature-gate-default.rs (100%) rename src/test/ui/{ => specialization}/specialization-feature-gate-default.stderr (100%) rename src/test/ui/{ => specialization}/specialization-feature-gate-overlap.rs (100%) rename src/test/ui/{ => specialization}/specialization-feature-gate-overlap.stderr (100%) rename src/test/{compile-fail => ui}/specialization/specialization-no-default.rs (100%) create mode 100644 src/test/ui/specialization/specialization-no-default.stderr rename src/test/{compile-fail => ui}/specialization/specialization-overlap-negative.rs (100%) create mode 100644 src/test/ui/specialization/specialization-overlap-negative.stderr rename src/test/{compile-fail => ui}/specialization/specialization-overlap.rs (100%) create mode 100644 src/test/ui/specialization/specialization-overlap.stderr rename src/test/{compile-fail => ui}/specialization/specialization-polarity.rs (100%) create mode 100644 src/test/ui/specialization/specialization-polarity.stderr create mode 100644 src/test/ui/stability-attribute/auxiliary/stability_attribute_issue.rs rename src/test/{compile-fail => ui/stability-attribute}/stability-attribute-issue-43027.rs (100%) create mode 100644 src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr create mode 100644 src/test/ui/stability-attribute/stability-attribute-issue.rs create mode 100644 src/test/ui/stability-attribute/stability-attribute-issue.stderr rename src/test/{compile-fail => ui/stability-attribute}/stability-attribute-non-staged-force-unstable.rs (100%) create mode 100644 src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr rename src/test/{compile-fail => ui/stability-attribute}/stability-attribute-non-staged.rs (100%) create mode 100644 src/test/ui/stability-attribute/stability-attribute-non-staged.stderr rename src/test/{compile-fail => ui/stability-attribute}/stability-attribute-sanity-2.rs (93%) create mode 100644 src/test/ui/stability-attribute/stability-attribute-sanity-2.stderr rename src/test/{compile-fail => ui/stability-attribute}/stability-attribute-sanity-3.rs (91%) create mode 100644 src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr rename src/test/{compile-fail => ui/stability-attribute}/stability-attribute-sanity.rs (87%) create mode 100644 src/test/ui/stability-attribute/stability-attribute-sanity.stderr rename src/test/{compile-fail => ui}/stable-features.rs (79%) create mode 100644 src/test/ui/stable-features.stderr rename src/test/{compile-fail => ui/static/auxiliary}/static-priv-by-default.rs (100%) rename src/test/{compile-fail => ui/static}/auxiliary/static_priv_by_default.rs (100%) rename src/test/{compile-fail => ui/static}/static-closures.rs (100%) create mode 100644 src/test/ui/static/static-closures.stderr rename src/test/{compile-fail => ui/static}/static-drop-scope.rs (100%) create mode 100644 src/test/ui/static/static-drop-scope.stderr rename src/test/{compile-fail => ui/static}/static-items-cant-move.rs (100%) create mode 100644 src/test/ui/static/static-items-cant-move.stderr create mode 100644 src/test/ui/static/static-lifetime-bound.nll.stderr rename src/test/{compile-fail => ui/static}/static-lifetime-bound.rs (100%) create mode 100644 src/test/ui/static/static-lifetime-bound.stderr rename src/test/ui/{ => static}/static-lifetime.rs (100%) rename src/test/ui/{ => static}/static-lifetime.stderr (100%) rename src/test/{compile-fail => ui/static}/static-method-privacy.rs (100%) create mode 100644 src/test/ui/static/static-method-privacy.stderr rename src/test/{compile-fail => ui/static}/static-mut-bad-types.rs (100%) create mode 100644 src/test/ui/static/static-mut-bad-types.stderr rename src/test/{compile-fail => ui/static}/static-mut-foreign-requires-unsafe.rs (100%) create mode 100644 src/test/ui/static/static-mut-foreign-requires-unsafe.stderr rename src/test/{compile-fail => ui/static}/static-mut-not-constant.rs (100%) create mode 100644 src/test/ui/static/static-mut-not-constant.stderr rename src/test/{compile-fail => ui/static}/static-mut-not-pat.rs (100%) create mode 100644 src/test/ui/static/static-mut-not-pat.stderr rename src/test/{compile-fail => ui/static}/static-mut-requires-unsafe.rs (100%) create mode 100644 src/test/ui/static/static-mut-requires-unsafe.stderr rename src/test/{compile-fail => ui/static}/static-priv-by-default2.rs (100%) create mode 100644 src/test/ui/static/static-priv-by-default2.stderr rename src/test/{compile-fail => ui/static}/static-reference-to-fn-1.rs (100%) create mode 100644 src/test/ui/static/static-reference-to-fn-1.stderr create mode 100644 src/test/ui/static/static-reference-to-fn-2.nll.stderr rename src/test/{compile-fail => ui/static}/static-reference-to-fn-2.rs (100%) create mode 100644 src/test/ui/static/static-reference-to-fn-2.stderr rename src/test/{compile-fail => ui/static}/static-region-bound.rs (100%) create mode 100644 src/test/ui/static/static-region-bound.stderr rename src/test/{compile-fail => ui/static}/static-vec-repeat-not-constant.rs (100%) create mode 100644 src/test/ui/static/static-vec-repeat-not-constant.stderr rename src/test/{compile-fail => ui}/staticness-mismatch.rs (100%) create mode 100644 src/test/ui/staticness-mismatch.stderr create mode 100644 src/test/ui/std-uncopyable-atomics.nll.stderr rename src/test/{compile-fail => ui}/std-uncopyable-atomics.rs (100%) create mode 100644 src/test/ui/std-uncopyable-atomics.stderr rename src/test/{compile-fail => ui}/stmt_expr_attrs_no_feature.rs (97%) create mode 100644 src/test/ui/stmt_expr_attrs_no_feature.stderr rename src/test/ui/{ => str}/str-array-assignment.rs (100%) rename src/test/ui/{ => str}/str-array-assignment.stderr (95%) rename src/test/ui/{ => str}/str-as-char.fixed (100%) rename src/test/ui/{ => str}/str-as-char.rs (100%) rename src/test/ui/{ => str}/str-as-char.stderr (100%) rename src/test/ui/{ => str}/str-concat-on-double-ref.rs (100%) rename src/test/ui/{ => str}/str-concat-on-double-ref.stderr (100%) rename src/test/{compile-fail => ui/str}/str-idx.rs (100%) create mode 100644 src/test/ui/str/str-idx.stderr rename src/test/ui/{ => str}/str-lit-type-mismatch.rs (100%) rename src/test/ui/{ => str}/str-lit-type-mismatch.stderr (100%) rename src/test/{compile-fail => ui/str}/str-mut-idx.rs (100%) create mode 100644 src/test/ui/str/str-mut-idx.stderr rename src/test/{compile-fail => ui/structs}/auxiliary/struct_field_privacy.rs (100%) rename src/test/{compile-fail => ui/structs}/auxiliary/struct_variant_privacy.rs (100%) rename src/test/{compile-fail => ui/structs}/struct-base-wrong-type-2.rs (100%) create mode 100644 src/test/ui/structs/struct-base-wrong-type-2.stderr rename src/test/{compile-fail => ui/structs}/struct-base-wrong-type.rs (100%) create mode 100644 src/test/ui/structs/struct-base-wrong-type.stderr rename src/test/ui/{ => structs}/struct-duplicate-comma.rs (100%) rename src/test/ui/{ => structs}/struct-duplicate-comma.stderr (100%) rename src/test/{compile-fail => ui/structs}/struct-field-cfg.rs (100%) create mode 100644 src/test/ui/structs/struct-field-cfg.stderr rename src/test/ui/{ => structs}/struct-field-init-syntax.rs (100%) rename src/test/ui/{ => structs}/struct-field-init-syntax.stderr (100%) rename src/test/{compile-fail => ui/structs}/struct-field-privacy.rs (100%) create mode 100644 src/test/ui/structs/struct-field-privacy.stderr rename src/test/ui/{ => structs}/struct-fields-decl-dupe.rs (100%) rename src/test/ui/{ => structs}/struct-fields-decl-dupe.stderr (100%) rename src/test/{compile-fail => ui/structs}/struct-fields-dupe.rs (100%) create mode 100644 src/test/ui/structs/struct-fields-dupe.stderr rename src/test/ui/{ => structs}/struct-fields-hints-no-dupe.rs (100%) rename src/test/ui/{ => structs}/struct-fields-hints-no-dupe.stderr (100%) rename src/test/ui/{ => structs}/struct-fields-hints.rs (100%) rename src/test/ui/{ => structs}/struct-fields-hints.stderr (100%) rename src/test/{compile-fail => ui/structs}/struct-fields-missing.rs (100%) create mode 100644 src/test/ui/structs/struct-fields-missing.stderr rename src/test/{compile-fail => ui/structs}/struct-fields-shorthand-unresolved.rs (100%) create mode 100644 src/test/ui/structs/struct-fields-shorthand-unresolved.stderr rename src/test/{compile-fail => ui/structs}/struct-fields-shorthand.rs (100%) create mode 100644 src/test/ui/structs/struct-fields-shorthand.stderr rename src/test/ui/{ => structs}/struct-fields-too-many.rs (100%) rename src/test/ui/{ => structs}/struct-fields-too-many.stderr (100%) rename src/test/{compile-fail => ui/structs}/struct-fields-typo.rs (100%) create mode 100644 src/test/ui/structs/struct-fields-typo.stderr rename src/test/{compile-fail => ui/structs}/struct-like-enum-nonexhaustive.rs (100%) create mode 100644 src/test/ui/structs/struct-like-enum-nonexhaustive.stderr rename src/test/ui/{ => structs}/struct-missing-comma.rs (100%) rename src/test/ui/{ => structs}/struct-missing-comma.stderr (100%) rename src/test/{compile-fail => ui/structs}/struct-pat-derived-error.rs (100%) create mode 100644 src/test/ui/structs/struct-pat-derived-error.stderr rename src/test/{compile-fail => ui/structs}/struct-path-alias-bounds.rs (100%) create mode 100644 src/test/ui/structs/struct-path-alias-bounds.stderr rename src/test/{compile-fail => ui/structs}/struct-path-associated-type.rs (100%) create mode 100644 src/test/ui/structs/struct-path-associated-type.stderr rename src/test/ui/{ => structs}/struct-path-self-type-mismatch.rs (100%) rename src/test/ui/{ => structs}/struct-path-self-type-mismatch.stderr (100%) rename src/test/{compile-fail => ui/structs}/struct-path-self.rs (100%) create mode 100644 src/test/ui/structs/struct-path-self.stderr rename src/test/{compile-fail => ui/structs}/struct-pattern-match-useless.rs (100%) create mode 100644 src/test/ui/structs/struct-pattern-match-useless.stderr rename src/test/{compile-fail => ui/structs}/struct-variant-privacy-xc.rs (100%) create mode 100644 src/test/ui/structs/struct-variant-privacy-xc.stderr rename src/test/{compile-fail => ui/structs}/struct-variant-privacy.rs (100%) create mode 100644 src/test/ui/structs/struct-variant-privacy.stderr rename src/test/{compile-fail => ui/structs}/structure-constructor-type-mismatch.rs (100%) create mode 100644 src/test/ui/structs/structure-constructor-type-mismatch.stderr create mode 100644 src/test/ui/substs-ppaux.normal.stderr rename src/test/{compile-fail => ui}/substs-ppaux.rs (100%) create mode 100644 src/test/ui/substs-ppaux.verbose.stderr rename src/test/{compile-fail => ui}/suffixed-literal-meta.rs (98%) create mode 100644 src/test/ui/suffixed-literal-meta.stderr rename src/test/ui/{ => suggestions}/auxiliary/struct_field_privacy.rs (100%) create mode 100644 src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs create mode 100644 src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr create mode 100644 src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs create mode 100644 src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr create mode 100644 src/test/ui/suggestions/dont-suggest-ref/simple.rs create mode 100644 src/test/ui/suggestions/dont-suggest-ref/simple.stderr rename src/test/ui/{ => suggestions}/suggest-labels.rs (100%) rename src/test/ui/{ => suggestions}/suggest-labels.stderr (100%) rename src/test/ui/{ => suggestions}/suggest-methods.rs (100%) rename src/test/ui/{ => suggestions}/suggest-methods.stderr (100%) rename src/test/ui/{ => suggestions}/suggest-private-fields.rs (100%) rename src/test/ui/{ => suggestions}/suggest-private-fields.stderr (100%) rename src/test/ui/{ => suggestions}/suggest-ref-mut.rs (100%) rename src/test/ui/{ => suggestions}/suggest-ref-mut.stderr (100%) rename src/test/ui/{ => suggestions}/suggest-remove-refs-1.rs (100%) rename src/test/ui/{ => suggestions}/suggest-remove-refs-1.stderr (100%) rename src/test/ui/{ => suggestions}/suggest-remove-refs-2.rs (100%) rename src/test/ui/{ => suggestions}/suggest-remove-refs-2.stderr (100%) rename src/test/ui/{ => suggestions}/suggest-remove-refs-3.rs (100%) rename src/test/ui/{ => suggestions}/suggest-remove-refs-3.stderr (100%) rename src/test/{compile-fail => ui}/super-at-top-level.rs (100%) create mode 100644 src/test/ui/super-at-top-level.stderr rename src/test/{compile-fail => ui}/suppressed-error.rs (100%) create mode 100644 src/test/ui/suppressed-error.stderr rename src/test/ui/{ => svh}/auxiliary/svh-a-base.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-a-change-lit.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-a-change-significant-cfg.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-a-change-trait-bound.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-a-change-type-arg.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-a-change-type-ret.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-a-change-type-static.rs (98%) rename src/test/ui/{ => svh}/auxiliary/svh-b.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-uta-base.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-uta-change-use-trait.rs (100%) rename src/test/ui/{ => svh}/auxiliary/svh-utb.rs (100%) rename src/test/ui/{ => svh}/svh-change-lit.rs (100%) rename src/test/ui/{ => svh}/svh-change-lit.stderr (100%) rename src/test/ui/{ => svh}/svh-change-significant-cfg.rs (100%) rename src/test/ui/{ => svh}/svh-change-significant-cfg.stderr (100%) rename src/test/ui/{ => svh}/svh-change-trait-bound.rs (100%) rename src/test/ui/{ => svh}/svh-change-trait-bound.stderr (100%) rename src/test/ui/{ => svh}/svh-change-type-arg.rs (100%) rename src/test/ui/{ => svh}/svh-change-type-arg.stderr (100%) rename src/test/ui/{ => svh}/svh-change-type-ret.rs (100%) rename src/test/ui/{ => svh}/svh-change-type-ret.stderr (100%) rename src/test/ui/{ => svh}/svh-change-type-static.rs (100%) rename src/test/ui/{ => svh}/svh-change-type-static.stderr (100%) rename src/test/ui/{ => svh}/svh-use-trait.rs (100%) rename src/test/ui/{ => svh}/svh-use-trait.stderr (100%) rename src/test/{compile-fail => ui}/symbol-names/basic.rs (100%) create mode 100644 src/test/ui/symbol-names/basic.stderr rename src/test/{compile-fail => ui}/symbol-names/impl1.rs (100%) create mode 100644 src/test/ui/symbol-names/impl1.stderr rename src/test/{compile-fail => ui}/syntax-extension-minor.rs (100%) create mode 100644 src/test/ui/syntax-extension-minor.stderr rename src/test/{compile-fail => ui}/syntax-trait-polarity-feature-gate.rs (100%) create mode 100644 src/test/ui/syntax-trait-polarity-feature-gate.stderr rename src/test/{compile-fail => ui}/syntax-trait-polarity.rs (100%) create mode 100644 src/test/ui/syntax-trait-polarity.stderr rename src/test/{compile-fail => ui}/synthetic-param.rs (100%) create mode 100644 src/test/ui/synthetic-param.stderr rename src/test/{compile-fail => ui}/tag-that-dare-not-speak-its-name.rs (100%) create mode 100644 src/test/ui/tag-that-dare-not-speak-its-name.stderr rename src/test/{compile-fail => ui}/tag-type-args.rs (100%) create mode 100644 src/test/ui/tag-type-args.stderr rename src/test/{compile-fail => ui}/tag-variant-cast-non-nullary.rs (100%) create mode 100644 src/test/ui/tag-variant-cast-non-nullary.stderr rename src/test/{compile-fail => ui}/tag-variant-disr-dup.rs (100%) create mode 100644 src/test/ui/tag-variant-disr-dup.stderr rename src/test/{compile-fail => ui}/tail-typeck.rs (100%) create mode 100644 src/test/ui/tail-typeck.stderr rename src/test/{compile-fail => ui}/terr-in-field.rs (100%) create mode 100644 src/test/ui/terr-in-field.stderr rename src/test/{compile-fail => ui}/terr-sorts.rs (100%) create mode 100644 src/test/ui/terr-sorts.stderr rename src/test/{compile-fail => ui}/test-cfg.rs (100%) create mode 100644 src/test/ui/test-cfg.stderr create mode 100644 src/test/ui/test-on-macro.rs create mode 100644 src/test/ui/test-on-macro.stderr create mode 100644 src/test/ui/test-shadowing/auxiliary/test_macro.rs create mode 100644 src/test/ui/test-shadowing/test-cant-be-shadowed.rs rename src/test/{compile-fail => ui}/test-warns-dead-code.rs (100%) create mode 100644 src/test/ui/test-warns-dead-code.stderr create mode 100644 src/test/ui/thread-local-in-ctfe.nll.stderr rename src/test/{compile-fail => ui}/thread-local-in-ctfe.rs (100%) create mode 100644 src/test/ui/thread-local-in-ctfe.stderr create mode 100644 src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs create mode 100644 src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr create mode 100644 src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs create mode 100644 src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr create mode 100644 src/test/ui/tool-attributes/tool-attributes-shadowing.rs create mode 100644 src/test/ui/tool-attributes/tool-attributes-shadowing.stderr rename src/test/{compile-fail/tool_lints.rs => ui/tool_lints-fail.rs} (100%) create mode 100644 src/test/ui/tool_lints-fail.stderr rename src/test/{compile-fail => ui}/trace_macros-format.rs (100%) create mode 100644 src/test/ui/trace_macros-format.stderr rename src/test/{compile-fail => ui}/trace_macros-gate.rs (100%) create mode 100644 src/test/ui/trace_macros-gate.stderr rename src/test/{compile-fail/trait-alias.rs => ui/trait-alias-fail.rs} (100%) create mode 100644 src/test/ui/trait-alias-fail.stderr rename src/test/{compile-fail => ui/traits}/auxiliary/crate_a1.rs (100%) rename src/test/{compile-fail => ui/traits}/auxiliary/trait_bounds_on_structs_and_enums_xc.rs (100%) rename src/test/{run-pass => ui/traits}/auxiliary/trait_safety_lib.rs (100%) rename src/test/ui/{ => traits}/trait-alias.rs (100%) rename src/test/ui/{ => traits}/trait-alias.stderr (100%) rename src/test/{compile-fail => ui/traits}/trait-as-struct-constructor.rs (100%) create mode 100644 src/test/ui/traits/trait-as-struct-constructor.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-not-on-bare-trait.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-not-on-struct.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-not-on-struct.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-on-structs-and-enums-in-fns.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-on-structs-and-enums-in-fns.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-on-structs-and-enums-in-impls.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-on-structs-and-enums-in-impls.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-on-structs-and-enums-locals.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-on-structs-and-enums-locals.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-on-structs-and-enums-static.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-on-structs-and-enums-static.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-on-structs-and-enums-xc.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-on-structs-and-enums-xc.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-on-structs-and-enums-xc1.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-on-structs-and-enums-xc1.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-on-structs-and-enums.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr rename src/test/{compile-fail => ui/traits}/trait-bounds-sugar.rs (100%) create mode 100644 src/test/ui/traits/trait-bounds-sugar.stderr rename src/test/{compile-fail => ui/traits}/trait-coercion-generic-bad.rs (100%) create mode 100644 src/test/ui/traits/trait-coercion-generic-bad.stderr create mode 100644 src/test/ui/traits/trait-coercion-generic-regions.nll.stderr rename src/test/{compile-fail => ui/traits}/trait-coercion-generic-regions.rs (100%) create mode 100644 src/test/ui/traits/trait-coercion-generic-regions.stderr rename src/test/ui/{ => traits}/trait-duplicate-methods.rs (100%) rename src/test/ui/{ => traits}/trait-duplicate-methods.stderr (100%) rename src/test/{compile-fail => ui/traits}/trait-impl-1.rs (100%) create mode 100644 src/test/ui/traits/trait-impl-1.stderr rename src/test/{compile-fail => ui/traits}/trait-impl-can-not-have-untraitful-items.rs (100%) create mode 100644 src/test/ui/traits/trait-impl-can-not-have-untraitful-items.stderr rename src/test/{compile-fail => ui/traits}/trait-impl-different-num-params.rs (100%) create mode 100644 src/test/ui/traits/trait-impl-different-num-params.stderr rename src/test/{compile-fail => ui/traits}/trait-impl-for-module.rs (100%) create mode 100644 src/test/ui/traits/trait-impl-for-module.stderr rename src/test/{compile-fail => ui/traits}/trait-impl-method-mismatch.rs (100%) create mode 100644 src/test/ui/traits/trait-impl-method-mismatch.stderr rename src/test/{compile-fail => ui/traits}/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs (100%) create mode 100644 src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr rename src/test/{compile-fail => ui/traits}/trait-item-privacy.rs (100%) create mode 100644 src/test/ui/traits/trait-item-privacy.stderr rename src/test/{compile-fail => ui/traits}/trait-matching-lifetimes.rs (100%) create mode 100644 src/test/ui/traits/trait-matching-lifetimes.stderr rename src/test/ui/{ => traits}/trait-method-private.rs (100%) rename src/test/ui/{ => traits}/trait-method-private.stderr (100%) rename src/test/ui/{ => traits}/trait-object-auto-dedup-in-impl.rs (100%) rename src/test/ui/{ => traits}/trait-object-auto-dedup-in-impl.stderr (100%) rename src/test/{compile-fail => ui/traits}/trait-object-macro-matcher.rs (100%) create mode 100644 src/test/ui/traits/trait-object-macro-matcher.stderr rename src/test/{compile-fail => ui/traits}/trait-object-safety.rs (100%) create mode 100644 src/test/ui/traits/trait-object-safety.stderr rename src/test/{compile-fail => ui/traits}/trait-object-vs-lifetime-2.rs (100%) create mode 100644 src/test/ui/traits/trait-object-vs-lifetime-2.stderr rename src/test/{compile-fail => ui/traits}/trait-object-vs-lifetime.rs (94%) create mode 100644 src/test/ui/traits/trait-object-vs-lifetime.stderr rename src/test/{compile-fail => ui/traits}/trait-or-new-type-instead.rs (100%) create mode 100644 src/test/ui/traits/trait-or-new-type-instead.stderr rename src/test/{compile-fail => ui/traits}/trait-privacy.rs (100%) create mode 100644 src/test/ui/traits/trait-privacy.stderr rename src/test/{compile-fail => ui/traits}/trait-resolution-in-overloaded-op.rs (100%) create mode 100644 src/test/ui/traits/trait-resolution-in-overloaded-op.stderr rename src/test/ui/{ => traits}/trait-safety-fn-body.rs (100%) rename src/test/ui/{ => traits}/trait-safety-fn-body.stderr (100%) rename src/test/{compile-fail => ui/traits}/trait-safety-inherent-impl.rs (100%) create mode 100644 src/test/ui/traits/trait-safety-inherent-impl.stderr rename src/test/{compile-fail => ui/traits}/trait-safety-trait-impl-cc.rs (100%) create mode 100644 src/test/ui/traits/trait-safety-trait-impl-cc.stderr rename src/test/{compile-fail => ui/traits}/trait-safety-trait-impl.rs (100%) create mode 100644 src/test/ui/traits/trait-safety-trait-impl.stderr rename src/test/{compile-fail => ui/traits}/trait-static-method-generic-inference.rs (100%) create mode 100644 src/test/ui/traits/trait-static-method-generic-inference.stderr rename src/test/ui/{ => traits}/trait-suggest-where-clause.rs (100%) rename src/test/ui/{ => traits}/trait-suggest-where-clause.stderr (97%) rename src/test/{compile-fail => ui/traits}/trait-test-2.rs (81%) create mode 100644 src/test/ui/traits/trait-test-2.stderr rename src/test/{compile-fail => ui/traits}/trait-test.rs (100%) create mode 100644 src/test/ui/traits/trait-test.stderr rename src/test/{compile-fail => ui/traits}/traits-assoc-type-in-supertrait-bad.rs (100%) create mode 100644 src/test/ui/traits/traits-assoc-type-in-supertrait-bad.stderr rename src/test/{compile-fail => ui/traits}/traits-inductive-overflow-simultaneous.rs (100%) create mode 100644 src/test/ui/traits/traits-inductive-overflow-simultaneous.stderr rename src/test/{compile-fail => ui/traits}/traits-inductive-overflow-supertrait-oibit.rs (100%) create mode 100644 src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr rename src/test/{compile-fail => ui/traits}/traits-inductive-overflow-supertrait.rs (100%) create mode 100644 src/test/ui/traits/traits-inductive-overflow-supertrait.stderr rename src/test/{compile-fail => ui/traits}/traits-inductive-overflow-two-traits.rs (100%) create mode 100644 src/test/ui/traits/traits-inductive-overflow-two-traits.stderr rename src/test/{compile-fail => ui/traits}/traits-issue-23003-overflow.rs (100%) create mode 100644 src/test/ui/traits/traits-issue-23003-overflow.stderr rename src/test/{compile-fail => ui/traits}/traits-multidispatch-bad.rs (100%) create mode 100644 src/test/ui/traits/traits-multidispatch-bad.stderr rename src/test/ui/{ => traits}/traits-multidispatch-convert-ambig-dest.rs (100%) rename src/test/ui/{ => traits}/traits-multidispatch-convert-ambig-dest.stderr (100%) rename src/test/{compile-fail => ui/traits}/traits-negative-impls.rs (100%) create mode 100644 src/test/ui/traits/traits-negative-impls.stderr rename src/test/{compile-fail => ui/traits}/traits-repeated-supertrait-ambig.rs (100%) create mode 100644 src/test/ui/traits/traits-repeated-supertrait-ambig.stderr rename src/test/{compile-fail => ui/transmute}/transmute-different-sizes.rs (95%) create mode 100644 src/test/ui/transmute/transmute-different-sizes.stderr rename src/test/{compile-fail => ui/transmute}/transmute-fat-pointers.rs (96%) create mode 100644 src/test/ui/transmute/transmute-fat-pointers.stderr rename src/test/{compile-fail => ui/transmute}/transmute-impl.rs (95%) create mode 100644 src/test/ui/transmute/transmute-impl.stderr rename src/test/{compile-fail => ui/transmute}/transmute-imut-to-mut.rs (100%) create mode 100644 src/test/ui/transmute/transmute-imut-to-mut.stderr rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-associated-functions.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-copy-reborrow.nll.stderr (88%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-copy-reborrow.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-copy-reborrow.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-copy.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-copy.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-projection-error.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-projection-error.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-projection.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-projection.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-sized.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-sized.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-well-formed.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent-well-formed.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-inconsistent.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-leak-copy.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-leak-copy.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-leak.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-leak.stderr (98%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-lint.rs (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-lint.stderr (100%) rename src/test/ui/{ => trivial-bounds}/trivial-bounds-object.rs (100%) rename src/test/{compile-fail => ui}/trivial_casts.rs (100%) create mode 100644 src/test/ui/trivial_casts.stderr create mode 100644 src/test/ui/try-block/try-block-bad-lifetime.rs create mode 100644 src/test/ui/try-block/try-block-bad-lifetime.stderr create mode 100644 src/test/ui/try-block/try-block-bad-type.rs create mode 100644 src/test/ui/try-block/try-block-bad-type.stderr create mode 100644 src/test/ui/try-block/try-block-in-edition2015.rs create mode 100644 src/test/ui/try-block/try-block-in-edition2015.stderr create mode 100644 src/test/ui/try-block/try-block-in-match.rs create mode 100644 src/test/ui/try-block/try-block-in-match.stderr create mode 100644 src/test/ui/try-block/try-block-in-while.rs create mode 100644 src/test/ui/try-block/try-block-in-while.stderr create mode 100644 src/test/ui/try-block/try-block-maybe-bad-lifetime.rs create mode 100644 src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr create mode 100644 src/test/ui/try-block/try-block-opt-init.rs create mode 100644 src/test/ui/try-block/try-block-opt-init.stderr create mode 100644 src/test/ui/try-block/try-block-type-error.rs create mode 100644 src/test/ui/try-block/try-block-type-error.stderr delete mode 100644 src/test/ui/tuple-struct-fields/test.rs delete mode 100644 src/test/ui/tuple-struct-fields/test.stderr rename src/test/{compile-fail => ui/tuple}/tuple-arity-mismatch.rs (100%) create mode 100644 src/test/ui/tuple/tuple-arity-mismatch.stderr rename src/test/ui/{ => tuple}/tuple-float-index.fixed (100%) rename src/test/ui/{ => tuple}/tuple-float-index.rs (100%) rename src/test/ui/{ => tuple}/tuple-float-index.stderr (100%) rename src/test/{compile-fail => ui/tuple}/tuple-index-not-tuple.rs (100%) create mode 100644 src/test/ui/tuple/tuple-index-not-tuple.stderr rename src/test/{compile-fail => ui/tuple}/tuple-index-out-of-bounds.rs (100%) create mode 100644 src/test/ui/tuple/tuple-index-out-of-bounds.stderr create mode 100644 src/test/ui/tuple/tuple-struct-fields/test.rs create mode 100644 src/test/ui/tuple/tuple-struct-fields/test.stderr rename src/test/ui/{ => tuple}/tuple-struct-fields/test2.rs (100%) rename src/test/ui/{ => tuple}/tuple-struct-fields/test2.stderr (100%) rename src/test/ui/{ => tuple}/tuple-struct-fields/test3.rs (100%) rename src/test/ui/{ => tuple}/tuple-struct-fields/test3.stderr (100%) rename src/test/{compile-fail => ui/tuple}/tuple-struct-nonexhaustive.rs (100%) create mode 100644 src/test/ui/tuple/tuple-struct-nonexhaustive.stderr rename src/test/{compile-fail => ui}/tutorial-suffix-inference-test.rs (100%) create mode 100644 src/test/ui/tutorial-suffix-inference-test.stderr create mode 100644 src/test/ui/type/auxiliary/crate_a1.rs rename src/test/{compile-fail => ui/type}/auxiliary/crate_a2.rs (100%) rename src/test/ui/{ => type}/type-alias-bounds.rs (100%) rename src/test/ui/{ => type}/type-alias-bounds.stderr (100%) rename src/test/ui/{ => type}/type-annotation-needed.rs (100%) rename src/test/ui/{ => type}/type-annotation-needed.stderr (100%) rename src/test/{compile-fail => ui/type}/type-arg-out-of-scope.rs (100%) create mode 100644 src/test/ui/type/type-arg-out-of-scope.stderr rename src/test/ui/{ => type}/type-ascription-instead-of-initializer.rs (100%) rename src/test/ui/{ => type}/type-ascription-instead-of-initializer.stderr (100%) rename src/test/ui/{ => type}/type-ascription-instead-of-statement-end.rs (100%) rename src/test/ui/{ => type}/type-ascription-instead-of-statement-end.stderr (100%) rename src/test/{compile-fail => ui/type}/type-ascription-precedence.rs (100%) create mode 100644 src/test/ui/type/type-ascription-precedence.stderr rename src/test/{compile-fail => ui/type}/type-ascription-soundness.rs (100%) create mode 100644 src/test/ui/type/type-ascription-soundness.stderr rename src/test/ui/{ => type}/type-ascription-with-fn-call.rs (100%) rename src/test/ui/{ => type}/type-ascription-with-fn-call.stderr (100%) rename src/test/ui/{ => type}/type-check-defaults.rs (100%) rename src/test/ui/{ => type}/type-check-defaults.stderr (100%) rename src/test/ui/{ => type}/type-check/assignment-in-if.rs (100%) rename src/test/ui/{ => type}/type-check/assignment-in-if.stderr (100%) rename src/test/ui/{ => type}/type-check/cannot_infer_local_or_array.rs (100%) rename src/test/ui/{ => type}/type-check/cannot_infer_local_or_array.stderr (100%) rename src/test/ui/{ => type}/type-check/cannot_infer_local_or_vec.rs (100%) rename src/test/ui/{ => type}/type-check/cannot_infer_local_or_vec.stderr (100%) rename src/test/ui/{ => type}/type-check/cannot_infer_local_or_vec_in_tuples.rs (100%) rename src/test/ui/{ => type}/type-check/cannot_infer_local_or_vec_in_tuples.stderr (100%) rename src/test/ui/{ => type}/type-check/issue-22897.rs (100%) rename src/test/ui/{ => type}/type-check/issue-22897.stderr (100%) rename src/test/ui/{ => type}/type-check/issue-40294.rs (100%) rename src/test/ui/{ => type}/type-check/issue-40294.stderr (100%) rename src/test/ui/{ => type}/type-check/issue-41314.rs (100%) rename src/test/ui/{ => type}/type-check/issue-41314.stderr (100%) rename src/test/ui/{ => type}/type-check/missing_trait_impl.rs (100%) rename src/test/ui/{ => type}/type-check/missing_trait_impl.stderr (100%) rename src/test/ui/{ => type}/type-check/unknown_type_for_closure.rs (100%) rename src/test/ui/{ => type}/type-check/unknown_type_for_closure.stderr (100%) rename src/test/ui/{ => type}/type-dependent-def-issue-49241.rs (100%) rename src/test/ui/{ => type}/type-dependent-def-issue-49241.stderr (100%) rename src/test/{compile-fail => ui/type}/type-mismatch-multiple.rs (100%) create mode 100644 src/test/ui/type/type-mismatch-multiple.stderr rename src/test/{compile-fail => ui/type}/type-mismatch-same-crate-name.rs (100%) create mode 100644 src/test/ui/type/type-mismatch-same-crate-name.stderr rename src/test/ui/{ => type}/type-mismatch.rs (100%) rename src/test/ui/{ => type}/type-mismatch.stderr (100%) rename src/test/{compile-fail => ui/type}/type-parameter-defaults-referencing-Self-ppaux.rs (100%) create mode 100644 src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr rename src/test/{compile-fail => ui/type}/type-parameter-defaults-referencing-Self.rs (100%) create mode 100644 src/test/ui/type/type-parameter-defaults-referencing-Self.stderr rename src/test/{compile-fail => ui/type}/type-parameter-names.rs (100%) create mode 100644 src/test/ui/type/type-parameter-names.stderr rename src/test/{compile-fail => ui/type}/type-params-in-different-spaces-1.rs (100%) create mode 100644 src/test/ui/type/type-params-in-different-spaces-1.stderr rename src/test/{compile-fail => ui/type}/type-params-in-different-spaces-2.rs (100%) create mode 100644 src/test/ui/type/type-params-in-different-spaces-2.stderr rename src/test/{compile-fail => ui/type}/type-params-in-different-spaces-3.rs (100%) create mode 100644 src/test/ui/type/type-params-in-different-spaces-3.stderr rename src/test/{compile-fail => ui/type}/type-path-err-node-types.rs (100%) create mode 100644 src/test/ui/type/type-path-err-node-types.stderr rename src/test/ui/{ => type}/type-recursive.rs (100%) rename src/test/ui/{ => type}/type-recursive.stderr (100%) rename src/test/{compile-fail => ui/type}/type-shadow.rs (100%) create mode 100644 src/test/ui/type/type-shadow.stderr rename src/test/{compile-fail => ui}/type_length_limit.rs (100%) create mode 100644 src/test/ui/type_length_limit.stderr delete mode 100644 src/test/ui/typeck-builtin-bound-type-parameters.stderr rename src/test/{compile-fail => ui/typeck}/auxiliary/tdticc_coherence_lib.rs (100%) rename src/test/{compile-fail => ui/typeck}/typeck-auto-trait-no-supertraits-2.rs (100%) create mode 100644 src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr rename src/test/{compile-fail => ui/typeck}/typeck-auto-trait-no-supertraits.rs (100%) create mode 100644 src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr rename src/test/ui/{ => typeck}/typeck-builtin-bound-type-parameters.rs (84%) create mode 100644 src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr rename src/test/{compile-fail => ui/typeck}/typeck-cast-pointer-to-float.rs (100%) create mode 100644 src/test/ui/typeck/typeck-cast-pointer-to-float.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-assoc-type.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-constituent-types-2.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-constituent-types.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-cross-crate-coherence.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-negation-send.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-negation-send.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-negation-sync.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-negation.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-negation.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-precedence.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr rename src/test/{compile-fail => ui/typeck}/typeck-default-trait-impl-send-param.rs (100%) create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr rename src/test/{compile-fail => ui/typeck}/typeck-negative-impls-builtin.rs (100%) create mode 100644 src/test/ui/typeck/typeck-negative-impls-builtin.stderr rename src/test/{compile-fail => ui/typeck}/typeck-unsafe-always-share.rs (100%) create mode 100644 src/test/ui/typeck/typeck-unsafe-always-share.stderr rename src/test/ui/{ => typeck}/typeck_type_placeholder_item.rs (100%) rename src/test/ui/{ => typeck}/typeck_type_placeholder_item.stderr (100%) rename src/test/ui/{ => typeck}/typeck_type_placeholder_lifetime_1.rs (98%) create mode 100644 src/test/ui/typeck/typeck_type_placeholder_lifetime_1.stderr rename src/test/ui/{ => typeck}/typeck_type_placeholder_lifetime_2.rs (98%) create mode 100644 src/test/ui/typeck/typeck_type_placeholder_lifetime_2.stderr rename src/test/{compile-fail => ui/typeck}/typeck_type_placeholder_mismatch.rs (100%) create mode 100644 src/test/ui/typeck/typeck_type_placeholder_mismatch.stderr delete mode 100644 src/test/ui/typeck_type_placeholder_lifetime_1.stderr delete mode 100644 src/test/ui/typeck_type_placeholder_lifetime_2.stderr rename src/test/{compile-fail => ui/ufcs}/ufcs-explicit-self-bad.rs (100%) create mode 100644 src/test/ui/ufcs/ufcs-explicit-self-bad.stderr rename src/test/{compile-fail => ui/ufcs}/ufcs-partially-resolved.rs (100%) create mode 100644 src/test/ui/ufcs/ufcs-partially-resolved.stderr rename src/test/{compile-fail => ui/ufcs}/ufcs-qpath-missing-params.rs (91%) create mode 100644 src/test/ui/ufcs/ufcs-qpath-missing-params.stderr rename src/test/{compile-fail => ui/ufcs}/ufcs-qpath-self-mismatch.rs (100%) create mode 100644 src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr delete mode 100644 src/test/ui/unboxed-closure-sugar-wrong-trait.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-feature-gate.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-feature-gate.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-illegal-move.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-illegal-move.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-immutable-capture.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr rename src/test/ui/{ => unboxed-closures}/unboxed-closure-no-cyclic-sig.rs (100%) rename src/test/ui/{ => unboxed-closures}/unboxed-closure-no-cyclic-sig.stderr (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-region.rs (98%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-region.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-default.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-equiv.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-lifetime-elision.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-not-used-on-fn.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-region.rs (95%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-region.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-used-on-struct-1.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-used-on-struct-3.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-used-on-struct.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closure-sugar-wrong-number-number-type-parameters.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr rename src/test/ui/{ => unboxed-closures}/unboxed-closure-sugar-wrong-trait.rs (98%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-borrow-conflict.rs (98%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-failed-recursive-fn-1.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-failed-recursive-fn-2.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-fnmut-as-fn.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-infer-argument-types-two-region-pointers.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr rename src/test/ui/{ => unboxed-closures}/unboxed-closures-infer-fn-once-move-from-projection.rs (100%) rename src/test/ui/{ => unboxed-closures}/unboxed-closures-infer-fn-once-move-from-projection.stderr (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-infer-fnmut-missing-mut.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-infer-fnmut-move-missing-mut.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-infer-fnonce-call-twice.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-infer-fnonce-move-call-twice.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-mutate-upvar.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.nll.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.ast.stderr create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.mir.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-mutated-upvar-from-fn-closure.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.nll.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-recursive-fn-using-fn-mut.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-static-call-wrong-trait.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-type-mismatch.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-unsafe-extern-fn.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-wrong-abi.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr rename src/test/{compile-fail => ui/unboxed-closures}/unboxed-closures-wrong-arg-type-extern-fn.rs (100%) create mode 100644 src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr rename src/test/{compile-fail => ui/underscore-lifetime}/underscore-lifetime-binders.rs (100%) create mode 100644 src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr create mode 100644 src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr rename src/test/{compile-fail => ui/underscore-lifetime}/underscore-lifetime-elison-mismatch.rs (100%) create mode 100644 src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr rename src/test/{compile-fail => ui/uninhabited}/uninhabited-enum-cast.rs (100%) create mode 100644 src/test/ui/uninhabited/uninhabited-enum-cast.stderr rename src/test/{compile-fail => ui/uninhabited}/uninhabited-irrefutable.rs (100%) create mode 100644 src/test/ui/uninhabited/uninhabited-irrefutable.stderr rename src/test/{compile-fail => ui/uninhabited}/uninhabited-matches-feature-gated.rs (100%) create mode 100644 src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr rename src/test/{compile-fail => ui/uninhabited}/uninhabited-patterns.rs (100%) create mode 100644 src/test/ui/uninhabited/uninhabited-patterns.stderr create mode 100644 src/test/ui/union-ub-fat-ptr.rs create mode 100644 src/test/ui/union-ub-fat-ptr.stderr create mode 100644 src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr rename src/test/{compile-fail => ui}/union/union-borrow-move-parent-sibling.rs (100%) create mode 100644 src/test/ui/union/union-borrow-move-parent-sibling.stderr rename src/test/{compile-fail => ui}/union/union-const-pat.rs (100%) create mode 100644 src/test/ui/union/union-const-pat.stderr rename src/test/{compile-fail => ui}/union/union-copy.rs (100%) create mode 100644 src/test/ui/union/union-copy.stderr rename src/test/{compile-fail => ui}/union/union-derive-clone.rs (100%) create mode 100644 src/test/ui/union/union-derive-clone.stderr rename src/test/{compile-fail => ui}/union/union-derive.rs (100%) create mode 100644 src/test/ui/union/union-derive.stderr rename src/test/{compile-fail => ui}/union/union-empty.rs (100%) create mode 100644 src/test/ui/union/union-empty.stderr rename src/test/{compile-fail => ui}/union/union-generic.rs (100%) create mode 100644 src/test/ui/union/union-generic.stderr rename src/test/{compile-fail => ui}/union/union-lint-dead-code.rs (100%) create mode 100644 src/test/ui/union/union-lint-dead-code.stderr rename src/test/{compile-fail => ui}/union/union-nonrepresentable.rs (100%) create mode 100644 src/test/ui/union/union-nonrepresentable.stderr rename src/test/{compile-fail => ui}/union/union-repr-c.rs (100%) create mode 100644 src/test/ui/union/union-repr-c.stderr rename src/test/{compile-fail => ui}/union/union-unsafe.rs (100%) create mode 100644 src/test/ui/union/union-unsafe.stderr rename src/test/{compile-fail => ui}/union/union-unsized.rs (100%) create mode 100644 src/test/ui/union/union-unsized.stderr rename src/test/{compile-fail => ui}/union/union-with-drop-fields-lint.rs (100%) create mode 100644 src/test/ui/union/union-with-drop-fields-lint.stderr rename src/test/{compile-fail => ui}/unique-object-noncopyable.rs (100%) create mode 100644 src/test/ui/unique-object-noncopyable.stderr rename src/test/{compile-fail => ui}/unique-pinned-nocopy.rs (100%) create mode 100644 src/test/ui/unique-pinned-nocopy.stderr rename src/test/{compile-fail => ui}/unknown-lint-tool-name.rs (100%) create mode 100644 src/test/ui/unknown-lint-tool-name.stderr create mode 100644 src/test/ui/unknown-tool-name.rs create mode 100644 src/test/ui/unknown-tool-name.stderr create mode 100644 src/test/ui/unop-move-semantics.nll.stderr rename src/test/{compile-fail => ui}/unop-move-semantics.rs (100%) create mode 100644 src/test/ui/unop-move-semantics.stderr rename src/test/{compile-fail => ui}/unop-neg-bool.rs (100%) create mode 100644 src/test/ui/unop-neg-bool.stderr rename src/test/{compile-fail => ui/unreachable}/auxiliary/unreachable_variant.rs (100%) rename src/test/{compile-fail => ui/unreachable}/unreachable-arm.rs (100%) create mode 100644 src/test/ui/unreachable/unreachable-arm.stderr rename src/test/{compile-fail => ui/unreachable}/unreachable-code.rs (100%) create mode 100644 src/test/ui/unreachable/unreachable-code.stderr rename src/test/{compile-fail => ui/unreachable}/unreachable-in-call.rs (100%) create mode 100644 src/test/ui/unreachable/unreachable-in-call.stderr rename src/test/{compile-fail => ui/unreachable}/unreachable-loop-patterns.rs (100%) create mode 100644 src/test/ui/unreachable/unreachable-loop-patterns.stderr rename src/test/{compile-fail => ui/unreachable}/unreachable-try-pattern.rs (100%) create mode 100644 src/test/ui/unreachable/unreachable-try-pattern.stderr rename src/test/{compile-fail => ui/unreachable}/unreachable-variant.rs (100%) create mode 100644 src/test/ui/unreachable/unreachable-variant.stderr rename src/test/{compile-fail => ui/unresolved}/unresolved-extern-mod-suggestion.rs (100%) create mode 100644 src/test/ui/unresolved/unresolved-extern-mod-suggestion.stderr rename src/test/{compile-fail => ui/unresolved}/unresolved-import-recovery.rs (100%) create mode 100644 src/test/ui/unresolved/unresolved-import-recovery.stderr rename src/test/{compile-fail => ui/unresolved}/unresolved-import.rs (99%) create mode 100644 src/test/ui/unresolved/unresolved-import.stderr create mode 100644 src/test/ui/unrestricted-attribute-tokens.rs rename src/test/{compile-fail => ui/unsafe}/unsafe-around-compiler-generated-unsafe.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.stderr rename src/test/ui/{ => unsafe}/unsafe-block-without-braces.rs (100%) rename src/test/ui/{ => unsafe}/unsafe-block-without-braces.stderr (100%) rename src/test/ui/{ => unsafe}/unsafe-const-fn.rs (96%) rename src/test/ui/{ => unsafe}/unsafe-const-fn.stderr (100%) rename src/test/{compile-fail => ui/unsafe}/unsafe-fn-assign-deref-ptr.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.stderr rename src/test/{compile-fail => ui/unsafe}/unsafe-fn-autoderef.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-fn-autoderef.stderr rename src/test/{compile-fail => ui/unsafe}/unsafe-fn-called-from-safe.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-fn-called-from-safe.stderr rename src/test/{compile-fail => ui/unsafe}/unsafe-fn-deref-ptr.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-fn-deref-ptr.stderr rename src/test/{compile-fail => ui/unsafe}/unsafe-fn-used-as-value.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-fn-used-as-value.stderr rename src/test/{compile-fail => ui/unsafe}/unsafe-move-val-init.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-move-val-init.stderr rename src/test/{compile-fail => ui/unsafe}/unsafe-subtyping.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-subtyping.stderr rename src/test/{compile-fail => ui/unsafe}/unsafe-trait-impl.rs (100%) create mode 100644 src/test/ui/unsafe/unsafe-trait-impl.stderr rename src/test/{compile-fail => ui/unsized}/unsized-bare-typaram.rs (100%) create mode 100644 src/test/ui/unsized/unsized-bare-typaram.stderr rename src/test/{compile-fail => ui/unsized}/unsized-enum.rs (100%) create mode 100644 src/test/ui/unsized/unsized-enum.stderr rename src/test/ui/{ => unsized}/unsized-enum2.rs (100%) rename src/test/ui/{ => unsized}/unsized-enum2.stderr (95%) rename src/test/{compile-fail => ui/unsized}/unsized-inherent-impl-self-type.rs (100%) create mode 100644 src/test/ui/unsized/unsized-inherent-impl-self-type.stderr rename src/test/{compile-fail => ui/unsized}/unsized-struct.rs (100%) create mode 100644 src/test/ui/unsized/unsized-struct.stderr rename src/test/{compile-fail => ui/unsized}/unsized-trait-impl-self-type.rs (100%) create mode 100644 src/test/ui/unsized/unsized-trait-impl-self-type.stderr rename src/test/{compile-fail => ui/unsized}/unsized-trait-impl-trait-arg.rs (100%) create mode 100644 src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr rename src/test/{compile-fail => ui}/unsized3.rs (100%) create mode 100644 src/test/ui/unsized3.stderr rename src/test/{compile-fail => ui}/unsized5.rs (100%) create mode 100644 src/test/ui/unsized5.stderr rename src/test/{compile-fail => ui}/unsized6.rs (100%) create mode 100644 src/test/ui/unsized6.stderr rename src/test/{compile-fail => ui}/unsized7.rs (100%) create mode 100644 src/test/ui/unsized7.stderr rename src/test/{compile-fail => ui}/unspecified-self-in-trait-ref.rs (100%) create mode 100644 src/test/ui/unspecified-self-in-trait-ref.stderr rename src/test/{compile-fail => ui}/unsupported-cast.rs (100%) create mode 100644 src/test/ui/unsupported-cast.stderr rename src/test/{compile-fail => ui/unused}/unused-attr.rs (100%) create mode 100644 src/test/ui/unused/unused-attr.stderr rename src/test/{compile-fail => ui/unused}/unused-macro-rules.rs (100%) create mode 100644 src/test/ui/unused/unused-macro-rules.stderr rename src/test/{compile-fail => ui/unused}/unused-macro-with-bad-frag-spec.rs (100%) create mode 100644 src/test/ui/unused/unused-macro-with-bad-frag-spec.stderr rename src/test/{compile-fail => ui/unused}/unused-macro-with-follow-violation.rs (100%) create mode 100644 src/test/ui/unused/unused-macro-with-follow-violation.stderr rename src/test/{compile-fail => ui/unused}/unused-macro.rs (100%) create mode 100644 src/test/ui/unused/unused-macro.stderr rename src/test/{compile-fail => ui/unused}/unused-mut-warning-captured-var.rs (100%) create mode 100644 src/test/ui/unused/unused-mut-warning-captured-var.stderr rename src/test/{compile-fail => ui/unused}/unused-result.rs (100%) create mode 100644 src/test/ui/unused/unused-result.stderr create mode 100644 src/test/ui/use-self-in-inner-fn.rs create mode 100644 src/test/ui/use-self-in-inner-fn.stderr rename src/test/{compile-fail => ui/use}/auxiliary/use_from_trait_xc.rs (100%) create mode 100644 src/test/ui/use/use-after-move-based-on-type.nll.stderr rename src/test/{compile-fail => ui/use}/use-after-move-based-on-type.rs (100%) create mode 100644 src/test/ui/use/use-after-move-based-on-type.stderr create mode 100644 src/test/ui/use/use-after-move-implicity-coerced-object.nll.stderr rename src/test/{compile-fail => ui/use}/use-after-move-implicity-coerced-object.rs (100%) create mode 100644 src/test/ui/use/use-after-move-implicity-coerced-object.stderr rename src/test/{compile-fail => ui/use}/use-after-move-self-based-on-type.rs (100%) create mode 100644 src/test/ui/use/use-after-move-self-based-on-type.stderr create mode 100644 src/test/ui/use/use-after-move-self.nll.stderr rename src/test/{compile-fail => ui/use}/use-after-move-self.rs (100%) create mode 100644 src/test/ui/use/use-after-move-self.stderr rename src/test/{compile-fail => ui/use}/use-from-trait-xc.rs (100%) create mode 100644 src/test/ui/use/use-from-trait-xc.stderr rename src/test/{compile-fail => ui/use}/use-from-trait.rs (100%) create mode 100644 src/test/ui/use/use-from-trait.stderr rename src/test/{compile-fail => ui/use}/use-keyword.rs (100%) create mode 100644 src/test/ui/use/use-keyword.stderr rename src/test/{compile-fail => ui/use}/use-meta-mismatch.rs (100%) create mode 100644 src/test/ui/use/use-meta-mismatch.stderr rename src/test/ui/{ => use}/use-mod.rs (100%) rename src/test/ui/{ => use}/use-mod.stderr (100%) rename src/test/{compile-fail => ui/use/use-mod}/use-mod-2.rs (100%) create mode 100644 src/test/ui/use/use-mod/use-mod-2.stderr rename src/test/{compile-fail => ui/use/use-mod}/use-mod-3.rs (100%) create mode 100644 src/test/ui/use/use-mod/use-mod-3.stderr rename src/test/{compile-fail => ui/use/use-mod}/use-mod-4.rs (100%) create mode 100644 src/test/ui/use/use-mod/use-mod-4.stderr rename src/test/ui/{ => use}/use-nested-groups-error.rs (100%) rename src/test/ui/{ => use}/use-nested-groups-error.stderr (100%) rename src/test/ui/{ => use}/use-nested-groups-unused-imports.rs (100%) rename src/test/ui/{ => use}/use-nested-groups-unused-imports.stderr (100%) rename src/test/{compile-fail => ui/use}/use-paths-as-items.rs (100%) create mode 100644 src/test/ui/use/use-paths-as-items.stderr rename src/test/{compile-fail => ui/use}/use-self-type.rs (100%) create mode 100644 src/test/ui/use/use-self-type.stderr rename src/test/{compile-fail => ui/use}/use-super-global-path.rs (100%) create mode 100644 src/test/ui/use/use-super-global-path.stderr rename src/test/{compile-fail => ui}/used.rs (97%) create mode 100644 src/test/ui/used.stderr rename src/test/{compile-fail => ui}/useless-pub.rs (100%) create mode 100644 src/test/ui/useless-pub.stderr rename src/test/{compile-fail => ui}/useless_comment.rs (100%) create mode 100644 src/test/ui/useless_comment.stderr rename src/test/{compile-fail => ui}/user-defined-macro-rules.rs (97%) create mode 100644 src/test/ui/user-defined-macro-rules.stderr rename src/test/{compile-fail => ui}/utf8_idents.rs (100%) create mode 100644 src/test/ui/utf8_idents.stderr rename src/test/{compile-fail => ui/variadic}/variadic-ffi-2.rs (94%) create mode 100644 src/test/ui/variadic/variadic-ffi-2.stderr rename src/test/ui/{ => variadic}/variadic-ffi-3.rs (100%) rename src/test/ui/{ => variadic}/variadic-ffi-3.stderr (100%) rename src/test/{compile-fail => ui/variadic}/variadic-ffi.rs (93%) create mode 100644 src/test/ui/variadic/variadic-ffi.stderr rename src/test/{compile-fail => ui/variance}/variance-associated-types.rs (100%) create mode 100644 src/test/ui/variance/variance-associated-types.stderr create mode 100644 src/test/ui/variance/variance-btree-invariant-types.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-btree-invariant-types.rs (100%) create mode 100644 src/test/ui/variance/variance-btree-invariant-types.stderr rename src/test/{compile-fail => ui/variance}/variance-cell-is-invariant.rs (96%) create mode 100644 src/test/ui/variance/variance-cell-is-invariant.stderr create mode 100644 src/test/ui/variance/variance-contravariant-arg-object.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-contravariant-arg-object.rs (100%) create mode 100644 src/test/ui/variance/variance-contravariant-arg-object.stderr rename src/test/{compile-fail => ui/variance}/variance-contravariant-arg-trait-match.rs (97%) create mode 100644 src/test/ui/variance/variance-contravariant-arg-trait-match.stderr rename src/test/{compile-fail => ui/variance}/variance-contravariant-self-trait-match.rs (97%) create mode 100644 src/test/ui/variance/variance-contravariant-self-trait-match.stderr create mode 100644 src/test/ui/variance/variance-covariant-arg-object.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-covariant-arg-object.rs (100%) create mode 100644 src/test/ui/variance/variance-covariant-arg-object.stderr rename src/test/{compile-fail => ui/variance}/variance-covariant-arg-trait-match.rs (97%) create mode 100644 src/test/ui/variance/variance-covariant-arg-trait-match.stderr rename src/test/{compile-fail => ui/variance}/variance-covariant-self-trait-match.rs (97%) create mode 100644 src/test/ui/variance/variance-covariant-self-trait-match.stderr create mode 100644 src/test/ui/variance/variance-invariant-arg-object.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-invariant-arg-object.rs (100%) create mode 100644 src/test/ui/variance/variance-invariant-arg-object.stderr rename src/test/{compile-fail => ui/variance}/variance-invariant-arg-trait-match.rs (96%) create mode 100644 src/test/ui/variance/variance-invariant-arg-trait-match.stderr rename src/test/{compile-fail => ui/variance}/variance-invariant-self-trait-match.rs (96%) create mode 100644 src/test/ui/variance/variance-invariant-self-trait-match.stderr create mode 100644 src/test/ui/variance/variance-issue-20533.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-issue-20533.rs (100%) create mode 100644 src/test/ui/variance/variance-issue-20533.stderr rename src/test/{compile-fail => ui/variance}/variance-object-types.rs (100%) create mode 100644 src/test/ui/variance/variance-object-types.stderr rename src/test/{compile-fail => ui/variance}/variance-regions-direct.rs (100%) create mode 100644 src/test/ui/variance/variance-regions-direct.stderr rename src/test/{compile-fail => ui/variance}/variance-regions-indirect.rs (100%) create mode 100644 src/test/ui/variance/variance-regions-indirect.stderr rename src/test/{compile-fail => ui/variance}/variance-regions-unused-direct.rs (100%) create mode 100644 src/test/ui/variance/variance-regions-unused-direct.stderr rename src/test/{compile-fail => ui/variance}/variance-regions-unused-indirect.rs (100%) create mode 100644 src/test/ui/variance/variance-regions-unused-indirect.stderr rename src/test/{compile-fail => ui/variance}/variance-trait-bounds.rs (100%) create mode 100644 src/test/ui/variance/variance-trait-bounds.stderr create mode 100644 src/test/ui/variance/variance-trait-matching.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-trait-matching.rs (100%) create mode 100644 src/test/ui/variance/variance-trait-matching.stderr rename src/test/{compile-fail => ui/variance}/variance-trait-object-bound.rs (100%) create mode 100644 src/test/ui/variance/variance-trait-object-bound.stderr rename src/test/{compile-fail => ui/variance}/variance-types-bounds.rs (100%) create mode 100644 src/test/ui/variance/variance-types-bounds.stderr rename src/test/{compile-fail => ui/variance}/variance-types.rs (100%) create mode 100644 src/test/ui/variance/variance-types.stderr rename src/test/{compile-fail => ui/variance}/variance-unused-region-param.rs (100%) create mode 100644 src/test/ui/variance/variance-unused-region-param.stderr rename src/test/ui/{ => variance}/variance-unused-type-param.rs (100%) rename src/test/ui/{ => variance}/variance-unused-type-param.stderr (100%) create mode 100644 src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-use-contravariant-struct-1.rs (100%) create mode 100644 src/test/ui/variance/variance-use-contravariant-struct-1.stderr rename src/test/{compile-fail => ui/variance}/variance-use-contravariant-struct-2.rs (100%) create mode 100644 src/test/ui/variance/variance-use-contravariant-struct-2.stderr create mode 100644 src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-use-covariant-struct-1.rs (100%) create mode 100644 src/test/ui/variance/variance-use-covariant-struct-1.stderr rename src/test/{compile-fail => ui/variance}/variance-use-covariant-struct-2.rs (100%) create mode 100644 src/test/ui/variance/variance-use-covariant-struct-2.stderr create mode 100644 src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr rename src/test/{compile-fail => ui/variance}/variance-use-invariant-struct-1.rs (100%) create mode 100644 src/test/ui/variance/variance-use-invariant-struct-1.stderr rename src/test/{compile-fail => ui/variants}/auxiliary/variant-namespacing.rs (100%) rename src/test/{compile-fail => ui/variants}/variant-namespacing.rs (100%) create mode 100644 src/test/ui/variants/variant-namespacing.stderr rename src/test/{compile-fail => ui/variants}/variant-size-differences.rs (100%) create mode 100644 src/test/ui/variants/variant-size-differences.stderr rename src/test/{compile-fail => ui/variants}/variant-used-as-type.rs (100%) create mode 100644 src/test/ui/variants/variant-used-as-type.stderr rename src/test/{compile-fail => ui/vec}/vec-macro-with-comma-only.rs (100%) create mode 100644 src/test/ui/vec/vec-macro-with-comma-only.stderr create mode 100644 src/test/ui/vec/vec-mut-iter-borrow.nll.stderr rename src/test/{compile-fail => ui/vec}/vec-mut-iter-borrow.rs (100%) create mode 100644 src/test/ui/vec/vec-mut-iter-borrow.stderr rename src/test/{compile-fail => ui/vec}/vec-res-add.rs (100%) create mode 100644 src/test/ui/vec/vec-res-add.stderr rename src/test/{compile-fail => ui}/vector-cast-weirdness.rs (100%) create mode 100644 src/test/ui/vector-cast-weirdness.stderr rename src/test/{compile-fail => ui}/vtable-res-trait-param.rs (100%) create mode 100644 src/test/ui/vtable-res-trait-param.stderr create mode 100644 src/test/ui/walk-struct-literal-with.nll.stderr rename src/test/{compile-fail => ui}/walk-struct-literal-with.rs (100%) create mode 100644 src/test/ui/walk-struct-literal-with.stderr rename src/test/{compile-fail => ui}/warn-path-statement.rs (100%) create mode 100644 src/test/ui/warn-path-statement.stderr rename src/test/{compile-fail => ui/wf}/wf-array-elem-sized.rs (100%) create mode 100644 src/test/ui/wf/wf-array-elem-sized.stderr rename src/test/{compile-fail => ui/wf}/wf-const-type.rs (100%) create mode 100644 src/test/ui/wf/wf-const-type.stderr rename src/test/{compile-fail => ui/wf}/wf-enum-bound.rs (100%) create mode 100644 src/test/ui/wf/wf-enum-bound.stderr rename src/test/{compile-fail => ui/wf}/wf-enum-fields-struct-variant.rs (100%) create mode 100644 src/test/ui/wf/wf-enum-fields-struct-variant.stderr rename src/test/{compile-fail => ui/wf}/wf-enum-fields.rs (100%) create mode 100644 src/test/ui/wf/wf-enum-fields.stderr rename src/test/{compile-fail => ui/wf}/wf-fn-where-clause.rs (90%) create mode 100644 src/test/ui/wf/wf-fn-where-clause.stderr rename src/test/{compile-fail => ui/wf}/wf-impl-associated-type-region.rs (100%) create mode 100644 src/test/ui/wf/wf-impl-associated-type-region.stderr rename src/test/{compile-fail => ui/wf}/wf-impl-associated-type-trait.rs (100%) create mode 100644 src/test/ui/wf/wf-impl-associated-type-trait.stderr rename src/test/{compile-fail => ui/wf}/wf-in-fn-arg.rs (100%) create mode 100644 src/test/ui/wf/wf-in-fn-arg.stderr rename src/test/{compile-fail => ui/wf}/wf-in-fn-ret.rs (100%) create mode 100644 src/test/ui/wf/wf-in-fn-ret.stderr rename src/test/{compile-fail => ui/wf}/wf-in-fn-type-arg.rs (100%) create mode 100644 src/test/ui/wf/wf-in-fn-type-arg.stderr rename src/test/{compile-fail => ui/wf}/wf-in-fn-type-ret.rs (100%) create mode 100644 src/test/ui/wf/wf-in-fn-type-ret.stderr rename src/test/{compile-fail => ui/wf}/wf-in-fn-type-static.rs (100%) create mode 100644 src/test/ui/wf/wf-in-fn-type-static.stderr rename src/test/{compile-fail => ui/wf}/wf-in-fn-where-clause.rs (100%) create mode 100644 src/test/ui/wf/wf-in-fn-where-clause.stderr rename src/test/{compile-fail => ui/wf}/wf-in-obj-type-static.rs (100%) create mode 100644 src/test/ui/wf/wf-in-obj-type-static.stderr rename src/test/{compile-fail => ui/wf}/wf-in-obj-type-trait.rs (100%) create mode 100644 src/test/ui/wf/wf-in-obj-type-trait.stderr rename src/test/{compile-fail => ui/wf}/wf-inherent-impl-method-where-clause.rs (100%) create mode 100644 src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr rename src/test/{compile-fail => ui/wf}/wf-inherent-impl-where-clause.rs (100%) create mode 100644 src/test/ui/wf/wf-inherent-impl-where-clause.stderr create mode 100644 src/test/ui/wf/wf-misc-methods-issue-28609.nll.stderr rename src/test/{compile-fail => ui/wf}/wf-misc-methods-issue-28609.rs (100%) create mode 100644 src/test/ui/wf/wf-misc-methods-issue-28609.stderr rename src/test/{compile-fail => ui/wf}/wf-object-safe.rs (100%) create mode 100644 src/test/ui/wf/wf-object-safe.stderr create mode 100644 src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.rs create mode 100644 src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr create mode 100644 src/test/ui/wf/wf-static-method.nll.stderr rename src/test/{compile-fail => ui/wf}/wf-static-method.rs (100%) create mode 100644 src/test/ui/wf/wf-static-method.stderr rename src/test/{compile-fail => ui/wf}/wf-static-type.rs (100%) create mode 100644 src/test/ui/wf/wf-static-type.stderr rename src/test/{compile-fail => ui/wf}/wf-struct-bound.rs (100%) create mode 100644 src/test/ui/wf/wf-struct-bound.stderr rename src/test/{compile-fail => ui/wf}/wf-struct-field.rs (100%) create mode 100644 src/test/ui/wf/wf-struct-field.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-associated-type-bound.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-associated-type-bound.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-associated-type-region.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-associated-type-region.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-associated-type-trait.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-associated-type-trait.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-bound.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-bound.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-default-fn-arg.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-default-fn-arg.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-default-fn-ret.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-default-fn-ret.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-default-fn-where-clause.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-default-fn-where-clause.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-fn-arg.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-fn-arg.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-fn-ret.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-fn-ret.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-fn-where-clause.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-fn-where-clause.stderr rename src/test/{compile-fail => ui/wf}/wf-trait-superbound.rs (100%) create mode 100644 src/test/ui/wf/wf-trait-superbound.stderr rename src/test/{compile-fail => ui/where-clauses}/where-clause-constraints-are-local-for-inherent-impl.rs (100%) create mode 100644 src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr rename src/test/{compile-fail => ui/where-clauses}/where-clause-constraints-are-local-for-trait-impl.rs (100%) create mode 100644 src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr rename src/test/{compile-fail => ui/where-clauses}/where-clause-method-substituion.rs (100%) create mode 100644 src/test/ui/where-clauses/where-clause-method-substituion.stderr rename src/test/{compile-fail => ui/where-clauses}/where-clauses-method-unsatisfied.rs (100%) create mode 100644 src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr rename src/test/{compile-fail => ui/where-clauses}/where-clauses-unsatisfied.rs (100%) create mode 100644 src/test/ui/where-clauses/where-clauses-unsatisfied.stderr rename src/test/{compile-fail => ui/where-clauses}/where-equality-constraints.rs (100%) create mode 100644 src/test/ui/where-clauses/where-equality-constraints.stderr rename src/test/{compile-fail => ui/where-clauses}/where-for-self-2.rs (91%) create mode 100644 src/test/ui/where-clauses/where-for-self-2.stderr rename src/test/{compile-fail => ui/where-clauses}/where-for-self.rs (100%) create mode 100644 src/test/ui/where-clauses/where-for-self.stderr rename src/test/{compile-fail => ui/where-clauses}/where-lifetime-resolution.rs (100%) create mode 100644 src/test/ui/where-clauses/where-lifetime-resolution.stderr rename src/test/{compile-fail => ui}/while-let.rs (100%) create mode 100644 src/test/ui/while-let.stderr rename src/test/{compile-fail => ui}/while-type-error.rs (100%) create mode 100644 src/test/ui/while-type-error.stderr rename src/test/{compile-fail => ui}/windows-subsystem-invalid.rs (100%) create mode 100644 src/test/ui/windows-subsystem-invalid.stderr rename src/test/{compile-fail => ui}/write-to-static-mut-in-static.rs (100%) create mode 100644 src/test/ui/write-to-static-mut-in-static.stderr create mode 100644 src/test/ui/writing-to-immutable-vec.nll.stderr rename src/test/{compile-fail => ui}/writing-to-immutable-vec.rs (100%) create mode 100644 src/test/ui/writing-to-immutable-vec.stderr rename src/test/{compile-fail => ui}/wrong-mul-method-signature.rs (100%) create mode 100644 src/test/ui/wrong-mul-method-signature.stderr rename src/test/{compile-fail => ui}/wrong-ret-type.rs (100%) create mode 100644 src/test/ui/wrong-ret-type.stderr rename src/test/{compile-fail => ui}/xc-private-method.rs (100%) create mode 100644 src/test/ui/xc-private-method.stderr rename src/test/{compile-fail => ui}/xc-private-method2.rs (100%) create mode 100644 src/test/ui/xc-private-method2.stderr create mode 100644 src/test/ui/xcrate/auxiliary/static_priv_by_default.rs rename src/test/{run-pass => ui/xcrate}/auxiliary/xcrate_unit_struct.rs (100%) rename src/test/{compile-fail => ui/xcrate}/xcrate-private-by-default.rs (100%) create mode 100644 src/test/ui/xcrate/xcrate-private-by-default.stderr rename src/test/{compile-fail => ui/xcrate}/xcrate-unit-struct.rs (100%) create mode 100644 src/test/ui/xcrate/xcrate-unit-struct.stderr create mode 100644 src/tools/build-manifest/README.md delete mode 100644 src/vendor/aho-corasick/Cargo.toml.orig delete mode 100644 src/vendor/bitflags/.travis.yml create mode 100644 src/vendor/bitflags/CODE_OF_CONDUCT.md create mode 100644 src/vendor/cloudabi/.cargo-checksum.json rename src/vendor/{dtoa => cloudabi}/.cargo-ok (100%) create mode 100644 src/vendor/cloudabi/Cargo.toml create mode 100644 src/vendor/cloudabi/Cargo.toml.orig create mode 100644 src/vendor/cloudabi/bitflags.rs create mode 100644 src/vendor/cloudabi/cloudabi.rs mode change 100644 => 100755 src/vendor/cmake/src/lib.rs delete mode 100644 src/vendor/dtoa/.cargo-checksum.json delete mode 100644 src/vendor/dtoa/.travis.yml delete mode 100644 src/vendor/dtoa/Cargo.toml delete mode 100644 src/vendor/dtoa/Cargo.toml.orig delete mode 100644 src/vendor/dtoa/LICENSE-MIT delete mode 100644 src/vendor/dtoa/README.md delete mode 100644 src/vendor/dtoa/benches/bench.rs delete mode 100644 src/vendor/dtoa/src/diyfp.rs delete mode 100644 src/vendor/dtoa/src/dtoa.rs delete mode 100644 src/vendor/dtoa/src/lib.rs delete mode 100644 src/vendor/dtoa/tests/test.rs create mode 100644 src/vendor/error-chain/.cargo-checksum.json rename src/vendor/{rand-0.4.2 => error-chain}/.cargo-ok (100%) create mode 100644 src/vendor/error-chain/.gitignore create mode 100644 src/vendor/error-chain/.travis.yml create mode 100644 src/vendor/error-chain/CHANGELOG.md create mode 100644 src/vendor/error-chain/Cargo.toml create mode 100644 src/vendor/error-chain/Cargo.toml.orig rename src/vendor/{dtoa => error-chain}/LICENSE-APACHE (100%) create mode 100644 src/vendor/error-chain/LICENSE-MIT create mode 100644 src/vendor/error-chain/README.md create mode 100644 src/vendor/error-chain/examples/all.rs create mode 100644 src/vendor/error-chain/examples/chain_err.rs create mode 100644 src/vendor/error-chain/examples/doc.rs create mode 100644 src/vendor/error-chain/examples/quickstart.rs create mode 100644 src/vendor/error-chain/examples/size.rs create mode 100644 src/vendor/error-chain/src/backtrace.rs create mode 100644 src/vendor/error-chain/src/bin/has_backtrace.rs create mode 100644 src/vendor/error-chain/src/error_chain.rs create mode 100644 src/vendor/error-chain/src/example_generated.rs create mode 100644 src/vendor/error-chain/src/impl_error_chain_kind.rs create mode 100644 src/vendor/error-chain/src/lib.rs create mode 100644 src/vendor/error-chain/src/quick_main.rs create mode 100644 src/vendor/error-chain/tests/quick_main.rs create mode 100644 src/vendor/error-chain/tests/tests.rs create mode 100644 src/vendor/flate2/examples/gzdecoder-write.rs create mode 100644 src/vendor/flate2/tests/empty-read.rs create mode 100644 src/vendor/lazy_static/build.rs create mode 100644 src/vendor/lazy_static/src/heap_lazy.rs create mode 100644 src/vendor/lazy_static/src/inline_lazy.rs delete mode 100644 src/vendor/lazy_static/src/lazy.rs delete mode 100644 src/vendor/lazy_static/src/nightly_lazy.rs create mode 100644 src/vendor/libc/src/unix/hermit/aarch64.rs create mode 100644 src/vendor/libc/src/unix/hermit/mod.rs create mode 100644 src/vendor/libc/src/unix/hermit/x86_64.rs create mode 100644 src/vendor/libc/src/unix/notbsd/linux/musl/b32/powerpc.rs create mode 100644 src/vendor/lock_api/.cargo-checksum.json rename src/vendor/{termcolor-0.3.6 => lock_api}/.cargo-ok (100%) create mode 100644 src/vendor/lock_api/Cargo.toml create mode 100644 src/vendor/lock_api/Cargo.toml.orig create mode 100644 src/vendor/lock_api/src/lib.rs create mode 100644 src/vendor/lock_api/src/mutex.rs create mode 100644 src/vendor/lock_api/src/remutex.rs create mode 100644 src/vendor/lock_api/src/rwlock.rs create mode 100644 src/vendor/macro-utils/.cargo-checksum.json rename src/vendor/{wincolor-0.1.6 => macro-utils}/.cargo-ok (100%) create mode 100644 src/vendor/macro-utils/.gitignore create mode 100644 src/vendor/macro-utils/.travis.yml create mode 100644 src/vendor/macro-utils/Cargo.toml create mode 100644 src/vendor/macro-utils/Cargo.toml.orig create mode 100644 src/vendor/macro-utils/LICENSE create mode 100644 src/vendor/macro-utils/README.md create mode 100644 src/vendor/macro-utils/appveyor.yml create mode 100644 src/vendor/macro-utils/src/if_match.rs create mode 100644 src/vendor/macro-utils/src/lib.rs create mode 100644 src/vendor/macro-utils/src/tern_c.rs create mode 100644 src/vendor/macro-utils/src/tern_haskell.rs create mode 100644 src/vendor/macro-utils/src/tern_python.rs create mode 100644 src/vendor/matches/tests/macro_use_one.rs create mode 100755 src/vendor/memchr/ci/script.sh create mode 100644 src/vendor/memmap/.appveyor.yml create mode 100644 src/vendor/memmap/.cargo-checksum.json create mode 100644 src/vendor/memmap/.cargo-ok rename src/vendor/{dtoa => memmap}/.gitignore (100%) create mode 100644 src/vendor/memmap/.travis.yml create mode 100644 src/vendor/memmap/Cargo.toml create mode 100644 src/vendor/memmap/Cargo.toml.orig create mode 100644 src/vendor/memmap/LICENSE-APACHE create mode 100644 src/vendor/memmap/LICENSE-MIT create mode 100644 src/vendor/memmap/README.md create mode 100644 src/vendor/memmap/ci/install.sh create mode 100644 src/vendor/memmap/ci/script.sh create mode 100644 src/vendor/memmap/examples/cat.rs create mode 100644 src/vendor/memmap/src/lib.rs create mode 100644 src/vendor/memmap/src/unix.rs create mode 100644 src/vendor/memmap/src/windows.rs create mode 100644 src/vendor/minifier/src/json/json_minifier.rs create mode 100644 src/vendor/minifier/src/json/mod.rs create mode 100644 src/vendor/minifier/src/json/read/byte_to_char.rs create mode 100644 src/vendor/minifier/src/json/read/internal_buffer.rs create mode 100644 src/vendor/minifier/src/json/read/internal_reader.rs create mode 100644 src/vendor/minifier/src/json/read/json_read.rs create mode 100644 src/vendor/minifier/src/json/string.rs create mode 100644 src/vendor/minifier/tests/files/test.json create mode 100644 src/vendor/parking_lot/CHANGELOG.md delete mode 100644 src/vendor/parking_lot/src/raw_remutex.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/.cargo-checksum.json create mode 100644 src/vendor/parking_lot_core-0.2.14/.cargo-ok create mode 100644 src/vendor/parking_lot_core-0.2.14/Cargo.toml create mode 100644 src/vendor/parking_lot_core-0.2.14/Cargo.toml.orig create mode 100644 src/vendor/parking_lot_core-0.2.14/src/lib.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/parking_lot.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/spinwait.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/thread_parker/generic.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/thread_parker/linux.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/thread_parker/unix.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/thread_parker/windows/keyed_event.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/thread_parker/windows/mod.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/thread_parker/windows/waitaddress.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/util.rs create mode 100644 src/vendor/parking_lot_core-0.2.14/src/word_lock.rs create mode 100644 src/vendor/pkg-config/CHANGELOG.md create mode 100644 src/vendor/proc-macro2/build.rs delete mode 100644 src/vendor/rand-0.4.2/.cargo-checksum.json delete mode 100644 src/vendor/rand-0.4.2/CHANGELOG.md delete mode 100644 src/vendor/rand-0.4.2/Cargo.toml delete mode 100644 src/vendor/rand-0.4.2/Cargo.toml.orig delete mode 100644 src/vendor/rand-0.4.2/README.md delete mode 100644 src/vendor/rand-0.4.2/src/lib.rs delete mode 100644 src/vendor/rand-0.4.2/src/os.rs create mode 100644 src/vendor/rand-0.4.3/.cargo-checksum.json create mode 100644 src/vendor/rand-0.4.3/.cargo-ok rename src/vendor/{rand-0.4.2 => rand-0.4.3}/.gitignore (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/.travis.yml (100%) create mode 100644 src/vendor/rand-0.4.3/CHANGELOG.md create mode 100644 src/vendor/rand-0.4.3/Cargo.toml create mode 100644 src/vendor/rand-0.4.3/Cargo.toml.orig rename src/vendor/{rand-0.4.2 => rand-0.4.3}/LICENSE-APACHE (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/LICENSE-MIT (100%) create mode 100644 src/vendor/rand-0.4.3/README.md rename src/vendor/{rand-0.4.2 => rand-0.4.3}/appveyor.yml (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/benches/bench.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/benches/distributions/exponential.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/benches/distributions/gamma.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/benches/distributions/mod.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/benches/distributions/normal.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/benches/generators.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/benches/misc.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/distributions/exponential.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/distributions/gamma.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/distributions/mod.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/distributions/normal.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/distributions/range.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/distributions/ziggurat_tables.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/jitter.rs (100%) create mode 100644 src/vendor/rand-0.4.3/src/lib.rs create mode 100644 src/vendor/rand-0.4.3/src/os.rs rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/prng/chacha.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/prng/isaac.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/prng/isaac64.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/prng/mod.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/prng/xorshift.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/rand_impls.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/read.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/reseeding.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/src/seq.rs (100%) rename src/vendor/{rand-0.4.2 => rand-0.4.3}/utils/ziggurat_tables.py (100%) create mode 100644 src/vendor/rand/.cargo-checksum.json create mode 100644 src/vendor/rand/.cargo-ok create mode 100644 src/vendor/rand/.gitignore create mode 100644 src/vendor/rand/.travis.yml create mode 100644 src/vendor/rand/CHANGELOG.md create mode 100644 src/vendor/rand/CONTRIBUTING.md create mode 100644 src/vendor/rand/Cargo.toml create mode 100644 src/vendor/rand/Cargo.toml.orig create mode 100644 src/vendor/rand/LICENSE-APACHE create mode 100644 src/vendor/rand/LICENSE-MIT create mode 100644 src/vendor/rand/README.md create mode 100644 src/vendor/rand/UPDATING.md create mode 100644 src/vendor/rand/appveyor.yml create mode 100644 src/vendor/rand/benches/distributions.rs create mode 100644 src/vendor/rand/benches/generators.rs create mode 100644 src/vendor/rand/benches/misc.rs create mode 100644 src/vendor/rand/examples/monte-carlo.rs create mode 100644 src/vendor/rand/examples/monty-hall.rs create mode 100644 src/vendor/rand/src/distributions/bernoulli.rs create mode 100644 src/vendor/rand/src/distributions/binomial.rs create mode 100644 src/vendor/rand/src/distributions/cauchy.rs create mode 100644 src/vendor/rand/src/distributions/exponential.rs create mode 100644 src/vendor/rand/src/distributions/float.rs create mode 100644 src/vendor/rand/src/distributions/gamma.rs create mode 100644 src/vendor/rand/src/distributions/integer.rs create mode 100644 src/vendor/rand/src/distributions/log_gamma.rs create mode 100644 src/vendor/rand/src/distributions/mod.rs create mode 100644 src/vendor/rand/src/distributions/normal.rs create mode 100644 src/vendor/rand/src/distributions/other.rs create mode 100644 src/vendor/rand/src/distributions/pareto.rs create mode 100644 src/vendor/rand/src/distributions/poisson.rs create mode 100644 src/vendor/rand/src/distributions/uniform.rs create mode 100644 src/vendor/rand/src/distributions/ziggurat_tables.rs create mode 100644 src/vendor/rand/src/lib.rs create mode 100644 src/vendor/rand/src/prelude.rs create mode 100644 src/vendor/rand/src/prng/chacha.rs create mode 100644 src/vendor/rand/src/prng/hc128.rs create mode 100644 src/vendor/rand/src/prng/isaac.rs create mode 100644 src/vendor/rand/src/prng/isaac64.rs create mode 100644 src/vendor/rand/src/prng/isaac_array.rs create mode 100644 src/vendor/rand/src/prng/mod.rs create mode 100644 src/vendor/rand/src/prng/xorshift.rs create mode 100644 src/vendor/rand/src/rngs/adapter/mod.rs create mode 100644 src/vendor/rand/src/rngs/adapter/read.rs create mode 100644 src/vendor/rand/src/rngs/adapter/reseeding.rs create mode 100644 src/vendor/rand/src/rngs/entropy.rs create mode 100644 src/vendor/rand/src/rngs/jitter.rs create mode 100644 src/vendor/rand/src/rngs/mock.rs create mode 100644 src/vendor/rand/src/rngs/mod.rs create mode 100644 src/vendor/rand/src/rngs/os.rs create mode 100644 src/vendor/rand/src/rngs/small.rs create mode 100644 src/vendor/rand/src/rngs/std.rs create mode 100644 src/vendor/rand/src/rngs/thread.rs create mode 100644 src/vendor/rand/src/seq.rs create mode 100644 src/vendor/rand/tests/bool.rs create mode 100644 src/vendor/rand/utils/ci/install.sh create mode 100644 src/vendor/rand/utils/ci/script.sh create mode 100755 src/vendor/rand/utils/ziggurat_tables.py create mode 100644 src/vendor/rand_core/.cargo-checksum.json create mode 100644 src/vendor/rand_core/.cargo-ok create mode 100644 src/vendor/rand_core/CHANGELOG.md create mode 100644 src/vendor/rand_core/Cargo.toml create mode 100644 src/vendor/rand_core/Cargo.toml.orig create mode 100644 src/vendor/rand_core/LICENSE-APACHE create mode 100644 src/vendor/rand_core/LICENSE-MIT create mode 100644 src/vendor/rand_core/README.md create mode 100644 src/vendor/rand_core/src/block.rs create mode 100644 src/vendor/rand_core/src/error.rs create mode 100644 src/vendor/rand_core/src/impls.rs create mode 100644 src/vendor/rand_core/src/le.rs create mode 100644 src/vendor/rand_core/src/lib.rs create mode 100755 src/vendor/regex/ci/test-regex-capi create mode 100755 src/vendor/regex/scripts/scrape_crates_io.py create mode 100644 src/vendor/regex/tests/consistent.rs create mode 100644 src/vendor/regex/tests/crates_regex.rs create mode 100644 src/vendor/regex/tests/test_crates_regex.rs delete mode 100644 src/vendor/rustc-demangle/src/main.rs create mode 100644 src/vendor/ryu/.cargo-checksum.json create mode 100644 src/vendor/ryu/.cargo-ok create mode 100644 src/vendor/ryu/.gitignore create mode 100644 src/vendor/ryu/.travis.yml create mode 100644 src/vendor/ryu/Cargo.toml create mode 100644 src/vendor/ryu/Cargo.toml.orig create mode 100644 src/vendor/ryu/LICENSE-APACHE create mode 100644 src/vendor/ryu/LICENSE-BOOST create mode 100644 src/vendor/ryu/README.md create mode 100644 src/vendor/ryu/benchmark/benchmark.rs create mode 100644 src/vendor/ryu/build.rs create mode 100644 src/vendor/ryu/src/buffer/mod.rs create mode 100644 src/vendor/ryu/src/common.rs create mode 100644 src/vendor/ryu/src/d2s.rs create mode 100644 src/vendor/ryu/src/d2s_full_table.rs create mode 100644 src/vendor/ryu/src/d2s_intrinsics.rs create mode 100644 src/vendor/ryu/src/d2s_small_table.rs create mode 100644 src/vendor/ryu/src/digit_table.rs create mode 100644 src/vendor/ryu/src/f2s.rs create mode 100644 src/vendor/ryu/src/lib.rs create mode 100644 src/vendor/ryu/src/pretty/exponent.rs create mode 100644 src/vendor/ryu/src/pretty/mantissa.rs create mode 100644 src/vendor/ryu/src/pretty/mod.rs create mode 100644 src/vendor/ryu/tests/d2s_table_test.rs create mode 100644 src/vendor/ryu/tests/d2s_test.rs create mode 100644 src/vendor/ryu/tests/exhaustive.rs create mode 100644 src/vendor/ryu/tests/f2s_test.rs create mode 100644 src/vendor/ryu/tests/macros/mod.rs create mode 100644 src/vendor/same-file/LICENSE-MIT rename src/vendor/{termcolor-0.3.6 => same-file}/UNLICENSE (100%) create mode 100644 src/vendor/syn/src/verbatim.rs delete mode 100644 src/vendor/termcolor-0.3.6/.cargo-checksum.json delete mode 100644 src/vendor/termcolor-0.3.6/Cargo.toml delete mode 100644 src/vendor/termcolor-0.3.6/Cargo.toml.orig delete mode 100644 src/vendor/termcolor-0.3.6/README.md delete mode 100644 src/vendor/termcolor-0.3.6/src/lib.rs create mode 100644 src/vendor/termcolor/.cargo-checksum.json create mode 100644 src/vendor/termcolor/.cargo-ok create mode 100644 src/vendor/termcolor/.gitignore rename src/vendor/{termcolor-0.3.6 => termcolor}/COPYING (100%) create mode 100644 src/vendor/termcolor/Cargo.toml create mode 100644 src/vendor/termcolor/Cargo.toml.orig rename src/vendor/{termcolor-0.3.6 => termcolor}/LICENSE-MIT (100%) create mode 100644 src/vendor/termcolor/README.md rename src/vendor/{wincolor-0.1.6 => termcolor}/UNLICENSE (100%) create mode 100644 src/vendor/termcolor/src/lib.rs create mode 100644 src/vendor/thread_local/src/unreachable.rs create mode 100644 src/vendor/utf8-ranges/Cargo.toml.orig create mode 100755 src/vendor/utf8-ranges/ci/script.sh create mode 100644 src/vendor/version_check/.cargo-checksum.json create mode 100644 src/vendor/version_check/.cargo-ok create mode 100644 src/vendor/version_check/.gitignore create mode 100644 src/vendor/version_check/Cargo.toml create mode 100644 src/vendor/version_check/Cargo.toml.orig create mode 100644 src/vendor/version_check/LICENSE-APACHE create mode 100644 src/vendor/version_check/LICENSE-MIT create mode 100644 src/vendor/version_check/README.md create mode 100644 src/vendor/version_check/src/lib.rs create mode 100755 src/vendor/walkdir/ci/script.sh create mode 100644 src/vendor/winapi-util/.cargo-checksum.json create mode 100644 src/vendor/winapi-util/.cargo-ok create mode 100644 src/vendor/winapi-util/.gitignore create mode 100644 src/vendor/winapi-util/.travis.yml rename src/vendor/{wincolor-0.1.6 => winapi-util}/COPYING (100%) create mode 100644 src/vendor/winapi-util/Cargo.toml create mode 100644 src/vendor/winapi-util/Cargo.toml.orig create mode 100644 src/vendor/winapi-util/LICENSE-MIT create mode 100644 src/vendor/winapi-util/README.md create mode 100644 src/vendor/winapi-util/UNLICENSE create mode 100644 src/vendor/winapi-util/appveyor.yml create mode 100755 src/vendor/winapi-util/ci/script.sh create mode 100644 src/vendor/winapi-util/src/console.rs create mode 100644 src/vendor/winapi-util/src/file.rs create mode 100644 src/vendor/winapi-util/src/lib.rs create mode 100644 src/vendor/winapi-util/src/win.rs delete mode 100644 src/vendor/wincolor-0.1.6/.cargo-checksum.json delete mode 100644 src/vendor/wincolor-0.1.6/Cargo.toml delete mode 100644 src/vendor/wincolor-0.1.6/Cargo.toml.orig delete mode 100644 src/vendor/wincolor-0.1.6/src/lib.rs delete mode 100644 src/vendor/wincolor-0.1.6/src/win.rs create mode 100644 src/vendor/wincolor/.cargo-checksum.json create mode 100644 src/vendor/wincolor/.cargo-ok create mode 100644 src/vendor/wincolor/COPYING create mode 100644 src/vendor/wincolor/Cargo.toml create mode 100644 src/vendor/wincolor/Cargo.toml.orig rename src/vendor/{wincolor-0.1.6 => wincolor}/LICENSE-MIT (100%) rename src/vendor/{wincolor-0.1.6 => wincolor}/README.md (100%) create mode 100644 src/vendor/wincolor/UNLICENSE create mode 100644 src/vendor/wincolor/src/lib.rs create mode 100644 src/vendor/wincolor/src/win.rs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea9f2c1943..2e51a786f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -368,8 +368,7 @@ will run all the tests on every platform we support. If it all works out, [merge-queue]: https://buildbot2.rust-lang.org/homu/queue/rust Speaking of tests, Rust has a comprehensive test suite. More information about -it can be found -[here](https://github.com/rust-lang/rust/blob/master/src/test/COMPILER_TESTS.md). +it can be found [here][rctd]. ### External Dependencies [external-dependencies]: #external-dependencies @@ -405,7 +404,8 @@ before the PR is merged. [breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler Rust's build system builds a number of tools that make use of the -internals of the compiler. This includes clippy, +internals of the compiler. This includes +[Clippy](https://github.com/rust-lang-nursery/rust-clippy), [RLS](https://github.com/rust-lang-nursery/rls) and [rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools break because of your changes, you may run into a sort of "chicken and egg" @@ -653,5 +653,5 @@ are: [rustforge]: https://forge.rust-lang.org/ [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/ [ro]: http://www.rustaceans.org/ -[rctd]: ./src/test/COMPILER_TESTS.md +[rctd]: https://rust-lang-nursery.github.io/rustc-guide/tests/intro.html [cheatsheet]: https://buildbot2.rust-lang.org/homu/ diff --git a/COPYRIGHT b/COPYRIGHT index 9bc018d983..e2d0ed7722 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -10,8 +10,8 @@ Copyrights in the Rust project are retained by their contributors. No copyright assignment is required to contribute to the Rust project. Some files include explicit copyright notices and/or license notices. -For full authorship information, see AUTHORS.txt and the version control -history. +For full authorship information, see the version control history or +https://thanks.rust-lang.org Except as otherwise noted (below and/or in individual files), Rust is licensed under the Apache License, Version 2.0 or diff --git a/README.md b/README.md index a2acfe8b47..0e5b7170bc 100644 --- a/README.md +++ b/README.md @@ -125,9 +125,9 @@ you have a more recent version installed the build system doesn't understand then you may need to force rustbuild to use an older version. This can be done by manually calling the appropriate vcvars file before running the bootstrap. -``` -CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" -python x.py build +```batch +> CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" +> python x.py build ``` #### Specifying an ABI diff --git a/RELEASES.md b/RELEASES.md index 82472df727..819c918436 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -31,6 +31,8 @@ Cargo using `--target`][cargo/5614] - [Added the `cargo-fix` subcommand to automatically move project code from 2015 edition to 2018.][cargo/5723] +- [`cargo doc` can now optionally document private types using the + `--document-private-items` flag.][cargo/5543] Misc ---- @@ -68,6 +70,7 @@ Compatibility Notes [51178]: https://github.com/rust-lang/rust/pull/51178/ [51122]: https://github.com/rust-lang/rust/pull/51122 [50494]: https://github.com/rust-lang/rust/pull/50494/ +[cargo/5543]: https://github.com/rust-lang/cargo/pull/5543 [cargo/5614]: https://github.com/rust-lang/cargo/pull/5614/ [cargo/5723]: https://github.com/rust-lang/cargo/pull/5723/ [cargo/5831]: https://github.com/rust-lang/cargo/pull/5831/ @@ -294,7 +297,7 @@ Language Compiler -------- -- [Added the `armv5te-unknown-linux-musl` target.][50423] +- [Added the `armv5te-unknown-linux-musleabi` target.][50423] Libraries --------- @@ -370,6 +373,8 @@ Compatibility Notes - [The maximum number for `repr(align(N))` is now 2²⁹.][50378] Previously you could enter higher numbers but they were not supported by LLVM. Up to 512MB alignment should cover all use cases. +- The `.description()` method on the `std::error::Error` trait + [has been soft-deprecated][50163]. It is no longer required to implement it. [48553]: https://github.com/rust-lang/rust/pull/48553/ [48851]: https://github.com/rust-lang/rust/pull/48851/ @@ -383,6 +388,7 @@ Compatibility Notes [49719]: https://github.com/rust-lang/rust/pull/49719/ [49896]: https://github.com/rust-lang/rust/pull/49896/ [49968]: https://github.com/rust-lang/rust/pull/49968/ +[50163]: https://github.com/rust-lang/rust/pull/50163 [50177]: https://github.com/rust-lang/rust/pull/50177/ [50378]: https://github.com/rust-lang/rust/pull/50378/ [50398]: https://github.com/rust-lang/rust/pull/50398/ diff --git a/config.toml.example b/config.toml.example index 9907341633..3159c19528 100644 --- a/config.toml.example +++ b/config.toml.example @@ -21,6 +21,12 @@ # Indicates whether the LLVM build is a Release or Debug build #optimize = true +# Indicates whether LLVM should be built with ThinLTO. Note that this will +# only succeed if you use clang, lld, llvm-ar, and llvm-ranlib in your C/C++ +# toolchain (see the `cc`, `cxx`, `linker`, `ar`, and `ranlib` options below). +# More info at: https://clang.llvm.org/docs/ThinLTO.html#clang-bootstrap +#thin-lto = false + # Indicates whether an LLVM Release build should include debug info #release-debuginfo = false @@ -61,8 +67,8 @@ # the same format as above, but since these targets are experimental, they are # not built by default and the experimental Rust compilation targets that depend # on them will not work unless the user opts in to building them. By default the -# `WebAssembly` target is enabled when compiling LLVM from scratch. -#experimental-targets = "WebAssembly" +# `WebAssembly` and `RISCV` targets are enabled when compiling LLVM from scratch. +#experimental-targets = "WebAssembly;RISCV" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly @@ -76,6 +82,10 @@ # passed to prefer linking to shared libraries. #link-shared = false +# When building llvm, this configures what is being appended to the version. +# If absent, we let the version as-is. +#version-suffix = "-rust" + # On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass # with clang-cl, so this is special in that it only compiles LLVM with clang-cl #clang-cl = '/path/to/clang-cl.exe' @@ -354,6 +364,10 @@ # sysroot. #llvm-tools = false +# Indicates whether LLDB will be made available in the sysroot. +# This is only built if LLVM is also being built. +#lldb = false + # Whether to deny warnings in crates #deny-warnings = true @@ -363,6 +377,10 @@ # Whether to verify generated LLVM IR #verify-llvm-ir = false +# Map all debuginfo paths for libstd and crates to `/rust/$sha/$crate/...`, +# generally only set for releases +#remap-debuginfo = false + # ============================================================================= # Options for specific targets # @@ -384,6 +402,10 @@ # Note: an absolute path should be used, otherwise LLVM build will break. #ar = "ar" +# Ranlib to be used to assemble static libraries compiled from C/C++ code. +# Note: an absolute path should be used, otherwise LLVM build will break. +#ranlib = "ranlib" + # Linker to be used to link Rust code. Note that the # default value is platform specific, and if not specified it may also depend on # what platform is crossing to what platform. diff --git a/git-commit-hash b/git-commit-hash index 349324768f..4c97a81ef5 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -aa3ca1994904f2e056679fce1f185db8c7ed2703 \ No newline at end of file +0ebb250883d63faae833070c11287fc6e7305517 \ No newline at end of file diff --git a/src/Cargo.lock b/src/Cargo.lock index 64f6b718fa..35e7174917 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1,9 +1,9 @@ [[package]] name = "aho-corasick" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -12,7 +12,7 @@ version = "0.0.0" dependencies = [ "compiler_builtins 0.0.0", "core 0.0.0", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -20,7 +20,7 @@ name = "alloc_jemalloc" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", "libc 0.0.0", @@ -42,9 +42,9 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -82,7 +82,7 @@ dependencies = [ "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -90,7 +90,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -101,9 +101,9 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -112,8 +112,8 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -123,7 +123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -131,18 +131,18 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -156,8 +156,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -172,113 +172,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cargo" -version = "0.30.0" +version = "0.31.0" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.18.0", + "crates-io 0.19.0", "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opener 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "cargo_metadata" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cargo_metadata" version = "0.6.0" @@ -286,9 +229,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -297,17 +240,17 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.18" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chalk-engine" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -339,7 +282,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -351,38 +294,50 @@ dependencies = [ name = "clippy" version = "0.0.212" dependencies = [ - "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", + "clippy_dev 0.0.1", "clippy_lints 0.0.212", "compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", + "rustc_tools_util 0.1.0", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clippy-mini-macro-test" version = "0.2.0" +[[package]] +name = "clippy_dev" +version = "0.0.1" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "clippy_lints" version = "0.0.212" dependencies = [ - "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -393,15 +348,15 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.31" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -425,14 +380,14 @@ name = "commoncrypto-sys" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "compiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -441,18 +396,18 @@ name = "compiletest" version = "0.0.0" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -464,13 +419,13 @@ dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -478,16 +433,7 @@ dependencies = [ name = "core" version = "0.0.0" dependencies = [ - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -496,15 +442,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation-sys" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -514,26 +452,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crates-io" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.19.0" dependencies = [ - "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crates-io" -version = "0.18.0" -dependencies = [ - "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -550,8 +475,8 @@ dependencies = [ "crossbeam-epoch 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -569,9 +494,9 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -583,9 +508,9 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -595,7 +520,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -621,12 +546,12 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -636,15 +561,15 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.7" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -655,12 +580,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "derive-new" -version = "0.5.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -691,11 +616,6 @@ dependencies = [ "core 0.0.0", ] -[[package]] -name = "dtoa" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "either" version = "1.5.0" @@ -706,11 +626,11 @@ name = "elasticlunr-rs" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "strum_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -720,19 +640,19 @@ name = "ena" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.5.10" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -777,9 +697,9 @@ name = "failure_derive" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -788,8 +708,8 @@ name = "filetime" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -800,10 +720,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "flate2" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -834,7 +754,7 @@ name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -844,7 +764,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -852,7 +771,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -876,24 +795,38 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "gcc" -version = "0.3.54" +name = "fwdansi" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "getopts" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "getset" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "git2" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -904,9 +837,9 @@ name = "git2-curl" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -917,14 +850,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "globset" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -936,14 +869,14 @@ name = "handlebars" version = "0.32.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -953,11 +886,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "home" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -966,7 +898,7 @@ name = "html5ever" version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -987,7 +919,7 @@ name = "idna" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -999,18 +931,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ignore" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1019,12 +951,12 @@ name = "installer" version = "0.0.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1039,7 +971,7 @@ name = "isatty" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1062,11 +994,16 @@ name = "jobserver" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "json" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "jsonrpc-core" version = "8.0.1" @@ -1074,9 +1011,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1093,12 +1030,12 @@ name = "languageserver-types" version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1110,13 +1047,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "0.6.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "lazycell" @@ -1133,66 +1068,74 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.42" +version = "0.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libgit2-sys" -version = "0.7.6" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libssh2-sys 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libssh2-sys" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libz-sys" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "linkchecker" version = "0.1.0" +[[package]] +name = "lock_api" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1200,7 +1143,7 @@ name = "log_settings" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1208,10 +1151,10 @@ name = "lzma-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1219,6 +1162,11 @@ name = "mac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "macro-utils" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "maplit" version = "1.0.1" @@ -1231,9 +1179,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1241,7 +1189,7 @@ dependencies = [ [[package]] name = "matches" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1253,31 +1201,31 @@ dependencies = [ "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1285,7 +1233,7 @@ name = "memmap" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1296,10 +1244,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "minifier" -version = "0.0.14" +version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1307,13 +1255,13 @@ name = "miniz-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miow" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "socket2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1328,10 +1276,9 @@ dependencies = [ "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "vergen 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1353,9 +1300,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1376,7 +1323,7 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1384,16 +1331,26 @@ name = "open" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "opener" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "openssl" version = "0.10.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1404,10 +1361,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-src" -version = "110.0.5+1.1.0h" +version = "110.0.7+1.1.0i" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1415,11 +1372,11 @@ name = "openssl-sys" version = "0.9.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-src 110.0.5+1.1.0h (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-src 110.0.7+1.1.0i (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1469,14 +1426,34 @@ dependencies = [ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1502,7 +1479,7 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1532,7 +1509,7 @@ version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1545,7 +1522,7 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1554,7 +1531,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1582,7 +1559,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.8" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1602,7 +1579,7 @@ dependencies = [ name = "profiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -1641,47 +1618,46 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "racer" -version = "2.1.2" +version = "2.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1706,10 +1682,10 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1730,23 +1706,23 @@ name = "regex" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1759,7 +1735,7 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1783,49 +1759,52 @@ dependencies = [ [[package]] name = "rls" -version = "0.130.0" +version = "0.130.5" dependencies = [ - "cargo 0.30.0", - "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo 0.31.0", + "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", "crossbeam-channel 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.45.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-rustc 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "rustfmt-nightly 0.99.1", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.99.4", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rls-analysis" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1837,18 +1816,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rls-data" -version = "0.16.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rls-rustc" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1857,8 +1836,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1883,16 +1862,16 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1900,201 +1879,116 @@ dependencies = [ "rustc_apfloat 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_fs_util 0.0.0", "rustc_target 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", - "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-ap-arena" -version = "209.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-arena" -version = "211.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "209.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-ap-rustc_cratesio_shim" -version = "211.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "209.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc-ap-rustc_data_structures" -version = "211.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-ap-rustc_errors" -version = "209.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-ap-rustc_errors" -version = "211.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "209.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc-ap-rustc_target" -version = "211.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-ap-serialize" -version = "209.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc-ap-serialize" -version = "211.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-ap-syntax" -version = "209.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax" -version = "211.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-ap-syntax_pos" -version = "209.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "211.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2128,10 +2022,10 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2143,7 +2037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "rustc-workspace-hack" version = "1.0.0" dependencies = [ - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2151,10 +2045,12 @@ dependencies = [ name = "rustc_allocator" version = "0.0.0" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2163,7 +2059,7 @@ dependencies = [ name = "rustc_apfloat" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", ] @@ -2174,7 +2070,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -2184,7 +2080,7 @@ name = "rustc_borrowck" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -2197,41 +2093,23 @@ dependencies = [ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc 0.0.0", - "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_allocator 0.0.0", - "rustc_apfloat 0.0.0", - "rustc_codegen_utils 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_incremental 0.0.0", + "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_llvm 0.0.0", - "rustc_mir 0.0.0", - "rustc_platform_intrinsics 0.0.0", - "rustc_target 0.0.0", - "serialize 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", - "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc_codegen_utils" version = "0.0.0" dependencies = [ - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_incremental 0.0.0", + "rustc_metadata_utils 0.0.0", "rustc_mir 0.0.0", "rustc_target 0.0.0", "syntax 0.0.0", @@ -2242,24 +2120,26 @@ dependencies = [ name = "rustc_cratesio_shim" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc_data_structures" version = "0.0.0" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "serialize 0.0.0", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2268,9 +2148,9 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ "arena 0.0.0", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", @@ -2302,22 +2182,28 @@ name = "rustc_errors" version = "0.0.0" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_cratesio_shim 0.0.0", "rustc_data_structures 0.0.0", "serialize 0.0.0", "syntax_pos 0.0.0", - "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc_fs_util" +version = "0.0.0" + [[package]] name = "rustc_incremental" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", + "rustc_fs_util 0.0.0", "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", @@ -2327,7 +2213,7 @@ dependencies = [ name = "rustc_lint" version = "0.0.0" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_mir 0.0.0", "rustc_target 0.0.0", @@ -2339,11 +2225,8 @@ dependencies = [ name = "rustc_llvm" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "build_helper 0.1.0", - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_cratesio_shim 0.0.0", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2353,7 +2236,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -2362,12 +2245,13 @@ dependencies = [ name = "rustc_metadata" version = "0.0.0" dependencies = [ - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_metadata_utils 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", "syntax 0.0.0", @@ -2375,16 +2259,25 @@ dependencies = [ "syntax_pos 0.0.0", ] +[[package]] +name = "rustc_metadata_utils" +version = "0.0.0" +dependencies = [ + "rustc 0.0.0", + "syntax 0.0.0", + "syntax_pos 0.0.0", +] + [[package]] name = "rustc_mir" version = "0.0.0" dependencies = [ "arena 0.0.0", - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", @@ -2393,6 +2286,7 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2404,7 +2298,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -2413,7 +2307,7 @@ dependencies = [ name = "rustc_passes" version = "0.0.0" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -2453,10 +2347,11 @@ name = "rustc_resolve" version = "0.0.0" dependencies = [ "arena 0.0.0", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_metadata 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2465,8 +2360,8 @@ dependencies = [ name = "rustc_save_analysis" version = "0.0.0" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2481,22 +2376,27 @@ dependencies = [ name = "rustc_target" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "serialize 0.0.0", ] +[[package]] +name = "rustc_tools_util" +version = "0.1.0" + [[package]] name = "rustc_traits" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2508,7 +2408,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", ] @@ -2518,12 +2418,13 @@ name = "rustc_typeck" version = "0.0.0" dependencies = [ "arena 0.0.0", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_platform_intrinsics 0.0.0", "rustc_target 0.0.0", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2540,9 +2441,9 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ - "minifier 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2562,45 +2463,50 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustfmt-nightly" -version = "0.99.1" +version = "0.99.4" dependencies = [ "assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ryu" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "same-file" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2608,7 +2514,7 @@ name = "schannel" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2628,7 +2534,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2638,17 +2544,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.70" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.70" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2656,22 +2562,25 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serialize" version = "0.0.0" +dependencies = [ + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "shell-escape" @@ -2690,7 +2599,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2701,8 +2610,8 @@ name = "socket2" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2720,40 +2629,31 @@ dependencies = [ "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.0.0", "core 0.0.0", "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", "profiler_builtins 0.0.0", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", "rustc_msan 0.0.0", "rustc_tsan 0.0.0", - "std_unicode 0.0.0", "unwind 0.0.0", ] -[[package]] -name = "std_unicode" -version = "0.0.0" -dependencies = [ - "compiler_builtins 0.0.0", - "core 0.0.0", -] - [[package]] name = "string_cache" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2790,9 +2690,9 @@ name = "strum_macros" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2817,11 +2717,11 @@ dependencies = [ [[package]] name = "syn" -version = "0.14.4" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2838,9 +2738,9 @@ name = "synstructure" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2848,13 +2748,14 @@ dependencies = [ name = "syntax" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "syntax_pos 0.0.0", ] @@ -2863,10 +2764,12 @@ name = "syntax_ext" version = "0.0.0" dependencies = [ "fmt_macros 0.0.0", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2876,7 +2779,7 @@ name = "syntax_pos" version = "0.0.0" dependencies = [ "arena 0.0.0", - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", @@ -2889,18 +2792,18 @@ version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempfile" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2939,10 +2842,10 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2950,7 +2853,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2973,20 +2876,19 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tidy" version = "0.1.0" dependencies = [ - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2994,7 +2896,7 @@ name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3004,7 +2906,7 @@ name = "toml" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3014,7 +2916,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3029,7 +2931,7 @@ name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3088,7 +2990,7 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3097,19 +2999,10 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "userenv-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "utf-8" version = "0.7.2" @@ -3117,12 +3010,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "utf8-ranges" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vcpkg" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3130,6 +3023,22 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vergen" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "version_check" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -3137,11 +3046,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.1.4" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3168,6 +3078,14 @@ name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3183,10 +3101,11 @@ dependencies = [ [[package]] name = "wincolor" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3194,7 +3113,7 @@ name = "xattr" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3211,7 +3130,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa" +"checksum aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee94e9463ccb9d681e7b708082687b2c56d2bd420ca8a3d3157d27d59508ec0" "checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" @@ -3220,29 +3139,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" -"checksum cargo 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21dd0ac7737313b8c5c6fbfaf351aa93d4e90f66d4a33a11d1f3fb29584ac631" -"checksum cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1efca0b863ca03ed4c109fb1c55e0bc4bbeb221d3e103d86251046b06a526bd0" "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" -"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275" -"checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e" -"checksum chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a146c19172c7eea48ea55a7123ac95da786639bc665097f1e14034ee5f1d8699" +"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" +"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" +"checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0" "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" "checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "95470235c31c726d72bf2e1f421adc1e65b9d561bf5529612cbe1a72da1467b3" +"checksum cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "704fbf3bb5149daab0afb255dbea24a1f08d2f4099cedb9baab6d470d4c5eefb" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" "checksum compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "d3064bc712922596dd5ab449fca9261d411893356581fe5297b96aa8f53bb1b8" -"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cc3532ec724375c7cb7ff0a097b714fde180bb1f6ed2ab27cfcd99ffca873cd2" -"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a3fb15cdbdd9cf8b82d97d0296bb5cd3631bba58d6e31650a002a8e7fb5721f9" -"checksum crates-io 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f78703ef5348db1e3244fb6b496e840965fb4754a5319270f2bd77ddb856e1c" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crossbeam-channel 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "efff2d411e0ac3731b9f6de882b2790fdd2de651577500a806ce78b95b2b9f31" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" @@ -3252,18 +3166,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ea52fab26a99d96cdff39d0ca75c9716125937f5dba2ab83923aaaf5928f684a" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" -"checksum curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "893713db705eab9847e050268507b0e2a2aad64e90a831874bd4e8e0d67f9523" -"checksum curl-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "de9cf174efdf90b5887c4e2e900769373c89c5e18152e8f3ed75b501a6f1c0fb" +"checksum curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "444c2f9e71458b34e75471ed8d756947a0bb920b8b8b9bfc56dfcc4fc6819a13" +"checksum curl-sys 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "78800a6de442f65dab6ce26c6f369c14fc585686432bf4b77119d2d384216c31" "checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142" -"checksum derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "899ec79626c14e00ccc9729b4d750bbe67fe76a8f436824c16e0233bbd9d7daa" +"checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a" "checksum derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46c7f14685a20f5dd08e7f754f2ea8cc064d8f4214ae21116c106a2768ba7b9b" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee" "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621" -"checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a" +"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257" "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" @@ -3271,7 +3184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" "checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" +"checksum flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "37847f133aae7acf82bb9577ccd8bda241df836787642654286e79679826a54b" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -3281,51 +3194,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" -"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" +"checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" -"checksum git2 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b87cffac882c99f9654ca5eb4c6c61527b47bc1e113304f8c57333567cd31f2" +"checksum getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54c7f36a235738bb25904d6a2b3dbb28f6f5736cd3918c4bf80d6bb236200782" +"checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" "checksum git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b502f6b1b467957403d168f0039e0c46fa6a1220efa2adaef25d5b267b5fe024" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142754da2c9b3722affd909f9e27f2a6700a7a303f362971e0a74c652005a43d" +"checksum globset 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e49edbcc9c7fc5beb8c0a54e7319ff8bed353a2b55e85811c6281188c2a6c84" "checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f94f6fbdc000a6eba0c8cf08632b2091bb59141d36ac321a2a96d6365e5e4dc" +"checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff" "checksum html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b04478cf718862650a0bf66acaf8f2f8c906fbc703f35c916c1f4211b069a364" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec" -"checksum ignore 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "787a5940ab88e0f2f3b2cad3687060bddcf67520f3b761abc31065c9c495d088" +"checksum ignore 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9faa7c84064f07b40da27044af629f578bc7994b650d3e458d0c29183c1d91" "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" "checksum isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6c324313540cd4d7ba008d43dc6606a32a5579f13cc17b2804c13096f0a5c522" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" "checksum jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "60af5f849e1981434e4a31d3d782c4774ae9b434ce55b101a96ecfd09147e8be" +"checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.45.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d91d91d1c23db74187096d191967cb49f49bb175ad6d855fa9229d16ef2c982" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3" -"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" +"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50" -"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" -"checksum libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c9051a4b288ba6f8728e9e52bb2510816946b8bcb2e20259e4d4cdc93b9ecafd" -"checksum libssh2-sys 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c628b499e8d1a4f4bd09a95d6cb1f8aeb231b46a9d40959bbd0408f14dd63adf" -"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum libgit2-sys 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "93f2b22fce91fb820363cf88a849a8f8fdfd8be37774b6a9dd6cbda05cf940e6" +"checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d" +"checksum libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "65ff614643d7635dfa2151913d95c4ee90ee1fe15d9e0980f4dcb1a7e5837c18" +"checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2" +"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd" "checksum lzma-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d1eaa027402541975218bb0eec67d6b0412f6233af96e0d096d31dbdfd22e614" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +"checksum macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2c4deaccc2ead6a28c16c0ba82f07d52b6475397415ce40876e559b0b0ea510" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475" -"checksum matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "835511bab37c34c47da5cb44844bea2cfde0236db0b506f90ea4224482c9774a" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f" -"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum minifier 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "78cb57f9a385530d60f2d67f6e108050b478b7a0ffd0bb9c350803e1356535dd" +"checksum minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9908ed7c62f990c21ab41fdca53a864a3ada0da69d8729c4de727b397e27bc11" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" -"checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d" +"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7" @@ -3333,91 +3249,87 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" +"checksum opener 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "176cd8eadff5ef9fa5c6d19452535662c02c6bf29b3d594a3fc01f749bb24c94" "checksum openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6c24d3508b4fb6da175c10baac54c578b33f09c89ae90c6fe9788b3b4768efdc" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-src 110.0.5+1.1.0h (registry+https://github.com/rust-lang/crates.io-index)" = "acff8dc857625032b2a38c88c4b960edcd674e4d211a2c81e7b0cf524d860a06" +"checksum openssl-src 110.0.7+1.1.0i (registry+https://github.com/rust-lang/crates.io-index)" = "c02d15268b7d1b3f0c83a2358f3d981139b54079440f1e2a29c60c1818ad5516" "checksum openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)" = "912f301a749394e1025d9dcddef6106ddee9252620e6d0a0e5f8d0681de9b129" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" +"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" +"checksum parking_lot_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06a2b6aae052309c2fd2161ef58f5067bc17bb758377a0de9d4b279d603fdd8a" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" "checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf" -"checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4" +"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" "checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" "checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" -"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" +"checksum pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "104630aa1c83213cbc76db0703630fcb0421dac3585063be4ce9a8a2feeaa745" "checksum polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b6b0a7f5f4278b991ffd14abce1d01b013121ad297460237ef0a2f08d43201" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" -"checksum proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c65b1ea15bb859d922cade2d1765b4b88beac339cbfad545ef2d2ef8c8215ee6" +"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" -"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" -"checksum racer 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c20890fccfc19a28835ee4ffab6af13d300a60a33be29162cfdf8db981811f25" -"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea" +"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" +"checksum racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4bc3847329b20ff5ba56c298938c179ae9911af15c9c10553f683b65164533" +"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" +"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" "checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1" "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13c93d55961981ba9226a213b385216f83ab43bd6ac53ab16b2eeb47e337cf4e" +"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05b06a75f5217880fc5e905952a42750bf44787e56a6c6d6852ed0992f5e1d54" +"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rls-analysis 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96f84d303dcbe1c1bdd41b10867d3399c38fbdac32c4e3645cdb6dbd7f82db1d" +"checksum rls-analysis 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c18011f4654e9f1c41717c5ac1323768af34de0f41e421bbe913d7e9b93581fd" "checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2" -"checksum rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd20763e1c60ae8945384c8a8fa4ac44f8afa7b0a817511f5e8927e5d24f988" -"checksum rls-rustc 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c8c09117ae2887baaa4b17fe1cb572f9b22e4d2c6a5cda04093d8b366b0be99" +"checksum rls-data 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f81e838ecff6830ed33c2907fd236f38d441c206e983a2aa29fbce99295fab9" +"checksum rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9dba7390427aefa953608429701e3665192ca810ba8ae09301e001b7c7bed0" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecbc8541b4c341d6271eae10f869dd9d36db871afe184f5b6f9bffbd6ed0373f" -"checksum rustc-ap-arena 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b098827864368459cbc7a79fbc54eafb92df7e00a46c0cda352b5a21583ee436" -"checksum rustc-ap-arena 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eec75ed880706dd9a05bc770c327ed142fa7d4b648d9757fbc71d821d68448a5" -"checksum rustc-ap-rustc_cratesio_shim 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4d923dea14fb085bca743fb982f6a3bc11c0d5d30b822bcf6fa16e9464a56c" -"checksum rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f5d54615bedbae65a976e0835edf0de90dd962ec818c0149fe181d5cd81da9e" -"checksum rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c6a5c9edc6b4ae035cdc03af7d8662d39fad7879c5501d103e7087dfaebc80" -"checksum rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7c51cc6e79eab25c7ea84a7e104e81e6f44cca32709df54c2cdb4e7059d7843" -"checksum rustc-ap-rustc_errors 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1e9bdc597abd95cebce0c14c1da58943a9e5b8255530a0fec30659d144eb0b" -"checksum rustc-ap-rustc_errors 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff050095b7afb254506591ee7d3a5d0fb9c03c16f8c2741b588178085e563d49" -"checksum rustc-ap-rustc_target 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142ddef3dc12dda2bcd3412f0d96d3745413a8fbc2f224f0cc97afa04c071d89" -"checksum rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53c7a8c21c3b05f24998fa6ab9ded6269810a2f3ae12ff301c432c1e9fa8e111" -"checksum rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b08f8f175b038a82caa7e51fc52b72ff96cfe8c1429755da30380dbd4199c7f" -"checksum rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4713c2c0c26a45ead8fb16fee88e16fecf999588ae6920847cbaeb19565b7f" -"checksum rustc-ap-syntax 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c802e0e1fbc64eddc21e0798527eb1f5fdbd5781d119bd2c44b6130afdc81cc" -"checksum rustc-ap-syntax 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "768e2698f912913be2ccd355b2dea62c978efc356f75db1400605f3642905d53" -"checksum rustc-ap-syntax_pos 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "008d47cc54ed12a2784217b9e6630a7fa1c8dc3591a283f65ad4b7fa307d49d5" -"checksum rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a280dc8919aa7f684832ba3eeab2f6c96dbe2e2e4f6a922f7f0bdb3a9dd9e641" -"checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" +"checksum rustc-ap-arena 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d24c8b3c1437fad023cb9472381216a1d41d82dbb2d2e6c7858bd6f50317719" +"checksum rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c5b02c76cd1ee4e9c97c8228701796d6b7431e8f100dea2d8af1d6c2c2bad56" +"checksum rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4076388154497fb9a007e3badd78e415402a5594111cd6bc7ce1420dd1b1818b" +"checksum rustc-ap-rustc_errors 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6c11e4789cbc276ceaa87d326c234b1a2d1e0fe6017b88a8a25903200060acb" +"checksum rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25f711bb152b9d7cdd69410cfe6d99aeb1409c959e0fdf3c8ca4d220e568aa52" +"checksum rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57638db658d4942d3f30a12566836f9a67a636ed8002c8cae1c9231214e39929" +"checksum rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6dbcf07abf7a9957dce8d34353d55dfb4cd882153181f24349f4690facb58f0" +"checksum rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0915cb5e166cabe588a129dec2d47357077e96fb1f9b57318fbe217eac4ce508" +"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a" "checksum rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "756567f00f7d89c9f89a5c401b8b1caaa122e27240b9eaadd0bb52ee0b680b1b" -"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" +"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" +"checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c" "checksum schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1fabf2a7b6483a141426e1afd09ad543520a77ac49bd03c286e7696ccfd77f" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920" -"checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124" +"checksum serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "22d340507cea0b7e6632900a176101fea959c7065d93ba555072da90aaaafc87" +"checksum serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "234fc8b737737b148ccd625175fc6390f5e4dacfdaa543cb93a3430d984a9119" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" -"checksum serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2" +"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8" +"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum socket2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "962a516af4d3a7c272cb3a1d50a8cc4e5b41802e4ad54cfb7bee8ba61d37d703" "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" @@ -3428,18 +3340,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strum_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1292d85e688e4696ecb69b2db2648994fb8af266974e89be53cefdf003861a5d" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" -"checksum syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2beff8ebc3658f07512a413866875adddd20f4fd47b2a4e6c9da65cd281baaea" +"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f41ca4a5689f06998f0247fcb60da6c760f1950cc9df2a10d71575ad0b062a" -"checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b" +"checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76" "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" -"checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836" +"checksum termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3390f44f1f706d8870297b6a2c4f92d9ab65a37c265fbbc6ac4ee72bcc2f3698" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8" @@ -3453,20 +3365,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" -"checksum userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d28ea36bbd9192d75bd9fa9b39f96ddb986eaee824adae5d53b6e51919b2f3" "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cbe533e138811704c0e3cbde65a818b35d3240409b4346256c5ede403e082474" +"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" +"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum vergen 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a16834fc61e1492c07dae49b6c14b55f8b1d43a5f5f9e9a2ecc063f47b9f93c" +"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" +"checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" -"checksum wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9dc3aa9dcda98b5a16150c54619c1ead22e3d3a5d458778ae914be760aa981a" +"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" "checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" "checksum xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "df8bf41d3030c3577c9458fd6640a05afbf43b150d0b531b16bd77d3f794f27a" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 2e5b39ca5d..3e91c2b3e8 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -41,13 +41,13 @@ num_cpus = "1.0" getopts = "0.2" cc = "1.0.1" libc = "0.2" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" +serde = "1.0.8" +serde_derive = "1.0.8" +serde_json = "1.0.2" toml = "0.4" lazy_static = "0.2" time = "0.1" -petgraph = "0.4.12" +petgraph = "0.4.13" [dev-dependencies] pretty_assertions = "0.5" diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 98c353eb6e..1e01d68fb3 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -8,14 +8,14 @@ system. The rustbuild build system has a primary entry point, a top level `x.py` script: -``` -python ./x.py build +```sh +$ python ./x.py build ``` Note that if you're on Unix you should be able to execute the script directly: -``` -./x.py build +```sh +$ ./x.py build ``` The script accepts commands, flags, and arguments to determine what to do: @@ -129,18 +129,18 @@ To follow this course of action, first thing you will want to do is to install a nightly, presumably using `rustup`. You will then want to configure your directory to use this build, like so: -``` +```sh # configure to use local rust instead of downloading a beta. # `--local-rust-root` is optional here. If elided, we will # use whatever rustc we find on your PATH. -> ./configure --local-rust-root=~/.cargo/ --enable-local-rebuild +$ ./configure --local-rust-root=~/.cargo/ --enable-local-rebuild ``` After that, you can use the `--incremental` flag to actually do incremental builds: -``` -> ./x.py build --incremental +```sh +$ ./x.py build --incremental ``` The `--incremental` flag will store incremental compilation artifacts @@ -159,7 +159,7 @@ will still be using the local nightly as your bootstrap). This build system houses all output under the `build` directory, which looks like this: -``` +```sh # Root folder of all output. Everything is scoped underneath here build/ diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 7192cae895..b89976eca2 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -263,6 +263,10 @@ fn main() { if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } + + if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { + cmd.arg("--remap-path-prefix").arg(&map); + } } else { // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { @@ -287,15 +291,6 @@ fn main() { cmd.arg("-Z").arg("verify-llvm-ir"); } - let color = match env::var("RUSTC_COLOR") { - Ok(s) => usize::from_str(&s).expect("RUSTC_COLOR should be an integer"), - Err(_) => 0, - }; - - if color != 0 { - cmd.arg("--color=always"); - } - if env::var_os("RUSTC_DENY_WARNINGS").is_some() && env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { cmd.arg("-Dwarnings"); diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index a54e58665c..bb5a21e3e4 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -37,6 +37,8 @@ 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` + //arguments here let mut cmd = Command::new(rustdoc); cmd.args(&args) .arg("--cfg") diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 71c1c61e3d..d9c66ce2d7 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -88,7 +88,10 @@ def _download(path, url, probably_big, verbose, exception): option = "-#" else: option = "-s" - run(["curl", option, "--retry", "3", "-Sf", "-o", path, url], + run(["curl", option, + "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds + "--connect-timeout", "30", # timeout if cannot connect within 30 seconds + "--retry", "3", "-Sf", "-o", path, url], verbose=verbose, exception=exception) @@ -718,6 +721,10 @@ class RustBuild(object): config = self.get_toml('lld') if config is None or config == 'false': continue + if module.endswith("lldb") or module.endswith("clang"): + config = self.get_toml('lldb') + if config is None or config == 'false': + continue check = self.check_submodule(module, slow_submodules) filtered_submodules.append((module, check)) submodules_names.append(module) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index dc0b0aaf0b..b842bc43f5 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -32,7 +32,7 @@ use native; use test; use tool; use util::{add_lib_path, exe, libdir}; -use {Build, DocTests, Mode}; +use {Build, DocTests, Mode, GitRepo}; pub use Compiler; @@ -461,6 +461,7 @@ impl<'a> Builder<'a> { dist::Rustfmt, dist::Clippy, dist::LlvmTools, + dist::Lldb, dist::Extended, dist::HashSign ), @@ -707,6 +708,80 @@ impl<'a> Builder<'a> { ) -> Command { let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); + + // command specific path, we call clear_if_dirty with this + let mut my_out = match cmd { + "build" => self.cargo_out(compiler, mode, target), + + // This is the intended out directory for crate documentation. + "doc" => self.crate_doc_out(target), + + _ => self.stage_out(compiler, mode), + }; + + // This is for the original compiler, but if we're forced to use stage 1, then + // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since + // we copy the libs forward. + let cmp = if self.force_use_stage1(compiler, target) { + self.compiler(1, compiler.host) + } else { + compiler + }; + + let libstd_stamp = match cmd { + "check" => check::libstd_stamp(self, cmp, target), + _ => compile::libstd_stamp(self, cmp, target), + }; + + let libtest_stamp = match cmd { + "check" => check::libtest_stamp(self, cmp, target), + _ => compile::libstd_stamp(self, cmp, target), + }; + + let librustc_stamp = match cmd { + "check" => check::librustc_stamp(self, cmp, target), + _ => compile::librustc_stamp(self, cmp, target), + }; + + if cmd == "doc" { + if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen { + // This is the intended out directory for compiler documentation. + my_out = self.compiler_doc_out(target); + } + let rustdoc = self.rustdoc(compiler.host); + self.clear_if_dirty(&my_out, &rustdoc); + } else if cmd != "test" { + match mode { + Mode::Std => { + self.clear_if_dirty(&my_out, &self.rustc(compiler)); + }, + Mode::Test => { + self.clear_if_dirty(&my_out, &libstd_stamp); + }, + Mode::Rustc => { + self.clear_if_dirty(&my_out, &self.rustc(compiler)); + self.clear_if_dirty(&my_out, &libstd_stamp); + self.clear_if_dirty(&my_out, &libtest_stamp); + }, + Mode::Codegen => { + self.clear_if_dirty(&my_out, &librustc_stamp); + }, + Mode::ToolBootstrap => { }, + Mode::ToolStd => { + self.clear_if_dirty(&my_out, &libstd_stamp); + }, + Mode::ToolTest => { + self.clear_if_dirty(&my_out, &libstd_stamp); + self.clear_if_dirty(&my_out, &libtest_stamp); + }, + Mode::ToolRustc => { + self.clear_if_dirty(&my_out, &libstd_stamp); + self.clear_if_dirty(&my_out, &libtest_stamp); + self.clear_if_dirty(&my_out, &librustc_stamp); + }, + } + } + cargo .env("CARGO_TARGET_DIR", out_dir) .arg(cmd); @@ -826,7 +901,7 @@ impl<'a> Builder<'a> { if let Some(ref error_format) = self.config.rustc_error_format { cargo.env("RUSTC_ERROR_FORMAT", error_format); } - if cmd != "build" && cmd != "check" && want_rustdoc { + if cmd != "build" && cmd != "check" && cmd != "rustc" && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.config.build)); } @@ -875,6 +950,10 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string()); } + if let Some(map) = self.build.debuginfo_map(GitRepo::Rustc) { + cargo.env("RUSTC_DEBUGINFO_MAP", map); + } + // Enable usage of unstable features cargo.env("RUSTC_BOOTSTRAP", "1"); self.add_rust_test_threads(&mut cargo); @@ -963,7 +1042,7 @@ impl<'a> Builder<'a> { let cc = ccacheify(&self.cc(target)); cargo.env(format!("CC_{}", target), &cc).env("CC", &cc); - let cflags = self.cflags(target).join(" "); + let cflags = self.cflags(target, GitRepo::Rustc).join(" "); cargo .env(format!("CFLAGS_{}", target), cflags.clone()) .env("CFLAGS", cflags.clone()); @@ -987,7 +1066,7 @@ impl<'a> Builder<'a> { } } - if cmd == "build" + if (cmd == "build" || cmd == "rustc") && mode == Mode::Std && self.config.extended && compiler.is_final_stage(self) diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index 698903f128..d5da0cabec 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -39,7 +39,7 @@ use std::process::Command; use build_helper::output; use cc; -use Build; +use {Build, GitRepo}; use config::Target; use cache::Interned; @@ -107,7 +107,7 @@ pub fn find(build: &mut Build) { build.cc.insert(target, compiler); build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target))); - build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target))); + build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target, GitRepo::Rustc))); if let Some(ar) = ar { build.verbose(&format!("AR_{} = {:?}", &target, ar)); build.ar.insert(target, ar); diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 04d576df95..fa2b58fb2d 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -24,7 +24,7 @@ use Build; use config::Config; // The version number -pub const CFG_RELEASE_NUM: &str = "1.29.0"; +pub const CFG_RELEASE_NUM: &str = "1.30.0"; pub struct GitInfo { inner: Option, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 2f0ae7d9d2..11463c1a05 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -12,7 +12,7 @@ use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot}; use builder::{RunConfig, Builder, ShouldRun, Step}; -use tool::{self, prepare_tool_cargo, SourceType}; +use tool::{prepare_tool_cargo, SourceType}; use {Compiler, Mode}; use cache::{INTERNER, Interned}; use std::path::PathBuf; @@ -40,16 +40,14 @@ impl Step for Std { let target = self.target; let compiler = builder.compiler(0, builder.config.build); - let out_dir = builder.stage_out(compiler, Mode::Std); - builder.clear_if_dirty(&out_dir, &builder.rustc(compiler)); - let mut cargo = builder.cargo(compiler, Mode::Std, target, "check"); std_cargo(builder, &compiler, target, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage)); - println!("Checking std artifacts ({} -> {})", &compiler.host, target); + builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libstd_stamp(builder, compiler, target), true); @@ -87,17 +85,16 @@ impl Step for Rustc { let compiler = builder.compiler(0, builder.config.build); let target = self.target; - let stage_out = builder.stage_out(compiler, Mode::Rustc); - builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target)); - builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target)); + builder.ensure(Test { target }); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "check"); rustc_cargo(builder, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage)); - println!("Checking compiler artifacts ({} -> {})", &compiler.host, target); + builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &librustc_stamp(builder, compiler, target), true); @@ -137,8 +134,9 @@ impl Step for CodegenBackend { let target = self.target; let backend = self.backend; + builder.ensure(Rustc { target }); + let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "check"); - let features = builder.rustc_features().to_string(); cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); rustc_cargo_env(builder, &mut cargo); @@ -146,7 +144,8 @@ impl Step for CodegenBackend { let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage)); run_cargo(builder, - cargo.arg("--features").arg(features), + &mut cargo, + vec![], &codegen_backend_stamp(builder, compiler, target, backend), true); } @@ -175,16 +174,16 @@ impl Step for Test { let compiler = builder.compiler(0, builder.config.build); let target = self.target; - let out_dir = builder.stage_out(compiler, Mode::Test); - builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target)); + builder.ensure(Std { target }); let mut cargo = builder.cargo(compiler, Mode::Test, target, "check"); test_cargo(builder, &compiler, target, &mut cargo); let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage)); - println!("Checking test artifacts ({} -> {})", &compiler.host, target); + builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libtest_stamp(builder, compiler, target), true); @@ -217,10 +216,7 @@ impl Step for Rustdoc { let compiler = builder.compiler(0, builder.config.build); let target = self.target; - let stage_out = builder.stage_out(compiler, Mode::ToolRustc); - builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target)); - builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target)); - builder.clear_if_dirty(&stage_out, &librustc_stamp(builder, compiler, target)); + builder.ensure(Rustc { target }); let mut cargo = prepare_tool_cargo(builder, compiler, @@ -234,17 +230,13 @@ impl Step for Rustdoc { println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target); run_cargo(builder, &mut cargo, + vec![], &rustdoc_stamp(builder, compiler, target), true); let libdir = builder.sysroot_libdir(compiler, target); add_to_sysroot(&builder, &libdir, &rustdoc_stamp(builder, compiler, target)); - - builder.ensure(tool::CleanTools { - compiler, - target, - cause: Mode::Rustc, - }); + builder.cargo(compiler, Mode::ToolRustc, target, "clean"); } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 04e8e133b0..608f2c982c 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -29,10 +29,9 @@ use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use serde_json; -use util::{exe, libdir, is_dylib, CiEnv}; -use {Compiler, Mode}; +use util::{exe, libdir, is_dylib}; +use {Compiler, Mode, GitRepo}; use native; -use tool; use cache::{INTERNER, Interned}; use builder::{Step, RunConfig, ShouldRun, Builder}; @@ -107,8 +106,6 @@ impl Step for Std { copy_musl_third_party_objects(builder, target, &libdir); } - let out_dir = builder.cargo_out(compiler, Mode::Std, target); - builder.clear_if_dirty(&out_dir, &builder.rustc(compiler)); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); std_cargo(builder, &compiler, target, &mut cargo); @@ -117,6 +114,7 @@ impl Step for Std { &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libstd_stamp(builder, compiler, target), false); @@ -157,7 +155,6 @@ pub fn std_cargo(builder: &Builder, cargo.arg("--features").arg("c mem") .args(&["-p", "alloc"]) .args(&["-p", "compiler_builtins"]) - .args(&["-p", "std_unicode"]) .arg("--manifest-path") .arg(builder.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); } else { @@ -246,11 +243,7 @@ impl Step for StdLink { copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); } - builder.ensure(tool::CleanTools { - compiler: target_compiler, - target, - cause: Mode::Std, - }); + builder.cargo(target_compiler, Mode::ToolStd, target, "clean"); } } @@ -387,8 +380,6 @@ impl Step for Test { return; } - let out_dir = builder.cargo_out(compiler, Mode::Test, target); - builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Test, target, "build"); test_cargo(builder, &compiler, target, &mut cargo); @@ -397,6 +388,7 @@ impl Step for Test { &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libtest_stamp(builder, compiler, target), false); @@ -447,11 +439,8 @@ impl Step for TestLink { target)); add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target), &libtest_stamp(builder, compiler, target)); - builder.ensure(tool::CleanTools { - compiler: target_compiler, - target, - cause: Mode::Test, - }); + + builder.cargo(target_compiler, Mode::ToolTest, target, "clean"); } } @@ -518,9 +507,6 @@ impl Step for Rustc { compiler: builder.compiler(self.compiler.stage, builder.config.build), target: builder.config.build, }); - let cargo_out = builder.cargo_out(compiler, Mode::Rustc, target); - builder.clear_if_dirty(&cargo_out, &libstd_stamp(builder, compiler, target)); - builder.clear_if_dirty(&cargo_out, &libtest_stamp(builder, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build"); rustc_cargo(builder, &mut cargo); @@ -530,6 +516,7 @@ impl Step for Rustc { compiler.stage, &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &librustc_stamp(builder, compiler, target), false); @@ -611,11 +598,7 @@ impl Step for RustcLink { target)); add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target), &librustc_stamp(builder, compiler, target)); - builder.ensure(tool::CleanTools { - compiler: target_compiler, - target, - cause: Mode::Rustc, - }); + builder.cargo(target_compiler, Mode::ToolRustc, target, "clean"); } } @@ -671,20 +654,49 @@ impl Step for CodegenBackend { return; } - let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build"); - let mut features = builder.rustc_features().to_string(); + let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); + + let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "rustc"); cargo.arg("--manifest-path") .arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); rustc_cargo_env(builder, &mut cargo); - features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); + let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); + + let mut cargo_tails_args = vec![]; + + if builder.config.llvm_thin_lto { + cargo_tails_args.push("--".to_string()); + + let num_jobs = builder.jobs(); - let tmp_stamp = builder.cargo_out(compiler, Mode::Codegen, target) - .join(".tmp.stamp"); + if !target.contains("msvc") { + // Here we assume that the linker is clang. If it's not, there'll + // be linker errors. + cargo_tails_args.push("-Clink-arg=-fuse-ld=lld".to_string()); + cargo_tails_args.push("-Clink-arg=-flto=thin".to_string()); + + if builder.config.llvm_optimize { + cargo_tails_args.push("-Clink-arg=-O2".to_string()); + } + + // Let's make LLD respect the `-j` option. + let num_jobs_arg = format!("-Clink-arg=-Wl,--thinlto-jobs={}", num_jobs); + cargo_tails_args.push(num_jobs_arg); + } else { + // Here we assume that the linker is lld-link.exe. lld-link.exe + // does not need the extra arguments except for num_jobs + let num_jobs_arg = format!("-Clink-arg=/opt:lldltojobs={}", num_jobs); + cargo_tails_args.push(num_jobs_arg); + } + } + + let tmp_stamp = out_dir.join(".tmp.stamp"); let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage)); let files = run_cargo(builder, cargo.arg("--features").arg(features), + cargo_tails_args, &tmp_stamp, false); if builder.config.dry_run { @@ -863,7 +875,7 @@ pub fn compiler_file(builder: &Builder, target: Interned, file: &str) -> PathBuf { let mut cmd = Command::new(compiler); - cmd.args(builder.cflags(target)); + cmd.args(builder.cflags(target, GitRepo::Rustc)); cmd.arg(format!("-print-file-name={}", file)); let out = output(&mut cmd); PathBuf::from(out.trim()) @@ -1022,30 +1034,11 @@ pub fn add_to_sysroot(builder: &Builder, sysroot_dst: &Path, stamp: &Path) { } } -// Avoiding a dependency on winapi to keep compile times down -#[cfg(unix)] -fn stderr_isatty() -> bool { - use libc; - unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } -} -#[cfg(windows)] -fn stderr_isatty() -> bool { - type DWORD = u32; - type BOOL = i32; - type HANDLE = *mut u8; - const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; - extern "system" { - fn GetStdHandle(which: DWORD) -> HANDLE; - fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: *mut DWORD) -> BOOL; - } - unsafe { - let handle = GetStdHandle(STD_ERROR_HANDLE); - let mut out = 0; - GetConsoleMode(handle, &mut out) != 0 - } -} - -pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check: bool) +pub fn run_cargo(builder: &Builder, + cargo: &mut Command, + tail_args: Vec, + stamp: &Path, + is_check: bool) -> Vec { if builder.config.dry_run { @@ -1066,7 +1059,7 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check: // files we need to probe for later. let mut deps = Vec::new(); let mut toplevel = Vec::new(); - let ok = stream_cargo(builder, cargo, &mut |msg| { + let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| { let filenames = match msg { CargoMessage::CompilerArtifact { filenames, .. } => filenames, _ => return, @@ -1191,6 +1184,7 @@ pub fn run_cargo(builder: &Builder, cargo: &mut Command, stamp: &Path, is_check: pub fn stream_cargo( builder: &Builder, cargo: &mut Command, + tail_args: Vec, cb: &mut dyn FnMut(CargoMessage), ) -> bool { if builder.config.dry_run { @@ -1201,13 +1195,8 @@ pub fn stream_cargo( cargo.arg("--message-format").arg("json") .stdout(Stdio::piped()); - if stderr_isatty() && builder.ci_env == CiEnv::None && - // if the terminal is reported as dumb, then we don't want to enable color for rustc - env::var_os("TERM").map(|t| t != *"dumb").unwrap_or(true) { - // since we pass message-format=json to cargo, we need to tell the rustc - // wrapper to give us colored output if necessary. This is because we - // only want Cargo's JSON output, not rustcs. - cargo.env("RUSTC_COLOR", "1"); + for arg in tail_args { + cargo.arg(arg); } builder.verbose(&format!("running: {:?}", cargo)); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0a8a5c87d0..cc6d76c76f 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -77,6 +77,7 @@ pub struct Config { pub llvm_enabled: bool, pub llvm_assertions: bool, pub llvm_optimize: bool, + pub llvm_thin_lto: bool, pub llvm_release_debuginfo: bool, pub llvm_version_check: bool, pub llvm_static_stdcpp: bool, @@ -85,8 +86,10 @@ pub struct Config { pub llvm_targets: Option, pub llvm_experimental_targets: String, pub llvm_link_jobs: Option, + pub llvm_version_suffix: Option, pub lld_enabled: bool, + pub lldb_enabled: bool, pub llvm_tools_enabled: bool, // rust codegen options @@ -106,6 +109,7 @@ pub struct Config { pub rust_codegen_backends: Vec>, pub rust_codegen_backends_dir: String, pub rust_verify_llvm_ir: bool, + pub rust_remap_debuginfo: bool, pub build: Interned, pub hosts: Vec>, @@ -162,6 +166,7 @@ pub struct Target { pub cc: Option, pub cxx: Option, pub ar: Option, + pub ranlib: Option, pub linker: Option, pub ndk: Option, pub crt_static: Option, @@ -245,6 +250,7 @@ struct Llvm { ninja: Option, assertions: Option, optimize: Option, + thin_lto: Option, release_debuginfo: Option, version_check: Option, static_libstdcpp: Option, @@ -252,6 +258,7 @@ struct Llvm { experimental_targets: Option, link_jobs: Option, link_shared: Option, + version_suffix: Option, clang_cl: Option } @@ -310,10 +317,12 @@ struct Rust { codegen_backends_dir: Option, wasm_syscall: Option, lld: Option, + lldb: Option, llvm_tools: Option, deny_warnings: Option, backtrace_on_ice: Option, verify_llvm_ir: Option, + remap_debuginfo: Option, } /// TOML representation of how each build target is configured. @@ -325,6 +334,7 @@ struct TomlTarget { cc: Option, cxx: Option, ar: Option, + ranlib: Option, linker: Option, android_ndk: Option, crt_static: Option, @@ -501,14 +511,16 @@ impl Config { set(&mut config.llvm_enabled, llvm.enabled); llvm_assertions = llvm.assertions; set(&mut config.llvm_optimize, llvm.optimize); + set(&mut config.llvm_thin_lto, llvm.thin_lto); set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo); set(&mut config.llvm_version_check, llvm.version_check); set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); set(&mut config.llvm_link_shared, llvm.link_shared); config.llvm_targets = llvm.targets.clone(); config.llvm_experimental_targets = llvm.experimental_targets.clone() - .unwrap_or("WebAssembly".to_string()); + .unwrap_or("WebAssembly;RISCV".to_string()); config.llvm_link_jobs = llvm.link_jobs; + config.llvm_version_suffix = llvm.version_suffix.clone(); config.llvm_clang_cl = llvm.clang_cl.clone(); } @@ -538,6 +550,7 @@ impl Config { } set(&mut config.wasm_syscall, rust.wasm_syscall); set(&mut config.lld_enabled, rust.lld); + set(&mut config.lldb_enabled, rust.lldb); set(&mut config.llvm_tools_enabled, rust.llvm_tools); config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false); config.rustc_default_linker = rust.default_linker.clone(); @@ -546,6 +559,7 @@ impl Config { set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings)); set(&mut config.backtrace_on_ice, rust.backtrace_on_ice); set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir); + set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo); if let Some(ref backends) = rust.codegen_backends { config.rust_codegen_backends = backends.iter() @@ -578,6 +592,7 @@ impl Config { target.cc = cfg.cc.clone().map(PathBuf::from); target.cxx = cfg.cxx.clone().map(PathBuf::from); target.ar = cfg.ar.clone().map(PathBuf::from); + target.ranlib = cfg.ranlib.clone().map(PathBuf::from); target.linker = cfg.linker.clone().map(PathBuf::from); target.crt_static = cfg.crt_static.clone(); target.musl_root = cfg.musl_root.clone().map(PathBuf::from); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 9fdba044f4..cf7f78eeba 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -68,6 +68,7 @@ o("cargo-openssl-static", "build.openssl-static", "static openssl in cargo") o("profiler", "build.profiler", "build the profiler runtime") o("emscripten", None, "compile the emscripten backend as well as LLVM") o("full-tools", None, "enable all tools") +o("lldb", "rust.lldb", "build lldb") # Optimization and debugging options. These may be overridden by the release # channel, etc. @@ -350,7 +351,7 @@ set('build.configure-args', sys.argv[1:]) # all the various comments and whatnot. # # Note that the `target` section is handled separately as we'll duplicate it -# per configure dtarget, so there's a bit of special handling for that here. +# per configured target, so there's a bit of special handling for that here. sections = {} cur_section = None sections[None] = [] diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c6b39a52ae..2d94704fda 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -47,6 +47,8 @@ pub fn pkgname(builder: &Builder, component: &str) -> String { format!("{}-{}", component, builder.rustfmt_package_vers()) } else if component == "llvm-tools" { format!("{}-{}", component, builder.llvm_tools_package_vers()) + } else if component == "lldb" { + format!("{}-{}", component, builder.lldb_package_vers()) } else { assert!(component.starts_with("rust")); format!("{}-{}", component, builder.rust_package_vers()) @@ -499,6 +501,13 @@ impl Step for Rustc { 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 + // tools/LLDB come later, so let's just throw it in the rustc + // component for now. + maybe_install_llvm_dylib(builder, host, image); + // Copy over lld if it's there if builder.config.lld_enabled { let exe = exe("rust-lld", &compiler.host); @@ -856,7 +865,6 @@ impl Step for Src { "src/librustc_msan", "src/librustc_tsan", "src/libstd", - "src/libstd_unicode", "src/libunwind", "src/rustc/compiler_builtins_shim", "src/rustc/libc_shim", @@ -1397,6 +1405,7 @@ impl Step for Extended { let rls_installer = builder.ensure(Rls { stage, target }); let llvm_tools_installer = builder.ensure(LlvmTools { stage, target }); let clippy_installer = builder.ensure(Clippy { stage, target }); + let lldb_installer = builder.ensure(Lldb { target }); let mingw_installer = builder.ensure(Mingw { host: target }); let analysis_installer = builder.ensure(Analysis { compiler: builder.compiler(stage, self.host), @@ -1436,6 +1445,7 @@ impl Step for Extended { tarballs.extend(clippy_installer.clone()); tarballs.extend(rustfmt_installer.clone()); tarballs.extend(llvm_tools_installer.clone()); + tarballs.extend(lldb_installer.clone()); tarballs.push(analysis_installer); tarballs.push(std_installer); if builder.config.docs { @@ -1870,6 +1880,7 @@ impl Step for HashSign { cmd.arg(builder.package_vers(&builder.release_num("clippy"))); cmd.arg(builder.package_vers(&builder.release_num("rustfmt"))); cmd.arg(builder.llvm_tools_package_vers()); + cmd.arg(builder.lldb_package_vers()); cmd.arg(addr); builder.create_dir(&distdir(builder)); @@ -1881,6 +1892,42 @@ impl Step for HashSign { } } +// Maybe add libLLVM.so to the lib-dir. It will only have been built if +// LLVM tools are linked dynamically. +// Note: This function does no yet support Windows but we also don't support +// linking LLVM tools dynamically on Windows yet. +fn maybe_install_llvm_dylib(builder: &Builder, + target: Interned, + image: &Path) { + let src_libdir = builder + .llvm_out(target) + .join("lib"); + let dst_libdir = image.join("lib/rustlib").join(&*target).join("lib"); + t!(fs::create_dir_all(&dst_libdir)); + + 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); + } + return + } + + // Usually libLLVM.so is a symlink to something like libLLVM-6.0.so. + // Since tools link to the latter rather than the former, we have to + // follow the symlink to find out what to distribute. + let llvm_dylib_path = src_libdir.join("libLLVM.so"); + if llvm_dylib_path.exists() { + let llvm_dylib_path = llvm_dylib_path.canonicalize().unwrap_or_else(|e| { + panic!("dist: Error calling canonicalize path `{}`: {}", + llvm_dylib_path.display(), e); + }); + + + builder.install(&llvm_dylib_path, &dst_libdir, 0o644); + } +} + #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct LlvmTools { pub stage: u32, @@ -1925,16 +1972,16 @@ impl Step for LlvmTools { drop(fs::remove_dir_all(&image)); // Prepare the image directory - let bindir = builder + let src_bindir = builder .llvm_out(target) .join("bin"); - let dst = image.join("lib/rustlib") - .join(target) + let dst_bindir = image.join("lib/rustlib") + .join(&*target) .join("bin"); - t!(fs::create_dir_all(&dst)); + t!(fs::create_dir_all(&dst_bindir)); for tool in LLVM_TOOLS { - let exe = bindir.join(exe(tool, &target)); - builder.install(&exe, &dst, 0o755); + let exe = src_bindir.join(exe(tool, &target)); + builder.install(&exe, &dst_bindir, 0o755); } // Prepare the overlay @@ -1964,3 +2011,121 @@ impl Step for LlvmTools { Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } } + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Lldb { + pub target: Interned, +} + +impl Step for Lldb { + type Output = Option; + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/lldb") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(Lldb { + target: run.target, + }); + } + + fn run(self, builder: &Builder) -> Option { + let target = self.target; + + if builder.config.dry_run { + return None; + } + + let bindir = builder + .llvm_out(target) + .join("bin"); + let lldb_exe = bindir.join(exe("lldb", &target)); + if !lldb_exe.exists() { + return None; + } + + builder.info(&format!("Dist Lldb ({})", target)); + let src = builder.src.join("src/tools/lldb"); + let name = pkgname(builder, "lldb"); + + let tmp = tmpdir(builder); + let image = tmp.join("lldb-image"); + drop(fs::remove_dir_all(&image)); + + // Prepare the image directory + let root = image.join("lib/rustlib").join(&*target); + let dst = root.join("bin"); + t!(fs::create_dir_all(&dst)); + for program in &["lldb", "lldb-argdumper", "lldb-mi", "lldb-server"] { + let exe = bindir.join(exe(program, &target)); + builder.install(&exe, &dst, 0o755); + } + + // The libraries. + let libdir = builder.llvm_out(target).join("lib"); + let dst = root.join("lib"); + t!(fs::create_dir_all(&dst)); + for entry in t!(fs::read_dir(&libdir)) { + let entry = entry.unwrap(); + if let Ok(name) = entry.file_name().into_string() { + if name.starts_with("liblldb.") && !name.ends_with(".a") { + if t!(entry.file_type()).is_symlink() { + builder.copy_to_folder(&entry.path(), &dst); + } else { + builder.install(&entry.path(), &dst, 0o755); + } + } + } + } + + // The lldb scripts might be installed in lib/python$version + // or in lib64/python$version. If lib64 exists, use it; + // otherwise lib. + let libdir = builder.llvm_out(target).join("lib64"); + let (libdir, libdir_name) = if libdir.exists() { + (libdir, "lib64") + } else { + (builder.llvm_out(target).join("lib"), "lib") + }; + for entry in t!(fs::read_dir(&libdir)) { + let entry = t!(entry); + if let Ok(name) = entry.file_name().into_string() { + if name.starts_with("python") { + let dst = root.join(libdir_name) + .join(entry.file_name()); + t!(fs::create_dir_all(&dst)); + builder.cp_r(&entry.path(), &dst); + break; + } + } + } + + // Prepare the overlay + let overlay = tmp.join("lldb-overlay"); + drop(fs::remove_dir_all(&overlay)); + builder.create_dir(&overlay); + builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644); + builder.create(&overlay.join("version"), &builder.lldb_vers()); + + // Generate the installer tarball + let mut cmd = rust_installer(builder); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=lldb-installed.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(builder)) + .arg("--output-dir").arg(&distdir(builder)) + .arg("--non-installed-overlay").arg(&overlay) + .arg(format!("--package-name={}-{}", name, target)) + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg("--component-name=lldb-preview"); + + + builder.run(&mut cmd); + Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) + } +} diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 9dbbe6bcfe..17ccb04a71 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -455,7 +455,6 @@ impl Step for Std { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -480,7 +479,6 @@ impl Step for Std { // This way rustdoc generates output directly into the output, and rustdoc // will also directly handle merging. let my_out = builder.crate_doc_out(target); - builder.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Std, target, "doc"); @@ -489,7 +487,7 @@ impl Step for Std { // Keep a whitelist so we do not build internal stdlib crates, these will be // build by the rustc step later if enabled. cargo.arg("--no-deps"); - for krate in &["alloc", "core", "std", "std_unicode"] { + for krate in &["alloc", "core", "std"] { cargo.arg("-p").arg(krate); // Create all crate output directories first to make sure rustdoc uses // relative links. @@ -535,7 +533,6 @@ impl Step for Test { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -551,7 +548,6 @@ impl Step for Test { // See docs in std above for why we symlink let my_out = builder.crate_doc_out(target); - builder.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Test, target, "doc"); @@ -603,7 +599,6 @@ impl Step for WhitelistedRustc { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -619,7 +614,6 @@ impl Step for WhitelistedRustc { // See docs in std above for why we symlink let my_out = builder.crate_doc_out(target); - builder.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc"); @@ -678,7 +672,6 @@ impl Step for Rustc { // Get the correct compiler for this stage. let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -699,7 +692,6 @@ impl Step for Rustc { // We do not symlink to the same shared folder that already contains std library // documentation from previous steps as we do not want to include that. let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target).join("doc"); - builder.clear_if_dirty(&out, &rustdoc); t!(symlink_dir_force(&builder.config, &out, &out_dir)); // Build cargo command. @@ -712,7 +704,7 @@ impl Step for Rustc { // Find dependencies for top level crates. let mut compiler_crates = HashSet::new(); - for root_crate in &["rustc", "rustc_driver"] { + for root_crate in &["rustc", "rustc_driver", "rustc_codegen_llvm"] { let interned_root_crate = INTERNER.intern_str(root_crate); find_compiler_crates(builder, &interned_root_crate, &mut compiler_crates); } @@ -780,7 +772,6 @@ impl Step for Rustdoc { // Get the correct compiler for this stage. let compiler = builder.compiler(stage, builder.config.build); - let rustdoc = builder.rustdoc(compiler.host); let compiler = if builder.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -803,7 +794,6 @@ impl Step for Rustdoc { .join(target) .join("doc"); t!(fs::create_dir_all(&out_dir)); - builder.clear_if_dirty(&out, &rustdoc); t!(symlink_dir_force(&builder.config, &out, &out_dir)); // Build cargo command. diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 6a013053e5..2084b8bdb6 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -121,8 +121,12 @@ To learn more about a subcommand, run `./x.py -h`" opts.optmulti("", "exclude", "build paths to exclude", "PATH"); opts.optopt("", "on-fail", "command to run on failure", "CMD"); opts.optflag("", "dry-run", "dry run; don't build anything"); - opts.optopt("", "stage", "stage to build", "N"); - opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling", "N"); + opts.optopt("", "stage", + "stage to build (indicates compiler to use/test, e.g. stage 0 uses the \ + bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)", + "N"); + opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling \ + (pass multiple times to keep e.g. both stages 0 and 1)", "N"); opts.optopt("", "src", "path to the root of the rust checkout", "DIR"); opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS"); opts.optflag("h", "help", "print this help message"); @@ -258,7 +262,7 @@ Arguments: ./x.py build --stage 1 src/libtest - This will first build everything once (like --stage 0 without further + This will first build everything once (like `--stage 0` without further arguments would), and then use the compiler built in stage 0 to build src/libtest and its dependencies. Once this is done, build/$ARCH/stage1 contains a usable compiler.", @@ -290,10 +294,14 @@ Arguments: ./x.py test src/test/run-pass ./x.py test src/libstd --test-args hash_map - ./x.py test src/libstd --stage 0 + ./x.py test src/libstd --stage 0 --no-doc ./x.py test src/test/ui --bless ./x.py test src/test/ui --compare-mode nll + Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`; + just like `build src/libstd --stage N` it tests the compiler produced by the previous + stage. + If no arguments are passed then the complete artifacts for that stage are compiled and tested. diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs index 6445ce8da3..e6ee525ca2 100644 --- a/src/bootstrap/job.rs +++ b/src/bootstrap/job.rs @@ -37,7 +37,7 @@ //! Note that this module has a #[cfg(windows)] above it as none of this logic //! is required on Unix. -#![allow(bad_style, dead_code)] +#![allow(nonstandard_style, dead_code)] use std::env; use std::io; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 1efff19dfb..6b88516bac 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -151,6 +151,11 @@ use std::process::{self, Command}; use std::slice; use std::str; +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; + use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime}; use filetime::FileTime; @@ -206,6 +211,7 @@ const LLVM_TOOLS: &[&str] = &[ "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume "llvm-objdump", // used to disassemble programs "llvm-profdata", // used to inspect and merge files generated by profiles + "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide "llvm-size", // used to prints the size of the linker sections of a program "llvm-strip", // used to discard symbols from binary files to reduce their size ]; @@ -231,6 +237,11 @@ pub enum DocTests { Only, } +pub enum GitRepo { + Rustc, + Llvm, +} + /// Global configuration for the build system. /// /// This structure transitively contains all configuration for the build system. @@ -276,6 +287,7 @@ pub struct Build { cc: HashMap, cc::Tool>, cxx: HashMap, cc::Tool>, ar: HashMap, PathBuf>, + ranlib: HashMap, PathBuf>, // Misc crates: HashMap, Crate>, is_sudo: bool, @@ -340,6 +352,7 @@ pub enum Mode { /// Compile a tool which uses all libraries we compile (up to rustc). /// Doesn't use the stage0 compiler libraries like "other", and includes /// tools like rustdoc, cargo, rls, etc. + ToolTest, ToolStd, ToolRustc, } @@ -401,6 +414,7 @@ impl Build { cc: HashMap::new(), cxx: HashMap::new(), ar: HashMap::new(), + ranlib: HashMap::new(), crates: HashMap::new(), lldb_version: None, lldb_python_dir: None, @@ -555,10 +569,11 @@ impl Build { let suffix = match mode { Mode::Std => "-std", Mode::Test => "-test", - Mode::Codegen => "-rustc", Mode::Rustc => "-rustc", + Mode::Codegen => "-codegen", Mode::ToolBootstrap => "-bootstrap-tools", Mode::ToolStd => "-tools", + Mode::ToolTest => "-tools", Mode::ToolRustc => "-tools", }; self.out.join(&*compiler.host) @@ -730,6 +745,21 @@ impl Build { self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32) } + fn debuginfo_map(&self, which: GitRepo) -> Option { + if !self.config.rust_remap_debuginfo { + return None + } + + let path = match which { + GitRepo::Rustc => { + let sha = self.rust_info.sha().expect("failed to find sha"); + format!("/rustc/{}", sha) + } + GitRepo::Llvm => format!("/rustc/llvm"), + }; + Some(format!("{}={}", self.src.display(), path)) + } + /// Returns the path to the C compiler for the target specified. fn cc(&self, target: Interned) -> &Path { self.cc[&target].path() @@ -737,7 +767,7 @@ impl Build { /// Returns a list of flags to pass to the C compiler for the target /// specified. - fn cflags(&self, target: Interned) -> Vec { + fn cflags(&self, target: Interned, which: GitRepo) -> Vec { // Filter out -O and /O (the optimization flags) that we picked up from // cc-rs because the build scripts will determine that for themselves. let mut base = self.cc[&target].args().iter() @@ -759,6 +789,16 @@ impl Build { if &*target == "i686-pc-windows-gnu" { base.push("-fno-omit-frame-pointer".into()); } + + if let Some(map) = self.debuginfo_map(which) { + let cc = self.cc(target); + if cc.ends_with("clang") || cc.ends_with("gcc") { + base.push(format!("-fdebug-prefix-map={}", map).into()); + } else if cc.ends_with("clang-cl.exe") { + base.push("-Xclang".into()); + base.push(format!("-fdebug-prefix-map={}", map).into()); + } + } base } @@ -767,6 +807,11 @@ impl Build { self.ar.get(&target).map(|p| &**p) } + /// Returns the path to the `ranlib` utility for the target specified. + fn ranlib(&self, target: Interned) -> Option<&Path> { + self.ranlib.get(&target).map(|p| &**p) + } + /// Returns the path to the C++ compiler for the target specified. fn cxx(&self, target: Interned) -> Result<&Path, String> { match self.cxx.get(&target) { @@ -1005,6 +1050,18 @@ impl Build { self.rust_version() } + fn lldb_package_vers(&self) -> String { + self.package_vers(&self.rust_version()) + } + + fn lldb_vers(&self) -> String { + self.rust_version() + } + + fn llvm_link_tools_dynamically(&self, target: Interned) -> bool { + (target.contains("linux-gnu") || target.contains("apple-darwin")) + } + /// Returns the `version` string associated with this compiler for Rust /// itself. /// @@ -1123,20 +1180,24 @@ impl Build { pub fn copy(&self, src: &Path, dst: &Path) { if self.config.dry_run { return; } let _ = fs::remove_file(&dst); - // Attempt to "easy copy" by creating a hard link (symlinks don't work on - // windows), but if that fails just fall back to a slow `copy` operation. - if let Ok(()) = fs::hard_link(src, dst) { - return - } - if let Err(e) = fs::copy(src, dst) { - panic!("failed to copy `{}` to `{}`: {}", src.display(), - dst.display(), e) + let metadata = t!(src.symlink_metadata()); + if metadata.file_type().is_symlink() { + let link = t!(fs::read_link(src)); + t!(symlink_file(link, dst)); + } else if let Ok(()) = fs::hard_link(src, dst) { + // Attempt to "easy copy" by creating a hard link + // (symlinks don't work on windows), but if that fails + // just fall back to a slow `copy` operation. + } else { + if let Err(e) = fs::copy(src, dst) { + panic!("failed to copy `{}` to `{}`: {}", src.display(), + dst.display(), e) + } + t!(fs::set_permissions(dst, metadata.permissions())); + let atime = FileTime::from_last_access_time(&metadata); + let mtime = FileTime::from_last_modification_time(&metadata); + t!(filetime::set_file_times(dst, atime, mtime)); } - let metadata = t!(src.metadata()); - t!(fs::set_permissions(dst, metadata.permissions())); - let atime = FileTime::from_last_access_time(&metadata); - let mtime = FileTime::from_last_modification_time(&metadata); - t!(filetime::set_file_times(dst, atime, mtime)); } /// Search-and-replaces within a file. (Not maximally efficiently: allocates a diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 9aeb4e0eda..424264647f 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -33,6 +33,7 @@ use util::{self, exe}; use build_helper::up_to_date; use builder::{Builder, RunConfig, ShouldRun, Step}; use cache::Interned; +use GitRepo; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Llvm { @@ -145,15 +146,20 @@ impl Step for Llvm { .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") + .define("LLVM_INCLUDE_BENCHMARKS", "OFF") .define("LLVM_ENABLE_ZLIB", "OFF") .define("WITH_POLLY", "OFF") .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") - .define("LLVM_ENABLE_LIBXML2", "OFF") .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string()) .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target); + if builder.config.llvm_thin_lto && !emscripten { + cfg.define("LLVM_ENABLE_LTO", "Thin") + .define("LLVM_ENABLE_LLD", "ON"); + } + // By default, LLVM will automatically find OCaml and, if it finds it, // install the LLVM bindings in LLVM_OCAML_INSTALL_PATH, which defaults // to /usr/bin/ocaml. @@ -163,19 +169,18 @@ impl Step for Llvm { cfg.define("LLVM_OCAML_INSTALL_PATH", env::var_os("LLVM_OCAML_INSTALL_PATH").unwrap_or_else(|| "usr/lib/ocaml".into())); + let want_lldb = builder.config.lldb_enabled && !self.emscripten; + // This setting makes the LLVM tools link to the dynamic LLVM library, // which saves both memory during parallel links and overall disk space - // for the tools. We don't distribute any of those tools, so this is - // just a local concern. However, it doesn't work well everywhere. - // - // If we are shipping llvm tools then we statically link them LLVM - if (target.contains("linux-gnu") || target.contains("apple-darwin")) && - !builder.config.llvm_tools_enabled { - cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); + // for the tools. We don't do this on every platform as it doesn't work + // equally well everywhere. + if builder.llvm_link_tools_dynamically(target) && !emscripten { + cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } // For distribution we want the LLVM tools to be *statically* linked to libstdc++ - if builder.config.llvm_tools_enabled { + if builder.config.llvm_tools_enabled || want_lldb { if !target.contains("windows") { if target.contains("apple") { cfg.define("CMAKE_EXE_LINKER_FLAGS", "-static-libstdc++"); @@ -196,6 +201,17 @@ impl Step for Llvm { cfg.define("LLVM_BUILD_32_BITS", "ON"); } + if want_lldb { + cfg.define("LLVM_EXTERNAL_CLANG_SOURCE_DIR", builder.src.join("src/tools/clang")); + cfg.define("LLVM_EXTERNAL_LLDB_SOURCE_DIR", builder.src.join("src/tools/lldb")); + // For the time being, disable code signing. + cfg.define("LLDB_CODESIGN_IDENTITY", ""); + } else { + // LLDB requires libxml2; but otherwise we want it to be disabled. + // See https://github.com/rust-lang/rust/pull/50104 + cfg.define("LLVM_ENABLE_LIBXML2", "OFF"); + } + if let Some(num_linkers) = builder.config.llvm_link_jobs { if num_linkers > 0 { cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string()); @@ -224,6 +240,14 @@ impl Step for Llvm { cfg.define("LLVM_NATIVE_BUILD", builder.llvm_out(builder.config.build).join("build")); } + if let Some(ref suffix) = builder.config.llvm_version_suffix { + cfg.define("LLVM_VERSION_SUFFIX", suffix); + } + + if let Some(ref python) = builder.config.python { + cfg.define("PYTHON_EXECUTABLE", python); + } + configure_cmake(builder, target, &mut cfg, false); // FIXME: we don't actually need to build all LLVM tools and all LLVM @@ -350,8 +374,8 @@ fn configure_cmake(builder: &Builder, } cfg.build_arg("-j").build_arg(builder.jobs().to_string()); - cfg.define("CMAKE_C_FLAGS", builder.cflags(target).join(" ")); - let mut cxxflags = builder.cflags(target).join(" "); + cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" ")); + let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" "); if building_dist_binaries { if builder.config.llvm_static_stdcpp && !target.contains("windows") { cxxflags.push_str(" -static-libstdc++"); @@ -366,6 +390,14 @@ fn configure_cmake(builder: &Builder, } } + if let Some(ranlib) = builder.ranlib(target) { + if ranlib.is_absolute() { + // LLVM build breaks if `CMAKE_RANLIB` is a relative path, for some reason it + // tries to resolve this path in the LLVM build directory. + cfg.define("CMAKE_RANLIB", sanitize_cc(ranlib)); + } + } + if env::var_os("SCCACHE_ERROR_LOG").is_some() { cfg.env("RUST_LOG", "sccache=warn"); } @@ -607,6 +639,7 @@ impl Step for Openssl { "aarch64-linux-android" => "linux-aarch64", "aarch64-unknown-linux-gnu" => "linux-aarch64", "aarch64-unknown-linux-musl" => "linux-aarch64", + "aarch64-unknown-netbsd" => "BSD-generic64", "arm-linux-androideabi" => "android", "arm-unknown-linux-gnueabi" => "linux-armv4", "arm-unknown-linux-gnueabihf" => "linux-armv4", @@ -648,7 +681,7 @@ impl Step for Openssl { }; configure.arg(os); configure.env("CC", builder.cc(target)); - for flag in builder.cflags(target) { + for flag in builder.cflags(target, GitRepo::Rustc) { configure.arg(flag); } // There is no specific os target for android aarch64 or x86_64, diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index c7f514da93..c2610de23b 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -176,7 +176,7 @@ pub fn check(build: &mut Build) { if target.contains("-none-") { if build.no_std(*target).is_none() { let target = build.config.target_config.entry(target.clone()) - .or_insert(Default::default()); + .or_default(); target.no_std = true; } @@ -192,7 +192,7 @@ pub fn check(build: &mut Build) { // fall back to the system toolchain in /usr before giving up if build.musl_root(*target).is_none() && build.config.build == *target { let target = build.config.target_config.entry(target.clone()) - .or_insert(Default::default()); + .or_default(); target.musl_root = Some("/usr".into()); } match build.musl_root(*target) { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 24a1dbbde6..92665c09f7 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -34,7 +34,7 @@ use tool::{self, Tool, SourceType}; use toolstate::ToolState; use util::{self, dylib_path, dylib_path_var}; use Crate as CargoCrate; -use {DocTests, Mode}; +use {DocTests, Mode, GitRepo}; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -237,6 +237,8 @@ impl Step for Cargo { // Don't run cross-compile tests, we may not have cross-compiled libstd libs // available. cargo.env("CFG_DISABLE_CROSS_TESTS", "1"); + // Disable a test that has issues with mingw. + cargo.env("CARGO_TEST_DISABLE_GIT_CLI", "1"); try_run( builder, @@ -298,6 +300,8 @@ impl Step for Rls { cargo.env("RLS_TEST_WORKSPACE_DIR", test_workspace_path); builder.add_rustc_lib_path(compiler, &mut cargo); + cargo.arg("--") + .args(builder.config.cmd.test_args()); if try_run(builder, &mut cargo) { builder.save_toolstate("rls", ToolState::TestPass); @@ -973,9 +977,19 @@ impl Step for Compiletest { builder.ensure(compile::Rustc { compiler, target }); } - if builder.no_std(target) != Some(true) { + if builder.no_std(target) == Some(true) { + // the `test` doesn't compile for no-std targets + builder.ensure(compile::Std { compiler, target }); + } else { builder.ensure(compile::Test { compiler, target }); } + + if builder.no_std(target) == Some(true) { + // for no_std run-make (e.g. thumb*), + // we need a host compiler which is called by cargo. + builder.ensure(compile::Std { compiler, target: compiler.host }); + } + builder.ensure(native::TestHelpers { target }); builder.ensure(RemoteCopyLibs { compiler, target }); @@ -1128,7 +1142,7 @@ impl Step for Compiletest { .arg("--cxx") .arg(builder.cxx(target).unwrap()) .arg("--cflags") - .arg(builder.cflags(target).join(" ")) + .arg(builder.cflags(target, GitRepo::Rustc).join(" ")) .arg("--llvm-components") .arg(llvm_components.trim()) .arg("--llvm-cxxflags") diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 5e68b797b3..e5299761a1 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -19,62 +19,12 @@ use Mode; use Compiler; use builder::{Step, RunConfig, ShouldRun, Builder}; use util::{exe, add_lib_path}; -use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp}; +use compile; use native; use channel::GitInfo; use cache::Interned; use toolstate::ToolState; -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct CleanTools { - pub compiler: Compiler, - pub target: Interned, - pub cause: Mode, -} - -impl Step for CleanTools { - type Output = (); - - fn should_run(run: ShouldRun) -> ShouldRun { - run.never() - } - - fn run(self, builder: &Builder) { - let compiler = self.compiler; - let target = self.target; - let cause = self.cause; - - // This is for the original compiler, but if we're forced to use stage 1, then - // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since - // we copy the libs forward. - let tools_dir = builder.stage_out(compiler, Mode::ToolRustc); - let compiler = if builder.force_use_stage1(compiler, target) { - builder.compiler(1, compiler.host) - } else { - compiler - }; - - for &cur_mode in &[Mode::Std, Mode::Test, Mode::Rustc] { - let stamp = match cur_mode { - Mode::Std => libstd_stamp(builder, compiler, target), - Mode::Test => libtest_stamp(builder, compiler, target), - Mode::Rustc => librustc_stamp(builder, compiler, target), - _ => panic!(), - }; - - if builder.clear_if_dirty(&tools_dir, &stamp) { - break; - } - - // If we are a rustc tool, and std changed, we also need to clear ourselves out -- our - // dependencies depend on std. Therefore, we iterate up until our own mode. - if cause == cur_mode { - break; - } - } - } -} - #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum SourceType { InTree, @@ -136,7 +86,7 @@ impl Step for ToolBuild { let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool)); builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| { + let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { | "rls" @@ -183,7 +133,7 @@ impl Step for ToolBuild { let mut artifacts = builder.tool_artifacts.borrow_mut(); let prev_artifacts = artifacts .entry(target) - .or_insert_with(Default::default); + .or_default(); if let Some(prev) = prev_artifacts.get(&*id) { if prev.1 != val.1 { duplicates.push(( @@ -221,6 +171,10 @@ impl Step for ToolBuild { prev.0, &prev_features - &cur_features, prev.1); } println!(""); + println!("to fix this you will probably want to edit the local \ + src/tools/rustc-workspace-hack/Cargo.toml crate, as \ + that will update the dependency graph to ensure that \ + these crates all share the same feature set"); panic!("tools should not compile multiple copies of the same crate"); } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index be03796921..8ce8f20add 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -137,7 +137,7 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> { // // Copied from std #[cfg(windows)] - #[allow(bad_style)] + #[allow(nonstandard_style)] fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> { use std::ptr; use std::ffi::OsStr; diff --git a/src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile b/src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile deleted file mode 100644 index 34c6e640ab..0000000000 --- a/src/ci/docker/disabled/dist-armebv7r-none-eabihf/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - file \ - curl \ - ca-certificates \ - python2.7 \ - git \ - cmake \ - sudo \ - xz-utils \ - bzip2 \ - libssl-dev \ - pkg-config - - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV BASE_URL=https://releases.linaro.org/components/toolchain/binaries/latest/armeb-eabi/ -ENV GCC_LINARO=gcc-linaro-7.2.1-2017.11-x86_64_armeb-eabi - -RUN curl -sL $BASE_URL/$GCC_LINARO.tar.xz | tar -xJ - -ENV PATH=$PATH:/$GCC_LINARO/bin - -ENV TARGET=armebv7r-none-eabihf - -ENV CC_armebv7r_none_eabihf=armeb-eabi-gcc \ - CFLAGS_armebv7r_none_eabihf="-march=armv7-r" - -ENV RUST_CONFIGURE_ARGS --disable-docs - -ENV SCRIPT python2.7 ../x.py dist --target $TARGET diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index 6302f55009..e2484b7224 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -102,11 +102,18 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi ENV TARGETS=$TARGETS,thumbv7m-none-eabi ENV TARGETS=$TARGETS,thumbv7em-none-eabi ENV TARGETS=$TARGETS,thumbv7em-none-eabihf +ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf +ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf +ENV TARGETS=$TARGETS,armebv7r-none-eabi +ENV TARGETS=$TARGETS,armebv7r-none-eabihf +ENV TARGETS=$TARGETS,armv7r-none-eabi +ENV TARGETS=$TARGETS,armv7r-none-eabihf ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ - CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc + CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \ + CC_armebv7r_none_eabi=arm-none-eabi-gcc ENV RUST_CONFIGURE_ARGS \ --musl-root-armv5te=/musl-armv5te \ @@ -119,7 +126,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-emscripten \ --disable-docs -ENV SCRIPT \ +ENV SCRIPT \ python2.7 ../x.py test --target $RUN_MAKE_TARGETS src/test/run-make && \ python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index 5726fab752..01f6db03e8 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -93,7 +93,10 @@ ENV RUST_CONFIGURE_ARGS \ --enable-sanitizers \ --enable-profiler \ --enable-compiler-docs \ - --set target.x86_64-unknown-linux-gnu.linker=clang + --set target.x86_64-unknown-linux-gnu.linker=clang \ + --set target.x86_64-unknown-linux-gnu.ar=/rustroot/bin/llvm-ar \ + --set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \ + --set llvm.thin-lto=true ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=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 b0c27aa45b..4595eacb31 100755 --- a/src/ci/docker/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/dist-x86_64-linux/build-clang.sh @@ -30,6 +30,12 @@ curl https://releases.llvm.org/$LLVM/cfe-$LLVM.src.tar.xz | \ xz -d | \ tar xf - -C tools/clang --strip-components=1 +mkdir -p tools/lld + +curl https://releases.llvm.org/$LLVM/lld-$LLVM.src.tar.xz | \ + xz -d | \ + tar xf - -C tools/lld --strip-components=1 + mkdir ../clang-build cd ../clang-build diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index b1ee636644..3a7714d32f 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -119,10 +119,6 @@ fi # goes ahead and sets it for all builders. args="$args --privileged" -if [ "$CI" != "" ]; then - args="$args --dns 8.8.8.8 --dns 8.8.4.4 --dns 1.1.1.1 --dns 1.0.0.1" -fi - exec docker \ run \ --volume "$root_dir:/checkout:ro" \ diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh index 4ca7389d6d..e6a48a96da 100644 --- a/src/ci/docker/scripts/musl.sh +++ b/src/ci/docker/scripts/musl.sh @@ -32,7 +32,7 @@ shift export CFLAGS="-fPIC $CFLAGS" -# FIXME: remove the patch when upate to 1.1.20 +# FIXME: remove the patch when updating to 1.1.20 MUSL=musl-1.1.19 # may have been downloaded in a previous run diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index 16055078ad..d876cb7f37 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -17,9 +17,11 @@ TOOLSTATE_FILE="$(realpath $2)" OS="$3" COMMIT="$(git rev-parse HEAD)" CHANGED_FILES="$(git diff --name-status HEAD HEAD^)" -SIX_WEEK_CYCLE="$(( ($(date +%s) / 604800 - 3) % 6 ))" -# ^ 1970 Jan 1st is a Thursday, and our release dates are also on Thursdays, -# thus we could divide by 604800 (7 days in seconds) directly. +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. touch "$TOOLSTATE_FILE" @@ -98,7 +100,7 @@ change_toolstate() { 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 -eq 5 ]; then + if [ $SIX_WEEK_CYCLE -ge 35 ]; then python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed fi sed -i "1 a\\ diff --git a/src/ci/run.sh b/src/ci/run.sh index 9be3199e27..a965c44031 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -51,10 +51,11 @@ fi # # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` # either automatically or manually. -export RUST_RELEASE_CHANNEL=stable +export RUST_RELEASE_CHANNEL=beta if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo" if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" diff --git a/src/doc/book/2018-edition/src/appendix-01-keywords.md b/src/doc/book/2018-edition/src/appendix-01-keywords.md index 077b92ba6f..62fc7b95b3 100644 --- a/src/doc/book/2018-edition/src/appendix-01-keywords.md +++ b/src/doc/book/2018-edition/src/appendix-01-keywords.md @@ -1,9 +1,10 @@ ## Appendix A: Keywords The following list contains keywords that are reserved for current or future -use by the Rust language. As such, they cannot be used as identifiers, such as -names of functions, variables, parameters, struct fields, modules, crates, -constants, macros, static values, attributes, types, traits, or lifetimes. +use by the Rust language. As such, they cannot be used as identifiers (except as +[raw identifiers][raw-identifiers]), including names of functions, variables, +parameters, struct fields, modules, crates, constants, macros, static values, +attributes, types, traits, or lifetimes. ### Keywords Currently in Use @@ -70,3 +71,49 @@ for potential future use. * `unsized` * `virtual` * `yield` + +### Raw identifiers +[raw-identifiers]: #raw-identifiers + +Raw identifiers let you use keywords where they would not normally be allowed by +prefixing them with `r#`. + +For example, `match` is a keyword. If you try to compile this function: + +```rust,ignore +fn match(needle: &str, haystack: &str) -> bool { + haystack.contains(needle) +} +``` + +You'll get this error: + +```text +error: expected identifier, found keyword `match` + --> src/main.rs:4:4 + | +4 | fn match(needle: &str, haystack: &str) -> bool { + | ^^^^^ expected identifier, found keyword +``` + +You can write this with a raw identifier: + +```rust +fn r#match(needle: &str, haystack: &str) -> bool { + haystack.contains(needle) +} + +fn main() { + assert!(r#match("foo", "foobar")); +} +``` + +Note the `r#` prefix on both the function name as well as the call. + +#### Motivation + +This feature is useful for a few reasons, but the primary motivation was +inter-edition situations. For example, `try` is not a keyword in the 2015 +edition, but is in the 2018 edition. So if you have a library that is written +in Rust 2015 and has a `try` function, to call it in Rust 2018, you'll need +to use the raw identifier. diff --git a/src/doc/book/2018-edition/src/appendix-03-derivable-traits.md b/src/doc/book/2018-edition/src/appendix-03-derivable-traits.md index 49e903c2ab..0bb5423956 100644 --- a/src/doc/book/2018-edition/src/appendix-03-derivable-traits.md +++ b/src/doc/book/2018-edition/src/appendix-03-derivable-traits.md @@ -15,8 +15,8 @@ library that you can use with `derive`. Each section covers: * Examples of operations that require the trait If you want different behavior than that provided by the `derive` attribute, -consult the standard library documentation for each trait for details on how to -manually implement them. +consult the [standard library documentation](../../std/index.html) +for each trait for details of how to manually implement them. The rest of the traits defined in the standard library can’t be implemented on your types using `derive`. These traits don’t have sensible default behavior, diff --git a/src/doc/book/2018-edition/src/ch03-01-variables-and-mutability.md b/src/doc/book/2018-edition/src/ch03-01-variables-and-mutability.md index 58bdac8fc7..3129ce9d3c 100644 --- a/src/doc/book/2018-edition/src/ch03-01-variables-and-mutability.md +++ b/src/doc/book/2018-edition/src/ch03-01-variables-and-mutability.md @@ -127,7 +127,8 @@ computed at runtime. Here’s an example of a constant declaration where the constant’s name is `MAX_POINTS` and its value is set to 100,000. (Rust’s constant naming -convention is to use all uppercase with underscores between words): +convention is to use all uppercase with underscores between words, +and underscores can be inserted in numeric literals to improve readability): ```rust const MAX_POINTS: u32 = 100_000; diff --git a/src/doc/book/2018-edition/src/ch03-02-data-types.md b/src/doc/book/2018-edition/src/ch03-02-data-types.md index 5b049d305a..8cb4d79cc1 100644 --- a/src/doc/book/2018-edition/src/ch03-02-data-types.md +++ b/src/doc/book/2018-edition/src/ch03-02-data-types.md @@ -109,7 +109,7 @@ your program to *panic*, which is the term Rust uses when a program exits with an error. We'll discuss panics more in Chapter 9. In release builds, Rust does not check for overflow, and instead will -do something called "two's compliment wrapping." In short, `256` becomes +do something called "two's complement wrapping." In short, `256` becomes `0`, `257` becomes `1`, etc. Relying on overflow is considered an error, even if this behavior happens. If you want this behavior explicitly, the standard library has a type, `Wrapping`, that provides it explicitly. diff --git a/src/doc/book/2018-edition/src/ch08-03-hash-maps.md b/src/doc/book/2018-edition/src/ch08-03-hash-maps.md index ecf147eda6..5cb18aad07 100644 --- a/src/doc/book/2018-edition/src/ch08-03-hash-maps.md +++ b/src/doc/book/2018-edition/src/ch08-03-hash-maps.md @@ -4,8 +4,8 @@ The last of our common collections is the *hash map*. The type `HashMap` stores a mapping of keys of type `K` to values of type `V`. It does this via a *hashing function*, which determines how it places these keys and values into memory. Many programming languages support this kind of data structure, but -they often use a different name, such as hash, map, object, hash table, or -associative array, just to name a few. +they often use a different name, such as hash, map, object, hash table, +dictionary, or associative array, just to name a few. Hash maps are useful when you want to look up data not by using an index, as you can with vectors, but by using a key that can be of any type. For example, diff --git a/src/doc/book/2018-edition/src/ch09-02-recoverable-errors-with-result.md b/src/doc/book/2018-edition/src/ch09-02-recoverable-errors-with-result.md index 29b7d0b4d9..b03ef229ad 100644 --- a/src/doc/book/2018-edition/src/ch09-02-recoverable-errors-with-result.md +++ b/src/doc/book/2018-edition/src/ch09-02-recoverable-errors-with-result.md @@ -43,8 +43,9 @@ fn main() { Listing 9-3: Opening a file -How do we know `File::open` returns a `Result`? We could look at the standard -library API documentation, or we could ask the compiler! If we give `f` a type +How do we know `File::open` returns a `Result`? We could look at the +[standard library API documentation](../../std/index.html), +or we could ask the compiler! If we give `f` a type annotation that we know is *not* the return type of the function and then try to compile the code, the compiler will tell us that the types don’t match. The error message will then tell us what the type of `f` *is*. Let’s try it! We diff --git a/src/doc/book/2018-edition/src/ch09-03-to-panic-or-not-to-panic.md b/src/doc/book/2018-edition/src/ch09-03-to-panic-or-not-to-panic.md index 0d4cec876b..b116f238a1 100644 --- a/src/doc/book/2018-edition/src/ch09-03-to-panic-or-not-to-panic.md +++ b/src/doc/book/2018-edition/src/ch09-03-to-panic-or-not-to-panic.md @@ -81,14 +81,11 @@ bug in their code so they can fix it during development. Similarly, `panic!` is often appropriate if you’re calling external code that is out of your control and it returns an invalid state that you have no way of fixing. -When a bad state is reached, but it’s expected to happen no matter how well you -write your code, it’s still more appropriate to return a `Result` rather than -to make a `panic!` call. Examples include a parser being given malformed data -or an HTTP request returning a status that indicates you have hit a rate limit. -In these cases, you should indicate that failure is an expected possibility by -returning a `Result` to propagate these bad states upward so the calling code -can decide how to handle the problem. To call `panic!` wouldn’t be the best way -to handle these cases. +However, when failure is expected, it is more appropriate to return a `Result` +than to make a `panic!` call. Examples include a parser being given malformed +data or an HTTP request returning a status that indicates you have hit a rate +limit. In these cases, returning a `Result` indicates that failure is an +expected possibility that the calling code must decide how to handle. When your code performs operations on values, your code should verify the values are valid first and panic if the values aren’t valid. This is mostly for @@ -172,11 +169,11 @@ receives a value between 1 and 100: ```rust pub struct Guess { - value: u32, + value: i32, } impl Guess { - pub fn new(value: u32) -> Guess { + pub fn new(value: i32) -> Guess { if value < 1 || value > 100 { panic!("Guess value must be between 1 and 100, got {}.", value); } @@ -186,7 +183,7 @@ impl Guess { } } - pub fn value(&self) -> u32 { + pub fn value(&self) -> i32 { self.value } } @@ -196,11 +193,11 @@ impl Guess { values between 1 and 100 First, we define a struct named `Guess` that has a field named `value` that -holds a `u32`. This is where the number will be stored. +holds a `i32`. This is where the number will be stored. Then we implement an associated function named `new` on `Guess` that creates instances of `Guess` values. The `new` function is defined to have one -parameter named `value` of type `u32` and to return a `Guess`. The code in the +parameter named `value` of type `i32` and to return a `Guess`. The code in the body of the `new` function tests `value` to make sure it’s between 1 and 100. If `value` doesn’t pass this test, we make a `panic!` call, which will alert the programmer who is writing the calling code that they have a bug they need @@ -213,7 +210,7 @@ of a `panic!` in the API documentation that you create in Chapter 14. If to the `value` parameter and return the `Guess`. Next, we implement a method named `value` that borrows `self`, doesn’t have any -other parameters, and returns a `u32`. This kind of method is sometimes called +other parameters, and returns a `i32`. This kind of method is sometimes called a *getter*, because its purpose is to get some data from its fields and return it. This public method is necessary because the `value` field of the `Guess` struct is private. It’s important that the `value` field be private so code @@ -224,7 +221,7 @@ hasn’t been checked by the conditions in the `Guess::new` function. A function that has a parameter or returns only numbers between 1 and 100 could then declare in its signature that it takes or returns a `Guess` rather than a -`u32` and wouldn’t need to do any additional checks in its body. +`i32` and wouldn’t need to do any additional checks in its body. ## Summary diff --git a/src/doc/book/2018-edition/src/ch10-02-traits.md b/src/doc/book/2018-edition/src/ch10-02-traits.md index 7bc1caaf1c..5e8837eb1b 100644 --- a/src/doc/book/2018-edition/src/ch10-02-traits.md +++ b/src/doc/book/2018-edition/src/ch10-02-traits.md @@ -314,10 +314,6 @@ For example, to use display formatting on the type `T` in a function as well as the `summarize` method, we can use `T: Summary + Display` to say `T` can be any type that implements `Summary` and `Display`. This can grow quite complex! -```rust,ignore -fn some_function(t: T, u: U) -> i32 { -``` - #### `where` clauses for clearer code However, there are downsides to using too many trait bounds. Each generic has @@ -327,6 +323,10 @@ parameter list, making the function signature hard to read. For this reason, Rust has alternate syntax for specifying trait bounds inside a `where` clause after the function signature. So instead of writing this: +```rust,ignore +fn some_function(t: T, u: U) -> i32 { +``` + we can use a `where` clause, like this: ```rust,ignore @@ -357,7 +357,7 @@ fn returns_summarizable() -> impl Summary { ``` This signature says, "I'm going to return something that implements the -`Summary` trait, but I'm not going to tell you the exact type. In our case, +`Summary` trait, but I'm not going to tell you the exact type." In our case, we're returning a `Tweet`, but the caller doesn't know that. Why is this useful? In chapter 13, we're going to learn about two features diff --git a/src/doc/book/2018-edition/src/ch11-01-writing-tests.md b/src/doc/book/2018-edition/src/ch11-01-writing-tests.md index e55dfb2053..840b2bd742 100644 --- a/src/doc/book/2018-edition/src/ch11-01-writing-tests.md +++ b/src/doc/book/2018-edition/src/ch11-01-writing-tests.md @@ -619,11 +619,11 @@ happen when we expect them to: ```rust # fn main() {} pub struct Guess { - value: u32, + value: i32, } impl Guess { - pub fn new(value: u32) -> Guess { + pub fn new(value: i32) -> Guess { if value < 1 || value > 100 { panic!("Guess value must be between 1 and 100, got {}.", value); } @@ -666,13 +666,13 @@ that the `new` function will panic if the value is greater than 100: ```rust # fn main() {} # pub struct Guess { -# value: u32, +# value: i32, # } # // --snip-- impl Guess { - pub fn new(value: u32) -> Guess { + pub fn new(value: i32) -> Guess { if value < 1 { panic!("Guess value must be between 1 and 100, got {}.", value); } @@ -716,13 +716,13 @@ different messages depending on whether the value is too small or too large: ```rust # fn main() {} # pub struct Guess { -# value: u32, +# value: i32, # } # // --snip-- impl Guess { - pub fn new(value: u32) -> Guess { + pub fn new(value: i32) -> Guess { if value < 1 { panic!("Guess value must be greater than or equal to 1, got {}.", value); diff --git a/src/doc/book/2018-edition/src/ch12-02-reading-a-file.md b/src/doc/book/2018-edition/src/ch12-02-reading-a-file.md index 76e95a8b9f..f973a10b1d 100644 --- a/src/doc/book/2018-edition/src/ch12-02-reading-a-file.md +++ b/src/doc/book/2018-edition/src/ch12-02-reading-a-file.md @@ -33,7 +33,6 @@ shown in Listing 12-4: ```rust,should_panic use std::env; use std::fs; -use std::io::prelude::*; fn main() { # let args: Vec = env::args().collect(); @@ -55,19 +54,13 @@ fn main() { Listing 12-4: Reading the contents of the file specified by the second argument -First, we add some more `use` statements to bring in relevant parts of the -standard library: we need `std::fs` to handle files, and -`std::io::prelude::*` contains various useful traits for doing I/O, including -file I/O. In the same way that Rust has a general prelude that brings certain -types and functions into scope automatically, the `std::io` module has its -own prelude of common types and functions you’ll need when working with I/O. -Unlike with the default prelude, we must explicitly add a `use` statement for -the prelude from `std::io`. +First, we add another `use` statement to bring in a relevant part of the +standard library: we need `std::fs` to handle files. In `main`, we’ve added a new statement: `fs::read_to_string` will take the `filename`, open that file, and then produce a new `String` with its contents. -After that lines, we’ve again added a temporary `println!` statement that +After that line, we’ve again added a temporary `println!` statement that prints the value of `contents` after the file is read, so we can check that the program is working so far. diff --git a/src/doc/book/2018-edition/src/ch12-03-improving-error-handling-and-modularity.md b/src/doc/book/2018-edition/src/ch12-03-improving-error-handling-and-modularity.md index d515eb2c76..277c3b6e82 100644 --- a/src/doc/book/2018-edition/src/ch12-03-improving-error-handling-and-modularity.md +++ b/src/doc/book/2018-edition/src/ch12-03-improving-error-handling-and-modularity.md @@ -12,18 +12,19 @@ without breaking one of its parts. It’s best to separate functionality so each function is responsible for one task. This issue also ties into the second problem: although `query` and `filename` -are configuration variables to our program, variables like `f` and `contents` -are used to perform the program’s logic. The longer `main` becomes, the more -variables we’ll need to bring into scope; the more variables we have in scope, -the harder it will be to keep track of the purpose of each. It’s best to group -the configuration variables into one structure to make their purpose clear. +are configuration variables to our program, variables like `contents` are used +to perform the program’s logic. The longer `main` becomes, the more variables +we’ll need to bring into scope; the more variables we have in scope, the harder +it will be to keep track of the purpose of each. It’s best to group the +configuration variables into one structure to make their purpose clear. The third problem is that we’ve used `expect` to print an error message when -opening the file fails, but the error message just prints `file not found`. -Opening a file can fail in a number of ways besides the file being missing: for -example, the file might exist, but we might not have permission to open it. -Right now, if we’re in that situation, we’d print the `file not found` error -message, which would give the user the wrong information! +opening the file fails, but the error message just prints +`something went wrong`. Opening a file can fail in a number of ways: for +example, the file could be missing, or we might not have permission to open +it. Right now, regardless of the situation, we’d print the +`something went wrong` error message, which wouldn't give the user any +information! Fourth, we use `expect` repeatedly to handle different errors, and if the user runs our program without specifying enough arguments, they’ll get an `index out @@ -608,7 +609,6 @@ compile until we modify *src/main.rs* in the listing after this one. ```rust,ignore use std::error::Error; use std::fs; -use std::io::prelude::*; pub struct Config { pub query: String, diff --git a/src/doc/book/2018-edition/src/ch15-02-deref.md b/src/doc/book/2018-edition/src/ch15-02-deref.md index c9935916d8..4d5afc902a 100644 --- a/src/doc/book/2018-edition/src/ch15-02-deref.md +++ b/src/doc/book/2018-edition/src/ch15-02-deref.md @@ -211,8 +211,8 @@ call the `deref` method. This Rust feature lets us write code that functions identically whether we have a regular reference or a type that implements `Deref`. -The reason the `deref` method returns a reference to a value and that the plain -dereference outside the parentheses in `*(y.deref())` is still necessary is the +The reason the `deref` method returns a reference to a value, and that the plain +dereference outside the parentheses in `*(y.deref())` is still necessary, is the ownership system. If the `deref` method returned the value directly instead of a reference to the value, the value would be moved out of `self`. We don’t want to take ownership of the inner value inside `MyBox` in this case or in most diff --git a/src/doc/book/2018-edition/src/ch17-03-oo-design-patterns.md b/src/doc/book/2018-edition/src/ch17-03-oo-design-patterns.md index 80d61fc5a6..99447993ed 100644 --- a/src/doc/book/2018-edition/src/ch17-03-oo-design-patterns.md +++ b/src/doc/book/2018-edition/src/ch17-03-oo-design-patterns.md @@ -528,6 +528,9 @@ Let’s consider the first part of `main` in Listing 17-11: Filename: src/main.rs ```rust,ignore +# extern crate blog; +# use blog::Post; + fn main() { let mut post = Post::new(); diff --git a/src/doc/book/2018-edition/src/ch19-01-unsafe-rust.md b/src/doc/book/2018-edition/src/ch19-01-unsafe-rust.md index 42d5deda39..f396e6110d 100644 --- a/src/doc/book/2018-edition/src/ch19-01-unsafe-rust.md +++ b/src/doc/book/2018-edition/src/ch19-01-unsafe-rust.md @@ -335,10 +335,10 @@ location and creates a slice 10,000 items long. ```rust use std::slice; -let address = 0x012345usize; +let address = 0x01234usize; let r = address as *mut i32; -let slice = unsafe { +let slice : &[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) }; ``` @@ -348,7 +348,11 @@ location We don’t own the memory at this arbitrary location, and there is no guarantee that the slice this code creates contains valid `i32` values. Attempting to use -`slice` as though it’s a valid slice results in undefined behavior. +`slice` as though it’s a valid slice results in undefined behavior. If we would +not have taken care to align `address` to 4 (the alignment of `i32`), then even +just calling `slice::from_raw_parts_mut` would already be undefined behavior -- +slices must always be aligned, even if they are not used (and even if they are +empty). #### Using `extern` Functions to Call External Code diff --git a/src/doc/book/2018-edition/src/ch19-03-advanced-traits.md b/src/doc/book/2018-edition/src/ch19-03-advanced-traits.md index 7a3a405ee0..76901e87f2 100644 --- a/src/doc/book/2018-edition/src/ch19-03-advanced-traits.md +++ b/src/doc/book/2018-edition/src/ch19-03-advanced-traits.md @@ -513,7 +513,7 @@ implementation you want to call. ### Using Supertraits to Require One Trait’s Functionality Within Another Trait Sometimes, you might need one trait to use another trait’s functionality. In -this case, you need to rely on the dependent trait’s also being implemented. +this case, you need to rely on the dependent traits also being implemented. The trait you rely on is a *supertrait* of the trait you’re implementing. For example, let’s say we want to make an `OutlinePrint` trait with an diff --git a/src/doc/book/2018-edition/src/ch20-02-multithreaded.md b/src/doc/book/2018-edition/src/ch20-02-multithreaded.md index ff6986926c..2418195b17 100644 --- a/src/doc/book/2018-edition/src/ch20-02-multithreaded.md +++ b/src/doc/book/2018-edition/src/ch20-02-multithreaded.md @@ -1020,11 +1020,11 @@ shown in Listing 20-21. ```rust,ignore trait FnBox { - fn call_box(self: Box); + fn call_box(self: Box); } impl FnBox for F { - fn call_box(self: Box) { + fn call_box(self: Box) { (*self)() } } @@ -1126,6 +1126,11 @@ overloaded if the server receives a lot of requests. If we make a request to */sleep*, the server will be able to serve other requests by having another thread run them. +Note that if you open */sleep* in multiple browser windows simultaneously, they +might load 5 seconds apart from each other, because some web browsers execute +multiple instances of the same request sequentially for caching reasons. This +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. diff --git a/src/doc/book/2018-edition/src/foreword.md b/src/doc/book/2018-edition/src/foreword.md index 30b8f9609f..2265e27142 100644 --- a/src/doc/book/2018-edition/src/foreword.md +++ b/src/doc/book/2018-edition/src/foreword.md @@ -24,7 +24,7 @@ Programmers who are already working with low-level code can use Rust to raise their ambitions. For example, introducing parallelism in Rust is a relatively low-risk operation: the compiler will catch the classical mistakes for you. And you can tackle more aggressive optimizations in your code with the confidence -that you won’t accidentally introduce crashes or exploits. +that you won’t accidentally introduce crashes or vulnerabilities. But Rust isn’t limited to low-level systems programming. It’s expressive and ergonomic enough to make CLI apps, web servers, and many other kinds of code diff --git a/src/doc/book/README.md b/src/doc/book/README.md index 58e7502390..54e9fff690 100644 --- a/src/doc/book/README.md +++ b/src/doc/book/README.md @@ -80,7 +80,9 @@ contributions should be to this edition. ### Second Edition -The second edition is frozen, and is not accepting any changes at this time. +No Starch Press has brought the second edition to print. Pull requests fixing +factual errors will be accepted and documented as errata; pull requests changing +wording or other small corrections should be made against the 2018 edition instead. ### First Edition diff --git a/src/doc/book/second-edition/src/ch17-02-trait-objects.md b/src/doc/book/second-edition/src/ch17-02-trait-objects.md index d90a11dfb5..d9368c420b 100644 --- a/src/doc/book/second-edition/src/ch17-02-trait-objects.md +++ b/src/doc/book/second-edition/src/ch17-02-trait-objects.md @@ -40,15 +40,17 @@ allow users to extend it with new types. To implement the behavior we want `gui` to have, we’ll define a trait named `Draw` that will have one method named `draw`. Then we can define a vector that -takes a *trait object*. A trait object points to an instance of a type that -implements the trait we specify. We create a trait object by specifying some +takes a *trait object*. A trait object points to both an instance of a type +implementing our specified trait, as well as a table used to look up trait +methods on that type at runtime. We create a trait object by specifying some sort of pointer, such as a `&` reference or a `Box` smart pointer, and then specifying the relevant trait. (We’ll talk about the reason trait objects must -use a pointer in Chapter 19 in the section “Dynamically Sized Types & Sized”.) -We can use trait objects in place of a generic or concrete type. Wherever we -use a trait object, Rust’s type system will ensure at compile time that any -value used in that context will implement the trait object’s trait. -Consequently, we don’t need to know all the possible types at compile time. +use a pointer in Chapter 19 in the section “Dynamically Sized Types and the +`Sized` Trait”.) We can use trait objects in place of a generic or concrete +type. Wherever we use a trait object, Rust’s type system will ensure at compile +time that any value used in that context will implement the trait object’s +trait. Consequently, we don’t need to know all the possible types at compile +time. We’ve mentioned that in Rust, we refrain from calling structs and enums “objects” to distinguish them from other languages’ objects. In a struct or diff --git a/src/doc/book/second-edition/src/ch19-01-unsafe-rust.md b/src/doc/book/second-edition/src/ch19-01-unsafe-rust.md index 42d5deda39..d55a88e4c5 100644 --- a/src/doc/book/second-edition/src/ch19-01-unsafe-rust.md +++ b/src/doc/book/second-edition/src/ch19-01-unsafe-rust.md @@ -335,7 +335,7 @@ location and creates a slice 10,000 items long. ```rust use std::slice; -let address = 0x012345usize; +let address = 0x01234usize; let r = address as *mut i32; let slice = unsafe { diff --git a/src/doc/index.md b/src/doc/index.md index 3a4f51069f..b1788d8c32 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -34,7 +34,7 @@ minimum. It also includes exercises! # Use Rust -Once you've gotten familliar with the language, these resources can help you +Once you've gotten familiar with the language, these resources can help you when you're actually using it day-to-day. ## The Standard Library @@ -43,6 +43,13 @@ Rust's standard library has [extensive API documentation](std/index.html), with explanations of how to use various things, as well as example code for accomplishing various tasks. +
+
+ + +
+
+ ## The Rustc Book [The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`. diff --git a/src/doc/man/rustdoc.1 b/src/doc/man/rustdoc.1 index a878380f55..d7f78e8f6f 100644 --- a/src/doc/man/rustdoc.1 +++ b/src/doc/man/rustdoc.1 @@ -119,7 +119,7 @@ See <\fBhttps://github.com/rust\-lang/rust/issues\fR> for issues. .SH "AUTHOR" -See \fIAUTHORS.txt\fR in the Rust source distribution. +See the version control history or <\fBhttps://thanks.rust\-lang.org\fR> .SH "COPYRIGHT" This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms. diff --git a/src/doc/nomicon/src/SUMMARY.md b/src/doc/nomicon/src/SUMMARY.md index b26f0f5512..dfb8e7bdf2 100644 --- a/src/doc/nomicon/src/SUMMARY.md +++ b/src/doc/nomicon/src/SUMMARY.md @@ -56,3 +56,5 @@ * [Final Code](vec-final.md) * [Implementing Arc and Mutex](arc-and-mutex.md) * [FFI](ffi.md) +* [Beneath `std`](beneath-std.md) + * [#[panic_handler]](panic-handler.md) diff --git a/src/doc/nomicon/src/beneath-std.md b/src/doc/nomicon/src/beneath-std.md new file mode 100644 index 0000000000..2c759f0c19 --- /dev/null +++ b/src/doc/nomicon/src/beneath-std.md @@ -0,0 +1,10 @@ +# Beneath std + +This section documents (or will document) features that are provided by the standard library and +that `#![no_std]` developers have to deal with (i.e. provide) to build `#![no_std]` binary crates. A +(likely incomplete) list of such features is shown below: + +- #[lang = "eh_personality"] +- #[lang = "start"] +- #[lang = "termination"] +- #[panic_implementation] diff --git a/src/doc/nomicon/src/destructors.md b/src/doc/nomicon/src/destructors.md index daadd1fc02..ae91096a77 100644 --- a/src/doc/nomicon/src/destructors.md +++ b/src/doc/nomicon/src/destructors.md @@ -26,7 +26,7 @@ this is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: ```rust -#![feature(ptr_internals, allocator_api, unique)] +#![feature(ptr_internals, allocator_api)] use std::alloc::{Alloc, Global, GlobalAlloc, Layout}; use std::mem; @@ -53,7 +53,7 @@ use-after-free the `ptr` because when drop exits, it becomes inaccessible. However this wouldn't work: ```rust -#![feature(allocator_api, ptr_internals, unique)] +#![feature(allocator_api, ptr_internals)] use std::alloc::{Alloc, Global, GlobalAlloc, Layout}; use std::ptr::{drop_in_place, Unique, NonNull}; @@ -126,7 +126,7 @@ The classic safe solution to overriding recursive drop and allowing moving out of Self during `drop` is to use an Option: ```rust -#![feature(allocator_api, ptr_internals, unique)] +#![feature(allocator_api, ptr_internals)] use std::alloc::{Alloc, GlobalAlloc, Global, Layout}; use std::ptr::{drop_in_place, Unique, NonNull}; diff --git a/src/doc/nomicon/src/ffi.md b/src/doc/nomicon/src/ffi.md index 03693bbb31..d766cf26a6 100644 --- a/src/doc/nomicon/src/ffi.md +++ b/src/doc/nomicon/src/ffi.md @@ -737,11 +737,11 @@ void foo(struct Foo *arg); void bar(struct Bar *arg); ``` -To do this in Rust, let’s create our own opaque types with `enum`: +To do this in Rust, let’s create our own opaque types: ```rust -pub enum Foo {} -pub enum Bar {} +#[repr(C)] pub struct Foo { _private: [u8; 0] } +#[repr(C)] pub struct Bar { _private: [u8; 0] } extern "C" { pub fn foo(arg: *mut Foo); @@ -750,7 +750,18 @@ extern "C" { # fn main() {} ``` -By using an `enum` with no variants, we create an opaque type that we can’t -instantiate, as it has no variants. But because our `Foo` and `Bar` types are +By including a private field and no constructor, +we create an opaque type that we can't instantiate outside of this module. +(A struct with no field could be instantiated by anyone.) +We also want to use this type in FFI, so we have to add `#[repr(C)]`. +And to avoid warning around using `()` in FFI, we instead use an empty array, +which works just as well as an empty type but is FFI-compatible. + +But because our `Foo` and `Bar` types are different, we’ll get type safety between the two of them, so we cannot accidentally pass a pointer to `Foo` to `bar()`. + +Notice that it is a really bad idea to use an empty enum as FFI type. +The compiler relies on empty enums being uninhabited, so handling values of type +`&Empty` is a huge footgun and can lead to buggy program behavior (by triggering +undefined behavior). diff --git a/src/doc/nomicon/src/panic-handler.md b/src/doc/nomicon/src/panic-handler.md new file mode 100644 index 0000000000..b06707bf35 --- /dev/null +++ b/src/doc/nomicon/src/panic-handler.md @@ -0,0 +1,83 @@ +## #[panic_handler] + +`#[panic_handler]` is used to define the behavior of `panic!` in `#![no_std]` applications. +The `#[panic_handler]` attribute must be applied to a function with signature `fn(&PanicInfo) +-> !` and such function must appear *once* in the dependency graph of a binary / dylib / cdylib +crate. The API of `PanicInfo` can be found in the [API docs]. + +[API docs]: ../core/panic/struct.PanicInfo.html + +Given that `#![no_std]` applications have no *standard* output and that some `#![no_std]` +applications, e.g. embedded applications, need different panicking behaviors for development and for +release it can be helpful to have panic crates, crate that only contain a `#[panic_handler]`. +This way applications can easily swap the panicking behavior by simply linking to a different panic +crate. + +Below is shown an example where an application has a different panicking behavior depending on +whether is compiled using the dev profile (`cargo build`) or using the release profile (`cargo build +--release`). + +``` rust, ignore +// crate: panic-semihosting -- log panic messages to the host stderr using semihosting + +#![no_std] + +use core::fmt::{Write, self}; +use core::panic::PanicInfo; + +struct HStderr { + // .. +# _0: (), +} +# +# impl HStderr { +# fn new() -> HStderr { HStderr { _0: () } } +# } +# +# impl fmt::Write for HStderr { +# fn write_str(&mut self, _: &str) -> fmt::Result { Ok(()) } +# } + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + let mut host_stderr = HStderr::new(); + + // logs "panicked at '$reason', src/main.rs:27:4" to the host stderr + writeln!(host_stderr, "{}", info).ok(); + + loop {} +} +``` + +``` rust, ignore +// crate: panic-halt -- halt the thread on panic; messages are discarded + +#![no_std] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} +``` + +``` rust, ignore +// crate: app + +#![no_std] + +// dev profile +#[cfg(debug_assertions)] +extern crate panic_semihosting; + +// release profile +#[cfg(not(debug_assertions))] +extern crate panic_halt; + +// omitted: other `extern crate`s + +fn main() { + // .. +} +``` diff --git a/src/doc/nomicon/src/vec-final.md b/src/doc/nomicon/src/vec-final.md index 4e2daf3606..5c62d7f9c4 100644 --- a/src/doc/nomicon/src/vec-final.md +++ b/src/doc/nomicon/src/vec-final.md @@ -3,7 +3,6 @@ ```rust #![feature(ptr_internals)] #![feature(allocator_api)] -#![feature(unique)] use std::ptr::{Unique, NonNull, self}; use std::mem; @@ -290,7 +289,7 @@ pub struct Drain<'a, T: 'a> { impl<'a, T> Iterator for Drain<'a, T> { type Item = T; - fn next(&mut self) -> Option { self.iter.next_back() } + fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } @@ -305,5 +304,77 @@ impl<'a, T> Drop for Drain<'a, T> { } } -# fn main() {} +# fn main() { +# tests::create_push_pop(); +# tests::iter_test(); +# tests::test_drain(); +# tests::test_zst(); +# println!("All tests finished OK"); +# } + +# mod tests { +# use super::*; +# pub fn create_push_pop() { +# let mut v = Vec::new(); +# v.push(1); +# assert_eq!(1, v.len()); +# assert_eq!(1, v[0]); +# for i in v.iter_mut() { +# *i += 1; +# } +# v.insert(0, 5); +# let x = v.pop(); +# assert_eq!(Some(2), x); +# assert_eq!(1, v.len()); +# v.push(10); +# let x = v.remove(0); +# assert_eq!(5, x); +# assert_eq!(1, v.len()); +# } +# +# pub fn iter_test() { +# let mut v = Vec::new(); +# for i in 0..10 { +# v.push(Box::new(i)) +# } +# let mut iter = v.into_iter(); +# let first = iter.next().unwrap(); +# let last = iter.next_back().unwrap(); +# drop(iter); +# assert_eq!(0, *first); +# assert_eq!(9, *last); +# } +# +# pub fn test_drain() { +# let mut v = Vec::new(); +# for i in 0..10 { +# v.push(Box::new(i)) +# } +# { +# let mut drain = v.drain(); +# let first = drain.next().unwrap(); +# let last = drain.next_back().unwrap(); +# assert_eq!(0, *first); +# assert_eq!(9, *last); +# } +# assert_eq!(0, v.len()); +# v.push(Box::new(1)); +# assert_eq!(1, *v.pop().unwrap()); +# } +# +# pub fn test_zst() { +# let mut v = Vec::new(); +# for _i in 0..10 { +# v.push(()) +# } +# +# let mut count = 0; +# +# for _ in v.into_iter() { +# count += 1 +# } +# +# assert_eq!(10, count); +# } +# } ``` diff --git a/src/doc/nomicon/src/vec-layout.md b/src/doc/nomicon/src/vec-layout.md index 286682feba..c9962e2dec 100644 --- a/src/doc/nomicon/src/vec-layout.md +++ b/src/doc/nomicon/src/vec-layout.md @@ -71,7 +71,7 @@ take the hit and use std's Unique: ```rust -#![feature(ptr_internals, unique)] +#![feature(ptr_internals)] use std::ptr::{Unique, self}; diff --git a/src/doc/nomicon/src/what-unsafe-does.md b/src/doc/nomicon/src/what-unsafe-does.md index 91f9145fa0..9b941366c8 100644 --- a/src/doc/nomicon/src/what-unsafe-does.md +++ b/src/doc/nomicon/src/what-unsafe-does.md @@ -20,6 +20,7 @@ language cares about is preventing the following things: * Breaking the [pointer aliasing rules][] * Producing invalid primitive values: * dangling/null references + * null `fn` pointers * a `bool` that isn't 0 or 1 * an undefined `enum` discriminant * a `char` outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF] diff --git a/src/doc/reference/src/SUMMARY.md b/src/doc/reference/src/SUMMARY.md index 23e243fdbf..e6cef5030e 100644 --- a/src/doc/reference/src/SUMMARY.md +++ b/src/doc/reference/src/SUMMARY.md @@ -19,6 +19,8 @@ - [Crates and source files](crates-and-source-files.md) +- [Conditional compilation](conditional-compilation.md) + - [Items and attributes](items-and-attributes.md) - [Items](items.md) - [Modules](items/modules.md) diff --git a/src/doc/reference/src/attributes.md b/src/doc/reference/src/attributes.md index d6baf723e0..ae3149613f 100644 --- a/src/doc/reference/src/attributes.md +++ b/src/doc/reference/src/attributes.md @@ -13,12 +13,12 @@ > _MetaItem_ :\ >       IDENTIFIER\ >    | IDENTIFIER `=` LITERAL\ ->    | IDENTIFIER `(` LITERAL `)`\ >    | IDENTIFIER `(` _MetaSeq_ `)` > > _MetaSeq_ :\ >       EMPTY\ >    | _MetaItem_\ +>    | LITERAL\ >    | _MetaItem_ `,` _MetaSeq_ An _attribute_ is a general, free-form metadatum that is interpreted according @@ -30,14 +30,12 @@ Attributes may appear as any of: * A single identifier, the _attribute name_ * An identifier followed by the equals sign '=' and a literal, providing a key/value pair -* An identifier followed by a parenthesized literal, providing a - key/value pair * An identifier followed by a parenthesized list of sub-attribute arguments + which include literals _Inner attributes_, written with a bang ("!") after the hash ("#"), apply to the item that the attribute is declared within. _Outer attributes_, written without -the bang after the hash, apply to the item or generic parameter that follow the -attribute. +the bang after the hash, apply to the thing that follows the attribute. Attributes may be applied to many things in the language: @@ -83,6 +81,24 @@ fn some_unused_variables() { } ``` +There are three kinds of attributes: + +* Built-in attributes +* Macro attributes +* Derive mode helper attributes + +## Active and inert attributes + +An attribute is either active or inert. During attribute processing, *active +attributes* remove themselves from the thing they are on while *inert attriutes* +stay on. + +The `cfg` and `cfg_attr` attributes are active. The `test` attribute is inert +when compiling for tests and active otherwise. Attribute macros are active. +All other attributes are inert. + +--- + The rest of this page describes or links to descriptions of which attribute names have meaning. @@ -119,16 +135,6 @@ names have meaning. bar;` is equivalent to `mod bar { /* contents of foo.rs */ }`. The path is taken relative to the directory that the current module is in. -## Function-only attributes - -- `test` - indicates that this function is a test function, to only be compiled - in case of `--test`. - - `ignore` - indicates that this test function is disabled. -- `should_panic` - indicates that this test function should panic, inverting the - success condition. -- `cold` - The function is unlikely to be executed, so optimize it (and calls - to it) differently. - ## FFI attributes On an `extern` block, the following attributes are interpreted: @@ -172,19 +178,27 @@ which can be used to control type layout. - `macro_reexport` on an `extern crate` — re-export the named macros. -- `macro_export` - export a macro for cross-crate usage. +- `macro_export` - export a `macro_rules` macro for cross-crate usage. - `no_link` on an `extern crate` — even if we load this crate for macros, don't link it into the output. See the [macros section of the first edition of the book](../book/first-edition/macros.html#scoping-and-macro-importexport) for more -information on macro scope. +information on `macro_rules` macro scope. + +- `proc_macro` - Defines a [function-like macro]. + +- `proc_macro_derive` - Defines a [derive mode macro]. + +- `proc_macro_attribute` - Defines an [attribute macro]. ## Miscellaneous attributes - `export_name` - on statics and functions, this determines the name of the exported symbol. +- `global_allocator` - when applied to a static item implementing the + `GlobalAlloc` trait, sets the global allocator. - `link_section` - on statics and functions, this specifies the section of the object file that this item's contents will be placed into. - `no_mangle` - on any item, do not apply the standard name mangling. Set the @@ -228,103 +242,47 @@ are transformed into `doc` attributes. See [The Rustdoc Book] for reference material on this attribute. -### Conditional compilation +### Testing -Sometimes one wants to have different compiler outputs from the same code, -depending on build target, such as targeted operating system, or to enable -release builds. +The compiler comes with a default test framework. It works by attributing +functions with the `test` attribute. These functions are only compiled when +compiling with the test harness. Like [main], functions annotated with this +attribute must take no arguments, must not declare any +[trait or lifetime bounds], must not have any [where clauses], and its return +type must be one of the following: -Configuration options are boolean (on or off) and are named either with a -single identifier (e.g. `foo`) or an identifier and a string (e.g. `foo = "bar"`; -the quotes are required and spaces around the `=` are unimportant). Note that -similarly-named options, such as `foo`, `foo="bar"` and `foo="baz"` may each be -set or unset independently. +* `()` +* `Result<(), E> where E: Error` + + -Configuration options are either provided by the compiler or passed in on the -command line using `--cfg` (e.g. `rustc main.rs --cfg foo --cfg 'bar="baz"'`). -Rust code then checks for their presence using the `#[cfg(...)]` attribute: +> Note: The implementation of which return types are allowed is determined by +> the unstable [`Termination`] trait. -```rust -// The function is only included in the build when compiling for macOS -#[cfg(target_os = "macos")] -fn macos_only() { - // ... -} + -// This function is only included when either foo or bar is defined -#[cfg(any(foo, bar))] -fn needs_foo_or_bar() { - // ... -} +> Note: The test harness is ran by passing the `--test` argument to `rustc` or +> using `cargo test`. -// This function is only included when compiling for a unixish OS with a 32-bit -// architecture -#[cfg(all(unix, target_pointer_width = "32"))] -fn on_32bit_unix() { - // ... -} +Tests that return `()` pass as long as they terminate and do not panic. Tests +that return a `Result` pass as long as they return `Ok(())`. Tests that do not +terminate neither pass nor fail. -// This function is only included when foo is not defined -#[cfg(not(foo))] -fn needs_not_foo() { - // ... -} -``` +A function annotated with the `test` attribute can also be annotated with the +`ignore` attribute. The *`ignore` attribute* tells the test harness to not +execute that function as a test. It will still only be compiled when compiling +with the test harness. -This illustrates some conditional compilation can be achieved using the -`#[cfg(...)]` attribute. `any`, `all` and `not` can be used to assemble -arbitrarily complex configurations through nesting. - -The following configurations must be defined by the implementation: - -* `target_arch = "..."` - Target CPU architecture, such as `"x86"`, - `"x86_64"` `"mips"`, `"powerpc"`, `"powerpc64"`, `"arm"`, or - `"aarch64"`. This value is closely related to the first element of - the platform target triple, though it is not identical. -* `target_os = "..."` - Operating system of the target, examples - include `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, - `"freebsd"`, `"dragonfly"`, `"bitrig"` , `"openbsd"` or - `"netbsd"`. This value is closely related to the second and third - element of the platform target triple, though it is not identical. -* `target_family = "..."` - Operating system family of the target, e. g. - `"unix"` or `"windows"`. The value of this configuration option is defined - as a configuration itself, like `unix` or `windows`. -* `unix` - See `target_family`. -* `windows` - See `target_family`. -* `target_env = ".."` - Further disambiguates the target platform with - information about the ABI/libc. Presently this value is either - `"gnu"`, `"msvc"`, `"musl"`, or the empty string. For historical - reasons this value has only been defined as non-empty when needed - for disambiguation. Thus on many GNU platforms this value will be - empty. This value is closely related to the fourth element of the - platform target triple, though it is not identical. For example, - embedded ABIs such as `gnueabihf` will simply define `target_env` as - `"gnu"`. -* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or - `"big"`. -* `target_pointer_width = "..."` - Target pointer width in bits. This is set - to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for - 64-bit pointers. -* `target_has_atomic = "..."` - Set of integer sizes on which the target can perform - atomic operations. Values are `"8"`, `"16"`, `"32"`, `"64"` and `"ptr"`. -* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or - simply `"unknown"`. -* `test` - Enabled when compiling the test harness (using the `--test` flag). -* `debug_assertions` - Enabled by default when compiling without optimizations. - This can be used to enable extra debugging code in development but not in - production. For example, it controls the behavior of the standard library's - `debug_assert!` macro. - -You can also set another attribute based on a `cfg` variable with `cfg_attr`: - -```rust,ignore -#[cfg_attr(a, b)] -``` +A function annotated with the `test` attribute that returns `()` can also be +annotated with the `should_panic` attribute. The *`should_panic` attribute* +makes the test only pass if it actually panics. -This is the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise. +### Conditional compilation -Lastly, configuration options can be used in expressions by invoking the `cfg!` -macro: `cfg!(a)` evaluates to `true` if `a` is set, and `false` otherwise. +The `cfg` and `cfg_attr` attributes control conditional compilation of [items] +and attributes. See the [conditional compilation] section for reference material +on these attributes. ### Lint check attributes @@ -396,7 +354,7 @@ pub mod m3 { } ``` -#### `must_use` Attribute +#### `must_use` The `must_use` attribute can be used on user-defined composite types ([`struct`s][struct], [`enum`s][enum], and [`union`s][union]) and [functions]. @@ -495,25 +453,43 @@ When used on a function in an implementation, the attribute does nothing. The `must_use` attribute may also include a message by using `#[must_use = "message"]`. The message will be given alongside the warning. -### Inline attribute +### Optimization Hints + +The `cold` and `inline` attributes give suggestions to the compiler to compile +your code in a way that may be faster than what it would do without the hint. +The attributes are only suggestions, and the compiler may choose to ignore it. + +#### `inline` Attribute -The inline attribute suggests that the compiler should place a copy of -the function or static in the caller, rather than generating code to -call the function or access the static where it is defined. +The *`inline` attribute* suggests to the compiler that it should place a copy of +the attributed function in the caller, rather than generating code to call the +function where it is defined. -The compiler automatically inlines functions based on internal heuristics. -Incorrectly inlining functions can actually make the program slower, so it -should be used with care. +This attribute can be used on [functions] and function prototypes, although it +does not do anything on function prototypes. When this attribute is applied to +a function in a [trait], it applies only to that function when used as a default +function for a trait implementation and not to all trait implementations. -`#[inline]` and `#[inline(always)]` always cause the function to be serialized -into the crate metadata to allow cross-crate inlining. +> ***Note***: The compiler automatically inlines functions based on internal +> heuristics. Incorrectly inlining functions can actually make the program +> slower, so this attibute should be used with care. -There are three different types of inline attributes: +There are three ways of using the inline attribute: * `#[inline]` hints the compiler to perform an inline expansion. * `#[inline(always)]` asks the compiler to always perform an inline expansion. * `#[inline(never)]` asks the compiler to never perform an inline expansion. +#### `cold` Attribute + +The *`cold` attribute* suggests to the compiler that the attributed function is +unlikely to be called. + +This attribute can be used on [functions] and function prototypes, although it +does not do anything on function prototypes. When this attribute is applied to +a function in a [trait], it applies only to that function when used as a default +function for a trait implementation and not to all trait implementations. + ### `derive` The `derive` attribute allows certain traits to be automatically implemented @@ -544,7 +520,7 @@ impl PartialEq for Foo { } ``` -You can implement `derive` for your own type through [procedural macros]. +You can implement `derive` for your own traits through [procedural macros]. [Doc comments]: comments.html#doc-comments [The Rustdoc Book]: ../rustdoc/the-doc-attribute.html @@ -570,4 +546,13 @@ You can implement `derive` for your own type through [procedural macros]. [modules]: items/modules.html [statements]: statements.html [match expressions]: expressions/match-expr.html -[external blocks]: items/external-blocks.html \ No newline at end of file +[external blocks]: items/external-blocks.html +[items]: items.html +[attribute macro]: procedural-macros.html#attribute-macros +[function-like macro]: procedural-macros.html#function-like-procedural-macros +[conditional compilation]: conditional-compilation.html +[derive mode macro]: procedural-macros.html#derive-mode-macros +[trait]: items/traits.html[main]: crates-and-source-files.html +[`Termination`]: ../std/process/trait.Termination.html +[where clause]: items/where-clauses.html +[trait or lifetime bounds]: trait-bounds.html diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md index 0af417719a..612aac0c92 100644 --- a/src/doc/reference/src/behavior-considered-undefined.md +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -5,6 +5,16 @@ if it exhibits any of the behaviors in the following list. It is the programmer's responsibility when writing `unsafe` code that it is not possible to let `safe` code exhibit these behaviors. +
+ +***Warning:*** The following list is not exhaustive. There is no formal model of +Rust's semantics for what is and is not allowed in unsafe code, so there may be +more behavior considered unsafe. The following list is just what we know for +sure is undefined behavior. Please read the [Rustonomicon] before writing unsafe +code. + +
+ * Data races. * Dereferencing a null or dangling raw pointer. * Unaligned pointer reading and writing outside of [`read_unaligned`] @@ -37,3 +47,4 @@ to let `safe` code exhibit these behaviors. [`UnsafeCell`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html [`read_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.read_unaligned.html [`write_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.write_unaligned.html +[Rustonomicon]: ../nomicon/index.html diff --git a/src/doc/reference/src/conditional-compilation.md b/src/doc/reference/src/conditional-compilation.md new file mode 100644 index 0000000000..7df8566e76 --- /dev/null +++ b/src/doc/reference/src/conditional-compilation.md @@ -0,0 +1,102 @@ +## Conditional compilation + +Sometimes one wants to have different compiler outputs from the same code, +depending on build target, such as targeted operating system, or to enable +release builds. + +Configuration options are boolean (on or off) and are named either with a +single identifier (e.g. `foo`) or an identifier and a string (e.g. `foo = "bar"`; +the quotes are required and spaces around the `=` are unimportant). Note that +similarly-named options, such as `foo`, `foo="bar"` and `foo="baz"` may each be +set or unset independently. + +Configuration options are either provided by the compiler or passed in on the +command line using `--cfg` (e.g. `rustc main.rs --cfg foo --cfg 'bar="baz"'`). +Rust code then checks for their presence using the `#[cfg(...)]` [attribute]: + +```rust +// The function is only included in the build when compiling for macOS +#[cfg(target_os = "macos")] +fn macos_only() { + // ... +} + +// This function is only included when either foo or bar is defined +#[cfg(any(foo, bar))] +fn needs_foo_or_bar() { + // ... +} + +// This function is only included when compiling for a unixish OS with a 32-bit +// architecture +#[cfg(all(unix, target_pointer_width = "32"))] +fn on_32bit_unix() { + // ... +} + +// This function is only included when foo is not defined +#[cfg(not(foo))] +fn needs_not_foo() { + // ... +} +``` + +This illustrates some conditional compilation can be achieved using the +`#[cfg(...)]` [attribute]. `any`, `all` and `not` can be used to assemble +arbitrarily complex configurations through nesting. + +The following configurations must be defined by the implementation: + +* `target_arch = "..."` - Target CPU architecture, such as `"x86"`, + `"x86_64"` `"mips"`, `"powerpc"`, `"powerpc64"`, `"arm"`, or + `"aarch64"`. This value is closely related to the first element of + the platform target triple, though it is not identical. +* `target_os = "..."` - Operating system of the target, examples + include `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, + `"freebsd"`, `"dragonfly"`, `"bitrig"` , `"openbsd"` or + `"netbsd"`. This value is closely related to the second and third + element of the platform target triple, though it is not identical. +* `target_family = "..."` - Operating system family of the target, e. g. + `"unix"` or `"windows"`. The value of this configuration option is defined + as a configuration itself, like `unix` or `windows`. +* `unix` - See `target_family`. +* `windows` - See `target_family`. +* `target_env = ".."` - Further disambiguates the target platform with + information about the ABI/libc. Presently this value is either + `"gnu"`, `"msvc"`, `"musl"`, or the empty string. For historical + reasons this value has only been defined as non-empty when needed + for disambiguation. Thus on many GNU platforms this value will be + empty. This value is closely related to the fourth element of the + platform target triple, though it is not identical. For example, + embedded ABIs such as `gnueabihf` will simply define `target_env` as + `"gnu"`. +* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or + `"big"`. +* `target_pointer_width = "..."` - Target pointer width in bits. This is set + to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for + 64-bit pointers. +* `target_has_atomic = "..."` - Set of integer sizes on which the target can perform + atomic operations. Values are `"8"`, `"16"`, `"32"`, `"64"` and `"ptr"`. +* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or + simply `"unknown"`. +* `test` - Enabled when compiling the test harness (using the `--test` flag). +* `debug_assertions` - Enabled by default when compiling without optimizations. + This can be used to enable extra debugging code in development but not in + production. For example, it controls the behavior of the standard library's + `debug_assert!` macro. +* `proc_macro` - Set when the crate being compiled is being compiled with the + `proc_macro` [crate type]. + +You can also set another [attribute] based on a `cfg` variable with `cfg_attr`: + +```rust,ignore +#[cfg_attr(a, b)] +``` + +This is the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise. + +Lastly, configuration options can be used in expressions by invoking the `cfg!` +macro: `cfg!(a)` evaluates to `true` if `a` is set, and `false` otherwise. + +[attribute]: attributes.html +[crate type]: linkage.html \ No newline at end of file diff --git a/src/doc/reference/src/crates-and-source-files.md b/src/doc/reference/src/crates-and-source-files.md index 4a1ee898d3..656ae574c3 100644 --- a/src/doc/reference/src/crates-and-source-files.md +++ b/src/doc/reference/src/crates-and-source-files.md @@ -68,16 +68,20 @@ apply to the crate as a whole. A crate that contains a `main` [function] can be compiled to an executable. If a `main` function is present, it must take no arguments, must not declare any -[trait or lifetime bounds], must not have any [where clauses], and its return +[trait or lifetime bounds], must not have any [where clauses], and its return type must be one of the following: * `()` +* `Result<(), E> where E: Error` -* `Result where T: on this list, E: Error` + > Note: The implementation of which return types are allowed is determined by > the unstable [`Termination`] trait. + + The optional [_UTF8 byte order mark_] (UTF8BOM production) indicates that the file is encoded in UTF8. It can only occur at the beginning of the file and is ignored by the compiler. @@ -114,5 +118,5 @@ fn main() { [_utf8 byte order mark_]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 [function]: items/functions.html [`Termination`]: ../std/process/trait.Termination.html -[where clause]: items/where-clauses.html +[where clauses]: items/generics.html#where-clauses [trait or lifetime bounds]: trait-bounds.html diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md index fdb003a91a..25b586076f 100644 --- a/src/doc/reference/src/expressions.md +++ b/src/doc/reference/src/expressions.md @@ -203,7 +203,7 @@ Here are some examples: ### Implicit Borrows Certain expressions will treat an expression as a place expression by implicitly -borrowing it. For example, it is possible to compare two unsized [slices] for +borrowing it. For example, it is possible to compare two unsized [slices][slice] for equality directly, because the `==` operator implicitly borrows it's operands: ```rust diff --git a/src/doc/reference/src/expressions/block-expr.md b/src/doc/reference/src/expressions/block-expr.md index 81d46b8d14..3778aba75f 100644 --- a/src/doc/reference/src/expressions/block-expr.md +++ b/src/doc/reference/src/expressions/block-expr.md @@ -4,35 +4,85 @@ > _BlockExpression_ :\ >    `{`\ >       [_InnerAttribute_]\*\ ->       [_Statement_]\*\ +>       _Statements_\*\ >       [_Expression_]?\ >    `}` +> +> _Statements_ :\ +>    ( `;`\ +>    | [_ItemDeclaration_]\ +>    | [_LetStatement_] ;\ +>    | [_NonControlFlowExpressionStatement_][expression statement] ;\ +>    | [_FlowControlExpressionStatement_][expression statement] ;?\ +>    )\* + +A *block expression*, or *block*, is a control flow expression and anonymouse +namespace scope for items and variable declarations. As a control flow +expression, a block sequentially executes its component non-item declaration +statements and then its final optional expression. As an anonymous namespace +scope, item declarations are only in scope inside the block itself and variables +declared by `let` statements are in scope from the next statement until the end +of the block. + +Blocks are written as `{`, then any [inner attributes], then [statements], +then an optional expression, and finally a `}`. Statements are usually required +to be followed a semicolon, with two exceptions. Item declaration statements do +not need to be followed by a semicolon. Expression statements usually require +a following semicolon except if its outer expression is a flow control +expression. Furthermore, extra semicolons between statements are allowed, but +these semicolons do not affect semantics. + +> Note: The semicolon following a statement is not a part of the statement +> itself. They are invalid when using the `stmt` macro matcher. + +When evaluating a block expression, each statement, except for item declaration +statements, is executed sequentially. Then the final expression is executed, +if given. + +The type of a block is the type of the final expression, or `()` if the final +expression is omitted. -A _block expression_ is similar to a module in terms of the declarations that -are possible, but can also contain [statements] and end with -an [expression]. Each block conceptually introduces a new namespace scope. Use -items can bring new names into scopes and declared items are in scope for only -the block itself. +```rust +# fn fn_call() {} +let _: () = { + fn_call(); +}; -A block will execute each statement sequentially, and then execute the -expression, if given. If the block doesn't end in an expression, its value is -`()`: +let five: i32 = { + fn_call(); + 5 +}; -```rust -let x: () = { println!("Hello."); }; +assert_eq!(5, five); ``` -If it ends in an expression, its value and type are that of the expression: +> Note: As a control flow expression, if a block expression is the outer +> expression of an expression statement, the expected type is `()` unless it +> is followed immediately by a semicolon. -```rust -let x: i32 = { println!("Hello."); 5 }; +Blocks are always [value expressions] and evaluate the last expression in +value expression context. This can be used to force moving a value if really +needed. For example, the following example fails on the call to `consume_self` +because the struct was moved out of `s` in the block expression. -assert_eq!(5, x); -``` +```rust,compile_fail +struct Struct; -Blocks are always [value expressions] and evaluate the last expression in -value expression context. This can be used to force moving a value if really -needed. +impl Struct { + fn consume_self(self) {} + fn borrow_self(&self) {} +} + +fn move_by_block_expression() { + let s = Struct; + + // Move the value out of `s` in the block expreesion. + (&{ s }).borrow_self(); + + // Fails to execute because `s` is moved out of. + s.consume_self(); +} +``` ## `unsafe` blocks @@ -42,8 +92,8 @@ needed. _See [`unsafe` block](unsafe-blocks.html) for more information on when to use `unsafe`_ -A block of code can be prefixed with the `unsafe` keyword, to permit calling -`unsafe` functions or dereferencing raw pointers within a safe function. Examples: +A block of code can be prefixed with the `unsafe` keyword to permit [unsafe +operations]. Examples: ```rust unsafe { @@ -53,8 +103,8 @@ unsafe { assert_eq!(*a.offset(1), 17); } -# unsafe fn f() -> i32 { 10 } -let a = unsafe { f() }; +# unsafe fn an_unsafe_fn() -> i32 { 10 } +let a = unsafe { an_unsafe_fn() }; ``` ## Attributes on block expressions @@ -62,7 +112,7 @@ let a = unsafe { f() }; Block expressions allow [outer attributes] and [inner attributes] directly after the opening brace when the block expression is the outer expression of an [expression statement] or the final expression of another block expression. The -attributes that have meaning on a block expression are [`cfg`], and [the lint +attributes that have meaning on a block expression are [`cfg`] and [the lint check attributes]. For example, this function returns `true` on unix platforms and `false` on other @@ -76,7 +126,9 @@ fn is_unix_platform() -> bool { ``` [_InnerAttribute_]: attributes.html -[_Statement_]: statements.html +[_ItemDeclaration_]: items.html +[_LetStatement_]: statements.html#let-statements +[expression statement]: statements.html#expression-statements [_Expression_]: expressions.html [expression]: expressions.html [statements]: statements.html @@ -84,5 +136,6 @@ fn is_unix_platform() -> bool { [outer attributes]: attributes.html [inner attributes]: attributes.html [expression statement]: statements.html#expression-statements -[`cfg`]: attributes.html#conditional-compilation +[`cfg`]: conditional-compilation.html [the lint check attributes]: attributes.html#lint-check-attributes +[unsafe operations]: unsafety.html diff --git a/src/doc/reference/src/expressions/match-expr.md b/src/doc/reference/src/expressions/match-expr.md index 3820420795..5dd6831025 100644 --- a/src/doc/reference/src/expressions/match-expr.md +++ b/src/doc/reference/src/expressions/match-expr.md @@ -23,8 +23,8 @@ > _MatchArmGuard_ :\ >    `if` [_Expression_] -A `match` expression branches on a *pattern*. The exact form of matching that -occurs depends on the pattern. Patterns consist of some combination of +A *`match` expression* branches on a pattern. The exact form of matching that +occurs depends on the pattern. *Patterns* consist of some combination of literals, destructured arrays or enum constructors, structs and tuples, variable binding specifications, wildcards (`..`), and placeholders (`_`). A `match` expression has a *head expression*, which is the value to compare to @@ -99,11 +99,12 @@ symbols, as appropriate. For example, these two matches on `x: &i32` are equivalent: ```rust -# let x = &3; -let y = match *x { 0 => "zero", _ => "some" }; -let z = match x { &0 => "zero", _ => "some" }; +let int_reference = &3; -assert_eq!(y, z); +let a = match *int_reference { 0 => "zero", _ => "some" }; +let b = match int_reference { &0 => "zero", _ => "some" }; + +assert_eq!(a, b); ``` Subpatterns can also be bound to variables by the use of the syntax `variable @ @@ -132,13 +133,13 @@ let message = match x { assert_eq!(message, "a few"); ``` -Other forms of [range] \(`..` for an exclusive range, or any range with one or +Other forms of [range] \(e.g `..` for an exclusive range, or any range with one or both endpoints left unspecified) are not supported in matches. The syntax `...` is also accepted for inclusive ranges in patterns only, for backwards compatibility. -Range patterns only work [`char`] and [numeric types]. A range pattern may not -be a sub-range of another range pattern inside the same `match`. +Range patterns only work with [`char`] and [numeric types]. A range pattern may +not be a sub-range of another range pattern inside the same `match`. Slice patterns can match both arrays of fixed size and slices of dynamic size. ```rust @@ -159,11 +160,16 @@ match v[..] { } ``` -Finally, match patterns can accept *pattern guards* to further refine the +Finally, match arms can accept *pattern 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. +When the pattern matches successfully, the pattern guard expression is executed. +If the expression is truthy, the pattern is successfully matched against. +Otherwise, the next pattern, including other matches with the `|` operator in +the same arm, is tested. + ```rust # let maybe_digit = Some(0); # fn process_digit(i: i32) { } @@ -175,6 +181,21 @@ let message = match maybe_digit { }; ``` +> Note: Multiple matches using the `|` operator can cause the pattern guard and +> and side effects it has to execute multiple times. For example: +> +> ```rust +> use std::cell::Cell; +> fn main() { +> let i : Cell = Cell::new(0); +> match 1 { +> 1 | _ if { i.set(i.get() + 1); false } => {} +> _ => {} +> } +> assert_eq!(i.get(), 2); +> } +> ``` + ## Attributes on match arms Outer attributes are allowed on match arms. The only attributes that have @@ -188,5 +209,6 @@ meaning on match arms are [`cfg`], `cold`, and the [lint check attributes]. [numeric types]: types.html#numeric-types [_InnerAttribute_]: attributes.html [_OuterAttribute_]: attributes.html -[`cfg`]: attributes.html#conditional-compilation +[`cfg`]: conditional-compilation.html [lint check attributes]: attributes.html#lint-check-attributes +[range]: expressions/range-expr.html diff --git a/src/doc/reference/src/expressions/method-call-expr.md b/src/doc/reference/src/expressions/method-call-expr.md index 4b5cab46db..28ea5f5ef9 100644 --- a/src/doc/reference/src/expressions/method-call-expr.md +++ b/src/doc/reference/src/expressions/method-call-expr.md @@ -101,3 +101,4 @@ method and you'll be fine. [disambiguating function call syntax]: expressions/call-expr.html#disambiguating-function-calls [dereference]: expressions/operator-expr.html#the-dereference-operator [methods]: items/associated-items.html#methods +[unsized coercion]: type-coercions.html#unsized-coercions diff --git a/src/doc/reference/src/identifiers.md b/src/doc/reference/src/identifiers.md index f9bddd2fa4..37a66787dd 100644 --- a/src/doc/reference/src/identifiers.md +++ b/src/doc/reference/src/identifiers.md @@ -5,8 +5,12 @@ >       [`a`-`z` `A`-`Z`] [`a`-`z` `A`-`Z` `0`-`9` `_`]\*\ >    | `_` [`a`-`z` `A`-`Z` `0`-`9` `_`]+ > +> RAW_IDENTIFIER : `r#` IDENTIFIER_OR_KEYWORD *Except `crate`, `extern`, `self`, `super`, `Self`* +> +> NON_KEYWORD_IDENTIFIER : IDENTIFIER_OR_KEYWORD *Except a [strict] or [reserved] keyword* +> > IDENTIFIER :\ -> IDENTIFIER_OR_KEYWORD *Except a [strict] or [reserved] keyword* +> NON_KEYWORD_IDENTIFIER | RAW_IDENTIFIER An identifier is any nonempty ASCII string of the following form: @@ -21,5 +25,10 @@ Or * The identifier is more than one character. `_` alone is not an identifier. * The remaining characters are alphanumeric or `_`. +A raw identifier is like a normal identifier, but prefixed by `r#`. (Note that +the `r#` prefix is not included as part of the actual identifier.) +Unlike a normal identifier, a raw identifier may be any strict or reserved +keyword except the ones listed above for `RAW_IDENTIFIER`. + [strict]: keywords.html#strict-keywords [reserved]: keywords.html#reserved-keywords diff --git a/src/doc/reference/src/introduction.md b/src/doc/reference/src/introduction.md index 9281e27b45..7a874c33d2 100644 --- a/src/doc/reference/src/introduction.md +++ b/src/doc/reference/src/introduction.md @@ -1,6 +1,6 @@ # Introduction -This document is the primary reference for the Rust programming language. It +This book is the primary reference for the Rust programming language. It provides three kinds of material: - Chapters that informally describe each language construct and their use. @@ -9,38 +9,133 @@ provides three kinds of material: - Appendix chapters providing rationale and references to languages that influenced the design. -This document does not serve as an introduction to the language. Background +> **Note**: You may also be interested in the [grammar]. + +
+ +Warning: This book is incomplete. Documenting everything takes a while. See +the [undocumented] page for what is not documented in this book. + +
+ +## What *The Reference* is Not + +This book does not serve as an introduction to the language. Background familiarity with the language is assumed. A separate [book] is available to help acquire such background familiarity. -This document also does not serve as a reference to the [standard] library +This book also does not serve as a reference to the [standard library] included in the language distribution. Those libraries are documented separately by extracting documentation attributes from their source code. Many of the features that one might expect to be language features are library features in Rust, so what you're looking for may be there, not here. -This document also only serves as a reference to what is available in stable -Rust. For unstable features being worked on, see the [Unstable Book]. This was -a recent change in scope, so unstable features are still documented, but are -in the process of being removed. +Similarly, this book does not usually document the specifics of `rustc` as a +tool or of Cargo. `rustc` has its own [book][rustc book]. Cargo has a +[book][cargo book] that contains a [reference][cargo reference]. There are a few +pages such as [linkage] that still describe how `rustc` works. + +This book also only serves as a reference to what is available in stable +Rust. For unstable features being worked on, see the [Unstable Book]. -Finally, this document is not normative. It may include details that are +Finally, this book is not normative. It may include details that are specific to `rustc` itself, and should not be taken as a specification for -the Rust language. We intend to produce such a document someday, but this -is what we have for now. +the Rust language. We intend to produce such a book someday, and until then, +the reference is the closest thing we have to one. + +## How to Use This Book + +This book does not assume you are reading this book sequentially. Each +chapter generally can be read standalone, but will cross-link to other chapters +for facets of the language they refer to, but do not discuss. + +There are two main ways to read this document. + +The first is to answer a specific question. If you know which chapter answers +that question, you can jump to that chapter in the table of contents. Otherwise, +you can press `s` or the click the magnifying glass on the top bar to search for +keywords related to your question. For example, say you wanted to know when a +temporary value created in a let statement is dropped. If you didn't already +know that the [lifetime of temporaries] is defined in the [expressions chapter], +you could search "temporary let" and the first search result will take you to +that section. + +The second is to generally improve your knowledge of a facet of the language. +In that case, just browse the table of contents until you see something you +want to know more about, and just start reading. If a link looks interesting, +click it, and read about that section. + +That said, there is no wrong way to read this book. Read it however you feel +helps you best. + +### Conventions + +Like all technical books, this book has certain conventions in how it displays +information. These conventions are documented here. + +* Statements that define a term contain that term in *italics*. Whenever that + term is used outside of that chapter, it is usually a link to the section that + has this definition. + + An *example term* is an example of a term beind defined. + +* Notes that contain useful information about the state of the book or point out + useful, but mostly out of scope, information are in blockquotes that start + with the word "Note:" in **bold**. + + > **Note**: This is an example note. + +* Warnings that show unsound behavior in the language or possibly confusing + interactions of language features are in a special warning box. + +
+ + Warning: This is an example warning. + +
+ +* Code snippets inline in the text are inside `` tags. + + Longer code examples are in a syntax highlighted box that has controls for + copying, executing, and showing hidden lines in the top right corner. + + ```rust + # // This is a hidden line. + fn main() { + println!("This is a code example"); + } + ``` + +* The grammar and lexical structure is in blockquotes with either "Lexer" or + "Syntax" in **bold superscript** as the first line. + + > **Syntax**\ + > _ExampleGrammar_:\ + >       `~` [_Expression_]\ + >    | `box` [_Expression_] -You may also be interested in the [grammar]. +## Contributing -You can contribute to this document by opening an issue or sending a pull -request to [the Rust Reference repository]. +We welcome contributions of all kinds. -N. B. This document may be incomplete. Documenting everything might take a -while. We have a [big issue] to track documentation for every Rust feature, -so check that out if you can't find something here. +You can contribute to this book by opening an issue or sending a pull +request to [the Rust Reference repository]. If this book does not answer +your question, and you think its answer is in scope of it, please do not +hesitate to file an issue or ask about it in the Rust docs channels on IRC or +discord. Knowing what people use this book for the most helps direct our +attention to making those sections the best that they can be. [book]: ../book/index.html -[standard]: ../std/index.html +[standard library]: ../std/index.html [grammar]: ../grammar.html [the Rust Reference repository]: https://github.com/rust-lang-nursery/reference/ [big issue]: https://github.com/rust-lang-nursery/reference/issues/9 -[Unstable Book]: https://doc.rust-lang.org/nightly/unstable-book/ \ No newline at end of file +[Unstable Book]: https://doc.rust-lang.org/nightly/unstable-book/ +[_Expression_]: expressions.html +[cargo book]: ../cargo/index.html +[cargo reference]: ../cargo/reference/index.html +[expressions chapter]: expressions.html +[lifetime of temporaries]: expressions.html#temporary-lifetimes +[linkage]: linkage.html +[rustc book]: ../rustc/index.html +[undocumented]: undocumented.html diff --git a/src/doc/reference/src/items/associated-items.md b/src/doc/reference/src/items/associated-items.md index 52a2d8b6bd..9b99037591 100644 --- a/src/doc/reference/src/items/associated-items.md +++ b/src/doc/reference/src/items/associated-items.md @@ -279,6 +279,7 @@ fn main() { [constants]: items/constant-items.html [constant item]: items/constant-items.html [functions]: items/functions.html +[function item]: types.html#function-item-types [method call operator]: expressions/method-call-expr.html [block]: expressions/block-expr.html [path]: paths.html diff --git a/src/doc/reference/src/items/enumerations.md b/src/doc/reference/src/items/enumerations.md index 9939516ce5..aab6b4f50e 100644 --- a/src/doc/reference/src/items/enumerations.md +++ b/src/doc/reference/src/items/enumerations.md @@ -141,3 +141,6 @@ enum ZeroVariants {} [`mem::discriminant`]: ../std/mem/fn.discriminant.html [numeric cast]: expressions/operator-expr.html#semantics [`repr` attribute]: attributes.html#ffi-attributes +[default representation]: type-layout.html#the-default-representation +[primitive representation]: type-layout.html#primitive-representations +[`C` representation]: type-layout.html#the-c-representation diff --git a/src/doc/reference/src/items/functions.md b/src/doc/reference/src/items/functions.md index a3252add2a..92af422a48 100644 --- a/src/doc/reference/src/items/functions.md +++ b/src/doc/reference/src/items/functions.md @@ -115,11 +115,13 @@ As non-Rust calling conventions do not support unwinding, unwinding past the end of an extern function will cause the process to abort. In LLVM, this is implemented by executing an illegal instruction. -## Function attributes +## Attributes on functions -Inner [attributes] on the function's block apply to the function item as a whole. +[Outer attributes][attributes] are allowed on functions. [Inner +attributes][attributes] are allowed directly after the `{` inside its [block]. -For example, this function will only be available while running tests. +This example shows an inner attribute on a function. The function will only be +available while running tests. ``` fn test_only() { @@ -130,6 +132,12 @@ fn test_only() { > Note: Except for lints, it is idiomatic to only use outer attributes on > function items. +The attributes that have meaning on a function are [`cfg`], [`deprecated`], +[`doc`], `export_name`, `link_section`, `no_mangle`, [the lint check +attributes], [`must_use`], [the procedural macro attributes], [the testing +attributes], and [the optimization hint +attributes]. + [external blocks]: items/external-blocks.html [path]: paths.html [block]: expressions/block-expr.html @@ -138,3 +146,11 @@ fn test_only() { [*function item type*]: types.html#function-item-types [Trait]: items/traits.html [attributes]: attributes.html +[`cfg`]: conditional-compilation.html +[the lint check attributes]: attributes.html#lint-check-attributes +[the procedural macro attributes]: procedural-macros.html +[the testing attributes]: attributes.html#testing +[the optimization hint attributes]: attributes.html#optimization-hints +[`deprecated`]: attributes.html#deprecation +[`doc`]: attributes.html#documentation +[`must_use`]: attributes.html#must_use \ No newline at end of file diff --git a/src/doc/reference/src/items/implementations.md b/src/doc/reference/src/items/implementations.md index 2609ca8b20..09b38406f5 100644 --- a/src/doc/reference/src/items/implementations.md +++ b/src/doc/reference/src/items/implementations.md @@ -1,11 +1,14 @@ # Implementations -An _implementation_ is an item that associates items with an *implementing type*. +An _implementation_ is an item that associates items with an _implementing type_. +Implementations are defined with the keyword `impl` and contain functions +that belong to an instance of the type that is being implemented or to the +type statically. -There are two types of implementations: inherent implementations and [trait] -implementations. +There are two types of implementations: -Implementations are defined with the keyword `impl`. +- inherent implementations +- [trait] implementations ## Inherent Implementations @@ -13,20 +16,16 @@ An inherent implementation is defined as the sequence of the `impl` keyword, generic type declarations, a path to a nominal type, a where clause, and a bracketed set of associable items. -The nominal type is called the *implementing type* and the associable items are -the *associated items* to the implementing type. - -Inherent implementations associate the associated items to the implementing -type. +The nominal type is called the _implementing type_ and the associable items are +the _associated items_ to the implementing type. +Inherent implementations associate the contained items to the implementing type. The associated item has a path of a path to the implementing type followed by -the associate item's path component. - -Inherent implementations cannot contain associated type aliases. - -A type can have multiple inherent implementations. +the associate item's path component. Inherent implementations cannot contain +associated type aliases. -The implementing type must be defined within the same crate. +A type can also have multiple inherent implementations. An implementing type +must be defined within the same crate as the original type definition. ```rust struct Point {x: i32, y: i32} @@ -43,14 +42,14 @@ my_point.log(); ## Trait Implementations -A *trait implementation* is defined like an inherent implementation except that +A _trait implementation_ is defined like an inherent implementation except that the optional generic type declarations is followed by a [trait] followed -by the keyword `for`. +by the keyword `for`. Followed by a path to a nominal type. -The trait is known as the *implemented trait*. + -The implementing type implements the implemented trait. +The trait is known as the _implemented trait_. The implementing type +implements the implemented trait. A trait implementation must define all non-default associated items declared by the implemented trait, may redefine default associated items defined by the @@ -105,18 +104,18 @@ be instantiable with the same set of types for the input type parameters. --> The `Orphan Check` states that every trait implementation must meet either of the following conditions: -1. The trait being implemented is defined in the same crate. +1. The trait being implemented is defined in the same crate. -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: +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: - ```ignore - T = C - | &C - | &mut C - | Box - ``` + ```ignore + T = C + | &C + | &mut C + | Box + ``` ## Generic Implementations @@ -146,7 +145,7 @@ attributes]. [trait]: items/traits.html [attributes]: attributes.html -[`cfg`]: attributes.html#conditional-compilation +[`cfg`]: conditional-compilation.html [`deprecated`]: attributes.html#deprecation [`doc`]: attributes.html#documentation [the lint check attributes]: attributes.html#lint-check-attributes diff --git a/src/doc/reference/src/items/static-items.md b/src/doc/reference/src/items/static-items.md index ca09f78e07..a5427df1ee 100644 --- a/src/doc/reference/src/items/static-items.md +++ b/src/doc/reference/src/items/static-items.md @@ -16,7 +16,7 @@ All access to a static is safe, but there are a number of restrictions on statics: * The type must have the `Sync` trait bound to allow thread-safe access. -* Statics allow using paths to statics in the [constant-expression] used to +* Statics allow using paths to statics in the [constant expression] used to initialize them, but statics may not refer to other statics by value, only through a reference. * Constants cannot refer to statics. diff --git a/src/doc/reference/src/items/traits.md b/src/doc/reference/src/items/traits.md index e667670eec..5e830a8c30 100644 --- a/src/doc/reference/src/items/traits.md +++ b/src/doc/reference/src/items/traits.md @@ -52,7 +52,7 @@ Object safe traits can be the base trait of a [trait object]. A trait is ## Supertraits **Supertraits** are traits that are required to be implemented for a type to -implement a specific trait. Furthermore, anywhere a [generic] or [trait object] +implement a specific trait. Furthermore, anywhere a [generic][generics] or [trait object] is bounded by a trait, it has access to the associated items of its supertraits. Supertraits are declared by trait bounds on the `Self` type of a trait and @@ -124,4 +124,4 @@ let nonsense = circle.radius() * circle.area(); [implementations]: items/implementations.html [generics]: items/generics.html [where clauses]: items/generics.html#where-clauses -[generic functions]: items/functions.html#generic-functions \ No newline at end of file +[generic functions]: items/functions.html#generic-functions diff --git a/src/doc/reference/src/keywords.md b/src/doc/reference/src/keywords.md index 94bba52ec7..8cf55de20c 100644 --- a/src/doc/reference/src/keywords.md +++ b/src/doc/reference/src/keywords.md @@ -106,7 +106,7 @@ is possible to declare a variable or method with the name `union`. [loop labels]: expressions/loop-expr.html#loop-labels [Macros]: macros.html [attributes]: attributes.html -[Macro placholders]: macros-by-example.html +[Macro placeholders]: macros-by-example.html [Crates]: crates-and-source-files.html [union]: items/unions.html [variants]: items/enumerations.html diff --git a/src/doc/reference/src/linkage.md b/src/doc/reference/src/linkage.md index 3e004315a6..691e465846 100644 --- a/src/doc/reference/src/linkage.md +++ b/src/doc/reference/src/linkage.md @@ -1,8 +1,11 @@ # Linkage -The Rust compiler supports various methods to link crates together both +> Note: This section is described more in terms of the compiler than of +> the language. + +The compiler supports various methods to link crates together both statically and dynamically. This section will explore the various methods to -link Rust crates together, and more information about native libraries can be +link crates together, and more information about native libraries can be found in the [FFI section of the book][ffi]. [ffi]: ../book/ffi.html @@ -35,7 +38,7 @@ be ignored in favor of only building the artifacts specified by command line. * `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system library will be produced. This is different from other library outputs in that - the Rust compiler will never attempt to link to `staticlib` outputs. The + the compiler will never attempt to link to `staticlib` outputs. The purpose of this output type is to create a static library containing all of the local crate's code along with all upstream dependencies. The static library is actually a `*.a` archive on linux and osx and a `*.lib` file on @@ -44,7 +47,7 @@ be ignored in favor of only building the artifacts specified by command line. dynamic dependencies on other Rust code. * `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system - library will be produced. This is used when compiling Rust code as + library will be produced. This is used when compiling a dynamic library to be loaded from another language. This output type will create `*.so` files on Linux, `*.dylib` files on macOS, and `*.dll` files on Windows. @@ -52,7 +55,7 @@ be ignored in favor of only building the artifacts specified by command line. * `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be produced. This is used as an intermediate artifact and can be thought of as a "static Rust library". These `rlib` files, unlike `staticlib` files, are - interpreted by the Rust compiler in future linkage. This essentially means + interpreted by the compiler in future linkage. This essentially means that `rustc` will look for metadata in `rlib` files like it looks for metadata in dynamic libraries. This form of output is used to produce statically linked executables as well as `staticlib` outputs. @@ -60,12 +63,13 @@ be ignored in favor of only building the artifacts specified by command line. * `--crate-type=proc-macro`, `#[crate_type = "proc-macro"]` - The output produced is not specified, but if a `-L` path is provided to it then the compiler will recognize the output artifacts as a macro and it can be loaded - for a program. If a crate is compiled with the `proc-macro` crate type it - will forbid exporting any items in the crate other than those functions - tagged `#[proc_macro_derive]` and those functions must also be placed at the - crate root. Finally, the compiler will automatically set the - `cfg(proc_macro)` annotation whenever any crate type of a compilation is the - `proc-macro` crate type. + for a program. Crates compiled with this crate type must only export + [procedural macros]. The compiler will automatically set the `proc_macro` + [configuration option]. The crates are always compiled with the same target + that the compiler itself was built with. For example, if you are executing + the compiler from Linux with an `x86_64` CPU, the target will be + `x86_64-unknown-linux-gnu` even if the crate is a dependency of another crate + being built for a different target. Note that these outputs are stackable in the sense that if multiple are specified, then the compiler will produce each form of output at once without @@ -124,7 +128,7 @@ dependencies will be used: In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for all compilation needs, and the other options are just available if more -fine-grained control is desired over the output format of a Rust crate. +fine-grained control is desired over the output format of a crate. ## Static and dynamic C runtimes @@ -205,3 +209,6 @@ a statically linked binary on MSVC you would execute: ```ignore,notrust RUSTFLAGS='-C target-feature=+crt-static' cargo build --target x86_64-pc-windows-msvc ``` + +[configuration option]: conditional-compilation.html +[procedural macros]: procedural-macros.html \ No newline at end of file diff --git a/src/doc/reference/src/macros-by-example.md b/src/doc/reference/src/macros-by-example.md index 26191aea37..bab21e93a3 100644 --- a/src/doc/reference/src/macros-by-example.md +++ b/src/doc/reference/src/macros-by-example.md @@ -31,6 +31,7 @@ syntax named by _designator_. Valid designators are: * `tt`: a token tree (a single [token] by matching `()`, `[]`, or `{}`) * `meta`: the contents of an [attribute] * `lifetime`: a lifetime. Examples: `'static`, `'a`. +* `vis`: a (visibility qualifier)[visibility-and-privacy] [item]: items.html [block]: expressions/block-expr.html @@ -43,6 +44,7 @@ syntax named by _designator_. Valid designators are: [path]: paths.html [token]: tokens.html [attribute]: attributes.html +[visibility-and-privacy]: visibility-and-privacy.html In the transcriber, the designator is already known, and so only the name of a matched nonterminal comes diff --git a/src/doc/reference/src/memory-model.md b/src/doc/reference/src/memory-model.md index aa57ae6ae9..1642e06c9b 100644 --- a/src/doc/reference/src/memory-model.md +++ b/src/doc/reference/src/memory-model.md @@ -1,10 +1,5 @@ # Memory model -A Rust program's memory consists of a static set of *items* and a *heap*. -Immutable portions of the heap may be safely shared between threads, mutable -portions may not be safely shared, but several mechanisms for effectively-safe -sharing of mutable values, built on unsafe code but enforcing a safe locking -discipline, exist in the standard library. - -Allocations in the stack consist of *variables*, and allocations in the heap -consist of *boxes*. +Rust does not yet have a defined memory model. Various academics and industry +are working on various proposals, but for now, this is an under-defined place +in the language. diff --git a/src/doc/reference/src/procedural-macros.md b/src/doc/reference/src/procedural-macros.md index 993bd0e445..a5d0783574 100644 --- a/src/doc/reference/src/procedural-macros.md +++ b/src/doc/reference/src/procedural-macros.md @@ -1,24 +1,295 @@ ## Procedural Macros *Procedural macros* allow creating syntax extensions as execution of a function. -Procedural macros can be used to implement custom [derive] on your own -types. See [the book][procedural macros] for a tutorial. +Procedural macros come in one of three flavors: -Procedural macros involve a few different parts of the language and its -standard libraries. First is the `proc_macro` crate, included with Rust, -that defines an interface for building a procedural macro. The -`#[proc_macro_derive(Foo)]` attribute is used to mark the deriving -function. This function must have the type signature: +* [Function-like macros] - `custom!(...)` +* [Derive mode macros] - `#[derive(CustomMode)]` +* [Attribute macros] - `#[CustomAttribute]` + +Procedural macros allow you to run code at compile time that operates over Rust +syntax, both consuming and producing Rust syntax. You can sort of think of +procedural macros as functions from an AST to another AST. + +Procedural macros must be defined in a crate with the [crate type] of +`proc-macro`. + +> **Note**: When using Cargo, Procedural macro crates are defined with the +> `proc-macro` key in your manfiest: +> +> ```toml +> [lib] +> proc-macro = true +> ``` + +As functions, they must either return syntax, panic, or loop endlessly. Returned +syntax either replaces or adds the syntax depending on the kind of procedural +macro. Panics are caught by the compiler and are turned into a compiler error. +Endless loops are not caught by the compiler which hangs the compiler. + +Procedural macros run during compilation, and thus have the same resources that +the compiler has. For example, standard input, error, and output are the same +that the compiler has access to. Similarly, file access is the same. Because +of this, procedural macros have the same security concerns that [Cargo's +build scripts] have. + +Procedural macros have two ways of reporting errors. The first is to panic. The +second is to emit a [`compile_error`] macro invocation. + +### The `proc_macro` crate + +Procedural macro crates almost always will link to the compiler-provided +[`proc_macro` crate]. The `proc_macro` crate provides types required for +writing procedural macros and facilities to make it easier. + +This crate primarily contains a [`TokenStream`] type. Procedural macros operate +over *token streams* instead of AST nodes, which is a far more stable interface +over time for both the compiler and for procedural macros to target. A +*token stream* is roughly equivalent to `Vec` where a `TokenTree` +can roughly be thought of as lexical token. For example `foo` is an `Ident` +token, `.` is a `Punct` token, and `1.2` is a `Literal` token. The `TokenStream` +type, unlike `Vec`, is cheap to clone. + +All tokens have an associated `Span`. A `Span` is an opaque value that cannot +be modified but can be manufactured. `Span`s represent an extent of source +code within a program and are primarily used for error reporting. You can modify +the `Span` of any token. + +### Procedural macro hygiene + +Procedural macros are *unhygienic*. This means they behave as if the output +token stream was simply written inline to the code it's next to. This means that +it's affected by external items and also affects external imports. + +Macro authors need to be careful to ensure their macros work in as many contexts +as possible given this limitation. This often includes using absolute paths to +items in libraries (for example, `::std::option::Option` instead of `Option`) or +by ensuring that generated functions have names that are unlikely to clash with +other functions (like `__internal_foo` instead of `foo`). + +### Function-like procedural macros + +*Function-like procedural macros* are procedural macros that are invoked using +the macro invocation operator (`!`). + +These macros are defined by a [public] [function] with the `proc_macro` +[attribute] and a signature of `(TokenStream) -> TokenStream`. The input +[`TokenStream`] is what is inside the delimiters of the macro invocation and the +output [`TokenStream`] replaces the entire macro invocation. It may contain an +arbitrary number of [items]. These macros cannot expand to syntax that defines +new `macro_rule` style macros. + +For example, the following macro definition ignores its input and outputs a +function `answer` into its scope. ```rust,ignore +extern crate proc_macro; use proc_macro::TokenStream; -#[proc_macro_derive(Hello)] -pub fn hello_world(input: TokenStream) -> TokenStream +#[proc_macro] +pub fn make_answer(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() +} ``` -Finally, procedural macros must be in their own crate, with the `proc-macro` -crate type. +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; + +make_answer!(); + +fn main() { + println!("{}", answer()); +} +``` + +These macros are only invokable in [modules]. They cannot even be invoked to +create [item declaration statements]. Furthermore, they must either be invoked +with curly braces and no semicolon or a different delimiter followed by a +semicolon. For example, `make_answer` from the previous example can be invoked +as `make_answer!{}`, `make_answer!();` or `make_answer![];`. + +### Derive mode macros + +*Derive mode macros* define new modes for the `derive` [attribute]. These macros +define new [items] given the token stream of a [struct], [enum], or [union]. +They also define [derive mode helper attributes]. + +Custom deriver modes are defined by a [public] [function] with the +`proc_macro_derive` attribute and a signature of `(TokenStream) -> TokenStream`. + +The input [`TokenStream`] is the token stream of the item that has the `derive` +attribute on it. The output [`TokenStream`] must be a set of items that are +then appended to the [module] or [block] that the item from the input +[`TokenStream`] is in. + +The following is an example of a derive mode macro. Instead of doing anything +useful with its input, it just appends a function `answer`. + +```rust,ignore +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(AnswerFn)] +pub fn derive_answer_fn(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() +} +``` + +And then using said derive mode: + +```rust,ignore +extern crate proc_macro_examples; +use proc_macro_examples::AnswerFn; + +#[derive(AnswerFn)] +struct Struct; + +fn main() { + assert_eq!(42, answer()); +} +``` + +#### Derive mode helper attributes + +Derive mode macros can add additional [attributes] into the scope of the [item] +they are on. Said attributes are called *derive mode helper attributes*. These +attributes are [inert], and their only purpose is to be fed into the derive +mode macro that defined them. That said, they can be seen by all macros. + +The way to define helper attributes is to put an `attributes` key in the +`proc_macro_derive` macro with a comma separated list of identifiers that are +the names of the helper attributes. + +For example, the following derive mode macro defines a helper attribute +`helper`, but ultimately doesn't do anything with it. + +```rust,ignore +# #[crate_type="proc-macro"] +# extern crate proc_macro; +# use proc_macro::TokenStream; + +#[proc_macro_derive(HelperAttr, attributes(helper))] +pub fn derive_helper_attr(_item: TokenStream) -> TokenStream { + TokenStream::new(); +} +``` + +And then usage on the derive mode 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: () +} +``` + +### Attribute macros + +*Attribute macros* define new [attributes] which can be attached to [items]. + +Attribute macros are defined by a [public] [function] with the +`proc_macro_attribute` [attribute] that a signature of +`(TokenStream, TokenStream) -> TokenStream`. The first [`TokenStream`] is the +attribute's metaitems, not including the delimiters. If the attribute is written +without a metaitem, the attribute [`TokenStream`] is empty. The second +[`TokenStream`] is of the rest of the [item] including other [attributes] on the +[item]. The returned [`TokenStream`] replaces the [item] with an arbitrary +number of [items]. These macros cannot expand to syntax that defines new +`macro_rule` style macros. + +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; +# use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn return_as_is(_attr: TokenStream, item: TokenStream) -> TokenStream { + item +} +``` + +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; +# use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn show_streams(attr: TokenStream, input: TokenStream) -> TokenStream { + println!("attr: \"{}\"", attr.to_string()); + println!("item: \"{}\"', input.to_string()); + item +} +``` + +```rust,ignore +// src/lib.rs +extern crate my_macro; + +use my_macro::show_streams; + +// Example: Basic function +#[show_streams] +fn invoke1() {} +// out: attr: "" +// out: item: "fn invoke1() { }" + +// Example: Attribute has a metaitem +#[show_streams(bar)] +fn invoke2() {} +// out: attr: "bar" +// out: item: "fn invoke2() {}" + +// Example: Multiple words in metaitem +#[show_streams(multiple words)] +fn invoke3() {} +// out: attr: "multiple words" +// out: item: "fn invoke3() {}" + +// Example: +#[show_streams { delimiters }] +fn invoke4() {} +// out: "delimiters" +// out: "fn invoke4() {}" +``` -[derive]: attributes.html#derive -[procedural macros]: ../book/first-edition/procedural-macros.html \ No newline at end of file +[`TokenStream`]: ../proc_macro/struct.TokenStream.html +[`TokenStream`s]: ../proc_macro/struct.TokenStream.html +[`compile_error`]: ../std/macro.compile_error.html +[`derive`]: attributes.html#derive +[`proc_macro` crate]: ../proc_macro/index.html +[Cargo's build scripts]: ../cargo/reference/build-scripts.html +[Derive mode macros]: #derive-mode-macros +[Attribute macros]: #attribute-macros +[Function-like macros]: #function-like-procedural-macros +[attribute]: attributes.html +[attributes]: attributes.html +[custom attributes]: attributes.html +[crate type]: linkage.html +[derive mode helper attributes]: #derive-mode-helper-attributes +[enum]: items/enumerations.html +[inert]: attributes.html#active-and-inert-attributes +[item]: items.html +[item declaration statements]: statements.html#item-declarations +[items]: items.html +[function]: items/functions.html +[macro]: macros.html +[module]: items/modules.html +[modules]: items/modules.html +[procedural macro tutorial]: ../book/2018-edition/appendix-04-macros.html#procedural-macros-for-custom-derive +[public]: visibility-and-privacy.html +[struct]: items/structs.html +[unions]: items/unions.html diff --git a/src/doc/reference/src/statements.md b/src/doc/reference/src/statements.md index bbe83d3752..52c78ba134 100644 --- a/src/doc/reference/src/statements.md +++ b/src/doc/reference/src/statements.md @@ -104,5 +104,5 @@ statement are [`cfg`], and [the lint check attributes]. [implementations]: items/implementations.html [variables]: variables.html [outer attributes]: attributes.html -[`cfg`]: attributes.html#conditional-compilation +[`cfg`]: conditional-compilation.html [the lint check attributes]: attributes.html#lint-check-attributes diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md index 2aae5086a4..204b9d99a0 100644 --- a/src/doc/reference/src/tokens.md +++ b/src/doc/reference/src/tokens.md @@ -1,9 +1,18 @@ # Tokens Tokens are primitive productions in the grammar defined by regular -(non-recursive) languages. "Simple" tokens are given in [string table -production] form, and occur in the rest of the -grammar in `monospace` font. Other tokens have exact rules given. +(non-recursive) languages. Rust source input can be broken down +into the following kinds of tokens: + +* [Keywords] +* [Identifiers][identifier] +* [Literals](#literals) +* [Lifetimes](#lifetimes-and-loop-labels) +* [Punctuation](#punctuation) +* [Delimiters](#delimiters) + +Within this documentation's grammar, "simple" tokens are given in [string +table production] form, and appear in `monospace` font. [string table production]: notation.html#string-table-productions @@ -493,7 +502,7 @@ The two values of the boolean type are written `true` and `false`. >    | `'_` > > LIFETIME_OR_LABEL :\ ->       `'` [IDENTIFIER][identifier] +>       `'` [NON_KEYWORD_IDENTIFIER][identifier] Lifetime parameters and [loop labels] use LIFETIME_OR_LABEL tokens. Any LIFETIME_TOKEN will be accepted by the lexer, and for example, can be used in @@ -501,21 +510,104 @@ macros. [loop labels]: expressions/loop-expr.html -## Symbols - -Symbols are a general class of printable [tokens] that play structural -roles in a variety of grammar productions. They are a -set of remaining miscellaneous printable tokens that do not -otherwise appear as [unary operators], [binary -operators], or [keywords]. -They are catalogued in [the Symbols section][symbols] of the Grammar document. - -[unary operators]: expressions/operator-expr.html#borrow-operators -[binary operators]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators +## Punctuation + +Punctuation symbol tokens are listed here for completeness. Their individual +usages and meanings are defined in the linked pages. + +| Symbol | Name | Usage | +|--------|-------------|-------| +| `+` | Plus | [Addition][arith], [Trait Bounds], [Macro Kleene Matcher][macros] +| `-` | Minus | [Subtraction][arith], [Negation] +| `*` | Star | [Multiplication][arith], [Dereference], [Raw Pointers], [Macro Kleene Matcher][macros] +| `/` | Slash | [Division][arith] +| `%` | Percent | [Remainder][arith] +| `^` | Caret | [Bitwise and Logical XOR][arith] +| `!` | Not | [Bitwise and Logical NOT][negation], [Macro Calls][macros], [Inner Attributes][attributes], [Never Type] +| `&` | And | [Bitwise and Logcal AND][arith], [Borrow], [References] +| \| | Or | [Bitwise and Logical OR][arith], [Closures], [Match] +| `&&` | AndAnd | [Lazy AND][lazy-bool], [Borrow], [References] +| \|\| | OrOr | [Lazy OR][lazy-bool], [Closures] +| `<<` | Shl | [Shift Left][arith], [Nested Generics][generics] +| `>>` | Shr | [Shift Right][arith], [Nested Generics][generics] +| `+=` | PlusEq | [Addition assignment][compound] +| `-=` | MinusEq | [Subtraction assignment][compound] +| `*=` | StarEq | [Multiplication assignment][compound] +| `/=` | SlashEq | [Division assignment][compound] +| `%=` | PercentEq | [Remainder assignment][compound] +| `^=` | CaretEq | [Bitwise XOR assignment][compound] +| `&=` | AndEq | [Bitwise And assignment][compound] +| \|= | OrEq | [Bitwise Or assignment][compound] +| `<<=` | ShlEq | [Shift Left assignment][compound] +| `>>=` | ShrEq | [Shift Right assignment][compound], [Nested Generics][generics] +| `=` | Eq | [Assignment], [Attributes], Various type definitions +| `==` | EqEq | [Equal][comparison] +| `!=` | Ne | [Not Equal][comparison] +| `>` | Gt | [Greater than][comparison], [Generics], [Paths] +| `<` | Lt | [Less than][comparison], [Generics], [Paths] +| `>=` | Ge | [Greater than or equal to][comparison], [Generics] +| `<=` | Le | [Less than or equal to][comparison] +| `@` | At | [Subpattern binding][match] +| `_` | Underscore | [Placeholder patterns][match], Inferred types +| `.` | Dot | [Field access][field], [Tuple index] +| `..` | DotDot | [Range][range], [Struct expressions], [Wildcard patterns][match] +| `...` | DotDotDot | [Variadic functions][extern] +| `..=` | DotDotEq | [Inclusive Range][range] +| `,` | Comma | Various separators +| `;` | Semi | Terminator for various items and statements, [Array types] +| `:` | Colon | Various separators +| `::` | PathSep | [Path separator][paths] +| `->` | RArrow | [Function return type][functions], [Closure return type][closures] +| `=>` | FatArrow | [Match arms][match], [Macros] +| `#` | Pound | [Attributes] +| `$` | Dollar | [Macros] +| `?` | Question | [Question mark operator][question], [Questionably sized][sized] + +## Delimiters + +Bracket punctuation is used in various parts of the grammar. An open bracket +must always be paired with a close bracket. Brackets and the tokens within +them are referred to as "token trees" in [macros]. The three types of brackets are: + +| Bracket | Type | +|---------|-----------------| +| `{` `}` | Curly braces | +| `[` `]` | Square brackets | +| `(` `)` | Parentheses | + + +[Operator expressions]: expressions/operator-expr.html [tokens]: #tokens -[symbols]: ../grammar.html#symbols [keywords]: keywords.html [identifier]: identifiers.html [tuples]: types.html#tuple-types [tuple structs]: items/structs.html [tuple variants]: items/enumerations.html +[arith]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators +[negation]: expressions/operator-expr.html#negation-operators +[lazy-bool]: expressions/operator-expr.html#lazy-boolean-operators +[compound]: expressions/operator-expr.html#compound-assignment-expressions +[comparison]: expressions/operator-expr.html#comparison-operators +[match]: expressions/match-expr.html +[field]: expressions/field-expr.html +[range]: expressions/range-expr.html +[trait bounds]: trait-bounds.html +[dereference]: expressions/operator-expr.html#the-dereference-operator +[raw pointers]: types.html#raw-pointers-const-and-mut +[macros]: macros-by-example.html +[attributes]: attributes.html +[never type]: types.html#never-type +[borrow]: expressions/operator-expr.html#borrow-operators +[references]: types.html#pointer-types +[closures]: expressions/closure-expr.html +[assignment]: expressions/operator-expr.html#assignment-expressions +[constant items]: items/constant-items.html +[generics]: items/generics.html +[paths]: paths.html +[array types]: types.html#array-and-slice-types +[functions]: items/functions.html +[question]: expressions/operator-expr.html#the-question-mark-operator +[sized]: trait-bounds.html#sized +[extern]: items/external-blocks.html +[struct expressions]: expressions/struct-expr.html +[tuple index]: expressions/tuple-expr.html#tuple-indexing-expressions diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index 7094b02885..db5c83942d 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -296,12 +296,29 @@ a `packed` type cannot transitively contain another `align`ed type.
-***Warning:*** Dereferencing an unaligned pointer is [undefined behaviour] and +***Warning:*** Dereferencing an unaligned pointer is [undefined behavior] and it is possible to [safely create unaligned pointers to `packed` fields][27060]. Like all ways to create undefined behavior in safe Rust, this is a bug.
+### The `transparent` Representation + +The `transparent` representation can only be used on `struct`s that have a +single non-zero sized field and any number of zero-sized fields, including +[`PhantomData`]. + +Structs with this representation have the same layout and ABI as the single +non-zero sized field. + +This is different than the `C` representation because +a struct with the `C` representation will always have the ABI of a `C` `struct` +while, for example, a struct with the `transparent` representation with a +primitive field will have the ABI of the primitive field. + +Because this representation delegates type layout to another type, it cannot be +used with any other representation. + [`align_of_val`]: ../std/mem/fn.align_of_val.html [`size_of_val`]: ../std/mem/fn.size_of_val.html [`align_of`]: ../std/mem/fn.align_of.html @@ -312,3 +329,4 @@ Like all ways to create undefined behavior in safe Rust, this is a bug. [zero-variant enumerations]: items/enumerations.html#zero-variant-enums [undefined behavior]: behavior-considered-undefined.html [27060]: https://github.com/rust-lang/rust/issues/27060 +[`PhantomData`]: special-types-and-traits.html#phantomdatat \ No newline at end of file diff --git a/src/doc/reference/src/types.md b/src/doc/reference/src/types.md index 4b12c4a22c..a39ba2781e 100644 --- a/src/doc/reference/src/types.md +++ b/src/doc/reference/src/types.md @@ -13,7 +13,7 @@ Some types are defined by the language, rather than as part of the standard library, these are called _primitive types_. Some of these are individual types: -* The boolean type `bool` with values `true` and `false`. +* The [boolean type] `bool` with values `true` and `false`. * The [machine types] (integer and floating-point). * The [machine-dependent integer types]. * The [textual types] `char` and `str`. @@ -29,10 +29,11 @@ language: * [References] * [Pointers] +[boolean type]: #boolean-type [machine types]: #machine-types [machine-dependent integer types]: #machine-dependent-integer-types [textual types]: #textual-types -[never-type]: #never-type +[never type]: #never-type [Tuples]: #tuple-types [Arrays]: #array-and-slice-types [Slices]: #array-and-slice-types @@ -42,18 +43,36 @@ language: [function]: #function-types [closure]: #closure-types +### Boolean type + +The `bool` type is a datatype which can be either `true` or `false`. The boolean +type uses one byte of memory. It is used in comparisons and bitwise operations +like `&`, `|`, and `!`. + +```rust +fn main() { + let x = true; + let y: bool = false; // with the boolean type annotation + + // Use of booleans in conditional expressions + if x { + println!("x is true"); + } +} +``` + ## Numeric types ### Machine types The machine types are the following: -* The unsigned word types `u8`, `u16`, `u32`, `u64`, and `u128` with values drawn from - the integer intervals [0, 2^8 - 1], [0, 2^16 - 1], [0, 2^32 - 1], +* The unsigned word types `u8`, `u16`, `u32`, `u64`, and `u128` with values + drawn from the integer intervals [0, 2^8 - 1], [0, 2^16 - 1], [0, 2^32 - 1], [0, 2^64 - 1], and [0, 2^128 - 1] respectively. -* The signed two's complement word types `i8`, `i16`, `i32`, `i64`, and `i128`, with - values drawn from the integer intervals [-(2^7), 2^7 - 1], +* The signed two's complement word types `i8`, `i16`, `i32`, `i64`, and `i128`, + with values drawn from the integer intervals [-(2^7), 2^7 - 1], [-(2^15), 2^15 - 1], [-(2^31), 2^31 - 1], [-(2^63), 2^63 - 1], and [-(2^127), 2^127 - 1] respectively. @@ -343,7 +362,7 @@ let foo_ptr_2 = if want_i32 { ``` All function items implement [`Fn`], [`FnMut`], [`FnOnce`], [`Copy`], -[`Clone]`, [`Send`], and [`Sync`]. +[`Clone`], [`Send`], and [`Sync`]. ## Function pointer types diff --git a/src/doc/reference/src/undocumented.md b/src/doc/reference/src/undocumented.md index 71bd1b2c0d..6cac6f8c7a 100644 --- a/src/doc/reference/src/undocumented.md +++ b/src/doc/reference/src/undocumented.md @@ -9,24 +9,19 @@ to shrink! - [`libstd` facade] - [Trait reform] – some partial documentation exists (the use of `Self`), but not for everything: e.g. coherence and orphan rules. -- [Attributes on `match` arms] – the underlying idea is documented in the - [Attributes] section, but the applicability to internal items is never - specified. - [Flexible target specification] - Some---but not all---flags are documented in [Conditional compilation] -- [Require parentheses for chained comparisons] - [`dllimport`] - one element mentioned but not explained at [FFI attributes] - [define `crt_link`] -- [define `unaligned_access`] +- `impl Trait` [`libstd` facade]: https://github.com/rust-lang/rfcs/pull/40 [Trait reform]: https://github.com/rust-lang/rfcs/pull/48 [Attributes on `match` arms]: https://github.com/rust-lang/rfcs/pull/49 +[Attributes]: attributes.html [Flexible target specification]: https://github.com/rust-lang/rfcs/pull/131 [Conditional compilation]: attributes.html#conditional-compilation -[Unambiguous function call syntax]: https://github.com/rust-lang/rfcs/pull/132 [Integer overflow not `unsafe`]: https://github.com/rust-lang/rfcs/pull/560 [`dllimport`]: https://github.com/rust-lang/rfcs/pull/1717 [FFI attributes]: attributes.html#ffi-attributes [define `crt_link`]: https://github.com/rust-lang/rfcs/pull/1721 -[define `unaligned_access`]: https://github.com/rust-lang/rfcs/pull/1725 diff --git a/src/doc/reference/src/unsafety.md b/src/doc/reference/src/unsafety.md index 452215d8db..53cf7448fa 100644 --- a/src/doc/reference/src/unsafety.md +++ b/src/doc/reference/src/unsafety.md @@ -1,6 +1,6 @@ # Unsafety -Unsafe operations are those that potentially violate the memory-safety +Unsafe operations are those that can potentially violate the memory-safety guarantees of Rust's static semantics. The following language level features cannot be used in the safe subset of @@ -11,4 +11,4 @@ Rust: - Reading a field of a [`union`](items/unions.html), or writing to a field of a union that isn't [`Copy`](special-types-and-traits.html#copy). - Calling an unsafe function (including an intrinsic or foreign function). -- Implementing an unsafe trait. +- Implementing an unsafe trait. \ No newline at end of file diff --git a/src/doc/rust-by-example/src/SUMMARY.md b/src/doc/rust-by-example/src/SUMMARY.md index 24f7ce8303..31792d0fa7 100644 --- a/src/doc/rust-by-example/src/SUMMARY.md +++ b/src/doc/rust-by-example/src/SUMMARY.md @@ -196,7 +196,10 @@ - [Integration testing](testing/integration_testing.md) - [Dev-dependencies](testing/dev_dependencies.md) +- [Unsafe Operations](unsafe.md) + +- [Compatibility](compatibility.md) + - [Raw identifiers](compatibility/raw_identifiers.md) + - [Meta](meta.md) - [Documentation](meta/doc.md) - -- [Unsafe Operations](unsafe.md) diff --git a/src/doc/rust-by-example/src/compatibility.md b/src/doc/rust-by-example/src/compatibility.md new file mode 100644 index 0000000000..c756e25d71 --- /dev/null +++ b/src/doc/rust-by-example/src/compatibility.md @@ -0,0 +1,7 @@ +# Compatibility + +The Rust language is fastly evolving, and because of this certain compatibility +issues can arise, despite efforts to ensure forwards-compatibility wherever +possible. + +* [Raw identifiers](compatibility/raw_identifiers.html) diff --git a/src/doc/rust-by-example/src/compatibility/raw_identifiers.md b/src/doc/rust-by-example/src/compatibility/raw_identifiers.md new file mode 100644 index 0000000000..eb42cf645a --- /dev/null +++ b/src/doc/rust-by-example/src/compatibility/raw_identifiers.md @@ -0,0 +1,42 @@ +# Raw identifiers + +Rust, like many programming languages, has the concept of "keywords". +These identifiers mean something to the language, and so you cannot use them in +places like variable names, function names, and other places. +Raw identifiers let you use keywords where they would not normally be allowed. +This is particularly useful when Rust introduces new keywords, and a library +using an older edition of Rust has a variable or function with the same name +as a keyword introduced in a newer edition. + +For example, consider a crate `foo` compiled with the 2015 edition of Rust that +exports a function named `try`. This keyword is reserved for a new feature in +the 2018 edition, so without raw identifiers, we would have no way to name the +function. + +```rust,ignore +extern crate foo; + +fn main() { + foo::try(); +} +``` + +You'll get this error: + +```text +error: expected identifier, found keyword `try` + --> src/main.rs:4:4 + | +4 | foo::try(); + | ^^^ expected identifier, found keyword +``` + +You can write this with a raw identifier: + +```rust,ignore +extern crate foo; + +fn main() { + foo::r#try(); +} +``` diff --git a/src/doc/rust-by-example/src/custom_types/constants.md b/src/doc/rust-by-example/src/custom_types/constants.md index 1d1df092a9..5fb868b9b5 100644 --- a/src/doc/rust-by-example/src/custom_types/constants.md +++ b/src/doc/rust-by-example/src/custom_types/constants.md @@ -5,18 +5,13 @@ including global. Both require explicit type annotation: * `const`: An unchangeable value (the common case). * `static`: A possibly `mut`able variable with [`'static`][static] lifetime. - -One special case is the `"string"` literal. It can be assigned directly to a -`static` variable without modification because its type signature: -`&'static str` has the required lifetime of `'static`. All other reference -types must be specifically annotated so that they fulfill the `'static` -lifetime. This may seem minor though because the required explicit annotation -hides the distinction. + The static lifetime is inferred and does not have to be specified. + Accessing or modifying a mutable static variable is [`unsafe`][unsafe]. ```rust,editable,ignore,mdbook-runnable // Globals are declared outside all other scopes. -static LANGUAGE: &'static str = "Rust"; -const THRESHOLD: i32 = 10; +static LANGUAGE: &str = "Rust"; +const THRESHOLD: i32 = 10; fn is_big(n: i32) -> bool { // Access constant in some function @@ -44,3 +39,4 @@ https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md), [`'static` lifetime][static] [static]: scope/lifetime/static_lifetime.html +[unsafe]: unsafe.html diff --git a/src/doc/rust-by-example/src/flow_control/match/binding.md b/src/doc/rust-by-example/src/flow_control/match/binding.md index dc6322bb92..9a22503207 100644 --- a/src/doc/rust-by-example/src/flow_control/match/binding.md +++ b/src/doc/rust-by-example/src/flow_control/match/binding.md @@ -11,7 +11,7 @@ fn age() -> u32 { } fn main() { - println!("Tell me type of person you are"); + println!("Tell me what type of person you are"); match age() { 0 => println!("I'm not born yet I guess"), diff --git a/src/doc/rust-by-example/src/hello/print.md b/src/doc/rust-by-example/src/hello/print.md index e62da894f8..c8e0006d24 100644 --- a/src/doc/rust-by-example/src/hello/print.md +++ b/src/doc/rust-by-example/src/hello/print.md @@ -7,7 +7,7 @@ some of which include: * `print!`: same as `format!` but the text is printed to the console (io::stdout). * `println!`: same as `print!` but a newline is appended. * `eprint!`: same as `format!` but the text is printed to the standard error (io::stderr). -* `eprintln!`: sames as `eprint!`but a newline is appended. +* `eprintln!`: same as `eprint!`but a newline is appended. All parse text in the same fashion. A plus is that the formatting correctness will be checked at compile time. diff --git a/src/doc/rust-by-example/src/index.md b/src/doc/rust-by-example/src/index.md index 5f3a1ed613..128b9c0179 100644 --- a/src/doc/rust-by-example/src/index.md +++ b/src/doc/rust-by-example/src/index.md @@ -51,10 +51,12 @@ Now let's begin! - [Testing](testing.html) - All sorts of testing in Rust. -- [Meta](meta.html) - Documentation, Benchmarking. - - [Unsafe Operations](unsafe.html) +- [Compatibility](compatibility.html) + +- [Meta](meta.html) - Documentation, Benchmarking. + [rust]: https://www.rust-lang.org/ [install]: https://www.rust-lang.org/install.html diff --git a/src/doc/rust-by-example/src/macros/designators.md b/src/doc/rust-by-example/src/macros/designators.md index a06d1d41a3..0ff2ed7f87 100644 --- a/src/doc/rust-by-example/src/macros/designators.md +++ b/src/doc/rust-by-example/src/macros/designators.md @@ -59,3 +59,4 @@ This is a list of all the designators: * `stmt` (*statement*) * `tt` (*token tree*) * `ty` (*type*) +* `vis` (*visibility qualifier*) diff --git a/src/doc/rust-by-example/src/mod/use.md b/src/doc/rust-by-example/src/mod/use.md index 9d04b826aa..736aad6bd1 100644 --- a/src/doc/rust-by-example/src/mod/use.md +++ b/src/doc/rust-by-example/src/mod/use.md @@ -1,9 +1,25 @@ # The `use` declaration The `use` declaration can be used to bind a full path to a new name, for easier -access. +access. It is often used like this: -```rust,editable +```rust,editable,ignore +// extern crate deeply; // normally, this would exist and not be commented out! + +use deeply::nested::{ + my_first_function, + my_second_function, + AndATraitType +}; + +fn main() { + my_first_function(); +} +``` + +You can use the `as` keyword to bind imports to a different name: + +```rust,editable,ignore // Bind the `deeply::nested::function` path to `other_function`. use deeply::nested::function as other_function; @@ -37,4 +53,4 @@ fn main() { function(); } -``` \ No newline at end of file +``` diff --git a/src/doc/rust-by-example/src/primitives/array.md b/src/doc/rust-by-example/src/primitives/array.md index 6c0fda962c..fe4bee94c2 100644 --- a/src/doc/rust-by-example/src/primitives/array.md +++ b/src/doc/rust-by-example/src/primitives/array.md @@ -45,7 +45,7 @@ fn main() { println!("borrow a section of the array as a slice"); analyze_slice(&ys[1 .. 4]); - // Out of bound indexing yields a panic + // Out of bound indexing causes compile error println!("{}", xs[5]); } ``` diff --git a/src/doc/rust-by-example/src/std_misc/channels.md b/src/doc/rust-by-example/src/std_misc/channels.md index e88605543f..8c4d45165f 100644 --- a/src/doc/rust-by-example/src/std_misc/channels.md +++ b/src/doc/rust-by-example/src/std_misc/channels.md @@ -16,13 +16,14 @@ fn main() { // where `T` is the type of the message to be transferred // (type annotation is superfluous) let (tx, rx): (Sender, Receiver) = mpsc::channel(); + let mut children = Vec::new(); for id in 0..NTHREADS { // The sender endpoint can be copied let thread_tx = tx.clone(); // Each thread will send its id via the channel - thread::spawn(move || { + let child = thread::spawn(move || { // The thread takes ownership over `thread_tx` // Each thread queues a message in the channel thread_tx.send(id).unwrap(); @@ -31,6 +32,8 @@ fn main() { // immediately after sending its message println!("thread {} finished", id); }); + + children.push(child); } // Here, all the messages are collected @@ -40,8 +43,13 @@ fn main() { // `recv` will block the current thread if there are no messages available ids.push(rx.recv()); } + + // Wait for the threads to complete any remaining work + for child in children { + child.join().expect("oops! the child thread panicked"); + } // Show the order in which the messages were sent println!("{:?}", ids); } -``` \ No newline at end of file +``` diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index eff0942890..4fc5f42dd5 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -153,7 +153,7 @@ This option allows you to put extra data in each output filename. This flag lets you control how many threads are used when doing code generation. -Increasing paralellism may speed up compile times, but may also +Increasing parallelism may speed up compile times, but may also produce slower code. ## remark diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md index bf345a2438..49c0026ce1 100644 --- a/src/doc/rustc/src/lints/index.md +++ b/src/doc/rustc/src/lints/index.md @@ -12,7 +12,7 @@ $ cat main.rs fn main() { let x = 5; } -> rustc main.rs +$ rustc main.rs warning: unused variable: `x` --> main.rs:2:9 | diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index 19bb6707d2..072c758593 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -45,7 +45,7 @@ pub fn foo() { This will produce this warning: -```console +```bash $ rustc lib.rs --crate-type=lib warning: unused variable: `x` --> lib.rs:2:9 @@ -69,7 +69,7 @@ fn main() { ``` ```bash -> rustc main.rs +$ rustc main.rs error: bitshift exceeds the type's number of bits --> main.rs:2:13 | @@ -129,7 +129,10 @@ warning: missing documentation for a function | 1 | pub fn foo() {} | ^^^^^^^^^^^^ -> rustc lib.rs --crate-type=lib -D missing-docs +``` + +```bash +$ rustc lib.rs --crate-type=lib -D missing-docs error: missing documentation for crate --> lib.rs:1:1 | @@ -150,13 +153,13 @@ error: aborting due to 2 previous errors You can also pass each flag more than once for changing multiple lints: ```bash -rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables +$ rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables ``` And of course, you can mix these four flags together: ```bash -rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables +$ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables ``` ### Via an attribute @@ -164,7 +167,7 @@ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables You can also modify the lint level with a crate-wide attribute: ```bash -> cat lib.rs +$ cat lib.rs #![warn(missing_docs)] 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 3a85a40fd1..ff9e0235a0 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -56,7 +56,7 @@ mod m { pub struct S(u8); fn f() { - // this is trying to use S from the 'use' line, but becuase the `u8` is + // this is trying to use S from the 'use' line, but because the `u8` is // not pub, it is private ::S; } @@ -103,7 +103,7 @@ This warning can always be fixed by removing the unused pattern in the ## mutable-transmutes -This lint catches transmuting from `&T` to `&mut T` becuase it is undefined +This lint catches transmuting from `&T` to `&mut T` because it is undefined behavior. Some example code that triggers this lint: ```rust,ignore 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 b49708ff6a..de76ddf33c 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -603,11 +603,11 @@ fn foo() { This will produce: ```text -warning: function cannot return without recurring +warning: function cannot return without recursing --> src/main.rs:1:1 | 1 | fn foo() { - | ^^^^^^^^ cannot return without recurring + | ^^^^^^^^ cannot return without recursing 2 | foo(); | ----- recursive call site | diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 417608cc5c..aba485f752 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -345,3 +345,17 @@ $ rustdoc src/lib.rs --sysroot /path/to/sysroot Similar to `rustc --sysroot`, this lets you change the sysroot `rustdoc` uses when compiling your code. + +### `--edition`: control the edition of docs and doctests + +Using this flag looks like this: + +```bash +$ 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 +the given edition as well. As with `rustc`, the default edition that `rustdoc` will use is `2015` +(the first edition). + diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 7f110d6a3d..071575b1fc 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -1,6 +1,6 @@ # Unstable features -Rustdoc is under active developement, and like the Rust compiler, some features are only available +Rustdoc is under active development, and like the Rust compiler, some features are only available on the nightly releases. Some of these are new and need some more testing before they're able to get released to the world at large, and some of them are tied to features in the Rust compiler that are themselves unstable. Several features here require a matching `#![feature(...)]` attribute to @@ -106,27 +106,25 @@ The `#[doc(cfg(...))]` attribute has another effect: When Rustdoc renders docume item, it will be accompanied by a banner explaining that the item is only available on certain platforms. -As mentioned earlier, getting the items to Rustdoc requires some extra preparation. The standard -library adds a `--cfg dox` flag to every Rustdoc command, but the same thing can be accomplished by -adding a feature to your Cargo.toml and adding `--feature dox` (or whatever you choose to name the -feature) to your `cargo doc` calls. +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. +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. -Either way, once you create an environment for the documentation, you can start to augment your -`#[cfg]` attributes to allow both the target platform *and* the documentation configuration to leave -the item in. For example, `#[cfg(any(windows, feature = "dox"))]` 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: +For example, `#[cfg(any(windows, rustdoc))]` 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: ```rust #![feature(doc_cfg)] /// Token struct that can only be used on Windows. -#[cfg(any(windows, feature = "dox"))] +#[cfg(any(windows, rustdoc))] #[doc(cfg(windows))] pub struct WindowsToken; /// Token struct that can only be used on Unix. -#[cfg(any(unix, feature = "dox"))] +#[cfg(any(unix, rustdoc))] #[doc(cfg(unix))] pub struct UnixToken; ``` @@ -348,18 +346,20 @@ details. [issue-display-warnings]: https://github.com/rust-lang/rust/issues/41574 -### `--edition`: control the edition of docs and doctests +### `--extern-html-root-url`: control how rustdoc links to non-local crates Using this flag looks like this: ```bash -$ rustdoc src/lib.rs -Z unstable-options --edition 2018 -$ rustdoc --test src/lib.rs -Z unstable-options --edition 2018 +$ rustdoc src/lib.rs -Z unstable-options --extern-html-root-url some-crate=https://example.com/some-crate/1.0.1 ``` -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). +Ordinarily, when rustdoc wants to link to a type from a different crate, it looks in two places: +docs that already exist in the output directory, or the `#![doc(doc_html_root)]` set in the other +crate. However, if you want to link to docs that exist in neither of those places, you can use these +flags to control that behavior. When the `--extern-html-root-url` flag is given with a name matching +one of your dependencies, rustdoc use that URL for those docs. Keep in mind that if those docs exist +in the output directory, those local docs will still override this flag. ### `-Z force-unstable-if-unmarked` diff --git a/src/doc/unstable-book/src/language-features/attr-literals.md b/src/doc/unstable-book/src/language-features/attr-literals.md deleted file mode 100644 index 6606f3c4e5..0000000000 --- a/src/doc/unstable-book/src/language-features/attr-literals.md +++ /dev/null @@ -1,30 +0,0 @@ -# `attr_literals` - -The tracking issue for this feature is: [#34981] - -[#34981]: https://github.com/rust-lang/rust/issues/34981 - ------------------------- - -At present, literals are only accepted as the value of a key-value pair in -attributes. What's more, only _string_ literals are accepted. This means that -literals can only appear in forms of `#[attr(name = "value")]` or -`#[attr = "value"]`. - -The `attr_literals` unstable feature allows other types of literals to be used -in attributes. Here are some examples of attributes that can now be used with -this feature enabled: - -```rust,ignore -#[attr] -#[attr(true)] -#[attr(ident)] -#[attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))] -#[attr(100)] -#[attr(enabled = true)] -#[enabled(true)] -#[attr("hello")] -#[repr(C, align = 4)] -#[repr(C, align(4))] -``` - diff --git a/src/doc/unstable-book/src/language-features/catch-expr.md b/src/doc/unstable-book/src/language-features/catch-expr.md deleted file mode 100644 index 247333d841..0000000000 --- a/src/doc/unstable-book/src/language-features/catch-expr.md +++ /dev/null @@ -1,30 +0,0 @@ -# `catch_expr` - -The tracking issue for this feature is: [#31436] - -[#31436]: https://github.com/rust-lang/rust/issues/31436 - ------------------------- - -The `catch_expr` feature adds support for a `catch` expression. The `catch` -expression creates a new scope one can use the `?` operator in. - -```rust -#![feature(catch_expr)] - -use std::num::ParseIntError; - -let result: Result = do catch { - "1".parse::()? - + "2".parse::()? - + "3".parse::()? -}; -assert_eq!(result, Ok(6)); - -let result: Result = do catch { - "1".parse::()? - + "foo".parse::()? - + "3".parse::()? -}; -assert!(result.is_err()); -``` diff --git a/src/doc/unstable-book/src/language-features/crate-in-paths.md b/src/doc/unstable-book/src/language-features/crate-in-paths.md deleted file mode 100644 index f1656993e8..0000000000 --- a/src/doc/unstable-book/src/language-features/crate-in-paths.md +++ /dev/null @@ -1,54 +0,0 @@ -# `crate_in_paths` - -The tracking issue for this feature is: [#44660] - -[#44660]: https://github.com/rust-lang/rust/issues/44660 - ------------------------- - -The `crate_in_paths` feature allows to explicitly refer to the crate root in absolute paths -using keyword `crate`. - -`crate` can be used *only* in absolute paths, i.e. either in `::crate::a::b::c` form or in `use` -items where the starting `::` is added implicitly. -Paths like `crate::a::b::c` are not accepted currently. - -This feature is required in `feature(extern_absolute_paths)` mode to refer to any absolute path -in the local crate (absolute paths refer to extern crates by default in that mode), but can be -used without `feature(extern_absolute_paths)` as well. - -```rust -#![feature(crate_in_paths)] - -// Imports, `::` is added implicitly -use crate::m::f; -use crate as root; - -mod m { - pub fn f() -> u8 { 1 } - pub fn g() -> u8 { 2 } - pub fn h() -> u8 { 3 } - - // OK, visibilities implicitly add starting `::` as well, like imports - pub(in crate::m) struct S; -} - -mod n -{ - use crate::m::f; - use crate as root; - pub fn check() { - assert_eq!(f(), 1); - // `::` is required in non-import paths - assert_eq!(::crate::m::g(), 2); - assert_eq!(root::m::h(), 3); - } -} - -fn main() { - assert_eq!(f(), 1); - assert_eq!(::crate::m::g(), 2); - assert_eq!(root::m::h(), 3); - n::check(); -} -``` diff --git a/src/doc/unstable-book/src/language-features/custom-test-frameworks.md b/src/doc/unstable-book/src/language-features/custom-test-frameworks.md new file mode 100644 index 0000000000..3990b6ad2f --- /dev/null +++ b/src/doc/unstable-book/src/language-features/custom-test-frameworks.md @@ -0,0 +1,33 @@ +# `custom_test_frameworks` + +The tracking issue for this feature is: [#50297] + +[#50297]: https://github.com/rust-lang/rust/issues/50297 + +------------------------ + +The `custom_test_frameworks` feature allows the use of `#[test_case]` and `#![test_runner]`. +Any function, const, or static can be annotated with `#[test_case]` causing it to be aggregated (like `#[test]`) +and be passed to the test runner determined by the `#![test_runner]` crate attribute. + +```rust +#![feature(custom_test_frameworks)] +#![test_runner(my_runner)] + +fn my_runner(tests: &[&i32]) { + for t in tests { + if **t == 0 { + println!("PASSED"); + } else { + println!("FAILED"); + } + } +} + +#[test_case] +const WILL_PASS: i32 = 0; + +#[test_case] +const WILL_FAIL: i32 = 4; +``` + 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 ddc538e121..96c66a1515 100644 --- a/src/doc/unstable-book/src/language-features/doc-cfg.md +++ b/src/doc/unstable-book/src/language-features/doc-cfg.md @@ -12,13 +12,17 @@ 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 +crate. + This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the standard library be documented. ```rust #![feature(doc_cfg)] -#[cfg(any(windows, feature = "documentation"))] +#[cfg(any(windows, rustdoc))] #[doc(cfg(windows))] /// The application's icon in the notification area (a.k.a. system tray). /// @@ -39,4 +43,4 @@ pub struct Icon { ``` [#43781]: https://github.com/rust-lang/rust/issues/43781 -[#43348]: https://github.com/rust-lang/rust/issues/43348 \ No newline at end of file +[#43348]: https://github.com/rust-lang/rust/issues/43348 diff --git a/src/doc/unstable-book/src/language-features/extern-absolute-paths.md b/src/doc/unstable-book/src/language-features/extern-absolute-paths.md deleted file mode 100644 index f45c5053e8..0000000000 --- a/src/doc/unstable-book/src/language-features/extern-absolute-paths.md +++ /dev/null @@ -1,43 +0,0 @@ -# `extern_absolute_paths` - -The tracking issue for this feature is: [#44660] - -[#44660]: https://github.com/rust-lang/rust/issues/44660 - ------------------------- - -The `extern_absolute_paths` feature enables mode allowing to refer to names from other crates -"inline", without introducing `extern crate` items, using absolute paths like `::my_crate::a::b`. - -`::my_crate::a::b` will resolve to path `a::b` in crate `my_crate`. - -`feature(crate_in_paths)` can be used in `feature(extern_absolute_paths)` mode for referring -to absolute paths in the local crate (`::crate::a::b`). - -`feature(extern_in_paths)` provides the same effect by using keyword `extern` to refer to -paths from other crates (`extern::my_crate::a::b`). - -```rust,ignore -#![feature(extern_absolute_paths)] - -// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern` -// options, or standard Rust distribution, or some other means. - -use xcrate::Z; - -fn f() { - use xcrate; - use xcrate as ycrate; - let s = xcrate::S; - assert_eq!(format!("{:?}", s), "S"); - let z = ycrate::Z; - assert_eq!(format!("{:?}", z), "Z"); -} - -fn main() { - let s = ::xcrate::S; - assert_eq!(format!("{:?}", s), "S"); - let z = Z; - assert_eq!(format!("{:?}", z), "Z"); -} -``` diff --git a/src/doc/unstable-book/src/language-features/infer-outlives-requirements.md b/src/doc/unstable-book/src/language-features/infer-outlives-requirements.md deleted file mode 100644 index 73c7eafdb9..0000000000 --- a/src/doc/unstable-book/src/language-features/infer-outlives-requirements.md +++ /dev/null @@ -1,67 +0,0 @@ -# `infer_outlives_requirements` - -The tracking issue for this feature is: [#44493] - -[#44493]: https://github.com/rust-lang/rust/issues/44493 - ------------------------- -The `infer_outlives_requirements` feature indicates that certain -outlives requirements can be infered by the compiler rather than -stating them explicitly. - -For example, currently generic struct definitions that contain -references, require where-clauses of the form T: 'a. By using -this feature the outlives predicates will be infered, although -they may still be written explicitly. - -```rust,ignore (pseudo-Rust) -struct Foo<'a, T> - where T: 'a // <-- currently required - { - bar: &'a T, - } -``` - - -## Examples: - - -```rust,ignore (pseudo-Rust) -#![feature(infer_outlives_requirements)] - -// Implicitly infer T: 'a -struct Foo<'a, T> { - bar: &'a T, -} -``` - -```rust,ignore (pseudo-Rust) -#![feature(infer_outlives_requirements)] - -// Implicitly infer `U: 'b` -struct Foo<'b, U> { - bar: Bar<'b, U> -} - -struct Bar<'a, T> where T: 'a { - x: &'a (), - y: T, -} -``` - -```rust,ignore (pseudo-Rust) -#![feature(infer_outlives_requirements)] - -// Implicitly infer `b': 'a` -struct Foo<'a, 'b, T> { - x: &'a &'b T -} -``` - -```rust,ignore (pseudo-Rust) -#![feature(infer_outlives_requirements)] - -// Implicitly infer `::Item : 'a` -struct Foo<'a, T: Iterator> { - bar: &'a T::Item -``` diff --git a/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md b/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md index f50472fb41..6187f395b0 100644 --- a/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md +++ b/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md @@ -6,7 +6,7 @@ The tracking issue for this feature is: [#44493] ------------------------ The `infer_static_outlives_requirements` feature indicates that certain -`'static` outlives requirements can be infered by the compiler rather than +`'static` outlives requirements can be inferred by the compiler rather than stating them explicitly. Note: It is an accompanying feature to `infer_outlives_requirements`, @@ -14,7 +14,7 @@ which must be enabled to infer outlives requirements. For example, currently generic struct definitions that contain references, require where-clauses of the form T: 'static. By using -this feature the outlives predicates will be infered, although +this feature the outlives predicates will be inferred, although they may still be written explicitly. ```rust,ignore (pseudo-Rust) diff --git a/src/doc/unstable-book/src/language-features/macro-vis-matcher.md b/src/doc/unstable-book/src/language-features/macro-vis-matcher.md deleted file mode 100644 index 7918a35684..0000000000 --- a/src/doc/unstable-book/src/language-features/macro-vis-matcher.md +++ /dev/null @@ -1,14 +0,0 @@ -# `macro_vis_matcher` - -The tracking issue for this feature is: [#41022] - -With this feature gate enabled, the [list of fragment specifiers][frags] gains one more entry: - -* `vis`: a visibility qualifier. Examples: nothing (default visibility); `pub`; `pub(crate)`. - -A `vis` variable may be followed by a comma, ident, type, or path. - -[#41022]: https://github.com/rust-lang/rust/issues/41022 -[frags]: ../book/first-edition/macros.html#syntactic-requirements - ------------------------- diff --git a/src/doc/unstable-book/src/language-features/on-unimplemented.md b/src/doc/unstable-book/src/language-features/on-unimplemented.md index 70c7c110b7..f787f62975 100644 --- a/src/doc/unstable-book/src/language-features/on-unimplemented.md +++ b/src/doc/unstable-book/src/language-features/on-unimplemented.md @@ -8,7 +8,9 @@ The tracking issue for this feature is: [#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. +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: @@ -41,7 +43,98 @@ error[E0277]: the trait bound `&[{integer}]: MyIterator` is not satisfied | = 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`: -error: aborting due to previous error + - `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. + +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` +``` diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 19ece09509..b408d5d080 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -183,7 +183,6 @@ that warns about any item named `lintme`. ```rust,ignore #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -#![feature(macro_vis_matcher)] #![feature(macro_at_most_once_rep)] extern crate syntax; diff --git a/src/doc/unstable-book/src/language-features/self-in-typedefs.md b/src/doc/unstable-book/src/language-features/self-in-typedefs.md new file mode 100644 index 0000000000..2416e85c17 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/self-in-typedefs.md @@ -0,0 +1,24 @@ +# `self_in_typedefs` + +The tracking issue for this feature is: [#49303] + +[#49303]: https://github.com/rust-lang/rust/issues/49303 + +------------------------ + +The `self_in_typedefs` feature gate lets you use the special `Self` identifier +in `struct`, `enum`, and `union` type definitions. + +A simple example is: + +```rust +#![feature(self_in_typedefs)] + +enum List +where + Self: PartialOrd // can write `Self` instead of `List` +{ + Nil, + Cons(T, Box) // likewise here +} +``` diff --git a/src/doc/unstable-book/src/language-features/self-struct-ctor.md b/src/doc/unstable-book/src/language-features/self-struct-ctor.md new file mode 100644 index 0000000000..b4742c48a3 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/self-struct-ctor.md @@ -0,0 +1,33 @@ +# `self_struct_ctor` + +The tracking issue for this feature is: [#51994] +[#51994]: https://github.com/rust-lang/rust/issues/51994 + +------------------------ + +The `self_struct_ctor` feature gate lets you use the special `Self` +identifier as a constructor and a pattern. + +A simple example is: + +```rust +#![feature(self_struct_ctor)] + +struct ST(i32, i32); + +impl ST { + fn new() -> Self { + ST(0, 1) + } + + fn ctor() -> Self { + Self(1,2) // constructed by `Self`, it is the same as `ST(1, 2)` + } + + fn pattern(self) { + match self { + Self(x, y) => println!("{} {}", x, y), // used as a pattern + } + } +} +``` diff --git a/src/doc/unstable-book/src/language-features/tool-attributes.md b/src/doc/unstable-book/src/language-features/tool-attributes.md deleted file mode 100644 index 15fc84a3e2..0000000000 --- a/src/doc/unstable-book/src/language-features/tool-attributes.md +++ /dev/null @@ -1,26 +0,0 @@ -# `tool_attributes` - -The tracking issue for this feature is: [#44690] - -[#44690]: https://github.com/rust-lang/rust/issues/44690 - ------------------------- - -Tool attributes let you use scoped attributes to control the behavior -of certain tools. - -Currently tool names which can be appear in scoped attributes are restricted to -`clippy` and `rustfmt`. - -## An example - -```rust -#![feature(tool_attributes)] - -#[rustfmt::skip] -fn foo() { println!("hello, world"); } - -fn main() { - foo(); -} -``` diff --git a/src/doc/unstable-book/src/language-features/try-blocks.md b/src/doc/unstable-book/src/language-features/try-blocks.md new file mode 100644 index 0000000000..866b37a39a --- /dev/null +++ b/src/doc/unstable-book/src/language-features/try-blocks.md @@ -0,0 +1,32 @@ +# `try_blocks` + +The tracking issue for this feature is: [#31436] + +[#31436]: https://github.com/rust-lang/rust/issues/31436 + +------------------------ + +The `try_blocks` feature adds support for `try` blocks. A `try` +block creates a new scope one can use the `?` operator in. + +```rust,ignore +// This code needs the 2018 edition + +#![feature(try_blocks)] + +use std::num::ParseIntError; + +let result: Result = try { + "1".parse::()? + + "2".parse::()? + + "3".parse::()? +}; +assert_eq!(result, Ok(6)); + +let result: Result = try { + "1".parse::()? + + "foo".parse::()? + + "3".parse::()? +}; +assert!(result.is_err()); +``` diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md new file mode 100644 index 0000000000..7a5fe5b7f2 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/unsized-locals.md @@ -0,0 +1,180 @@ +# `unsized_locals` + +The tracking issue for this feature is: [#48055] + +[#48055]: https://github.com/rust-lang/rust/issues/48055 + +------------------------ + +This implements [RFC1909]. When turned on, you can have unsized arguments and locals: + +[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-coercions.md + +```rust +#![feature(unsized_locals)] + +use std::any::Any; + +fn main() { + let x: Box = Box::new(42); + let x: dyn Any = *x; + // ^ unsized local variable + // ^^ unsized temporary + foo(x); +} + +fn foo(_: dyn Any) {} +// ^^^^^^ unsized argument +``` + +The RFC still forbids the following unsized expressions: + +```rust,ignore +#![feature(unsized_locals)] + +use std::any::Any; + +struct MyStruct { + content: T, +} + +struct MyTupleStruct(T); + +fn answer() -> Box { + Box::new(42) +} + +fn main() { + // You CANNOT have unsized statics. + static X: dyn Any = *answer(); // ERROR + const Y: dyn Any = *answer(); // ERROR + + // You CANNOT have struct initialized unsized. + MyStruct { content: *answer() }; // ERROR + MyTupleStruct(*answer()); // ERROR + (42, *answer()); // ERROR + + // You CANNOT have unsized return types. + fn my_function() -> dyn Any { *answer() } // ERROR + + // You CAN have unsized local variables... + let mut x: dyn Any = *answer(); // OK + // ...but you CANNOT reassign to them. + x = *answer(); // ERROR + + // You CANNOT even initialize them separately. + let y: dyn Any; // OK + y = *answer(); // ERROR + + // Not mentioned in the RFC, but by-move captured variables are also Sized. + let x: dyn Any = *answer(); + (move || { // ERROR + let y = x; + })(); + + // You CAN create a closure with unsized arguments, + // but you CANNOT call it. + // This is an implementation detail and may be changed in the future. + let f = |x: dyn Any| {}; + f(*answer()); // ERROR +} +``` + +However, the current implementation allows `MyTupleStruct(..)` to be unsized. This will be fixed in the future. + +## By-value trait objects + +With this feature, you can have by-value `self` arguments without `Self: Sized` bounds. + +```rust +#![feature(unsized_locals)] + +trait Foo { + fn foo(self) {} +} + +impl Foo for T {} + +fn main() { + let slice: Box<[i32]> = Box::new([1, 2, 3]); + <[i32] as Foo>::foo(*slice); +} +``` + +And `Foo` will also be object-safe. However, this object-safety is not yet implemented. + +```rust,ignore +#![feature(unsized_locals)] + +trait Foo { + fn foo(self) {} +} + +impl Foo for T {} + +fn main () { + let slice: Box = Box::new([1, 2, 3]); + // doesn't compile yet + ::foo(*slice); +} +``` + +Unfortunately, this is not implemented yet. + +One of the objectives of this feature is to allow `Box`, instead of `Box` in the future. See [#28796] for details. + +[#28796]: https://github.com/rust-lang/rust/issues/28796 + +## Variable length arrays + +The RFC also describes an extension to the array literal syntax: `[e; dyn n]`. In the syntax, `n` isn't necessarily a constant expression. The array is dynamically allocated on the stack and has the type of `[T]`, instead of `[T; n]`. + +```rust,ignore +#![feature(unsized_locals)] + +fn mergesort(a: &mut [T]) { + let mut tmp = [T; dyn a.len()]; + // ... +} + +fn main() { + let mut a = [3, 1, 5, 6]; + mergesort(&mut a); + assert_eq!(a, [1, 3, 5, 6]); +} +``` + +VLAs are not implemented yet. The syntax isn't final, either. We may need an alternative syntax for Rust 2015 because, in Rust 2015, expressions like `[e; dyn(1)]` would be ambiguous. One possible alternative proposed in the RFC is `[e; n]`: if `n` captures one or more local variables, then it is considered as `[e; dyn n]`. + +## Advisory on stack usage + +It's advised not to casually use the `#![feature(unsized_locals)]` feature. Typical use-cases are: + +- When you need a by-value trait objects. +- When you really need a fast allocation of small temporary arrays. + +Another pitfall is repetitive allocation and temporaries. Currently the compiler simply extends the stack frame every time it encounters an unsized assignment. So for example, the code + +```rust +#![feature(unsized_locals)] + +fn main() { + let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]); + let _x = {{{{{{{{{{*x}}}}}}}}}}; +} +``` + +and the code + +```rust +#![feature(unsized_locals)] + +fn main() { + for _ in 0..10 { + let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]); + let _x = *x; + } +} +``` + +will unnecessarily extend the stack frame. diff --git a/src/doc/unstable-book/src/language-features/used.md b/src/doc/unstable-book/src/language-features/used.md deleted file mode 100644 index c3b7f2e41e..0000000000 --- a/src/doc/unstable-book/src/language-features/used.md +++ /dev/null @@ -1,157 +0,0 @@ -# `used` - -The tracking issue for this feature -is: [40289](https://github.com/rust-lang/rust/issues/40289). - ------------------------- - -The `#[used]` attribute can be applied to `static` variables to prevent the Rust -compiler from optimizing them away even if they appear to be unused by the crate -(appear to be "dead code"). - -``` rust -#![feature(used)] - -#[used] -static FOO: i32 = 1; - -static BAR: i32 = 2; - -fn main() {} -``` - -If you compile this program into an object file, you'll see that `FOO` makes it -to the object file but `BAR` doesn't. Neither static variable is used by the -program. - -``` text -$ rustc -C opt-level=3 --emit=obj used.rs - -$ nm -C used.o -0000000000000000 T main - U std::rt::lang_start -0000000000000000 r used::FOO -0000000000000000 t used::main -``` - -Note that the *linker* knows nothing about the `#[used]` attribute and will -remove `#[used]` symbols if they are not referenced by other parts of the -program: - -``` text -$ rustc -C opt-level=3 used.rs - -$ nm -C used | grep FOO -``` - -"This doesn't sound too useful then!" you may think but keep reading. - -To preserve the symbols all the way to the final binary, you'll need the -cooperation of the linker. Here's one example: - -The ELF standard defines two special sections, `.init_array` and -`.pre_init_array`, that may contain function pointers which will be executed -*before* the `main` function is invoked. The linker will preserve symbols placed -in these sections (at least when linking programs that target the `*-*-linux-*` -targets). - -``` rust,ignore -#![feature(used)] - -extern "C" fn before_main() { - println!("Hello, world!"); -} - -#[link_section = ".init_array"] -#[used] -static INIT_ARRAY: [extern "C" fn(); 1] = [before_main]; - -fn main() {} -``` - -So, `#[used]` and `#[link_section]` can be combined to obtain "life before -main". - -``` text -$ rustc -C opt-level=3 before-main.rs - -$ ./before-main -Hello, world! -``` - -Another example: ARM Cortex-M microcontrollers need their reset handler, a -pointer to the function that will executed right after the microcontroller is -turned on, to be placed near the start of their FLASH memory to boot properly. - -This condition can be met using `#[used]` and `#[link_section]` plus a linker -script. - -``` rust,ignore -#![feature(panic_implementation)] -#![feature(used)] -#![no_main] -#![no_std] - -use core::panic::PanicInfo; - -extern "C" fn reset_handler() -> ! { - loop {} -} - -#[link_section = ".reset_handler"] -#[used] -static RESET_HANDLER: extern "C" fn() -> ! = reset_handler; - -#[panic_implementation] -fn panic_impl(info: &PanicInfo) -> ! { - loop {} -} -``` - -``` text -MEMORY -{ - FLASH : ORIGIN = 0x08000000, LENGTH = 128K - RAM : ORIGIN = 0x20000000, LENGTH = 20K -} - -SECTIONS -{ - .text ORIGIN(FLASH) : - { - /* Vector table */ - LONG(ORIGIN(RAM) + LENGTH(RAM)); /* initial SP value */ - KEEP(*(.reset_handler)); - - /* Omitted: The rest of the vector table */ - - *(.text.*); - } > FLASH - - /DISCARD/ : - { - /* Unused unwinding stuff */ - *(.ARM.exidx.*) - } -} -``` - -``` text -$ xargo rustc --target thumbv7m-none-eabi --release -- \ - -C link-arg=-Tlink.x -C link-arg=-nostartfiles - -$ arm-none-eabi-objdump -Cd target/thumbv7m-none-eabi/release/app -./target/thumbv7m-none-eabi/release/app: file format elf32-littlearm - - -Disassembly of section .text: - -08000000 : - 8000000: 20005000 .word 0x20005000 - -08000004 : - 8000004: 08000009 .... - -08000008 : - 8000008: e7fe b.n 8000008 -``` diff --git a/src/doc/unstable-book/src/library-features/future-atomic-orderings.md b/src/doc/unstable-book/src/library-features/future-atomic-orderings.md deleted file mode 100644 index 40c2ef2db0..0000000000 --- a/src/doc/unstable-book/src/library-features/future-atomic-orderings.md +++ /dev/null @@ -1,5 +0,0 @@ -# `future_atomic_orderings` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/io-error-internals.md b/src/doc/unstable-book/src/library-features/io-error-internals.md deleted file mode 100644 index 5bee18d33d..0000000000 --- a/src/doc/unstable-book/src/library-features/io-error-internals.md +++ /dev/null @@ -1,5 +0,0 @@ -# `io_error_internals` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py index 4a38d4be08..1797f6708a 100644 --- a/src/etc/debugger_pretty_printers_common.py +++ b/src/etc/debugger_pretty_printers_common.py @@ -47,6 +47,9 @@ TYPE_KIND_PTR = 15 TYPE_KIND_FIXED_SIZE_VEC = 16 TYPE_KIND_REGULAR_UNION = 17 TYPE_KIND_OS_STRING = 18 +TYPE_KIND_STD_VECDEQUE = 19 +TYPE_KIND_STD_BTREESET = 20 +TYPE_KIND_STD_BTREEMAP = 21 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$" ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR" @@ -62,6 +65,20 @@ STD_VEC_FIELD_NAME_BUF = "buf" STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF, STD_VEC_FIELD_NAME_LENGTH] +# std::collections::VecDeque<> related constants +STD_VECDEQUE_FIELD_NAME_TAIL = "tail" +STD_VECDEQUE_FIELD_NAME_HEAD = "head" +STD_VECDEQUE_FIELD_NAME_BUF = "buf" +STD_VECDEQUE_FIELD_NAMES = [STD_VECDEQUE_FIELD_NAME_TAIL, + STD_VECDEQUE_FIELD_NAME_HEAD, + STD_VECDEQUE_FIELD_NAME_BUF] + +# std::collections::BTreeSet<> related constants +STD_BTREESET_FIELD_NAMES = ["map"] + +# std::collections::BTreeMap<> related constants +STD_BTREEMAP_FIELD_NAMES = ["root", "length"] + # std::String related constants STD_STRING_FIELD_NAMES = ["vec"] @@ -161,6 +178,21 @@ class Type(object): self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)): return TYPE_KIND_STD_VEC + # STD COLLECTION VECDEQUE + if (unqualified_type_name.startswith("VecDeque<") and + self.__conforms_to_field_layout(STD_VECDEQUE_FIELD_NAMES)): + return TYPE_KIND_STD_VECDEQUE + + # STD COLLECTION BTREESET + if (unqualified_type_name.startswith("BTreeSet<") and + self.__conforms_to_field_layout(STD_BTREESET_FIELD_NAMES)): + return TYPE_KIND_STD_BTREESET + + # STD COLLECTION BTREEMAP + if (unqualified_type_name.startswith("BTreeMap<") and + self.__conforms_to_field_layout(STD_BTREEMAP_FIELD_NAMES)): + return TYPE_KIND_STD_BTREEMAP + # STD STRING if (unqualified_type_name.startswith("String") and self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)): @@ -325,6 +357,50 @@ def extract_length_ptr_and_cap_from_std_vec(vec_val): assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR return (length, data_ptr, capacity) + +def extract_tail_head_ptr_and_cap_from_std_vecdeque(vec_val): + assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VECDEQUE + tail_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_TAIL) + head_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_HEAD) + buf_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_BUF) + + tail = vec_val.get_child_at_index(tail_field_index).as_integer() + head = vec_val.get_child_at_index(head_field_index).as_integer() + buf = vec_val.get_child_at_index(buf_field_index) + + vec_ptr_val = buf.get_child_at_index(0) + capacity = buf.get_child_at_index(1).as_integer() + unique_ptr_val = vec_ptr_val.get_child_at_index(0) + data_ptr = unique_ptr_val.get_child_at_index(0) + assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR + return (tail, head, data_ptr, capacity) + + +def extract_length_and_ptr_from_std_btreeset(vec_val): + assert vec_val.type.get_type_kind() == TYPE_KIND_STD_BTREESET + map = vec_val.get_child_at_index(0) + root = map.get_child_at_index(0) + length = map.get_child_at_index(1).as_integer() + node = root.get_child_at_index(0) + ptr = node.get_child_at_index(0) + unique_ptr_val = ptr.get_child_at_index(0) + data_ptr = unique_ptr_val.get_child_at_index(0) + assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR + return (length, data_ptr) + + +def extract_length_and_ptr_from_std_btreemap(vec_val): + assert vec_val.type.get_type_kind() == TYPE_KIND_STD_BTREEMAP + root = vec_val.get_child_at_index(0) + length = vec_val.get_child_at_index(1).as_integer() + node = root.get_child_at_index(0) + ptr = node.get_child_at_index(0) + unique_ptr_val = ptr.get_child_at_index(0) + data_ptr = unique_ptr_val.get_child_at_index(0) + assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR + return (length, data_ptr) + + def extract_length_and_ptr_from_slice(slice_val): assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 0612873e28..216915dba5 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -124,6 +124,15 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_STD_VEC: return RustStdVecPrinter(val) + if type_kind == rustpp.TYPE_KIND_STD_VECDEQUE: + return RustStdVecDequePrinter(val) + + if type_kind == rustpp.TYPE_KIND_STD_BTREESET: + return RustStdBTreeSetPrinter(val) + + if type_kind == rustpp.TYPE_KIND_STD_BTREEMAP: + return RustStdBTreeMapPrinter(val) + if type_kind == rustpp.TYPE_KIND_STD_STRING: return RustStdStringPrinter(val) @@ -274,6 +283,77 @@ class RustStdVecPrinter(object): yield (str(index), (gdb_ptr + index).dereference()) +class RustStdVecDequePrinter(object): + def __init__(self, val): + self.__val = val + + @staticmethod + def display_hint(): + return "array" + + def to_string(self): + (tail, head, data_ptr, cap) = \ + rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val) + return (self.__val.type.get_unqualified_type_name() + + ("(len: %i, cap: %i)" % (head - tail, cap))) + + def children(self): + (tail, head, data_ptr, cap) = \ + rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val) + gdb_ptr = data_ptr.get_wrapped_value() + for index in xrange(tail, head): + yield (str(index), (gdb_ptr + index).dereference()) + + +class RustStdBTreeSetPrinter(object): + def __init__(self, val): + self.__val = val + + @staticmethod + def display_hint(): + return "array" + + def to_string(self): + (length, data_ptr) = \ + rustpp.extract_length_and_ptr_from_std_btreeset(self.__val) + return (self.__val.type.get_unqualified_type_name() + + ("(len: %i)" % length)) + + def children(self): + (length, data_ptr) = \ + rustpp.extract_length_and_ptr_from_std_btreeset(self.__val) + val = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3) + gdb_ptr = val.get_wrapped_value() + for index in xrange(length): + yield (str(index), gdb_ptr[index]) + + +class RustStdBTreeMapPrinter(object): + def __init__(self, val): + self.__val = val + + @staticmethod + def display_hint(): + return "map" + + def to_string(self): + (length, data_ptr) = \ + rustpp.extract_length_and_ptr_from_std_btreemap(self.__val) + return (self.__val.type.get_unqualified_type_name() + + ("(len: %i)" % length)) + + def children(self): + (length, data_ptr) = \ + rustpp.extract_length_and_ptr_from_std_btreemap(self.__val) + keys = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3) + keys_ptr = keys.get_wrapped_value() + vals = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(4) + vals_ptr = vals.get_wrapped_value() + for index in xrange(length): + yield (str(index), keys_ptr[index]) + yield (str(index), vals_ptr[index]) + + class RustStdStringPrinter(object): def __init__(self, val): self.__val = val @@ -287,6 +367,7 @@ class RustStdStringPrinter(object): def display_hint(self): return "string" + class RustOsStringPrinter(object): def __init__(self, val): self.__val = val diff --git a/src/etc/rust-gdb b/src/etc/rust-gdb index 6835d6aa90..743952a5be 100755 --- a/src/etc/rust-gdb +++ b/src/etc/rust-gdb @@ -20,7 +20,7 @@ GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc" # Set the environment variable `RUST_GDB` to overwrite the call to a # different/specific command (defaults to `gdb`). RUST_GDB="${RUST_GDB:-gdb}" -PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" ${RUST_GDB} \ +PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" exec ${RUST_GDB} \ --directory="$GDB_PYTHON_MODULE_DIRECTORY" \ -iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \ "$@" diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui new file mode 100755 index 0000000000..7e179ba927 --- /dev/null +++ b/src/etc/rust-gdbgui @@ -0,0 +1,65 @@ +#!/bin/sh +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# Exit if anything fails +set -e + +if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ]; then + echo " +rust-gdbgui +=========== +gdbgui - https://gdbgui.com - is a graphical front-end to GDB +that runs in a browser. This script invokes gdbgui with the Rust +pretty printers loaded. + +Simple usage : rust-gdbgui target/debug/myprog +With arguments: rust-gdbgui 'target/debug/myprog arg1 arg2...' + (note the quotes) + + +Hints +===== +gdbgui won't be able to find the rust 'main' method automatically, so +in its options make sure to disable the 'Add breakpoint to main after +loading executable' setting to avoid a 'File not found: main' warning +on startup. + +Instead, type 'main' into gdbgui's file browser and you should get +auto-completion on the filename. Just pick 'main.rs', add a breakpoint +by clicking in the line number gutter, and type 'r' or hit the Restart +icon to start your program running. +" + exit 0 +fi + +# Find out where the pretty printer Python module is +RUSTC_SYSROOT=`rustc --print=sysroot` +GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc" + +# Set the environment variable `RUST_GDB` to overwrite the call to a +# different/specific command (defaults to `gdb`). +RUST_GDB="${RUST_GDB:-gdb}" + +# Set the environment variable `RUST_GDBGUI` to overwrite the call to a +# different/specific command (defaults to `gdbgui`). +RUST_GDBGUI="${RUST_GDBGUI:-gdbgui}" + +# These arguments get passed through to GDB and make it load the +# Rust pretty printers. +GDB_ARGS="--directory=\"$GDB_PYTHON_MODULE_DIRECTORY\" -iex \"add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY\"" + +# Finally we execute gdbgui. +PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" \ + exec ${RUST_GDBGUI} \ + --gdb ${RUST_GDB} \ + --gdb-args "${GDB_ARGS}" \ + "${@}" + diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb index f70ab65bce..6ed8210349 100755 --- a/src/etc/rust-lldb +++ b/src/etc/rust-lldb @@ -12,30 +12,35 @@ # Exit if anything fails set -e -LLDB_VERSION=`lldb --version 2>/dev/null | head -1 | cut -d. -f1` +# Find out where to look for the pretty printer Python module +RUSTC_SYSROOT=`rustc --print sysroot` + +# Find the host triple so we can find lldb in rustlib. +host=`rustc -vV | sed -n -e 's/^host: //p'` -if [ "$LLDB_VERSION" = "lldb-350" ] -then - echo "***" +lldb=lldb +if [ -f "$RUSTC_SYSROOT/lib/rustlib/$host/bin/lldb" ]; then + lldb="$RUSTC_SYSROOT/lib/rustlib/$host/bin/lldb" +else + LLDB_VERSION=`"$lldb" --version 2>/dev/null | head -1 | cut -d. -f1` + + if [ "$LLDB_VERSION" = "lldb-350" ] + then + echo "***" echo \ "WARNING: This version of LLDB has known issues with Rust and cannot \ display the contents of local variables!" - echo "***" + echo "***" + fi fi -# Create a tempfile containing the LLDB script we want to execute on startup -TMPFILE=`mktemp /tmp/rust-lldb-commands.XXXXXX` - -# Make sure to delete the tempfile no matter what -trap "rm -f $TMPFILE; exit" INT TERM EXIT - -# Find out where to look for the pretty printer Python module -RUSTC_SYSROOT=`rustc --print sysroot` - -# Write the LLDB script to the tempfile -echo "command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_rust_formatters.py\"" >> $TMPFILE -echo "type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust" >> $TMPFILE -echo "type category enable Rust" >> $TMPFILE +# Prepare commands that will be loaded before any file on the command line has been loaded +script_import="command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_rust_formatters.py\"" +category_definition="type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust" +category_enable="type category enable Rust" -# Call LLDB with the script added to the argument list -lldb --source-before-file="$TMPFILE" "$@" +# Call LLDB with the commands added to the argument list +exec "$lldb" --one-line-before-file="$script_import" \ + --one-line-before-file="$category_definition" \ + --one-line-before-file="$category_enable" \ + "$@" diff --git a/src/etc/test-float-parse/many-digits.rs b/src/etc/test-float-parse/many-digits.rs index 674c30ad84..469a38da2b 100644 --- a/src/etc/test-float-parse/many-digits.rs +++ b/src/etc/test-float-parse/many-digits.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rand)] - extern crate rand; mod _common; diff --git a/src/etc/test-float-parse/rand-f64.rs b/src/etc/test-float-parse/rand-f64.rs index 1d82912054..2994dd9d5e 100644 --- a/src/etc/test-float-parse/rand-f64.rs +++ b/src/etc/test-float-parse/rand-f64.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rand)] - extern crate rand; mod _common; diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index ada21e04b3..642a43d4d9 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -14,7 +14,7 @@ core = { path = "../libcore" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } [dev-dependencies] -rand = "0.4" +rand = "0.5" [[test]] name = "collectionstests" @@ -23,3 +23,8 @@ path = "../liballoc/tests/lib.rs" [[bench]] name = "collectionsbenches" path = "../liballoc/benches/lib.rs" + +[[bench]] +name = "vec_deque_append_bench" +path = "../liballoc/benches/vec_deque_append.rs" +harness = false diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 84bd275df3..3bd0c243b3 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -56,6 +56,22 @@ pub struct Global; /// # Safety /// /// See [`GlobalAlloc::alloc`]. +/// +/// # Examples +/// +/// ``` +/// use std::alloc::{alloc, dealloc, Layout}; +/// +/// unsafe { +/// let layout = Layout::new::(); +/// let ptr = alloc(layout); +/// +/// *(ptr as *mut u16) = 42; +/// assert_eq!(*(ptr as *mut u16), 42); +/// +/// dealloc(ptr, layout); +/// } +/// ``` #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn alloc(layout: Layout) -> *mut u8 { @@ -110,6 +126,21 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 /// # Safety /// /// See [`GlobalAlloc::alloc_zeroed`]. +/// +/// # Examples +/// +/// ``` +/// use std::alloc::{alloc_zeroed, dealloc, Layout}; +/// +/// unsafe { +/// let layout = Layout::new::(); +/// let ptr = alloc_zeroed(layout); +/// +/// assert_eq!(*(ptr as *mut u16), 0); +/// +/// dealloc(ptr, layout); +/// } +/// ``` #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { @@ -214,7 +245,7 @@ mod tests { .unwrap_or_else(|_| handle_alloc_error(layout)); let mut i = ptr.cast::().as_ptr(); - let end = i.offset(layout.size() as isize); + let end = i.add(layout.size()); while i < end { assert_eq!(*i, 0); i = i.offset(1); diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 4f69aa6670..b4f4fd74f3 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rand)] #![feature(repr_simd)] #![feature(slice_sort_by_cached_key)] #![feature(test)] diff --git a/src/liballoc/benches/vec_deque_append.rs b/src/liballoc/benches/vec_deque_append.rs new file mode 100644 index 0000000000..bd33565113 --- /dev/null +++ b/src/liballoc/benches/vec_deque_append.rs @@ -0,0 +1,48 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(duration_as_u128)] +use std::{collections::VecDeque, time::Instant}; + +const VECDEQUE_LEN: i32 = 100000; +const WARMUP_N: usize = 100; +const BENCH_N: usize = 1000; + +fn main() { + let a: VecDeque = (0..VECDEQUE_LEN).collect(); + let b: VecDeque = (0..VECDEQUE_LEN).collect(); + + for _ in 0..WARMUP_N { + let mut c = a.clone(); + let mut d = b.clone(); + c.append(&mut d); + } + + let mut durations = Vec::with_capacity(BENCH_N); + + for _ in 0..BENCH_N { + let mut c = a.clone(); + let mut d = b.clone(); + let before = Instant::now(); + c.append(&mut d); + let after = Instant::now(); + durations.push(after.duration_since(before)); + } + + let l = durations.len(); + durations.sort(); + + 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() + ); +} diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index c6741ddb82..5ae5339138 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -141,6 +141,41 @@ impl ToOwned for T /// let mut input = Cow::from(vec![-1, 0, 1]); /// abs_all(&mut input); /// ``` +/// +/// Another example showing how to keep `Cow` in a struct: +/// +/// ``` +/// use std::borrow::{Cow, ToOwned}; +/// +/// struct Items<'a, X: 'a> where [X]: ToOwned> { +/// values: Cow<'a, [X]>, +/// } +/// +/// impl<'a, X: Clone + 'a> Items<'a, X> where [X]: ToOwned> { +/// fn new(v: Cow<'a, [X]>) -> Self { +/// Items { values: v } +/// } +/// } +/// +/// // Creates a container from borrowed values of a slice +/// let readonly = [1, 2]; +/// let borrowed = Items::new((&readonly[..]).into()); +/// match borrowed { +/// Items { values: Cow::Borrowed(b) } => println!("borrowed {:?}", b), +/// _ => panic!("expect borrowed value"), +/// } +/// +/// let mut clone_on_write = borrowed; +/// // Mutates the data from slice into owned vec and pushes a new value on top +/// clone_on_write.values.to_mut().push(3); +/// println!("clone_on_write = {:?}", clone_on_write.values); +/// +/// // The data was mutated. Let check it out. +/// match clone_on_write { +/// Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"), +/// _ => panic!("expect owned data"), +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2cf9b13a67..29ba433bec 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -64,12 +64,14 @@ use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; use core::hash::{Hash, Hasher}; use core::iter::FusedIterator; use core::marker::{Unpin, Unsize}; -use core::mem::{self, PinMut}; +use core::mem; +use core::pin::PinMut; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; -use core::task::{Context, Poll, Executor, SpawnErrorKind, SpawnObjError}; +use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError}; use raw_vec::RawVec; +use pin::PinBox; use str::from_boxed_utf8_unchecked; /// A pointer type for heap allocation. @@ -126,7 +128,9 @@ impl Box { Box(Unique::new_unchecked(raw)) } - /// Consumes the `Box`, returning the wrapped raw pointer. + /// Consumes the `Box`, returning a wrapped raw pointer. + /// + /// The pointer will be properly aligned and non-null. /// /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the @@ -704,7 +708,7 @@ impl Clone for Box<[T]> { impl Drop for BoxBuilder { fn drop(&mut self) { let mut data = self.data.ptr(); - let max = unsafe { data.offset(self.len as isize) }; + let max = unsafe { data.add(self.len) }; while data != max { unsafe { @@ -745,6 +749,31 @@ impl AsMut for Box { } } +/* Nota bene + * + * We could have chosen not to add this impl, and instead have written a + * function of Pin> to Pin. Such a function would not be sound, + * because Box implements Unpin even when T does not, as a result of + * this impl. + * + * We chose this API instead of the alternative for a few reasons: + * - Logically, it is helpful to understand pinning in regard to the + * memory region being pointed to. For this reason none of the + * standard library pointer types support projecting through a pin + * (Box is the only pointer type in std for which this would be + * safe.) + * - It is in practice very useful to have Box be unconditionally + * Unpin because of trait objects, for which the structural auto + * trait functionality does not apply (e.g. Box would + * otherwise not be Unpin). + * + * Another type with the same semantics as Box but only a conditional + * implementation of `Unpin` (where `T: Unpin`) would be valid/safe, and + * could have a method to project a Pin from it. + */ +#[unstable(feature = "pin", issue = "49150")] +impl Unpin for Box { } + #[unstable(feature = "generator_trait", issue = "43122")] impl Generator for Box where T: Generator + ?Sized @@ -756,166 +785,6 @@ impl Generator for Box } } -/// A pinned, heap allocated reference. -#[unstable(feature = "pin", issue = "49150")] -#[fundamental] -#[repr(transparent)] -pub struct PinBox { - inner: Box, -} - -#[unstable(feature = "pin", issue = "49150")] -impl PinBox { - /// Allocate memory on the heap, move the data into it and pin it. - #[unstable(feature = "pin", issue = "49150")] - pub fn new(data: T) -> PinBox { - PinBox { inner: Box::new(data) } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl PinBox { - /// Get a pinned reference to the data in this PinBox. - #[inline] - pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> { - unsafe { PinMut::new_unchecked(&mut *self.inner) } - } - - /// Constructs a `PinBox` from a raw pointer. - /// - /// After calling this function, the raw pointer is owned by the - /// resulting `PinBox`. Specifically, the `PinBox` destructor will call - /// the destructor of `T` and free the allocated memory. Since the - /// way `PinBox` allocates and releases memory is unspecified, the - /// only valid pointer to pass to this function is the one taken - /// from another `PinBox` via the [`PinBox::into_raw`] function. - /// - /// This function is unsafe because improper use may lead to - /// memory problems. For example, a double-free may occur if the - /// function is called twice on the same raw pointer. - /// - /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(pin)] - /// use std::boxed::PinBox; - /// let x = PinBox::new(5); - /// let ptr = PinBox::into_raw(x); - /// let x = unsafe { PinBox::from_raw(ptr) }; - /// ``` - #[inline] - pub unsafe fn from_raw(raw: *mut T) -> Self { - PinBox { inner: Box::from_raw(raw) } - } - - /// Consumes the `PinBox`, returning the wrapped raw pointer. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `PinBox`. In particular, the - /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `PinBox` with the [`PinBox::from_raw`] function. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(pin)] - /// use std::boxed::PinBox; - /// let x = PinBox::new(5); - /// let ptr = PinBox::into_raw(x); - /// ``` - #[inline] - pub fn into_raw(b: PinBox) -> *mut T { - Box::into_raw(b.inner) - } - - /// Get a mutable reference to the data inside this PinBox. - /// - /// This function is unsafe. Users must guarantee that the data is never - /// moved out of this reference. - #[inline] - pub unsafe fn get_mut<'a>(this: &'a mut PinBox) -> &'a mut T { - &mut *this.inner - } - - /// Convert this PinBox into an unpinned Box. - /// - /// This function is unsafe. Users must guarantee that the data is never - /// moved out of the box. - #[inline] - pub unsafe fn unpin(this: PinBox) -> Box { - this.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl From> for PinBox { - fn from(boxed: Box) -> PinBox { - PinBox { inner: boxed } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl From> for Box { - fn from(pinned: PinBox) -> Box { - pinned.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl Deref for PinBox { - type Target = T; - - fn deref(&self) -> &T { - &*self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl DerefMut for PinBox { - fn deref_mut(&mut self) -> &mut T { - &mut *self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Display for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Debug for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Pointer for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // It's not possible to extract the inner Uniq directly from the Box, - // instead we cast it to a *const which aliases the Unique - let ptr: *const T = &*self.inner; - fmt::Pointer::fmt(&ptr, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl, U: ?Sized> CoerceUnsized> for PinBox {} - -#[unstable(feature = "pin", issue = "49150")] -impl Unpin for PinBox {} - #[unstable(feature = "futures_api", issue = "50547")] impl Future for Box { type Output = F::Output; @@ -925,15 +794,6 @@ impl Future for Box { } } -#[unstable(feature = "futures_api", issue = "50547")] -impl Future for PinBox { - type Output = F::Output; - - fn poll(mut self: PinMut, cx: &mut Context) -> Poll { - self.as_pin_mut().poll(cx) - } -} - #[unstable(feature = "futures_api", issue = "50547")] unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box where F: Future + 'a @@ -954,30 +814,14 @@ unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box } #[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox - where F: Future + 'a -{ - fn into_raw(self) -> *mut () { - PinBox::into_raw(self) as *mut () - } - - unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - let ptr = ptr as *mut F; - let pin: PinMut = PinMut::new_unchecked(&mut *ptr); - pin.poll(cx) - } - - unsafe fn drop(ptr: *mut ()) { - drop(PinBox::from_raw(ptr as *mut F)) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -impl Executor for Box - where E: Executor + ?Sized +impl Spawn for Box + where Sp: Spawn + ?Sized { - fn spawn_obj(&mut self, task: FutureObj<'static, ()>) -> Result<(), SpawnObjError> { - (**self).spawn_obj(task) + fn spawn_obj( + &mut self, + future: FutureObj<'static, ()>, + ) -> Result<(), SpawnObjError> { + (**self).spawn_obj(future) } fn status(&self) -> Result<(), SpawnErrorKind> { @@ -985,13 +829,6 @@ impl Executor for Box } } -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { - fn from(boxed: PinBox) -> Self { - FutureObj::new(boxed) - } -} - #[unstable(feature = "futures_api", issue = "50547")] impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { fn from(boxed: Box) -> Self { @@ -1000,15 +837,15 @@ impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> } #[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { - fn from(boxed: PinBox) -> Self { +impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { + fn from(boxed: Box) -> Self { LocalFutureObj::new(boxed) } } -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { - fn from(boxed: Box) -> Self { - LocalFutureObj::new(boxed) +#[unstable(feature = "pin", issue = "49150")] +impl From> for Box { + fn from(pinned: PinBox) -> Box { + unsafe { PinBox::unpin(pinned) } } } diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 0ae45b3123..0315545262 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -1151,12 +1151,12 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> let new_len = self.node.len() - self.idx - 1; ptr::copy_nonoverlapping( - self.node.keys().as_ptr().offset(self.idx as isize + 1), + self.node.keys().as_ptr().add(self.idx + 1), new_node.keys.as_mut_ptr(), new_len ); ptr::copy_nonoverlapping( - self.node.vals().as_ptr().offset(self.idx as isize + 1), + self.node.vals().as_ptr().add(self.idx + 1), new_node.vals.as_mut_ptr(), new_len ); @@ -1209,17 +1209,17 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: let new_len = self.node.len() - self.idx - 1; ptr::copy_nonoverlapping( - self.node.keys().as_ptr().offset(self.idx as isize + 1), + self.node.keys().as_ptr().add(self.idx + 1), new_node.data.keys.as_mut_ptr(), new_len ); ptr::copy_nonoverlapping( - self.node.vals().as_ptr().offset(self.idx as isize + 1), + self.node.vals().as_ptr().add(self.idx + 1), new_node.data.vals.as_mut_ptr(), new_len ); ptr::copy_nonoverlapping( - self.node.as_internal().edges.as_ptr().offset(self.idx as isize + 1), + self.node.as_internal().edges.as_ptr().add(self.idx + 1), new_node.edges.as_mut_ptr(), new_len + 1 ); @@ -1283,14 +1283,14 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: slice_remove(self.node.keys_mut(), self.idx)); ptr::copy_nonoverlapping( right_node.keys().as_ptr(), - left_node.keys_mut().as_mut_ptr().offset(left_len as isize + 1), + left_node.keys_mut().as_mut_ptr().add(left_len + 1), right_len ); ptr::write(left_node.vals_mut().get_unchecked_mut(left_len), slice_remove(self.node.vals_mut(), self.idx)); ptr::copy_nonoverlapping( right_node.vals().as_ptr(), - left_node.vals_mut().as_mut_ptr().offset(left_len as isize + 1), + left_node.vals_mut().as_mut_ptr().add(left_len + 1), right_len ); @@ -1309,7 +1309,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: .as_internal_mut() .edges .as_mut_ptr() - .offset(left_len as isize + 1), + .add(left_len + 1), right_len + 1 ); @@ -1394,10 +1394,10 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: // Make room for stolen elements in the right child. ptr::copy(right_kv.0, - right_kv.0.offset(count as isize), + right_kv.0.add(count), right_len); ptr::copy(right_kv.1, - right_kv.1.offset(count as isize), + right_kv.1.add(count), right_len); // Move elements from the left child to the right one. @@ -1418,7 +1418,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: // Make room for stolen edges. let right_edges = right.reborrow_mut().as_internal_mut().edges.as_mut_ptr(); ptr::copy(right_edges, - right_edges.offset(count as isize), + right_edges.add(count), right_len + 1); right.correct_childrens_parent_links(count, count + right_len + 1); @@ -1463,10 +1463,10 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: move_kv(right_kv, count - 1, parent_kv, 0, 1); // Fix right indexing - ptr::copy(right_kv.0.offset(count as isize), + ptr::copy(right_kv.0.add(count), right_kv.0, new_right_len); - ptr::copy(right_kv.1.offset(count as isize), + ptr::copy(right_kv.1.add(count), right_kv.1, new_right_len); } @@ -1480,7 +1480,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: // Fix right indexing. let right_edges = right.reborrow_mut().as_internal_mut().edges.as_mut_ptr(); - ptr::copy(right_edges.offset(count as isize), + ptr::copy(right_edges.add(count), right_edges, new_right_len + 1); right.correct_childrens_parent_links(0, new_right_len + 1); @@ -1497,11 +1497,11 @@ unsafe fn move_kv( dest: (*mut K, *mut V), dest_offset: usize, count: usize) { - ptr::copy_nonoverlapping(source.0.offset(source_offset as isize), - dest.0.offset(dest_offset as isize), + ptr::copy_nonoverlapping(source.0.add(source_offset), + dest.0.add(dest_offset), count); - ptr::copy_nonoverlapping(source.1.offset(source_offset as isize), - dest.1.offset(dest_offset as isize), + ptr::copy_nonoverlapping(source.1.add(source_offset), + dest.1.add(dest_offset), count); } @@ -1513,8 +1513,8 @@ unsafe fn move_edges( { let source_ptr = source.as_internal_mut().edges.as_mut_ptr(); let dest_ptr = dest.as_internal_mut().edges.as_mut_ptr(); - ptr::copy_nonoverlapping(source_ptr.offset(source_offset as isize), - dest_ptr.offset(dest_offset as isize), + ptr::copy_nonoverlapping(source_ptr.add(source_offset), + dest_ptr.add(dest_offset), count); dest.correct_childrens_parent_links(dest_offset, dest_offset + count); } @@ -1604,8 +1604,8 @@ pub mod marker { unsafe fn slice_insert(slice: &mut [T], idx: usize, val: T) { ptr::copy( - slice.as_ptr().offset(idx as isize), - slice.as_mut_ptr().offset(idx as isize + 1), + slice.as_ptr().add(idx), + slice.as_mut_ptr().add(idx + 1), slice.len() - idx ); ptr::write(slice.get_unchecked_mut(idx), val); @@ -1614,8 +1614,8 @@ unsafe fn slice_insert(slice: &mut [T], idx: usize, val: T) { unsafe fn slice_remove(slice: &mut [T], idx: usize) -> T { let ret = ptr::read(slice.get_unchecked(idx)); ptr::copy( - slice.as_ptr().offset(idx as isize + 1), - slice.as_mut_ptr().offset(idx as isize), + slice.as_ptr().add(idx + 1), + slice.as_mut_ptr().add(idx), slice.len() - idx - 1 ); ret diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 9844de9a57..2ef84dbade 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -1222,7 +1222,7 @@ mod tests { use std::thread; use std::vec::Vec; - use rand::{thread_rng, Rng}; + use rand::{thread_rng, RngCore}; use super::{LinkedList, Node}; diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index ba92b88613..c53549ab85 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -19,6 +19,7 @@ use core::cmp::Ordering; use core::fmt; +use core::isize; use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; use core::ops::Bound::{Excluded, Included, Unbounded}; @@ -126,13 +127,13 @@ impl VecDeque { /// Moves an element out of the buffer #[inline] unsafe fn buffer_read(&mut self, off: usize) -> T { - ptr::read(self.ptr().offset(off as isize)) + ptr::read(self.ptr().add(off)) } /// Writes an element into the buffer, moving it. #[inline] unsafe fn buffer_write(&mut self, off: usize, value: T) { - ptr::write(self.ptr().offset(off as isize), value); + ptr::write(self.ptr().add(off), value); } /// Returns `true` if and only if the buffer is at full capacity. @@ -177,8 +178,8 @@ impl VecDeque { src, len, self.cap()); - ptr::copy(self.ptr().offset(src as isize), - self.ptr().offset(dst as isize), + ptr::copy(self.ptr().add(src), + self.ptr().add(dst), len); } @@ -197,11 +198,38 @@ impl VecDeque { src, len, self.cap()); - ptr::copy_nonoverlapping(self.ptr().offset(src as isize), - self.ptr().offset(dst as isize), + ptr::copy_nonoverlapping(self.ptr().add(src), + self.ptr().add(dst), len); } + /// Copies all values from `src` to the back of `self`, wrapping around if needed. + /// + /// # Safety + /// + /// The capacity must be sufficient to hold self.len() + src.len() elements. + /// If so, this function never panics. + #[inline] + unsafe fn copy_slice(&mut self, src: &[T]) { + /// This is guaranteed by `RawVec`. + debug_assert!(self.capacity() <= isize::MAX as usize); + + let expected_new_len = self.len() + src.len(); + debug_assert!(self.capacity() >= expected_new_len); + + let dst_high_ptr = self.ptr().add(self.head); + let dst_high_len = self.cap() - self.head; + + let split = cmp::min(src.len(), dst_high_len); + let (src_high, src_low) = src.split_at(split); + + ptr::copy_nonoverlapping(src_high.as_ptr(), dst_high_ptr, src_high.len()); + ptr::copy_nonoverlapping(src_low.as_ptr(), self.ptr(), src_low.len()); + + self.head = self.wrap_add(self.head, src.len()); + debug_assert!(self.len() == expected_new_len); + } + /// Copies a potentially wrapping block of memory len long from src to dest. /// (abs(dst - src) + len) must be no larger than cap() (There must be at /// most one continuous overlapping region between src and dest). @@ -419,7 +447,7 @@ impl VecDeque { pub fn get(&self, index: usize) -> Option<&T> { if index < self.len() { let idx = self.wrap_add(self.tail, index); - unsafe { Some(&*self.ptr().offset(idx as isize)) } + unsafe { Some(&*self.ptr().add(idx)) } } else { None } @@ -448,7 +476,7 @@ impl VecDeque { pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { if index < self.len() { let idx = self.wrap_add(self.tail, index); - unsafe { Some(&mut *self.ptr().offset(idx as isize)) } + unsafe { Some(&mut *self.ptr().add(idx)) } } else { None } @@ -484,8 +512,8 @@ impl VecDeque { let ri = self.wrap_add(self.tail, i); let rj = self.wrap_add(self.tail, j); unsafe { - ptr::swap(self.ptr().offset(ri as isize), - self.ptr().offset(rj as isize)) + ptr::swap(self.ptr().add(ri), + self.ptr().add(rj)) } } @@ -1024,7 +1052,7 @@ impl VecDeque { iter: Iter { tail: drain_tail, head: drain_head, - ring: unsafe { self.buffer_as_mut_slice() }, + ring: unsafe { self.buffer_as_slice() }, }, } } @@ -1788,20 +1816,20 @@ impl VecDeque { // `at` lies in the first half. let amount_in_first = first_len - at; - ptr::copy_nonoverlapping(first_half.as_ptr().offset(at as isize), + ptr::copy_nonoverlapping(first_half.as_ptr().add(at), other.ptr(), amount_in_first); // just take all of the second half. ptr::copy_nonoverlapping(second_half.as_ptr(), - other.ptr().offset(amount_in_first as isize), + other.ptr().add(amount_in_first), second_len); } else { // `at` lies in the second half, need to factor in the elements we skipped // in the first half. let offset = at - first_len; let amount_in_second = second_len - offset; - ptr::copy_nonoverlapping(second_half.as_ptr().offset(offset as isize), + ptr::copy_nonoverlapping(second_half.as_ptr().add(offset), other.ptr(), amount_in_second); } @@ -1834,8 +1862,22 @@ impl VecDeque { #[inline] #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { - // naive impl - self.extend(other.drain(..)); + unsafe { + // Guarantees there is space in `self` for `other`. + self.reserve(other.len()); + + { + let (src_high, src_low) = other.as_slices(); + + // This is only safe because copy_slice never panics when capacity is sufficient. + self.copy_slice(src_low); + self.copy_slice(src_high); + } + + // Some values now exist in both `other` and `self` but are made inaccessible + // in`other`. + other.tail = other.head; + } } /// Retains only the elements specified by the predicate. @@ -1988,11 +2030,11 @@ pub struct Iter<'a, T: 'a> { #[stable(feature = "collection_debug", since = "1.17.0")] impl<'a, T: 'a + fmt::Debug> fmt::Debug for Iter<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); f.debug_tuple("Iter") - .field(&self.ring) - .field(&self.tail) - .field(&self.head) - .finish() + .field(&front) + .field(&back) + .finish() } } @@ -2085,11 +2127,11 @@ pub struct IterMut<'a, T: 'a> { #[stable(feature = "collection_debug", since = "1.17.0")] impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (front, back) = RingSlices::ring_slices(&*self.ring, self.head, self.tail); f.debug_tuple("IterMut") - .field(&self.ring) - .field(&self.tail) - .field(&self.head) - .finish() + .field(&front) + .field(&back) + .finish() } } @@ -2370,7 +2412,7 @@ macro_rules! __impl_slice_eq1 { __impl_slice_eq1! { $Lhs, $Rhs, Sized } }; ($Lhs: ty, $Rhs: ty, $Bound: ident) => { - #[stable(feature = "vec-deque-partial-eq-slice", since = "1.17.0")] + #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")] impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { fn eq(&self, other: &$Rhs) -> bool { if self.len() != other.len() { @@ -2552,24 +2594,24 @@ impl From> for Vec { // Need to move the ring to the front of the buffer, as vec will expect this. if other.is_contiguous() { - ptr::copy(buf.offset(tail as isize), buf, len); + ptr::copy(buf.add(tail), buf, len); } else { if (tail - head) >= cmp::min(cap - tail, head) { // There is enough free space in the centre for the shortest block so we can // do this in at most three copy moves. if (cap - tail) > head { // right hand block is the long one; move that enough for the left - ptr::copy(buf.offset(tail as isize), - buf.offset((tail - head) as isize), + ptr::copy(buf.add(tail), + buf.add(tail - head), cap - tail); // copy left in the end - ptr::copy(buf, buf.offset((cap - head) as isize), head); + ptr::copy(buf, buf.add(cap - head), head); // shift the new thing to the start - ptr::copy(buf.offset((tail - head) as isize), buf, len); + ptr::copy(buf.add(tail - head), buf, len); } else { // left hand block is the long one, we can do it in two! - ptr::copy(buf, buf.offset((cap - tail) as isize), head); - ptr::copy(buf.offset(tail as isize), buf, cap - tail); + ptr::copy(buf, buf.add(cap - tail), head); + ptr::copy(buf.add(tail), buf, cap - tail); } } else { // Need to use N swaps to move the ring @@ -2593,8 +2635,8 @@ impl From> for Vec { let mut right_offset = 0; for i in left_edge..right_edge { right_offset = (i - left_edge) % (cap - right_edge); - let src: isize = (right_edge + right_offset) as isize; - ptr::swap(buf.offset(i as isize), buf.offset(src)); + let src = right_edge + right_offset; + ptr::swap(buf.add(i), buf.add(src)); } let n_ops = right_edge - left_edge; left_edge += n_ops; @@ -2967,4 +3009,21 @@ mod tests { } } + #[test] + fn issue_53529() { + use boxed::Box; + + let mut dst = VecDeque::new(); + dst.push_front(Box::new(1)); + dst.push_front(Box::new(2)); + assert_eq!(*dst.pop_back().unwrap(), 1); + + let mut src = VecDeque::new(); + src.push_front(Box::new(2)); + dst.append(&mut src); + for a in dst { + assert_eq!(*a, 2); + } + } + } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ef619527e0..2d271fd0dc 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -74,27 +74,26 @@ #![needs_allocator] #![deny(missing_debug_implementations)] -#![cfg_attr(test, allow(deprecated))] // rand -#![cfg_attr(not(test), feature(exact_size_is_empty))] +#![cfg_attr(not(test), feature(fn_traits))] #![cfg_attr(not(test), feature(generator_trait))] -#![cfg_attr(test, feature(rand, test))] +#![cfg_attr(not(stage0), feature(nll))] +#![cfg_attr(test, feature(test))] + #![feature(allocator_api)] #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] -#![feature(ascii_ctype)] #![feature(box_into_raw_non_null)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] -#![feature(collections_range)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![feature(core_intrinsics)] #![feature(custom_attribute)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] -#![feature(from_ref)] #![feature(fundamental)] #![feature(futures_api)] #![feature(lang_items)] @@ -118,14 +117,9 @@ #![feature(allocator_internals)] #![feature(on_unimplemented)] #![feature(exact_chunks)] -#![feature(pointer_methods)] -#![feature(inclusive_range_methods)] #![feature(rustc_const_unstable)] #![feature(const_vec_new)] -#![cfg_attr(not(test), feature(fn_traits, i128))] -#![cfg_attr(test, feature(test))] - // Allow testing this library #[cfg(test)] @@ -162,13 +156,11 @@ mod boxed { #[cfg(test)] mod boxed_test; pub mod collections; -#[cfg(any( - all(stage0, target_has_atomic = "ptr"), - all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas") -))] +#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] pub mod sync; pub mod rc; pub mod raw_vec; +pub mod pin; pub mod prelude; pub mod borrow; pub mod fmt; diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs new file mode 100644 index 0000000000..17bbc9882d --- /dev/null +++ b/src/liballoc/pin.rs @@ -0,0 +1,302 @@ +//! Types which pin data to its location in memory +//! +//! It is sometimes useful to have objects that are guaranteed to not move, +//! in the sense that their placement in memory does not change, and can thus be relied upon. +//! +//! A prime example of such a scenario would be building self-referencial structs, +//! since moving an object with pointers to itself will invalidate them, +//! which could cause undefined behavior. +//! +//! In order to prevent objects from moving, they must be *pinned*, +//! by wrapping the data in pinning pointer types, such as [`PinMut`] and [`PinBox`], +//! which are otherwise equivalent to `& mut` and [`Box`], respectively. +//! +//! First of all, these are pointer types because pinned data mustn't be passed around by value +//! (that would change its location in memory). +//! Secondly, since data can be moved out of `&mut` and [`Box`] with functions such as [`swap`], +//! which causes their contents to swap places in memory, +//! we need dedicated types that prohibit such operations. +//! +//! However, these restrictions are usually not necessary, +//! so most types implement the [`Unpin`] auto-trait, +//! which indicates that the type can be moved out safely. +//! Doing so removes the limitations of pinning types, +//! making them the same as their non-pinning counterparts. +//! +//! [`PinMut`]: struct.PinMut.html +//! [`PinBox`]: struct.PinBox.html +//! [`Unpin`]: trait.Unpin.html +//! [`swap`]: ../../std/mem/fn.swap.html +//! [`Box`]: ../boxed/struct.Box.html +//! +//! # Examples +//! +//! ```rust +//! #![feature(pin)] +//! +//! use std::pin::PinBox; +//! use std::marker::Pinned; +//! use std::ptr::NonNull; +//! +//! // This is a self referencial struct since the slice field points to the data field. +//! // We cannot inform the compiler about that with a normal reference, +//! // since this pattern cannot be described with the usual borrowing rules. +//! // Instead we use a raw pointer, though one which is known to not be null, +//! // since we know it's pointing at the string. +//! struct Unmovable { +//! data: String, +//! slice: NonNull, +//! _pin: Pinned, +//! } +//! +//! impl Unmovable { +//! // To ensure the data doesn't move when the function returns, +//! // we place it in the heap where it will stay for the lifetime of the object, +//! // and the only way to access it would be through a pointer to it. +//! fn new(data: String) -> PinBox { +//! let res = Unmovable { +//! data, +//! // we only create the pointer once the data is in place +//! // otherwise it will have already moved before we even started +//! slice: NonNull::dangling(), +//! _pin: Pinned, +//! }; +//! let mut boxed = PinBox::new(res); +//! +//! let slice = NonNull::from(&boxed.data); +//! // we know this is safe because modifying a field doesn't move the whole struct +//! unsafe { PinBox::get_mut(&mut boxed).slice = slice }; +//! boxed +//! } +//! } +//! +//! let unmoved = Unmovable::new("hello".to_string()); +//! // The pointer should point to the correct location, +//! // so long as the struct hasn't moved. +//! // Meanwhile, we are free to move the pointer around. +//! # #[allow(unused_mut)] +//! let mut still_unmoved = unmoved; +//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); +//! +//! // Since our type doesn't implement Unpin, this will fail to compile: +//! // let new_unmoved = Unmovable::new("world".to_string()); +//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); +//! ``` + +#![unstable(feature = "pin", issue = "49150")] + +pub use core::pin::*; +pub use core::marker::Unpin; + +use core::convert::From; +use core::fmt; +use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; +use core::marker::Unsize; +use core::ops::{CoerceUnsized, Deref, DerefMut}; +use core::task::{Context, Poll}; + +use boxed::Box; + +/// A pinned, heap allocated reference. +/// +/// This type is similar to [`Box`], except that it pins its value, +/// which prevents it from moving out of the reference, unless it implements [`Unpin`]. +/// +/// See the [module documentation] for furthur explaination on pinning. +/// +/// [`Box`]: ../boxed/struct.Box.html +/// [`Unpin`]: ../../std/marker/trait.Unpin.html +/// [module documentation]: index.html +#[unstable(feature = "pin", issue = "49150")] +#[fundamental] +#[repr(transparent)] +pub struct PinBox { + inner: Box, +} + +#[unstable(feature = "pin", issue = "49150")] +impl PinBox { + /// Allocate memory on the heap, move the data into it and pin it. + #[unstable(feature = "pin", issue = "49150")] + pub fn new(data: T) -> PinBox { + PinBox { inner: Box::new(data) } + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl PinBox { + /// Get a pinned reference to the data in this PinBox. + #[inline] + pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> { + unsafe { PinMut::new_unchecked(&mut *self.inner) } + } + + /// Constructs a `PinBox` from a raw pointer. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `PinBox`. Specifically, the `PinBox` destructor will call + /// the destructor of `T` and free the allocated memory. Since the + /// way `PinBox` allocates and releases memory is unspecified, the + /// only valid pointer to pass to this function is the one taken + /// from another `PinBox` via the [`PinBox::into_raw`] function. + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw + /// + /// # Examples + /// + /// ``` + /// #![feature(pin)] + /// use std::pin::PinBox; + /// let x = PinBox::new(5); + /// let ptr = PinBox::into_raw(x); + /// let x = unsafe { PinBox::from_raw(ptr) }; + /// ``` + #[inline] + pub unsafe fn from_raw(raw: *mut T) -> Self { + PinBox { inner: Box::from_raw(raw) } + } + + /// Consumes the `PinBox`, returning the wrapped raw pointer. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `PinBox`. In particular, the + /// caller should properly destroy `T` and release the memory. The + /// proper way to do so is to convert the raw pointer back into a + /// `PinBox` with the [`PinBox::from_raw`] function. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw + /// + /// # Examples + /// + /// ``` + /// #![feature(pin)] + /// use std::pin::PinBox; + /// let x = PinBox::new(5); + /// let ptr = PinBox::into_raw(x); + /// ``` + #[inline] + pub fn into_raw(b: PinBox) -> *mut T { + Box::into_raw(b.inner) + } + + /// Get a mutable reference to the data inside this PinBox. + /// + /// This function is unsafe. Users must guarantee that the data is never + /// moved out of this reference. + #[inline] + pub unsafe fn get_mut<'a>(this: &'a mut PinBox) -> &'a mut T { + &mut *this.inner + } + + /// Convert this PinBox into an unpinned Box. + /// + /// This function is unsafe. Users must guarantee that the data is never + /// moved out of the box. + #[inline] + pub unsafe fn unpin(this: PinBox) -> Box { + this.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl From> for PinBox { + fn from(boxed: Box) -> PinBox { + PinBox { inner: boxed } + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl Deref for PinBox { + type Target = T; + + fn deref(&self) -> &T { + &*self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl DerefMut for PinBox { + fn deref_mut(&mut self) -> &mut T { + &mut *self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Display for PinBox { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&*self.inner, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Debug for PinBox { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&*self.inner, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Pointer for PinBox { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // It's not possible to extract the inner Uniq directly from the Box, + // instead we cast it to a *const which aliases the Unique + let ptr: *const T = &*self.inner; + fmt::Pointer::fmt(&ptr, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl, U: ?Sized> CoerceUnsized> for PinBox {} + +#[unstable(feature = "pin", issue = "49150")] +impl Unpin for PinBox {} + +#[unstable(feature = "futures_api", issue = "50547")] +impl Future for PinBox { + type Output = F::Output; + + fn poll(mut self: PinMut, cx: &mut Context) -> Poll { + self.as_pin_mut().poll(cx) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox + where F: Future + 'a +{ + fn into_raw(self) -> *mut () { + PinBox::into_raw(self) as *mut () + } + + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + let ptr = ptr as *mut F; + let pin: PinMut = PinMut::new_unchecked(&mut *ptr); + pin.poll(cx) + } + + unsafe fn drop(ptr: *mut ()) { + drop(PinBox::from_raw(ptr as *mut F)) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { + fn from(boxed: PinBox) -> Self { + FutureObj::new(boxed) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { + fn from(boxed: PinBox) -> Self { + LocalFutureObj::new(boxed) + } +} diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 4f2686abf4..837770feec 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![unstable(feature = "raw_vec_internals", reason = "implemention detail", issue = "0")] +#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "0")] #![doc(hidden)] use core::cmp; @@ -282,7 +282,7 @@ impl RawVec { /// // double would have aborted or panicked if the len exceeded /// // `isize::MAX` so this is safe to do unchecked now. /// unsafe { - /// ptr::write(self.buf.ptr().offset(self.len as isize), elem); + /// ptr::write(self.buf.ptr().add(self.len), elem); /// } /// self.len += 1; /// } @@ -487,7 +487,7 @@ impl RawVec { /// // `isize::MAX` so this is safe to do unchecked now. /// for x in elems { /// unsafe { - /// ptr::write(self.buf.ptr().offset(self.len as isize), x.clone()); + /// ptr::write(self.buf.ptr().add(self.len), x.clone()); /// } /// self.len += 1; /// } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index be049eb6e5..fcd683e5e8 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -252,7 +252,7 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; use core::marker; -use core::marker::{Unsize, PhantomData}; +use core::marker::{Unpin, Unsize, PhantomData}; use core::mem::{self, align_of_val, forget, size_of_val}; use core::ops::Deref; use core::ops::CoerceUnsized; @@ -771,7 +771,7 @@ impl RcFromSlice for Rc<[T]> { }; for (i, item) in v.iter().enumerate() { - ptr::write(elems.offset(i as isize), item.clone()); + ptr::write(elems.add(i), item.clone()); guard.n_elems += 1; } @@ -806,9 +806,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { /// /// This will decrement the strong reference count. If the strong reference /// count reaches zero then the only other references (if any) are - /// [`Weak`][weak], so we `drop` the inner value. - /// - /// [weak]: struct.Weak.html + /// [`Weak`], so we `drop` the inner value. /// /// # Examples /// @@ -1173,9 +1171,8 @@ impl, U: ?Sized> CoerceUnsized> for Weak {} impl Weak { /// Constructs a new `Weak`, without allocating any memory. - /// Calling [`upgrade`] on the return value always gives [`None`]. + /// Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`]. /// - /// [`upgrade`]: struct.Weak.html#method.upgrade /// [`None`]: ../../std/option/enum.Option.html /// /// # Examples @@ -1321,9 +1318,8 @@ impl fmt::Debug for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { /// Constructs a new `Weak`, allocating memory for `T` without initializing - /// it. Calling [`upgrade`] on the return value always gives [`None`]. + /// it. Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`]. /// - /// [`upgrade`]: struct.Weak.html#method.upgrade /// [`None`]: ../../std/option/enum.Option.html /// /// # Examples @@ -1359,7 +1355,14 @@ trait RcBoxPtr { #[inline] fn inc_strong(&self) { - self.inner().strong.set(self.strong().checked_add(1).unwrap_or_else(|| unsafe { abort() })); + // We want to abort on overflow instead of dropping the value. + // The reference count will never be zero when this is called; + // nevertheless, we insert an abort here to hint LLVM at + // an otherwise missed optimization. + if self.strong() == 0 || self.strong() == usize::max_value() { + unsafe { abort(); } + } + self.inner().strong.set(self.strong() + 1); } #[inline] @@ -1374,7 +1377,14 @@ trait RcBoxPtr { #[inline] fn inc_weak(&self) { - self.inner().weak.set(self.weak().checked_add(1).unwrap_or_else(|| unsafe { abort() })); + // We want to abort on overflow instead of dropping the value. + // The reference count will never be zero when this is called; + // nevertheless, we insert an abort here to hint LLVM at + // an otherwise missed optimization. + if self.weak() == 0 || self.weak() == usize::max_value() { + unsafe { abort(); } + } + self.inner().weak.set(self.weak() + 1); } #[inline] @@ -1816,3 +1826,6 @@ impl AsRef for Rc { &**self } } + +#[unstable(feature = "pin", issue = "49150")] +impl Unpin for Rc { } diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index c27c596e79..6c0b1c33a1 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -392,6 +392,10 @@ impl [T] { /// Creates a vector by repeating a slice `n` times. /// + /// # Panics + /// + /// This function will panic if the capacity would overflow. + /// /// # Examples /// /// Basic usage: @@ -403,6 +407,16 @@ impl [T] { /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); /// } /// ``` + /// + /// A panic upon overflow: + /// + /// ```should_panic + /// #![feature(repeat_generic_slice)] + /// fn main() { + /// // this will panic at runtime + /// b"0123456789abcdef".repeat(usize::max_value()); + /// } + /// ``` #[unstable(feature = "repeat_generic_slice", reason = "it's on str, why not on slice?", issue = "48784")] @@ -417,7 +431,7 @@ impl [T] { // and `rem` is the remaining part of `n`. // Using `Vec` to access `set_len()`. - let mut buf = Vec::with_capacity(self.len() * n); + let mut buf = Vec::with_capacity(self.len().checked_mul(n).expect("capacity overflow")); // `2^expn` repetition is done by doubling `buf` `expn`-times. buf.extend(self); @@ -715,8 +729,8 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) { let len = v.len(); let v = v.as_mut_ptr(); - let v_mid = v.offset(mid as isize); - let v_end = v.offset(len as isize); + let v_mid = v.add(mid); + let v_end = v.add(len); // The merge process first copies the shorter run into `buf`. Then it traces the newly copied // run and the longer run forwards (or backwards), comparing their next unconsumed elements and @@ -742,7 +756,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) ptr::copy_nonoverlapping(v, buf, mid); hole = MergeHole { start: buf, - end: buf.offset(mid as isize), + end: buf.add(mid), dest: v, }; @@ -766,7 +780,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) ptr::copy_nonoverlapping(v_mid, buf, len - mid); hole = MergeHole { start: buf, - end: buf.offset((len - mid) as isize), + end: buf.add(len - mid), dest: v_mid, }; diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 870bf971cd..2af89562d6 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -513,7 +513,11 @@ impl str { unsafe { String::from_utf8_unchecked(slice.into_vec()) } } - /// Create a [`String`] by repeating a string `n` times. + /// Creates a new [`String`] by repeating a string `n` times. + /// + /// # Panics + /// + /// This function will panic if the capacity would overflow. /// /// [`String`]: string/struct.String.html /// @@ -524,6 +528,15 @@ impl str { /// ``` /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); /// ``` + /// + /// A panic upon overflow: + /// + /// ```should_panic + /// fn main() { + /// // this will panic at runtime + /// "0123456789abcdef".repeat(usize::max_value()); + /// } + /// ``` #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 631779a17a..837e17cf64 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -519,10 +519,11 @@ impl String { /// between the two. Not all byte slices are valid strings, however: strings /// are required to be valid UTF-8. During this conversion, /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with - /// `U+FFFD REPLACEMENT CHARACTER`, which looks like this: � + /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: � /// /// [`u8`]: ../../std/primitive.u8.html /// [byteslice]: ../../std/primitive.slice.html + /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html /// /// If you are sure that the byte slice is valid UTF-8, and you don't want /// to incur the overhead of the conversion, there is an unsafe version @@ -621,7 +622,7 @@ impl String { } /// Decode a UTF-16 encoded slice `v` into a `String`, replacing - /// invalid data with the replacement character (U+FFFD). + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. /// /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 @@ -629,6 +630,7 @@ impl String { /// /// [`from_utf8_lossy`]: #method.from_utf8_lossy /// [`Cow<'a, str>`]: ../borrow/enum.Cow.html + /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html /// /// # Examples /// @@ -750,7 +752,7 @@ impl String { self.vec } - /// Extracts a string slice containing the entire string. + /// Extracts a string slice containing the entire `String`. /// /// # Examples /// @@ -1188,8 +1190,8 @@ impl String { let next = idx + ch.len_utf8(); let len = self.len(); unsafe { - ptr::copy(self.vec.as_ptr().offset(next as isize), - self.vec.as_mut_ptr().offset(idx as isize), + ptr::copy(self.vec.as_ptr().add(next), + self.vec.as_mut_ptr().add(idx), len - next); self.vec.set_len(len - (next - idx)); } @@ -1230,8 +1232,8 @@ impl String { del_bytes += ch_len; } else if del_bytes > 0 { unsafe { - ptr::copy(self.vec.as_ptr().offset(idx as isize), - self.vec.as_mut_ptr().offset((idx - del_bytes) as isize), + ptr::copy(self.vec.as_ptr().add(idx), + self.vec.as_mut_ptr().add(idx - del_bytes), ch_len); } } @@ -1287,11 +1289,11 @@ impl String { let amt = bytes.len(); self.vec.reserve(amt); - ptr::copy(self.vec.as_ptr().offset(idx as isize), - self.vec.as_mut_ptr().offset((idx + amt) as isize), + ptr::copy(self.vec.as_ptr().add(idx), + self.vec.as_mut_ptr().add(idx + amt), len - idx); ptr::copy(bytes.as_ptr(), - self.vec.as_mut_ptr().offset(idx as isize), + self.vec.as_mut_ptr().add(idx), amt); self.vec.set_len(len + amt); } @@ -1452,8 +1454,8 @@ impl String { self.vec.clear() } - /// Creates a draining iterator that removes the specified range in the string - /// and yields the removed chars. + /// Creates a draining iterator that removes the specified range in the `String` + /// and yields the removed `chars`. /// /// Note: The element range is removed even if the iterator is not /// consumed until the end. @@ -1925,9 +1927,7 @@ impl<'a> Add<&'a str> for String { /// Implements the `+=` operator for appending to a `String`. /// -/// This has the same behavior as the [`push_str`] method. -/// -/// [`push_str`]: struct.String.html#method.push_str +/// This has the same behavior as the [`push_str`][String::push_str] method. #[stable(feature = "stringaddassign", since = "1.12.0")] impl<'a> AddAssign<&'a str> for String { #[inline] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index a00b6b4e43..8b4231dbdf 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -27,7 +27,7 @@ use core::mem::{self, align_of_val, size_of_val}; use core::ops::Deref; use core::ops::CoerceUnsized; use core::ptr::{self, NonNull}; -use core::marker::{Unsize, PhantomData}; +use core::marker::{Unpin, Unsize, PhantomData}; use core::hash::{Hash, Hasher}; use core::{isize, usize}; use core::convert::From; @@ -49,9 +49,10 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// /// The type `Arc` provides shared ownership of a value of type `T`, /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces -/// a new pointer to the same value in the heap. When the last `Arc` -/// pointer to a given value is destroyed, the pointed-to value is -/// also destroyed. +/// a new `Arc` instance, which points to the same value on the heap as the +/// source `Arc`, while increasing a reference count. When the last `Arc` +/// pointer to a given value is destroyed, the pointed-to value is also +/// destroyed. /// /// Shared references in Rust disallow mutation by default, and `Arc` is no /// exception: you cannot generally obtain a mutable reference to something @@ -107,7 +108,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// // The two syntaxes below are equivalent. /// let a = foo.clone(); /// let b = Arc::clone(&foo); -/// // a and b both point to the same memory location as foo. +/// // a, b, and foo are all Arcs that point to the same memory location /// ``` /// /// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly @@ -672,7 +673,7 @@ impl ArcFromSlice for Arc<[T]> { }; for (i, item) in v.iter().enumerate() { - ptr::write(elems.offset(i as isize), item.clone()); + ptr::write(elems.add(i), item.clone()); guard.n_elems += 1; } @@ -915,9 +916,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { /// /// This will decrement the strong reference count. If the strong reference /// count reaches zero then the only other references (if any) are - /// [`Weak`][weak], so we `drop` the inner value. - /// - /// [weak]: struct.Weak.html + /// [`Weak`], so we `drop` the inner value. /// /// # Examples /// @@ -1158,9 +1157,9 @@ impl Clone for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { /// Constructs a new `Weak`, without allocating memory. - /// Calling [`upgrade`] on the return value always gives [`None`]. + /// Calling [`upgrade`][Weak::upgrade] on the return value always + /// gives [`None`]. /// - /// [`upgrade`]: struct.Weak.html#method.upgrade /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples @@ -1942,3 +1941,6 @@ impl AsRef for Arc { &**self } } + +#[unstable(feature = "pin", issue = "49150")] +impl Unpin for Arc { } diff --git a/src/liballoc/task.rs b/src/liballoc/task.rs index 9792d52dd6..7a4eda21a6 100644 --- a/src/liballoc/task.rs +++ b/src/liballoc/task.rs @@ -12,16 +12,10 @@ pub use core::task::*; -#[cfg(any( - all(stage0, target_has_atomic = "ptr"), - all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas") -))] +#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] pub use self::if_arc::*; -#[cfg(any( - all(stage0, target_has_atomic = "ptr"), - all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas") -))] +#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] mod if_arc { use super::*; use core::marker::PhantomData; @@ -53,10 +47,7 @@ mod if_arc { } } - #[cfg(any( - all(stage0, target_has_atomic = "ptr"), - all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas") - ))] + #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] struct ArcWrapped(PhantomData); unsafe impl UnsafeWake for ArcWrapped { diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 618aff963f..710c659ac5 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -10,17 +10,14 @@ #![feature(allocator_api)] #![feature(alloc_system)] -#![feature(attr_literals)] #![feature(box_syntax)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(pattern)] -#![feature(rand)] #![feature(slice_sort_by_cached_key)] -#![feature(splice)] #![feature(str_escape)] -#![feature(string_retain)] #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(exact_chunks)] diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index df5e18a9a1..f33bf64d40 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -18,7 +18,8 @@ use std::sync::atomic::Ordering::Relaxed; use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; use std::thread; -use rand::{Rng, thread_rng}; +use rand::{Rng, RngCore, thread_rng}; +use rand::distributions::Standard; fn square(n: usize) -> usize { n * n @@ -405,7 +406,7 @@ fn test_sort() { for len in (2..25).chain(500..510) { for &modulus in &[5, 10, 100, 1000] { for _ in 0..10 { - let orig: Vec<_> = rng.gen_iter::() + let orig: Vec<_> = rng.sample_iter::(&Standard) .map(|x| x % modulus) .take(len) .collect(); diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index 6275c7bb11..a5fa7f0c4d 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -727,33 +727,33 @@ fn test_is_char_boundary() { } #[test] -fn test_trim_left_matches() { +fn test_trim_start_matches() { let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** "); let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** "); - assert_eq!(" *** *** ".trim_left_matches(chars), ""); - assert_eq!("foo *** ".trim_left_matches(chars), "foo *** "); + assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** "); + assert_eq!(" *** *** ".trim_start_matches(chars), ""); + assert_eq!("foo *** ".trim_start_matches(chars), "foo *** "); - assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11"); let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12"); - assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); + assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12"); + assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123"); } #[test] -fn test_trim_right_matches() { +fn test_trim_end_matches() { let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** "); let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo"); - assert_eq!(" *** *** ".trim_right_matches(chars), ""); - assert_eq!(" *** foo".trim_right_matches(chars), " *** foo"); + assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo"); + assert_eq!(" *** *** ".trim_end_matches(chars), ""); + assert_eq!(" *** foo".trim_end_matches(chars), " *** foo"); - assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar"); let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar"); - assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); + assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar"); + assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar"); } #[test] @@ -772,23 +772,23 @@ fn test_trim_matches() { } #[test] -fn test_trim_left() { - assert_eq!("".trim_left(), ""); - assert_eq!("a".trim_left(), "a"); - assert_eq!(" ".trim_left(), ""); - assert_eq!(" blah".trim_left(), "blah"); - assert_eq!(" \u{3000} wut".trim_left(), "wut"); - assert_eq!("hey ".trim_left(), "hey "); +fn test_trim_start() { + assert_eq!("".trim_start(), ""); + assert_eq!("a".trim_start(), "a"); + assert_eq!(" ".trim_start(), ""); + assert_eq!(" blah".trim_start(), "blah"); + assert_eq!(" \u{3000} wut".trim_start(), "wut"); + assert_eq!("hey ".trim_start(), "hey "); } #[test] -fn test_trim_right() { - assert_eq!("".trim_right(), ""); - assert_eq!("a".trim_right(), "a"); - assert_eq!(" ".trim_right(), ""); - assert_eq!("blah ".trim_right(), "blah"); - assert_eq!("wut \u{3000} ".trim_right(), "wut"); - assert_eq!(" hey".trim_right(), " hey"); +fn test_trim_end() { + assert_eq!("".trim_end(), ""); + assert_eq!("a".trim_end(), "a"); + assert_eq!(" ".trim_end(), ""); + assert_eq!("blah ".trim_end(), "blah"); + assert_eq!("wut \u{3000} ".trim_end(), "wut"); + assert_eq!(" hey".trim_end(), " hey"); } #[test] @@ -1518,12 +1518,20 @@ fn trim_ws() { "a \t "); assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()), " \t a"); + assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), + "a \t "); + assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), + " \t a"); assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a"); assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()), ""); assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()), ""); + assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), + ""); + assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), + ""); assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), ""); } diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 4d55584e2f..3ea6c87a65 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -928,6 +928,107 @@ fn test_append() { assert_eq!(a.iter().cloned().collect::>(), []); } +#[test] +fn test_append_permutations() { + fn construct_vec_deque( + push_back: usize, + pop_back: usize, + push_front: usize, + pop_front: usize, + ) -> VecDeque { + let mut out = VecDeque::new(); + for a in 0..push_back { + out.push_back(a); + } + for b in 0..push_front { + out.push_front(push_back + b); + } + for _ in 0..pop_back { + out.pop_back(); + } + for _ in 0..pop_front { + out.pop_front(); + } + out + } + + const MAX: usize = 5; + + // Many different permutations of both the `VecDeque` getting appended to + // and the one getting appended are generated to check `append`. + // This ensures all 6 code paths of `append` are tested. + for src_push_back in 0..MAX { + for src_push_front in 0..MAX { + // 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, + src_push_front, + src_pop_front, + ); + + 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) + { + let mut dst = construct_vec_deque( + dst_push_back, + dst_pop_back, + dst_push_front, + dst_pop_front, + ); + let mut src = src.clone(); + + // Assert that appending `src` to `dst` gives the same order + // of values as iterating over both in sequence. + let correct = dst + .iter() + .chain(src.iter()) + .cloned() + .collect::>(); + dst.append(&mut src); + assert_eq!(dst, correct); + assert!(src.is_empty()); + } + } + } + } + } + } + } + } +} + +struct DropCounter<'a> { + count: &'a mut u32, +} + +impl<'a> Drop for DropCounter<'a> { + fn drop(&mut self) { + *self.count += 1; + } +} + +#[test] +fn test_append_double_drop() { + let (mut count_a, mut count_b) = (0, 0); + { + let mut a = VecDeque::new(); + let mut b = VecDeque::new(); + a.push_back(DropCounter { count: &mut count_a }); + b.push_back(DropCounter { count: &mut count_b }); + + a.append(&mut b); + } + assert_eq!(count_a, 1); + assert_eq!(count_b, 1); +} + #[test] fn test_retain() { let mut buf = VecDeque::new(); diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5efe1e2330..7fc4453fec 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -690,14 +690,20 @@ impl Vec { /// [`drain`]: #method.drain #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { + 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 - while len < self.len { - // decrement len before the drop_in_place(), so a panic on Drop - // doesn't re-drop the just-failed value. - self.len -= 1; - let len = self.len; - ptr::drop_in_place(self.get_unchecked_mut(len)); + for _ in len..current_len { + local_len.decrement_len(1); + ptr = ptr.offset(-1); + ptr::drop_in_place(ptr); } } } @@ -850,7 +856,7 @@ impl Vec { // infallible // The spot to put the new value { - let p = self.as_mut_ptr().offset(index as isize); + let p = self.as_mut_ptr().add(index); // Shift everything over to make space. (Duplicating the // `index`th element into two consecutive places.) ptr::copy(p, p.offset(1), len - index); @@ -885,7 +891,7 @@ impl Vec { let ret; { // the place we are taking from. - let ptr = self.as_mut_ptr().offset(index as isize); + let ptr = self.as_mut_ptr().add(index); // copy it out, unsafely having a copy of the value on // the stack and in the vector at the same time. ret = ptr::read(ptr); @@ -1028,8 +1034,8 @@ impl Vec { let mut w: usize = 1; while r < ln { - let p_r = p.offset(r as isize); - let p_wm1 = p.offset((w - 1) as isize); + let p_r = p.add(r); + let p_wm1 = p.add(w - 1); if !same_bucket(&mut *p_r, &mut *p_wm1) { if r != w { let p_w = p_wm1.offset(1); @@ -1066,7 +1072,7 @@ impl Vec { self.reserve(1); } unsafe { - let end = self.as_mut_ptr().offset(self.len as isize); + let end = self.as_mut_ptr().add(self.len); ptr::write(end, value); self.len += 1; } @@ -1190,7 +1196,7 @@ impl Vec { self.set_len(start); // Use the borrow in the IterMut to indicate borrowing behavior of the // whole Drain iterator (like &mut T). - let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().offset(start as isize), + let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start); Drain { tail_start: end, @@ -1284,7 +1290,7 @@ impl Vec { self.set_len(at); other.set_len(other_len); - ptr::copy_nonoverlapping(self.as_ptr().offset(at as isize), + ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); } @@ -1467,7 +1473,7 @@ impl Vec { self.reserve(n); unsafe { - let mut ptr = self.as_mut_ptr().offset(self.len() as isize); + let mut ptr = self.as_mut_ptr().add(self.len()); // Use SetLenOnDrop to work around bug where compiler // may not realize the store through `ptr` through self.set_len() // don't alias. @@ -1512,6 +1518,11 @@ 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<'a> Drop for SetLenOnDrop<'a> { @@ -1788,7 +1799,7 @@ impl IntoIterator for Vec { let end = if mem::size_of::() == 0 { arith_offset(begin as *const i8, self.len() as isize) as *const T } else { - begin.offset(self.len() as isize) as *const T + begin.add(self.len()) as *const T }; let cap = self.buf.cap(); mem::forget(self); @@ -1887,7 +1898,7 @@ impl SpecExtend for Vec if let Some(additional) = high { self.reserve(additional); unsafe { - let mut ptr = self.as_mut_ptr().offset(self.len() as isize); + let mut ptr = self.as_mut_ptr().add(self.len()); let mut local_len = SetLenOnDrop::new(&mut self.len); for element in iterator { ptr::write(ptr, element); @@ -2399,9 +2410,8 @@ impl Iterator for IntoIter { // same pointer. self.ptr = arith_offset(self.ptr as *const i8, 1) as *mut T; - // Use a non-null pointer value - // (self.ptr might be null because of wrapping) - Some(ptr::read(1 as *mut T)) + // Make up a value of this ZST. + Some(mem::zeroed()) } else { let old = self.ptr; self.ptr = self.ptr.offset(1); @@ -2440,9 +2450,8 @@ impl DoubleEndedIterator for IntoIter { // See above for why 'ptr.offset' isn't used self.end = arith_offset(self.end as *const i8, -1) as *mut T; - // Use a non-null pointer value - // (self.end might be null because of wrapping) - Some(ptr::read(1 as *mut T)) + // Make up a value of this ZST. + Some(mem::zeroed()) } else { self.end = self.end.offset(-1); @@ -2550,8 +2559,8 @@ impl<'a, T> Drop for Drain<'a, T> { let start = source_vec.len(); let tail = self.tail_start; if tail != start { - let src = source_vec.as_ptr().offset(tail as isize); - let dst = source_vec.as_mut_ptr().offset(start as isize); + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); ptr::copy(src, dst, self.tail_len); } source_vec.set_len(start + self.tail_len); @@ -2661,7 +2670,7 @@ impl<'a, T> Drain<'a, T> { let range_start = vec.len; let range_end = self.tail_start; let range_slice = slice::from_raw_parts_mut( - vec.as_mut_ptr().offset(range_start as isize), + vec.as_mut_ptr().add(range_start), range_end - range_start); for place in range_slice { @@ -2682,8 +2691,8 @@ impl<'a, T> Drain<'a, T> { vec.buf.reserve(used_capacity, extra_capacity); let new_tail_start = self.tail_start + extra_capacity; - let src = vec.as_ptr().offset(self.tail_start as isize); - let dst = vec.as_mut_ptr().offset(new_tail_start as isize); + let src = vec.as_ptr().add(self.tail_start); + let dst = vec.as_mut_ptr().add(new_tail_start); ptr::copy(src, dst, self.tail_len); self.tail_start = new_tail_start; } diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 0aa46dc6d2..fbda425a70 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -105,11 +105,10 @@ fn main() { cmd.arg("--with-jemalloc-prefix=je_"); } - // FIXME: building with jemalloc assertions is currently broken. - // See . - //if cfg!(feature = "debug") { - // cmd.arg("--enable-debug"); - //} + if cfg!(feature = "debug") { + // Enable jemalloc assertions. + cmd.arg("--enable-debug"); + } cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index b3b2071551..bdf0e37a2e 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -16,6 +16,7 @@ #![feature(core_intrinsics)] #![feature(libc)] #![feature(linkage)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(staged_api)] #![feature(rustc_attrs)] #![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))] @@ -88,16 +89,16 @@ mod contents { // linkage directives are provided as part of the current compiler allocator // ABI - #[no_mangle] #[rustc_std_internal_symbol] + #[cfg_attr(stage0, no_mangle)] pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 { let flags = align_to_flags(align, size); let ptr = mallocx(size as size_t, flags) as *mut u8; ptr } - #[no_mangle] #[rustc_std_internal_symbol] + #[cfg_attr(stage0, no_mangle)] pub unsafe extern fn __rde_dealloc(ptr: *mut u8, size: usize, align: usize) { @@ -105,8 +106,8 @@ mod contents { sdallocx(ptr as *mut c_void, size, flags); } - #[no_mangle] #[rustc_std_internal_symbol] + #[cfg_attr(stage0, no_mangle)] pub unsafe extern fn __rde_realloc(ptr: *mut u8, _old_size: usize, align: usize, @@ -116,8 +117,8 @@ mod contents { ptr } - #[no_mangle] #[rustc_std_internal_symbol] + #[cfg_attr(stage0, no_mangle)] pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 { let ptr = if align <= MIN_ALIGN && align <= size { calloc(size as size_t, 1) as *mut u8 diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 64348e05de..65204ebf71 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -14,8 +14,10 @@ reason = "this library is unlikely to be stabilized in its current \ form or name", issue = "32838")] + #![feature(allocator_api)] #![feature(core_intrinsics)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(staged_api)] #![feature(rustc_attrs)] #![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))] @@ -174,7 +176,10 @@ mod platform { } } - #[cfg(any(target_os = "android", target_os = "redox", target_os = "solaris"))] + #[cfg(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris"))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { // On android we currently target API level 9 which unfortunately @@ -197,7 +202,10 @@ mod platform { libc::memalign(layout.align(), layout.size()) as *mut u8 } - #[cfg(not(any(target_os = "android", target_os = "redox", target_os = "solaris")))] + #[cfg(not(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris")))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); @@ -211,7 +219,7 @@ mod platform { } #[cfg(windows)] -#[allow(bad_style)] +#[allow(nonstandard_style)] mod platform { use MIN_ALIGN; use System; @@ -241,7 +249,7 @@ mod platform { } unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { - let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize); + let aligned = ptr.add(align - (ptr as usize & (align - 1))); *get_header(aligned) = Header(ptr); aligned } diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 0f4a5d16e1..6ad703180c 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -26,6 +26,7 @@ #![feature(alloc)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(raw_vec_internals)] #![cfg_attr(test, feature(test))] @@ -105,7 +106,7 @@ impl TypedArenaChunk { // A pointer as large as possible for zero-sized elements. !0 as *mut T } else { - self.start().offset(self.storage.cap() as isize) + self.start().add(self.storage.cap()) } } } @@ -178,7 +179,7 @@ impl TypedArena { unsafe { let start_ptr = self.ptr.get(); let arena_slice = slice::from_raw_parts_mut(start_ptr, slice.len()); - self.ptr.set(start_ptr.offset(arena_slice.len() as isize)); + self.ptr.set(start_ptr.add(arena_slice.len())); arena_slice.copy_from_slice(slice); arena_slice } diff --git a/src/libcompiler_builtins/Cargo.toml b/src/libcompiler_builtins/Cargo.toml index 3112662691..7eae2dc1f2 100644 --- a/src/libcompiler_builtins/Cargo.toml +++ b/src/libcompiler_builtins/Cargo.toml @@ -10,7 +10,7 @@ test = false cc = { optional = true, version = "1.0" } [dev-dependencies] -panic-implementation = { path = 'crates/panic-implementation' } +panic-handler = { path = 'crates/panic-handler' } [features] default = ["compiler-builtins"] diff --git a/src/libcompiler_builtins/README.md b/src/libcompiler_builtins/README.md index d10b44f8f7..cae885279a 100644 --- a/src/libcompiler_builtins/README.md +++ b/src/libcompiler_builtins/README.md @@ -69,13 +69,13 @@ features = ["c"] ### Porting Reminders -1. [Rust][4] and [C][5] have slightly different operator precedence. C evaluates comparisons (`== !=`) before bitwise operations (`& | ^`), while Rust evaluates the other way. +1. [Rust][5a] and [C][5b] have slightly different operator precedence. C evaluates comparisons (`== !=`) before bitwise operations (`& | ^`), while Rust evaluates the other way. 2. C assumes wrapping operations everywhere. Rust panics on overflow when in debug mode. Consider using the [Wrapping][6] type or the explicit [wrapping_*][7] functions where applicable. 3. Note [C implicit casts][8], especially integer promotion. Rust is much more explicit about casting, so be sure that any cast which affects the output is ported to the Rust implementation. 4. Rust has [many functions][9] for integer or floating point manipulation in the standard library. Consider using one of these functions rather than porting a new one. -[4]: https://doc.rust-lang.org/reference.html#operator-precedence -[5]: http://en.cppreference.com/w/c/language/operator_precedence +[5a]: https://doc.rust-lang.org/reference/expressions.html#expression-precedence +[5b]: http://en.cppreference.com/w/c/language/operator_precedence [6]: https://doc.rust-lang.org/core/num/struct.Wrapping.html [7]: https://doc.rust-lang.org/std/primitive.i32.html#method.wrapping_add [8]: http://en.cppreference.com/w/cpp/language/implicit_conversion diff --git a/src/libcompiler_builtins/compiler-rt/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/CMakeLists.txt index 6ece416f48..193342c1c6 100644 --- a/src/libcompiler_builtins/compiler-rt/CMakeLists.txt +++ b/src/libcompiler_builtins/compiler-rt/CMakeLists.txt @@ -59,6 +59,9 @@ if (NOT COMPILER_RT_ASAN_SHADOW_SCALE STREQUAL "") -D${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION}) endif() +set(COMPILER_RT_HWASAN_WITH_INTERCEPTORS ON CACHE BOOLEAN + "Enable libc interceptors in HWASan (testing mode)") + set(COMPILER_RT_BAREMETAL_BUILD OFF CACHE BOOLEAN "Build for a bare-metal target.") @@ -89,12 +92,12 @@ if (COMPILER_RT_STANDALONE_BUILD) endif() construct_compiler_rt_default_triple() -if ("${COMPILER_RT_DEFAULT_TARGET_ABI}" MATCHES "hf$") +if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*hf$") if (${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "^arm") set(COMPILER_RT_DEFAULT_TARGET_ARCH "armhf") endif() endif() -if ("${COMPILER_RT_DEFAULT_TARGET_ABI}" MATCHES "^android") +if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*") set(ANDROID 1) endif() pythonize_bool(ANDROID) @@ -142,10 +145,7 @@ set(CXXABIS none default libstdc++ libc++) set_property(CACHE SANITIZER_CXX_ABI PROPERTY STRINGS ;${CXXABIS}) if (SANITIZER_CXX_ABI STREQUAL "default") - if (CLANG_DEFAULT_CXX_STDLIB STREQUAL "libc++" AND (TARGET cxx OR HAVE_LIBCXX)) - set(SANITIZER_CXX_ABI_LIBNAME "libc++") - set(SANITIZER_CXX_ABI_INTREE 1) - elseif (APPLE) + if (APPLE) set(SANITIZER_CXX_ABI_LIBNAME "libc++") set(SANITIZER_CXX_ABI_SYSTEM 1) elseif (FUCHSIA) @@ -160,19 +160,14 @@ else() set(SANITIZER_CXX_ABI_SYSTEM 1) endif() -set(COMPILER_RT_RUNTIME "default" CACHE STRING - "Compiler runtime to use.") - -if (COMPILER_RT_RUNTIME STREQUAL "default") - if (CLANG_DEFAULT_RTLIB STREQUAL "compiler-rt") - set(COMPILER_RT_RUNTIME_LIBRARY "builtins") - elseif (FUCHSIA) - set(COMPILER_RT_RUNTIME_LIBRARY "builtins") - endif() -else() - set(COMPILER_RT_RUNTIME_LIBRARY "${COMPILER_RT_RUNTIME}") +set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY OFF) +if (FUCHSIA) + set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY ON) endif() +option(COMPILER_RT_USE_BUILTINS_LIBRARY + "Use compiler-rt builtins instead of libgcc" ${DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY}) + include(config-ix) #================================ @@ -321,7 +316,7 @@ append_list_if(COMPILER_RT_HAS_WD4800_FLAG /wd4800 SANITIZER_COMMON_CFLAGS) # Set common link flags. append_list_if(COMPILER_RT_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS) -if (COMPILER_RT_RUNTIME_LIBRARY STREQUAL "builtins") +if (COMPILER_RT_USE_BUILTINS_LIBRARY) list(APPEND SANITIZER_COMMON_LINK_LIBS ${COMPILER_RT_BUILTINS_LIBRARY}) else() if (ANDROID) @@ -333,6 +328,14 @@ endif() append_list_if(COMPILER_RT_HAS_LIBC c SANITIZER_COMMON_LINK_LIBS) +if(ANDROID) +# Put the Sanitizer shared libraries in the global group. For more details, see +# android-changes-for-ndk-developers.md#changes-to-library-search-order + if (COMPILER_RT_HAS_Z_GLOBAL) + list(APPEND SANITIZER_COMMON_LINK_FLAGS -Wl,-z,global) + endif() +endif() + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia") list(APPEND SANITIZER_COMMON_LINK_FLAGS -Wl,-z,defs,-z,now,-z,relro) list(APPEND SANITIZER_COMMON_LINK_LIBS zircon) @@ -353,6 +356,8 @@ if (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libc++") else() append_list_if(COMPILER_RT_HAS_LIBCXX c++ SANITIZER_CXX_ABI_LIBRARY) endif() +elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libcxxabi") + list(APPEND SANITIZER_CXX_ABI_LIBRARY "c++abi") elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libstdc++") append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ SANITIZER_CXX_ABI_LIBRARY) endif() diff --git a/src/libcompiler_builtins/compiler-rt/lib/builtins/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/CMakeLists.txt index 99184baf5b..82332967b1 100644 --- a/src/libcompiler_builtins/compiler-rt/lib/builtins/CMakeLists.txt +++ b/src/libcompiler_builtins/compiler-rt/lib/builtins/CMakeLists.txt @@ -406,6 +406,7 @@ if(MINGW) arm/aeabi_ldivmod.S arm/aeabi_uidivmod.S arm/aeabi_uldivmod.S + arm/chkstk.S divmoddi4.c divmodsi4.c divdi3.c @@ -566,6 +567,15 @@ else () set(_arch "arm") endif() + # For ARM archs, exclude any VFP builtins if VFP is not supported + if (${arch} MATCHES "^(arm|armhf|armv7|armv7s|armv7k|armv7m|armv7em)$") + string(REPLACE ";" " " _TARGET_${arch}_CFLAGS "${TARGET_${arch}_CFLAGS}") + check_compile_definition(__VFP_FP__ "${CMAKE_C_FLAGS} ${_TARGET_${arch}_CFLAGS}" COMPILER_RT_HAS_${arch}_VFP) + if(NOT COMPILER_RT_HAS_${arch}_VFP) + list(REMOVE_ITEM ${arch}_SOURCES ${arm_Thumb1_VFPv2_SOURCES} ${arm_Thumb1_SjLj_EH_SOURCES}) + endif() + endif() + # Filter out generic versions of routines that are re-implemented in # architecture specific manner. This prevents multiple definitions of the # same symbols, making the symbol selection non-deterministic. diff --git a/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt b/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt deleted file mode 100644 index 603c0b3bf3..0000000000 --- a/src/libcompiler_builtins/compiler-rt/lib/builtins/Darwin-excludes/10.4.txt +++ /dev/null @@ -1,137 +0,0 @@ -absvdi2 -absvsi2 -absvti2 -adddf3 -addsf3 -addtf3 -addvdi3 -addvsi3 -addvti3 -apple_versioning -ashldi3 -ashlti3 -ashrdi3 -ashrti3 -atomic_flag_clear -atomic_flag_clear_explicit -atomic_flag_test_and_set -atomic_flag_test_and_set_explicit -atomic_signal_fence -atomic_thread_fence -clear_cache -clzdi2 -clzsi2 -clzti2 -cmpdi2 -cmpti2 -comparedf2 -comparesf2 -ctzdi2 -ctzsi2 -ctzti2 -divdc3 -divdf3 -divdi3 -divmoddi4 -divmodsi4 -divsc3 -divsf3 -divsi3 -divtf3 -divti3 -divxc3 -enable_execute_stack -extendhfsf2 -extendsfdf2 -ffsdi2 -ffsti2 -fixdfdi -fixdfsi -fixdfti -fixsfdi -fixsfsi -fixsfti -fixunsdfdi -fixunsdfsi -fixunsdfti -fixunssfdi -fixunssfsi -fixunssfti -fixunsxfdi -fixunsxfsi -fixunsxfti -fixxfdi -fixxfti -floatdidf -floatdisf -floatdixf -floatsidf -floatsisf -floattidf -floattisf -floattixf -floatunsidf -floatunsisf -floatuntidf -floatuntisf -floatuntixf -gcc_personality_v0 -gnu_f2h_ieee -gnu_h2f_ieee -lshrdi3 -lshrti3 -moddi3 -modsi3 -modti3 -muldc3 -muldf3 -muldi3 -mulodi4 -mulosi4 -muloti4 -mulsc3 -mulsf3 -multf3 -multi3 -mulvdi3 -mulvsi3 -mulvti3 -mulxc3 -negdf2 -negdi2 -negsf2 -negti2 -negvdi2 -negvsi2 -negvti2 -paritydi2 -paritysi2 -parityti2 -popcountdi2 -popcountsi2 -popcountti2 -powidf2 -powisf2 -powitf2 -powixf2 -subdf3 -subsf3 -subtf3 -subvdi3 -subvsi3 -subvti3 -trampoline_setup -truncdfhf2 -truncdfsf2 -truncsfhf2 -ucmpdi2 -ucmpti2 -udivdi3 -udivmoddi4 -udivmodsi4 -udivmodti4 -udivsi3 -udivti3 -umoddi3 -umodsi3 -umodti3 diff --git a/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/chkstk.S b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/chkstk.S new file mode 100644 index 0000000000..e300210589 --- /dev/null +++ b/src/libcompiler_builtins/compiler-rt/lib/builtins/arm/chkstk.S @@ -0,0 +1,34 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +// __chkstk routine +// This routine is windows specific. +// http://msdn.microsoft.com/en-us/library/ms648426.aspx + +// This clobbers the register r12, and the condition codes, and uses r5 and r6 +// as temporaries by backing them up and restoring them afterwards. +// Does not modify any memory or the stack pointer. + +// movw r4, #256 // Number of bytes of stack, in units of 4 byte +// bl __chkstk +// sub.w sp, sp, r4 + +#define PAGE_SIZE 4096 + + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__chkstk) + lsl r4, r4, #2 + mov r12, sp + push {r5, r6} + mov r5, r4 +1: + sub r12, r12, #PAGE_SIZE + subs r5, r5, #PAGE_SIZE + ldr r6, [r12] + bgt 1b + + pop {r5, r6} + bx lr +END_COMPILERRT_FUNCTION(__chkstk) diff --git a/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi.cc b/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi.cc index 52f504bd28..a2f127f93c 100644 --- a/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi.cc +++ b/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi.cc @@ -132,7 +132,11 @@ void ShadowBuilder::Start() { void ShadowBuilder::AddUnchecked(uptr begin, uptr end) { uint16_t *shadow_begin = MemToShadow(begin, shadow_); uint16_t *shadow_end = MemToShadow(end - 1, shadow_) + 1; - memset(shadow_begin, kUncheckedShadow, + // memset takes a byte, so our unchecked shadow value requires both bytes to + // be the same. Make sure we're ok during compilation. + static_assert((kUncheckedShadow & 0xff) == ((kUncheckedShadow >> 8) & 0xff), + "Both bytes of the 16-bit value must be the same!"); + memset(shadow_begin, kUncheckedShadow & 0xff, (shadow_end - shadow_begin) * sizeof(*shadow_begin)); } diff --git a/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi_blacklist.txt b/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi_blacklist.txt index 3d73508f57..4a0f03949c 100644 --- a/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi_blacklist.txt +++ b/src/libcompiler_builtins/compiler-rt/lib/cfi/cfi_blacklist.txt @@ -1,13 +1,11 @@ [cfi-unrelated-cast] # The specification of std::get_temporary_buffer mandates a cast to -# uninitialized T* (libstdc++, libc++, MSVC stdlib). +# uninitialized T* (libstdc++, MSVC stdlib). fun:_ZSt20get_temporary_buffer* -fun:_ZNSt3__120get_temporary_buffer* fun:*get_temporary_buffer@.*@std@@* -# STL address-of magic (libstdc++, libc++). +# STL address-of magic (libstdc++). fun:*__addressof* -fun:_ZNSt3__19addressof* # Windows C++ stdlib headers that contain bad unrelated casts. src:*xmemory0 diff --git a/src/libcompiler_builtins/compiler-rt/lib/safestack/CMakeLists.txt b/src/libcompiler_builtins/compiler-rt/lib/safestack/CMakeLists.txt index 5a1bac2912..cc874a3fe8 100644 --- a/src/libcompiler_builtins/compiler-rt/lib/safestack/CMakeLists.txt +++ b/src/libcompiler_builtins/compiler-rt/lib/safestack/CMakeLists.txt @@ -6,29 +6,14 @@ include_directories(..) set(SAFESTACK_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -if(APPLE) - # Build universal binary on APPLE. +foreach(arch ${SAFESTACK_SUPPORTED_ARCH}) add_compiler_rt_runtime(clang_rt.safestack STATIC - OS osx - ARCHS ${SAFESTACK_SUPPORTED_ARCH} + ARCHS ${arch} SOURCES ${SAFESTACK_SOURCES} - $ - $ - $ + $ + $ + $ CFLAGS ${SAFESTACK_CFLAGS} PARENT_TARGET safestack) -else() - # Otherwise, build separate libraries for each target. - foreach(arch ${SAFESTACK_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.safestack - STATIC - ARCHS ${arch} - SOURCES ${SAFESTACK_SOURCES} - $ - $ - $ - CFLAGS ${SAFESTACK_CFLAGS} - PARENT_TARGET safestack) - endforeach() -endif() +endforeach() diff --git a/src/libcompiler_builtins/compiler-rt/lib/safestack/safestack.cc b/src/libcompiler_builtins/compiler-rt/lib/safestack/safestack.cc index 8b1fdb788f..673f5fd30c 100644 --- a/src/libcompiler_builtins/compiler-rt/lib/safestack/safestack.cc +++ b/src/libcompiler_builtins/compiler-rt/lib/safestack/safestack.cc @@ -14,11 +14,13 @@ // //===----------------------------------------------------------------------===// +#include #include #include #include #include #include +#include #include #include #if !defined(__NetBSD__) @@ -115,14 +117,6 @@ static inline void unsafe_stack_setup(void *start, size_t size, size_t guard) { unsafe_stack_guard = guard; } -static void unsafe_stack_free() { - if (unsafe_stack_start) { - UnmapOrDie((char *)unsafe_stack_start - unsafe_stack_guard, - unsafe_stack_size + unsafe_stack_guard); - } - unsafe_stack_start = nullptr; -} - /// Thread data for the cleanup handler static pthread_key_t thread_cleanup_key; @@ -149,26 +143,70 @@ static void *thread_start(void *arg) { tinfo->unsafe_stack_guard); // Make sure out thread-specific destructor will be called - // FIXME: we can do this only any other specific key is set by - // intercepting the pthread_setspecific function itself pthread_setspecific(thread_cleanup_key, (void *)1); return start_routine(start_routine_arg); } -/// Thread-specific data destructor +/// Linked list used to store exiting threads stack/thread information. +struct thread_stack_ll { + struct thread_stack_ll *next; + void *stack_base; + size_t size; + pid_t pid; + tid_t tid; +}; + +/// Linked list of unsafe stacks for threads that are exiting. We delay +/// unmapping them until the thread exits. +static thread_stack_ll *thread_stacks = nullptr; +static pthread_mutex_t thread_stacks_mutex = PTHREAD_MUTEX_INITIALIZER; + +/// Thread-specific data destructor. We want to free the unsafe stack only after +/// this thread is terminated. libc can call functions in safestack-instrumented +/// code (like free) after thread-specific data destructors have run. static void thread_cleanup_handler(void *_iter) { - // We want to free the unsafe stack only after all other destructors - // have already run. We force this function to be called multiple times. - // User destructors that might run more then PTHREAD_DESTRUCTOR_ITERATIONS-1 - // times might still end up executing after the unsafe stack is deallocated. - size_t iter = (size_t)_iter; - if (iter < PTHREAD_DESTRUCTOR_ITERATIONS) { - pthread_setspecific(thread_cleanup_key, (void *)(iter + 1)); - } else { - // This is the last iteration - unsafe_stack_free(); + CHECK_NE(unsafe_stack_start, nullptr); + pthread_setspecific(thread_cleanup_key, NULL); + + pthread_mutex_lock(&thread_stacks_mutex); + // Temporary list to hold the previous threads stacks so we don't hold the + // thread_stacks_mutex for long. + thread_stack_ll *temp_stacks = thread_stacks; + thread_stacks = nullptr; + pthread_mutex_unlock(&thread_stacks_mutex); + + pid_t pid = getpid(); + tid_t tid = GetTid(); + + // Free stacks for dead threads + thread_stack_ll **stackp = &temp_stacks; + while (*stackp) { + thread_stack_ll *stack = *stackp; + if (stack->pid != pid || TgKill(stack->pid, stack->tid, 0) == -ESRCH) { + UnmapOrDie(stack->stack_base, stack->size); + *stackp = stack->next; + free(stack); + } else + stackp = &stack->next; } + + thread_stack_ll *cur_stack = + (thread_stack_ll *)malloc(sizeof(thread_stack_ll)); + cur_stack->stack_base = (char *)unsafe_stack_start - unsafe_stack_guard; + cur_stack->size = unsafe_stack_size + unsafe_stack_guard; + cur_stack->pid = pid; + cur_stack->tid = tid; + + pthread_mutex_lock(&thread_stacks_mutex); + // Merge thread_stacks with the current thread's stack and any remaining + // temp_stacks + *stackp = thread_stacks; + cur_stack->next = temp_stacks; + thread_stacks = cur_stack; + pthread_mutex_unlock(&thread_stacks_mutex); + + unsafe_stack_start = nullptr; } static void EnsureInterceptorsInitialized(); @@ -256,6 +294,16 @@ __attribute__((section(".preinit_array"), } #endif +extern "C" + __attribute__((visibility("default"))) void *__get_unsafe_stack_bottom() { + return unsafe_stack_start; +} + +extern "C" + __attribute__((visibility("default"))) void *__get_unsafe_stack_top() { + return (char*)unsafe_stack_start + unsafe_stack_size; +} + extern "C" __attribute__((visibility("default"))) void *__get_unsafe_stack_start() { return unsafe_stack_start; diff --git a/src/libcompiler_builtins/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cc b/src/libcompiler_builtins/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cc index f25a75a863..e8fc3a8499 100644 --- a/src/libcompiler_builtins/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cc +++ b/src/libcompiler_builtins/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cc @@ -109,6 +109,7 @@ HANDLER(float_cast_overflow, "float-cast-overflow") HANDLER(load_invalid_value, "load-invalid-value") HANDLER(invalid_builtin, "invalid-builtin") HANDLER(function_type_mismatch, "function-type-mismatch") +HANDLER(implicit_conversion, "implicit-conversion") HANDLER(nonnull_arg, "nonnull-arg") HANDLER(nonnull_return, "nonnull-return") HANDLER(nullability_arg, "nullability-arg") diff --git a/src/libcompiler_builtins/crates/panic-handler/Cargo.toml b/src/libcompiler_builtins/crates/panic-handler/Cargo.toml new file mode 100644 index 0000000000..1dea613d19 --- /dev/null +++ b/src/libcompiler_builtins/crates/panic-handler/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "panic-handler" +version = "0.1.0" +authors = ["Alex Crichton "] + +[dependencies] diff --git a/src/libcompiler_builtins/crates/panic-handler/src/lib.rs b/src/libcompiler_builtins/crates/panic-handler/src/lib.rs new file mode 100644 index 0000000000..e970610873 --- /dev/null +++ b/src/libcompiler_builtins/crates/panic-handler/src/lib.rs @@ -0,0 +1,11 @@ +// Hack of a crate until rust-lang/rust#51647 is fixed + +#![feature(no_core, panic_handler)] +#![no_core] + +extern crate core; + +#[panic_handler] +fn panic(_: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/src/libcompiler_builtins/crates/panic-implementation/Cargo.toml b/src/libcompiler_builtins/crates/panic-implementation/Cargo.toml deleted file mode 100644 index a076cbc3cb..0000000000 --- a/src/libcompiler_builtins/crates/panic-implementation/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "panic-implementation" -version = "0.1.0" -authors = ["Alex Crichton "] - -[dependencies] diff --git a/src/libcompiler_builtins/crates/panic-implementation/src/lib.rs b/src/libcompiler_builtins/crates/panic-implementation/src/lib.rs deleted file mode 100644 index 1bb23970f7..0000000000 --- a/src/libcompiler_builtins/crates/panic-implementation/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Hack of a crate until rust-lang/rust#51647 is fixed - -#![feature(no_core, panic_implementation)] -#![no_core] - -extern crate core; - -#[panic_implementation] -fn panic(_: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/src/libcompiler_builtins/examples/intrinsics.rs b/src/libcompiler_builtins/examples/intrinsics.rs index c165fcccaf..a5be573944 100644 --- a/src/libcompiler_builtins/examples/intrinsics.rs +++ b/src/libcompiler_builtins/examples/intrinsics.rs @@ -6,18 +6,16 @@ #![allow(unused_features)] #![cfg_attr(thumb, no_main)] #![deny(dead_code)] -#![feature(alloc_system)] #![feature(asm)] #![feature(compiler_builtins_lib)] -#![feature(core_float)] #![feature(lang_items)] #![feature(start)] #![feature(allocator_api)] -#![feature(panic_implementation)] +#![feature(panic_handler)] #![cfg_attr(windows, feature(panic_unwind))] #![no_std] -extern crate panic_implementation; +extern crate panic_handler; #[cfg(not(thumb))] #[link(name = "c")] diff --git a/src/libcompiler_builtins/src/arm_linux.rs b/src/libcompiler_builtins/src/arm_linux.rs index 2291edf9f1..5ed379fa1e 100644 --- a/src/libcompiler_builtins/src/arm_linux.rs +++ b/src/libcompiler_builtins/src/arm_linux.rs @@ -125,9 +125,9 @@ atomic_rmw!(__sync_fetch_and_xor_1, u8, |a: u8, b: u8| a ^ b); atomic_rmw!(__sync_fetch_and_xor_2, u16, |a: u16, b: u16| a ^ b); atomic_rmw!(__sync_fetch_and_xor_4, u32, |a: u32, b: u32| a ^ b); -atomic_rmw!(__sync_fetch_and_nand_1, u8, |a: u8, b: u8| !a & b); -atomic_rmw!(__sync_fetch_and_nand_2, u16, |a: u16, b: u16| !a & b); -atomic_rmw!(__sync_fetch_and_nand_4, u32, |a: u32, b: u32| !a & b); +atomic_rmw!(__sync_fetch_and_nand_1, u8, |a: u8, b: u8| !(a & b)); +atomic_rmw!(__sync_fetch_and_nand_2, u16, |a: u16, b: u16| !(a & b)); +atomic_rmw!(__sync_fetch_and_nand_4, u32, |a: u32, b: u32| !(a & b)); atomic_rmw!(__sync_fetch_and_max_1, i8, |a: i8, b: i8| if a > b { a } else { b }); atomic_rmw!(__sync_fetch_and_max_2, i16, |a: i16, b: i16| if a > b { a } else { b }); diff --git a/src/libcompiler_builtins/src/float/conv.rs b/src/libcompiler_builtins/src/float/conv.rs index 53844c17b4..3171e45096 100644 --- a/src/libcompiler_builtins/src/float/conv.rs +++ b/src/libcompiler_builtins/src/float/conv.rs @@ -80,7 +80,10 @@ intrinsics! { int_to_float!(i, i32, f64) } - #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))] + #[use_c_shim_if(any( + all(target_arch = "x86", not(target_env = "msvc")), + all(target_arch = "x86_64", not(windows)), + ))] #[arm_aeabi_alias = __aeabi_l2f] pub extern "C" fn __floatdisf(i: i64) -> f32 { // On x86_64 LLVM will use native instructions for this conversion, we @@ -124,17 +127,19 @@ intrinsics! { int_to_float!(i, u32, f64) } - #[use_c_shim_if(all(not(target_env = "msvc"), - any(target_arch = "x86", - all(not(windows), target_arch = "x86_64"))))] + #[use_c_shim_if(any( + all(target_arch = "x86", not(target_env = "msvc")), + all(target_arch = "x86_64", not(windows)), + ))] #[arm_aeabi_alias = __aeabi_ul2f] pub extern "C" fn __floatundisf(i: u64) -> f32 { int_to_float!(i, u64, f32) } - #[use_c_shim_if(all(not(target_env = "msvc"), - any(target_arch = "x86", - all(not(windows), target_arch = "x86_64"))))] + #[use_c_shim_if(any( + all(target_arch = "x86", not(target_env = "msvc")), + all(target_arch = "x86_64", not(windows)), + ))] #[arm_aeabi_alias = __aeabi_ul2d] pub extern "C" fn __floatundidf(i: u64) -> f64 { int_to_float!(i, u64, f64) diff --git a/src/libcompiler_builtins/src/lib.rs b/src/libcompiler_builtins/src/lib.rs index 02b6c7db95..9f1dd15120 100644 --- a/src/libcompiler_builtins/src/lib.rs +++ b/src/libcompiler_builtins/src/lib.rs @@ -58,6 +58,9 @@ pub mod arm; #[cfg(all(kernel_user_helpers, target_os = "linux", target_arch = "arm"))] pub mod arm_linux; +#[cfg(any(target_arch = "riscv32"))] +pub mod riscv32; + #[cfg(target_arch = "x86")] pub mod x86; diff --git a/src/libcompiler_builtins/src/riscv32.rs b/src/libcompiler_builtins/src/riscv32.rs new file mode 100644 index 0000000000..9a3c1714c1 --- /dev/null +++ b/src/libcompiler_builtins/src/riscv32.rs @@ -0,0 +1,18 @@ +intrinsics! { + // Implementation from gcc + // https://raw.githubusercontent.com/gcc-mirror/gcc/master/libgcc/config/epiphany/mulsi3.c + pub extern "C" fn __mulsi3(a: u32, b: u32) -> u32 { + let (mut a, mut b) = (a, b); + let mut r = 0; + + while a > 0 { + if a & 1 > 0 { + r += b; + } + a >>= 1; + b <<= 1; + } + + r + } +} diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index 321ed892ea..0b01cfc488 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -20,4 +20,4 @@ name = "corebenches" path = "../libcore/benches/lib.rs" [dev-dependencies] -rand = "0.4" +rand = "0.5" diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index b6ac248b79..35e4eea756 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -19,10 +19,6 @@ use usize; use ptr::{self, NonNull}; use num::NonZeroUsize; -#[unstable(feature = "alloc_internals", issue = "0")] -#[cfg(stage0)] -pub type Opaque = u8; - /// Represents the combination of a starting address and /// a total capacity of the returned block. #[unstable(feature = "allocator_api", issue = "32838")] @@ -48,7 +44,7 @@ fn size_align() -> (usize, usize) { /// use specific allocators with looser requirements.) #[stable(feature = "alloc_layout", since = "1.28.0")] #[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[cfg_attr(not(stage0), lang = "alloc_layout")] +#[lang = "alloc_layout"] pub struct Layout { // size of the requested block of memory, measured in bytes. size_: usize, @@ -221,7 +217,7 @@ impl Layout { let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1); - return len_rounded_up.wrapping_sub(len); + len_rounded_up.wrapping_sub(len) } /// Creates a layout describing the record for `n` instances of @@ -975,9 +971,9 @@ pub unsafe trait Alloc { // _l <= layout.size() [guaranteed by usable_size()] // layout.size() <= new_layout.size() [required by this method] if new_size <= u { - return Ok(()); + Ok(()) } else { - return Err(CannotReallocInPlace); + Err(CannotReallocInPlace) } } @@ -1030,9 +1026,9 @@ pub unsafe trait Alloc { // layout.size() <= _u [guaranteed by usable_size()] // new_layout.size() <= layout.size() [required by this method] if l <= new_size { - return Ok(()); + Ok(()) } else { - return Err(CannotReallocInPlace); + Err(CannotReallocInPlace) } } diff --git a/src/libcore/benches/any.rs b/src/libcore/benches/any.rs index 67e02cf950..f4f01eb1cf 100644 --- a/src/libcore/benches/any.rs +++ b/src/libcore/benches/any.rs @@ -15,7 +15,7 @@ use test::{Bencher, black_box}; fn bench_downcast_ref(b: &mut Bencher) { b.iter(|| { let mut x = 0; - let mut y = &mut x as &mut Any; + let mut y = &mut x as &mut dyn Any; black_box(&mut y); black_box(y.downcast_ref::() == Some(&0)); }); diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 137e9fe2c1..009aba5f59 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1258,7 +1258,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> { let RefMut { value, borrow } = orig; RefMut { value: f(value), - borrow: borrow, + borrow, } } @@ -1324,7 +1324,7 @@ impl<'b> BorrowRefMut<'b> { match borrow.get() { UNUSED => { borrow.set(UNUSED - 1); - Some(BorrowRefMut { borrow: borrow }) + Some(BorrowRefMut { borrow }) }, _ => None, } @@ -1467,7 +1467,7 @@ impl UnsafeCell { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub const fn new(value: T) -> UnsafeCell { - UnsafeCell { value: value } + UnsafeCell { value } } /// Unwraps the value. diff --git a/src/libcore/char/decode.rs b/src/libcore/char/decode.rs index 0b8dce19df..cc52f048b8 100644 --- a/src/libcore/char/decode.rs +++ b/src/libcore/char/decode.rs @@ -11,135 +11,8 @@ //! UTF-8 and UTF-16 decoding iterators use fmt; -use iter::FusedIterator; use super::from_u32_unchecked; -/// An iterator over an iterator of bytes of the characters the bytes represent -/// as UTF-8 -#[unstable(feature = "decode_utf8", issue = "33906")] -#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: - https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] -#[derive(Clone, Debug)] -#[allow(deprecated)] -pub struct DecodeUtf8>(::iter::Peekable); - -/// Decodes an `Iterator` of bytes as UTF-8. -#[unstable(feature = "decode_utf8", issue = "33906")] -#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: - https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] -#[allow(deprecated)] -#[inline] -pub fn decode_utf8>(i: I) -> DecodeUtf8 { - DecodeUtf8(i.into_iter().peekable()) -} - -/// `::next` returns this for an invalid input sequence. -#[unstable(feature = "decode_utf8", issue = "33906")] -#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: - https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] -#[derive(PartialEq, Eq, Debug)] -#[allow(deprecated)] -pub struct InvalidSequence(()); - -#[unstable(feature = "decode_utf8", issue = "33906")] -#[allow(deprecated)] -impl> Iterator for DecodeUtf8 { - type Item = Result; - #[inline] - - fn next(&mut self) -> Option> { - self.0.next().map(|first_byte| { - // Emit InvalidSequence according to - // Unicode §5.22 Best Practice for U+FFFD Substitution - // http://www.unicode.org/versions/Unicode9.0.0/ch05.pdf#G40630 - - // Roughly: consume at least one byte, - // then validate one byte at a time and stop before the first unexpected byte - // (which might be the valid start of the next byte sequence). - - let mut code_point; - macro_rules! first_byte { - ($mask: expr) => { - code_point = u32::from(first_byte & $mask) - } - } - macro_rules! continuation_byte { - () => { continuation_byte!(0x80..=0xBF) }; - ($range: pat) => { - match self.0.peek() { - Some(&byte @ $range) => { - code_point = (code_point << 6) | u32::from(byte & 0b0011_1111); - self.0.next(); - } - _ => return Err(InvalidSequence(())) - } - } - } - - match first_byte { - 0x00..=0x7F => { - first_byte!(0b1111_1111); - } - 0xC2..=0xDF => { - first_byte!(0b0001_1111); - continuation_byte!(); - } - 0xE0 => { - first_byte!(0b0000_1111); - continuation_byte!(0xA0..=0xBF); // 0x80..=0x9F here are overlong - continuation_byte!(); - } - 0xE1..=0xEC | 0xEE..=0xEF => { - first_byte!(0b0000_1111); - continuation_byte!(); - continuation_byte!(); - } - 0xED => { - first_byte!(0b0000_1111); - continuation_byte!(0x80..=0x9F); // 0xA0..0xBF here are surrogates - continuation_byte!(); - } - 0xF0 => { - first_byte!(0b0000_0111); - continuation_byte!(0x90..=0xBF); // 0x80..0x8F here are overlong - continuation_byte!(); - continuation_byte!(); - } - 0xF1..=0xF3 => { - first_byte!(0b0000_0111); - continuation_byte!(); - continuation_byte!(); - continuation_byte!(); - } - 0xF4 => { - first_byte!(0b0000_0111); - continuation_byte!(0x80..=0x8F); // 0x90..0xBF here are beyond char::MAX - continuation_byte!(); - continuation_byte!(); - } - _ => return Err(InvalidSequence(())) // Illegal first byte, overlong, or beyond MAX - } - unsafe { - Ok(from_u32_unchecked(code_point)) - } - }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let (lower, upper) = self.0.size_hint(); - - // A code point is at most 4 bytes long. - let min_code_points = lower / 4; - - (min_code_points, upper) - } -} - -#[unstable(feature = "decode_utf8", issue = "33906")] -#[allow(deprecated)] -impl> FusedIterator for DecodeUtf8 {} - /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s. #[stable(feature = "decode_utf16", since = "1.9.0")] #[derive(Clone, Debug)] diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index eee78de903..64a17786b0 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -673,11 +673,11 @@ impl char { /// assert!('٣'.is_alphanumeric()); /// assert!('7'.is_alphanumeric()); /// assert!('৬'.is_alphanumeric()); + /// assert!('¾'.is_alphanumeric()); + /// assert!('①'.is_alphanumeric()); /// assert!('K'.is_alphanumeric()); /// assert!('و'.is_alphanumeric()); /// assert!('藏'.is_alphanumeric()); - /// assert!(!'¾'.is_alphanumeric()); - /// assert!(!'①'.is_alphanumeric()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -727,11 +727,11 @@ impl char { /// assert!('٣'.is_numeric()); /// assert!('7'.is_numeric()); /// assert!('৬'.is_numeric()); + /// assert!('¾'.is_numeric()); + /// assert!('①'.is_numeric()); /// assert!(!'K'.is_numeric()); /// assert!(!'و'.is_numeric()); /// assert!(!'藏'.is_numeric()); - /// assert!(!'¾'.is_numeric()); - /// assert!(!'①'.is_numeric()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1050,8 +1050,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1084,8 +1082,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1118,8 +1114,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1155,8 +1149,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1189,8 +1181,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1226,8 +1216,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1264,8 +1252,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1298,8 +1284,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1349,8 +1333,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; @@ -1385,8 +1367,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = 'A'; /// let uppercase_g = 'G'; /// let a = 'a'; diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs index 59bcf1383f..7e1313747e 100644 --- a/src/libcore/char/mod.rs +++ b/src/libcore/char/mod.rs @@ -50,11 +50,6 @@ pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error}; pub use unicode::tables::UNICODE_VERSION; #[unstable(feature = "unicode_version", issue = "49726")] pub use unicode::version::UnicodeVersion; -#[unstable(feature = "decode_utf8", issue = "33906")] -#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: - https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] -#[allow(deprecated)] -pub use self::decode::{decode_utf8, DecodeUtf8, InvalidSequence}; use fmt::{self, Write}; use iter::FusedIterator; @@ -317,8 +312,8 @@ impl Iterator for EscapeDefault { None } }, - EscapeDefaultState::Done => return None, - EscapeDefaultState::Unicode(ref mut i) => return i.nth(n), + EscapeDefaultState::Done => None, + EscapeDefaultState::Unicode(ref mut i) => i.nth(n), } } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 3626a266ad..ef7d83a099 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -75,7 +75,12 @@ use self::Ordering::*; /// the same book if their ISBN matches, even if the formats differ: /// /// ``` -/// enum BookFormat { Paperback, Hardback, Ebook } +/// enum BookFormat { +/// Paperback, +/// Hardback, +/// Ebook, +/// } +/// /// struct Book { /// isbn: i32, /// format: BookFormat, @@ -95,6 +100,84 @@ use self::Ordering::*; /// assert!(b1 != b3); /// ``` /// +/// ## How can I compare two different types? +/// +/// The type you can compare with is controlled by `PartialEq`'s type parameter. +/// For example, let's tweak our previous code a bit: +/// +/// ``` +/// enum BookFormat { +/// Paperback, +/// Hardback, +/// Ebook, +/// } +/// +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &BookFormat) -> bool { +/// match (&self.format, other) { +/// (BookFormat::Paperback, BookFormat::Paperback) => true, +/// (BookFormat::Hardback, BookFormat::Hardback) => true, +/// (BookFormat::Ebook, BookFormat::Ebook) => true, +/// (_, _) => false, +/// } +/// } +/// } +/// +/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; +/// +/// assert!(b1 == BookFormat::Paperback); +/// assert!(b1 != BookFormat::Ebook); +/// ``` +/// +/// By changing `impl PartialEq for Book` to `impl PartialEq for Book`, +/// we've changed what type we can use on the right side of the `==` operator. +/// This lets us use it in the `assert!` statements at the bottom. +/// +/// You can also combine these implementations to let the `==` operator work with +/// two different types: +/// +/// ``` +/// enum BookFormat { +/// Paperback, +/// Hardback, +/// Ebook, +/// } +/// +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &BookFormat) -> bool { +/// match (&self.format, other) { +/// (&BookFormat::Paperback, &BookFormat::Paperback) => true, +/// (&BookFormat::Hardback, &BookFormat::Hardback) => true, +/// (&BookFormat::Ebook, &BookFormat::Ebook) => true, +/// (_, _) => false, +/// } +/// } +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &Book) -> bool { +/// self.isbn == other.isbn +/// } +/// } +/// +/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; +/// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; +/// +/// assert!(b1 == BookFormat::Paperback); +/// assert!(b1 != BookFormat::Ebook); +/// assert!(b1 == b2); +/// ``` +/// /// # Examples /// /// ``` @@ -469,6 +552,7 @@ pub trait Ord: Eq + PartialOrd { /// assert_eq!(2, 2.max(2)); /// ``` #[stable(feature = "ord_max_min", since = "1.21.0")] + #[inline] fn max(self, other: Self) -> Self where Self: Sized { if other >= self { other } else { self } @@ -485,6 +569,7 @@ pub trait Ord: Eq + PartialOrd { /// assert_eq!(2, 2.min(2)); /// ``` #[stable(feature = "ord_max_min", since = "1.21.0")] + #[inline] fn min(self, other: Self) -> Self where Self: Sized { if self <= other { self } else { other } diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 11cc4ffecf..d533786884 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -48,6 +48,66 @@ #![stable(feature = "rust1", since = "1.0.0")] +/// An identity function. +/// +/// Two things are important to note about this function: +/// +/// - It is not always equivalent to a closure like `|x| x` since the +/// closure may coerce `x` into a different type. +/// +/// - It moves the input `x` passed to the function. +/// +/// While it might seem strange to have a function that just returns back the +/// input, there are some interesting uses. +/// +/// # Examples +/// +/// Using `identity` to do nothing among other interesting functions: +/// +/// ```rust +/// #![feature(convert_id)] +/// use std::convert::identity; +/// +/// fn manipulation(x: u32) -> u32 { +/// // Let's assume that this function does something interesting. +/// x + 1 +/// } +/// +/// let _arr = &[identity, manipulation]; +/// ``` +/// +/// Using `identity` to get a function that changes nothing in a conditional: +/// +/// ```rust +/// #![feature(convert_id)] +/// use std::convert::identity; +/// +/// # let condition = true; +/// +/// # fn manipulation(x: u32) -> u32 { x + 1 } +/// +/// let do_stuff = if condition { manipulation } else { identity }; +/// +/// // do more interesting stuff.. +/// +/// let _results = do_stuff(42); +/// ``` +/// +/// Using `identity` to keep the `Some` variants of an iterator of `Option`: +/// +/// ```rust +/// #![feature(convert_id)] +/// use std::convert::identity; +/// +/// let iter = vec![Some(1), None, Some(3)].into_iter(); +/// let filtered = iter.filter_map(identity).collect::>(); +/// assert_eq!(vec![1, 3], filtered); +/// ``` +#[unstable(feature = "convert_id", issue = "53500")] +#[rustc_const_unstable(feature = "const_convert_id")] +#[inline] +pub const fn identity(x: T) -> T { x } + /// A cheap reference-to-reference conversion. Used to convert a value to a /// reference value within generic code. /// diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs new file mode 100644 index 0000000000..a03756f9c2 --- /dev/null +++ b/src/libcore/ffi.rs @@ -0,0 +1,42 @@ +#![stable(feature = "", since = "1.30.0")] + +#![allow(non_camel_case_types)] + +//! Utilities related to FFI bindings. + +use ::fmt; + +/// Equivalent to C's `void` type when used as a [pointer]. +/// +/// In essence, `*const c_void` is equivalent to C's `const void*` +/// and `*mut c_void` is equivalent to C's `void*`. That said, this is +/// *not* the same as C's `void` return type, which is Rust's `()` type. +/// +/// Ideally, this type would be equivalent to [`!`], but currently it may +/// be more ideal to use `c_void` for FFI purposes. +/// +/// [`!`]: ../../std/primitive.never.html +/// [pointer]: ../../std/primitive.pointer.html +// NB: For LLVM to recognize the void pointer type and by extension +// functions like malloc(), we need to have it represented as i8* in +// LLVM bitcode. The enum used here ensures this and prevents misuse +// of the "raw" type by only having private variants.. We need two +// variants, because the compiler complains about the repr attribute +// otherwise. +#[repr(u8)] +#[stable(feature = "raw_os", since = "1.1.0")] +pub enum c_void { + #[unstable(feature = "c_void_variant", reason = "should not have to exist", + issue = "0")] + #[doc(hidden)] __variant1, + #[unstable(feature = "c_void_variant", reason = "should not have to exist", + issue = "0")] + #[doc(hidden)] __variant2, +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for c_void { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("c_void") + } +} diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 928f95e3ba..7d131b5c99 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1132,6 +1132,36 @@ impl<'a> Formatter<'a> { /// /// This function will correctly account for the flags provided as well as /// the minimum width. It will not take precision into account. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo { nb: i32 }; + /// + /// impl Foo { + /// fn new(nb: i32) -> Foo { + /// Foo { + /// nb, + /// } + /// } + /// } + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// // We need to remove "-" from the number output. + /// let tmp = self.nb.abs().to_string(); + /// + /// formatter.pad_integral(self.nb > 0, "Foo ", &tmp) + /// } + /// } + /// + /// assert_eq!(&format!("{}", Foo::new(2)), "2"); + /// assert_eq!(&format!("{}", Foo::new(-1)), "-1"); + /// assert_eq!(&format!("{:#}", Foo::new(-1)), "-Foo 1"); + /// 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, @@ -1232,7 +1262,7 @@ impl<'a> Formatter<'a> { // If our string is longer that the precision, then we must have // truncation. However other flags like `fill`, `width` and `align` // must act as always. - if let Some((i, _)) = s.char_indices().skip(max).next() { + if let Some((i, _)) = s.char_indices().nth(max) { // LLVM here can't prove that `..i` won't panic `&s[..i]`, but // we know that it can't panic. Use `get` + `unwrap_or` to avoid // `unsafe` and otherwise don't emit any panic-related code @@ -1381,12 +1411,48 @@ impl<'a> Formatter<'a> { /// Writes some data to the underlying buffer contained within this /// formatter. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo; + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// formatter.write_str("Foo") + /// // This is equivalent to: + /// // write!(formatter, "Foo") + /// } + /// } + /// + /// assert_eq!(&format!("{}", Foo), "Foo"); + /// assert_eq!(&format!("{:0>8}", Foo), "Foo"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_str(&mut self, data: &str) -> Result { self.buf.write_str(data) } /// Writes some formatted information into this instance. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// formatter.write_fmt(format_args!("Foo {}", self.0)) + /// } + /// } + /// + /// assert_eq!(&format!("{}", Foo(-1)), "Foo -1"); + /// assert_eq!(&format!("{:0>8}", Foo(2)), "Foo 2"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_fmt(&mut self, fmt: Arguments) -> Result { write(self.buf, fmt) diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 10b4ca9b0b..520b6ebbba 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -12,7 +12,7 @@ reason = "futures in libcore are unstable", issue = "50547")] -use mem::PinMut; +use pin::PinMut; use marker::Unpin; use task::{self, Poll}; diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index 98c504a3f7..68fe461aea 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -15,7 +15,7 @@ use fmt; use future::Future; use marker::{PhantomData, Unpin}; -use mem::PinMut; +use pin::PinMut; use task::{Context, Poll}; /// A custom trait object for polling futures, roughly akin to @@ -27,7 +27,7 @@ use task::{Context, Poll}; /// - The `Future` trait is currently not object safe: The `Future::poll` /// method makes uses the arbitrary self types feature and traits in which /// this feature is used are currently not object safe due to current compiler -/// limitations. (See tracking issue for arbitray self types for more +/// limitations. (See tracking issue for arbitrary self types for more /// information #44874) pub struct LocalFutureObj<'a, T> { ptr: *mut (), @@ -36,6 +36,8 @@ pub struct LocalFutureObj<'a, T> { _marker: PhantomData<&'a ()>, } +impl<'a, T> Unpin for LocalFutureObj<'a, T> {} + impl<'a, T> LocalFutureObj<'a, T> { /// Create a `LocalFutureObj` from a custom trait object representation. #[inline] @@ -100,10 +102,11 @@ impl<'a, T> Drop for LocalFutureObj<'a, T> { /// - The `Future` trait is currently not object safe: The `Future::poll` /// method makes uses the arbitrary self types feature and traits in which /// this feature is used are currently not object safe due to current compiler -/// limitations. (See tracking issue for arbitray self types for more +/// limitations. (See tracking issue for arbitrary self types for more /// information #44874) pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); +impl<'a, T> Unpin for FutureObj<'a, T> {} unsafe impl<'a, T> Send for FutureObj<'a, T> {} impl<'a, T> FutureObj<'a, T> { diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 854cb5f4e3..7756a6f71d 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -918,7 +918,7 @@ extern "rust-intrinsic" { /// // treat it as "dead", and therefore, you only have two real /// // mutable slices. /// (slice::from_raw_parts_mut(ptr, mid), - /// slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid)) + /// slice::from_raw_parts_mut(ptr.add(mid), len - mid)) /// } /// } /// ``` @@ -1087,11 +1087,9 @@ extern "rust-intrinsic" { /// Perform a volatile load from the `src` pointer /// The pointer is not required to be aligned. - #[cfg(not(stage0))] pub fn unaligned_volatile_load(src: *const T) -> T; /// Perform a volatile store to the `dst` pointer. /// The pointer is not required to be aligned. - #[cfg(not(stage0))] pub fn unaligned_volatile_store(dst: *mut T, val: T); /// Returns the square root of an `f32` diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 48c6eb9414..d45c123d33 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -507,7 +507,7 @@ pub trait Iterator { fn map(self, f: F) -> Map where Self: Sized, F: FnMut(Self::Item) -> B, { - Map{iter: self, f: f} + Map { iter: self, f } } /// Calls a closure on each element of an iterator. @@ -618,7 +618,7 @@ pub trait Iterator { fn filter

(self, predicate: P) -> Filter where Self: Sized, P: FnMut(&Self::Item) -> bool, { - Filter{iter: self, predicate: predicate} + Filter {iter: self, predicate } } /// Creates an iterator that both filters and maps. @@ -675,7 +675,7 @@ pub trait Iterator { fn filter_map(self, f: F) -> FilterMap where Self: Sized, F: FnMut(Self::Item) -> Option, { - FilterMap { iter: self, f: f } + FilterMap { iter: self, f } } /// Creates an iterator which gives the current iteration count as well as @@ -828,7 +828,7 @@ pub trait Iterator { fn skip_while

(self, predicate: P) -> SkipWhile where Self: Sized, P: FnMut(&Self::Item) -> bool, { - SkipWhile{iter: self, flag: false, predicate: predicate} + SkipWhile { iter: self, flag: false, predicate } } /// Creates an iterator that yields elements based on a predicate. @@ -908,7 +908,7 @@ pub trait Iterator { fn take_while

(self, predicate: P) -> TakeWhile where Self: Sized, P: FnMut(&Self::Item) -> bool, { - TakeWhile{iter: self, flag: false, predicate: predicate} + TakeWhile { iter: self, flag: false, predicate } } /// Creates an iterator that skips the first `n` elements. @@ -930,7 +930,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn skip(self, n: usize) -> Skip where Self: Sized { - Skip{iter: self, n: n} + Skip { iter: self, n } } /// Creates an iterator that yields its first `n` elements. @@ -962,7 +962,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn take(self, n: usize) -> Take where Self: Sized, { - Take{iter: self, n: n} + Take { iter: self, n } } /// An iterator adaptor similar to [`fold`] that holds internal state and @@ -1007,7 +1007,7 @@ pub trait Iterator { fn scan(self, initial_state: St, f: F) -> Scan where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option, { - Scan{iter: self, f: f, state: initial_state} + Scan { iter: self, f, state: initial_state } } /// Creates an iterator that works like map, but flattens nested structure. @@ -1110,7 +1110,7 @@ pub trait Iterator { /// /// [`flat_map()`]: #method.flat_map #[inline] - #[stable(feature = "iterator_flatten", since = "1.29")] + #[stable(feature = "iterator_flatten", since = "1.29.0")] fn flatten(self) -> Flatten where Self: Sized, Self::Item: IntoIterator { Flatten { inner: flatten_compat(self) } @@ -1256,7 +1256,7 @@ pub trait Iterator { fn inspect(self, f: F) -> Inspect where Self: Sized, F: FnMut(&Self::Item), { - Inspect{iter: self, f: f} + Inspect { iter: self, f } } /// Borrows an iterator, rather than consuming it. @@ -1794,7 +1794,6 @@ pub trait Iterator { /// # Examples /// /// ``` - /// #![feature(iterator_find_map)] /// let a = ["lol", "NaN", "2", "5"]; /// /// let mut first_number = a.iter().find_map(|s| s.parse().ok()); @@ -1802,9 +1801,7 @@ pub trait Iterator { /// assert_eq!(first_number, Some(2)); /// ``` #[inline] - #[unstable(feature = "iterator_find_map", - reason = "unstable new API", - issue = "49602")] + #[stable(feature = "iterator_find_map", since = "1.30.0")] fn find_map(&mut self, mut f: F) -> Option where Self: Sized, F: FnMut(Self::Item) -> Option, diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 35ae774110..ef3f4ced4f 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -2577,13 +2577,13 @@ impl FusedIterator for FlatMap /// [`flatten`]: trait.Iterator.html#method.flatten /// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[stable(feature = "iterator_flatten", since = "1.29")] +#[stable(feature = "iterator_flatten", since = "1.29.0")] pub struct Flatten where I::Item: IntoIterator { inner: FlattenCompat::IntoIter>, } -#[stable(feature = "iterator_flatten", since = "1.29")] +#[stable(feature = "iterator_flatten", since = "1.29.0")] impl fmt::Debug for Flatten where I: Iterator + fmt::Debug, U: Iterator + fmt::Debug, I::Item: IntoIterator, @@ -2593,7 +2593,7 @@ impl fmt::Debug for Flatten } } -#[stable(feature = "iterator_flatten", since = "1.29")] +#[stable(feature = "iterator_flatten", since = "1.29.0")] impl Clone for Flatten where I: Iterator + Clone, U: Iterator + Clone, I::Item: IntoIterator, @@ -2601,7 +2601,7 @@ impl Clone for Flatten fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } } } -#[stable(feature = "iterator_flatten", since = "1.29")] +#[stable(feature = "iterator_flatten", since = "1.29.0")] impl Iterator for Flatten where I: Iterator, U: Iterator, I::Item: IntoIterator @@ -2629,7 +2629,7 @@ impl Iterator for Flatten } } -#[stable(feature = "iterator_flatten", since = "1.29")] +#[stable(feature = "iterator_flatten", since = "1.29.0")] impl DoubleEndedIterator for Flatten where I: DoubleEndedIterator, U: DoubleEndedIterator, I::Item: IntoIterator @@ -2652,7 +2652,7 @@ impl DoubleEndedIterator for Flatten } } -#[stable(feature = "iterator_flatten", since = "1.29")] +#[stable(feature = "iterator_flatten", since = "1.29.0")] impl FusedIterator for Flatten where I: FusedIterator, U: Iterator, I::Item: IntoIterator {} diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 651c7a35d4..55addd86bc 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -165,8 +165,16 @@ macro_rules! step_impl_no_between { )*) } -step_impl_unsigned!(usize u8 u16 u32); -step_impl_signed!([isize: usize] [i8: u8] [i16: u16] [i32: u32]); +step_impl_unsigned!(usize u8 u16); +#[cfg(not(target_pointer_witdth = "16"))] +step_impl_unsigned!(u32); +#[cfg(target_pointer_witdth = "16")] +step_impl_no_between!(u32); +step_impl_signed!([isize: usize] [i8: u8] [i16: u16]); +#[cfg(not(target_pointer_witdth = "16"))] +step_impl_signed!([i32: u32]); +#[cfg(target_pointer_witdth = "16")] +step_impl_no_between!(i32); #[cfg(target_pointer_width = "64")] step_impl_unsigned!(u64); #[cfg(target_pointer_width = "64")] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 72074e1dbc..675e73e952 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -77,12 +77,11 @@ #![feature(arbitrary_self_types)] #![feature(asm)] #![feature(associated_type_defaults)] -#![feature(attr_literals)] #![feature(cfg_target_has_atomic)] #![feature(concat_idents)] #![feature(const_fn)] #![feature(const_int_ops)] -#![feature(core_float)] +#![feature(const_fn_union)] #![feature(custom_attribute)] #![feature(doc_cfg)] #![feature(doc_spotlight)] @@ -92,6 +91,7 @@ #![feature(lang_items)] #![feature(link_llvm_intrinsics)] #![feature(never_type)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(exhaustive_patterns)] #![feature(macro_at_most_once_rep)] #![feature(no_core)] @@ -102,8 +102,6 @@ #![feature(rustc_attrs)] #![feature(rustc_const_unstable)] #![feature(simd_ffi)] -#![feature(core_slice_ext)] -#![feature(core_str_ext)] #![feature(specialization)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] @@ -111,7 +109,6 @@ #![feature(untagged_unions)] #![feature(unwind_attributes)] #![feature(doc_alias)] -#![feature(inclusive_range_methods)] #![feature(mmx_target_feature)] #![feature(tbm_target_feature)] #![feature(sse4a_target_feature)] @@ -122,6 +119,14 @@ #![feature(const_slice_len)] #![feature(const_str_as_bytes)] #![feature(const_str_len)] +#![feature(const_let)] +#![feature(const_int_rotate)] +#![feature(const_int_wrapping)] +#![feature(const_int_sign)] +#![feature(const_int_conversion)] +#![feature(const_transmute)] +#![feature(reverse_bits)] +#![feature(non_exhaustive)] #[prelude_import] #[allow(unused)] @@ -192,10 +197,12 @@ pub mod cell; pub mod char; pub mod panic; pub mod panicking; +pub mod pin; pub mod iter; pub mod option; pub mod raw; pub mod result; +pub mod ffi; pub mod slice; pub mod str; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 83f9dfea8f..a0c87f13e5 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -349,6 +349,26 @@ macro_rules! try { /// write!(&mut v, "s = {:?}", s).unwrap(); // uses io::Write::write_fmt /// assert_eq!(v, b"s = \"abc 123\""); /// ``` +/// +/// Note: This macro can be used in `no_std` setups as well +/// In a `no_std` setup you are responsible for the +/// implementation details of the components. +/// +/// ```no_run +/// # extern crate core; +/// use core::fmt::Write; +/// +/// struct Example; +/// +/// impl Write for Example { +/// fn write_str(&mut self, _s: &str) -> core::fmt::Result { +/// unimplemented!(); +/// } +/// } +/// +/// let mut m = Example{}; +/// write!(&mut m, "Hello World").expect("Not written"); +/// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! write { @@ -396,6 +416,7 @@ macro_rules! write { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] macro_rules! writeln { ($dst:expr) => ( write!($dst, "\n") @@ -403,11 +424,8 @@ macro_rules! writeln { ($dst:expr,) => ( writeln!($dst) ); - ($dst:expr, $fmt:expr) => ( - write!($dst, concat!($fmt, "\n")) - ); - ($dst:expr, $fmt:expr, $($arg:tt)*) => ( - write!($dst, concat!($fmt, "\n"), $($arg)*) + ($dst:expr, $($arg:tt)*) => ( + $dst.write_fmt(format_args_nl!($($arg)*)) ); } @@ -543,7 +561,7 @@ macro_rules! unimplemented { /// into libsyntax itself. /// /// For more information, see documentation for `std`'s macros. -#[cfg(dox)] +#[cfg(rustdoc)] mod builtin { /// Unconditionally causes compilation to fail with the given error message when encountered. diff --git a/src/libcore/manually_drop_stage0.rs b/src/libcore/manually_drop_stage0.rs deleted file mode 100644 index 8643219cb6..0000000000 --- a/src/libcore/manually_drop_stage0.rs +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// A wrapper to inhibit compiler from automatically calling `T`’s destructor. -/// -/// This wrapper is 0-cost. -/// -/// # Examples -/// -/// This wrapper helps with explicitly documenting the drop order dependencies between fields of -/// the type: -/// -/// ```rust -/// use std::mem::ManuallyDrop; -/// struct Peach; -/// struct Banana; -/// struct Melon; -/// struct FruitBox { -/// // Immediately clear there’s something non-trivial going on with these fields. -/// peach: ManuallyDrop, -/// melon: Melon, // Field that’s independent of the other two. -/// banana: ManuallyDrop, -/// } -/// -/// impl Drop for FruitBox { -/// fn drop(&mut self) { -/// unsafe { -/// // Explicit ordering in which field destructors are run specified in the intuitive -/// // location – the destructor of the structure containing the fields. -/// // Moreover, one can now reorder fields within the struct however much they want. -/// ManuallyDrop::drop(&mut self.peach); -/// ManuallyDrop::drop(&mut self.banana); -/// } -/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets -/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`. -/// } -/// } -/// ``` -#[stable(feature = "manually_drop", since = "1.20.0")] -#[allow(unions_with_drop_fields)] -#[derive(Copy)] -pub union ManuallyDrop{ value: T } - -impl ManuallyDrop { - /// Wrap a value to be manually dropped. - /// - /// # Examples - /// - /// ```rust - /// use std::mem::ManuallyDrop; - /// ManuallyDrop::new(Box::new(())); - /// ``` - #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_manually_drop_new")] - #[inline] - pub const fn new(value: T) -> ManuallyDrop { - ManuallyDrop { value: value } - } - - /// Extract the value from the ManuallyDrop container. - /// - /// # Examples - /// - /// ```rust - /// use std::mem::ManuallyDrop; - /// let x = ManuallyDrop::new(Box::new(())); - /// let _: Box<()> = ManuallyDrop::into_inner(x); - /// ``` - #[stable(feature = "manually_drop", since = "1.20.0")] - #[inline] - pub fn into_inner(slot: ManuallyDrop) -> T { - unsafe { - slot.value - } - } - - /// Manually drops the contained value. - /// - /// # Safety - /// - /// This function runs the destructor of the contained value and thus the wrapped value - /// now represents uninitialized data. It is up to the user of this method to ensure the - /// uninitialized data is not actually used. - #[stable(feature = "manually_drop", since = "1.20.0")] - #[inline] - pub unsafe fn drop(slot: &mut ManuallyDrop) { - ptr::drop_in_place(&mut slot.value) - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl Deref for ManuallyDrop { - type Target = T; - #[inline] - fn deref(&self) -> &Self::Target { - unsafe { - &self.value - } - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl DerefMut for ManuallyDrop { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { - &mut self.value - } - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl ::fmt::Debug for ManuallyDrop { - fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result { - unsafe { - fmt.debug_tuple("ManuallyDrop").field(&self.value).finish() - } - } -} - -#[stable(feature = "manually_drop_impls", since = "1.22.0")] -impl Clone for ManuallyDrop { - fn clone(&self) -> Self { - ManuallyDrop::new(self.deref().clone()) - } - - fn clone_from(&mut self, source: &Self) { - self.deref_mut().clone_from(source); - } -} - -#[stable(feature = "manually_drop_impls", since = "1.22.0")] -impl Default for ManuallyDrop { - fn default() -> Self { - ManuallyDrop::new(Default::default()) - } -} - -#[stable(feature = "manually_drop_impls", since = "1.22.0")] -impl PartialEq for ManuallyDrop { - fn eq(&self, other: &Self) -> bool { - self.deref().eq(other) - } - - fn ne(&self, other: &Self) -> bool { - self.deref().ne(other) - } -} - -#[stable(feature = "manually_drop_impls", since = "1.22.0")] -impl Eq for ManuallyDrop {} - -#[stable(feature = "manually_drop_impls", since = "1.22.0")] -impl PartialOrd for ManuallyDrop { - fn partial_cmp(&self, other: &Self) -> Option<::cmp::Ordering> { - self.deref().partial_cmp(other) - } - - fn lt(&self, other: &Self) -> bool { - self.deref().lt(other) - } - - fn le(&self, other: &Self) -> bool { - self.deref().le(other) - } - - fn gt(&self, other: &Self) -> bool { - self.deref().gt(other) - } - - fn ge(&self, other: &Self) -> bool { - self.deref().ge(other) - } -} - -#[stable(feature = "manually_drop_impls", since = "1.22.0")] -impl Ord for ManuallyDrop { - fn cmp(&self, other: &Self) -> ::cmp::Ordering { - self.deref().cmp(other) - } -} - -#[stable(feature = "manually_drop_impls", since = "1.22.0")] -impl ::hash::Hash for ManuallyDrop { - fn hash(&self, state: &mut H) { - self.deref().hash(state); - } -} diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 4f37b46258..dd57d2dd00 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -95,7 +95,7 @@ impl !Send for *mut T { } message="the size for values of type `{Self}` cannot be known at compilation time", label="doesn't have a size known at compile-time", note="to learn more, visit ", + ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>", )] #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable pub trait Sized { @@ -511,7 +511,7 @@ macro_rules! impls{ /// let ptr = vec.as_ptr(); /// Slice { /// start: ptr, -/// end: unsafe { ptr.offset(vec.len() as isize) }, +/// end: unsafe { ptr.add(vec.len()) }, /// phantom: PhantomData, /// } /// } @@ -603,15 +603,38 @@ unsafe impl Freeze for *mut T {} unsafe impl<'a, T: ?Sized> Freeze for &'a T {} unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} -/// Types which can be moved out of a `PinMut`. +/// Types which can be safely moved after being pinned. /// -/// The `Unpin` trait is used to control the behavior of the [`PinMut`] type. If a -/// type implements `Unpin`, it is safe to move a value of that type out of the -/// `PinMut` pointer. +/// Since Rust itself has no notion of immovable types, and will consider moves to always be safe, +/// this trait cannot prevent types from moving by itself. +/// +/// Instead it can be used to prevent moves through the type system, +/// by controlling the behavior of special pointer types like [`PinMut`], +/// which "pin" the type in place by not allowing it to be moved out of them. +/// See the [`pin module`] documentation for more information on pinning. +/// +/// Implementing this trait lifts the restrictions of pinning off a type, +/// which then allows it to move out with functions such as [`replace`]. +/// +/// So this, for example, can only be done on types implementing `Unpin`: +/// +/// ```rust +/// #![feature(pin)] +/// use std::mem::replace; +/// use std::pin::PinMut; +/// +/// let mut string = "this".to_string(); +/// let mut pinned_string = PinMut::new(&mut string); +/// +/// // dereferencing the pointer mutably is only possible because String implements Unpin +/// replace(&mut *pinned_string, "other".to_string()); +/// ``` /// /// This trait is automatically implemented for almost every type. /// -/// [`PinMut`]: ../mem/struct.PinMut.html +/// [`replace`]: ../../std/mem/fn.replace.html +/// [`PinMut`]: ../pin/struct.PinMut.html +/// [`pin module`]: ../../std/pin/index.html #[unstable(feature = "pin", issue = "49150")] pub auto trait Unpin {} diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 1a54f03bb0..1803adee3c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -18,24 +18,24 @@ use clone; use cmp; use fmt; -use future::{Future, UnsafeFutureObj}; use hash; use intrinsics; -use marker::{Copy, PhantomData, Sized, Unpin, Unsize}; +use marker::{Copy, PhantomData, Sized}; use ptr; -use task::{Context, Poll}; -use ops::{Deref, DerefMut, CoerceUnsized}; +use ops::{Deref, DerefMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use intrinsics::transmute; -/// Leaks a value: takes ownership and "forgets" about the value **without running -/// its destructor**. +/// Takes ownership and "forgets" about the value **without running its destructor**. /// /// Any resources the value manages, such as heap memory or a file handle, will linger -/// forever in an unreachable state. +/// forever in an unreachable state. However, it does not guarantee that pointers +/// to this memory will remain valid. /// -/// If you want to dispose of a value properly, running its destructor, see +/// * If you want to leak memory, see [`Box::leak`][leak]. +/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw]. +/// * If you want to dispose of a value properly, running its destructor, see /// [`mem::drop`][drop]. /// /// # Safety @@ -59,15 +59,6 @@ pub use intrinsics::transmute; /// /// # Examples /// -/// Leak some heap memory by never deallocating it: -/// -/// ``` -/// use std::mem; -/// -/// let heap_memory = Box::new(3); -/// mem::forget(heap_memory); -/// ``` -/// /// Leak an I/O object, never closing the file: /// /// ```no_run @@ -137,38 +128,13 @@ pub use intrinsics::transmute; /// } /// ``` /// -/// ## Use case 3 -/// -/// You are transferring ownership across a [FFI] boundary to code written in -/// another language. You need to `forget` the value on the Rust side because Rust -/// code is no longer responsible for it. -/// -/// ```no_run -/// use std::mem; -/// -/// extern "C" { -/// fn my_c_function(x: *const u32); -/// } -/// -/// let x: Box = Box::new(3); -/// -/// // Transfer ownership into C code. -/// unsafe { -/// my_c_function(&*x); -/// } -/// mem::forget(x); -/// ``` -/// -/// In this case, C code must call back into Rust to free the object. Calling C's `free` -/// function on a [`Box`][box] is *not* safe! Also, `Box` provides an [`into_raw`][into_raw] -/// method which is the preferred way to do this in practice. -/// /// [drop]: fn.drop.html /// [uninit]: fn.uninitialized.html /// [clone]: ../clone/trait.Clone.html /// [swap]: fn.swap.html /// [FFI]: ../../book/first-edition/ffi.html /// [box]: ../../std/boxed/struct.Box.html +/// [leak]: ../../std/boxed/struct.Box.html#method.leak /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw /// [ub]: ../../reference/behavior-considered-undefined.html #[inline] @@ -319,6 +285,15 @@ pub fn forget(t: T) { /// [alignment]: ./fn.align_of.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +pub const fn size_of() -> usize { + intrinsics::size_of::() +} + +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +/// Ceci n'est pas la documentation pub const fn size_of() -> usize { unsafe { intrinsics::size_of::() } } @@ -368,6 +343,16 @@ pub fn size_of_val(val: &T) -> usize { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] +#[cfg(not(stage0))] +pub fn min_align_of() -> usize { + intrinsics::min_align_of::() +} + +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] +#[cfg(stage0)] +/// Ceci n'est pas la documentation pub fn min_align_of() -> usize { unsafe { intrinsics::min_align_of::() } } @@ -410,6 +395,15 @@ pub fn min_align_of_val(val: &T) -> usize { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +pub const fn align_of() -> usize { + intrinsics::min_align_of::() +} + +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +/// Ceci n'est pas la documentation pub const fn align_of() -> usize { unsafe { intrinsics::min_align_of::() } } @@ -953,18 +947,14 @@ pub fn discriminant(v: &T) -> Discriminant { /// } /// } /// ``` -#[cfg(not(stage0))] #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ManuallyDrop { +#[repr(transparent)] +pub struct ManuallyDrop { value: T, } -#[cfg(stage0)] -include!("manually_drop_stage0.rs"); - -#[cfg(not(stage0))] impl ManuallyDrop { /// Wrap a value to be manually dropped. /// @@ -981,28 +971,36 @@ impl ManuallyDrop { ManuallyDrop { value } } - /// Extract the value from the ManuallyDrop container. + /// Extract the value from the `ManuallyDrop` container. + /// + /// This allows the value to be dropped again. /// /// # Examples /// /// ```rust /// use std::mem::ManuallyDrop; /// let x = ManuallyDrop::new(Box::new(())); - /// let _: Box<()> = ManuallyDrop::into_inner(x); + /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub fn into_inner(slot: ManuallyDrop) -> T { slot.value } +} +impl ManuallyDrop { /// Manually drops the contained value. /// + /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead. + /// /// # Safety /// /// This function runs the destructor of the contained value and thus the wrapped value /// now represents uninitialized data. It is up to the user of this method to ensure the /// uninitialized data is not actually used. + /// + /// [`ManuallyDrop::into_inner`]: #method.into_inner #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub unsafe fn drop(slot: &mut ManuallyDrop) { @@ -1010,9 +1008,8 @@ impl ManuallyDrop { } } -#[cfg(not(stage0))] #[stable(feature = "manually_drop", since = "1.20.0")] -impl Deref for ManuallyDrop { +impl Deref for ManuallyDrop { type Target = T; #[inline] fn deref(&self) -> &Self::Target { @@ -1020,154 +1017,10 @@ impl Deref for ManuallyDrop { } } -#[cfg(not(stage0))] #[stable(feature = "manually_drop", since = "1.20.0")] -impl DerefMut for ManuallyDrop { +impl DerefMut for ManuallyDrop { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.value } } - -/// A pinned reference. -/// -/// A pinned reference is a lot like a mutable reference, except that it is not -/// safe to move a value out of a pinned reference unless the type of that -/// value implements the `Unpin` trait. -#[unstable(feature = "pin", issue = "49150")] -#[fundamental] -pub struct PinMut<'a, T: ?Sized + 'a> { - inner: &'a mut T, -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unpin> PinMut<'a, T> { - /// Construct a new `PinMut` around a reference to some data of a type that - /// implements `Unpin`. - #[unstable(feature = "pin", issue = "49150")] - pub fn new(reference: &'a mut T) -> PinMut<'a, T> { - PinMut { inner: reference } - } - - /// Get a mutable reference to the data inside of this `PinMut`. - #[unstable(feature = "pin", issue = "49150")] - pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T { - this.inner - } -} - - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> PinMut<'a, T> { - /// Construct a new `PinMut` around a reference to some data of a type that - /// may or may not implement `Unpin`. - /// - /// This constructor is unsafe because we do not know what will happen with - /// that data after the reference ends. If you cannot guarantee that the - /// data will never move again, calling this constructor is invalid. - #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn new_unchecked(reference: &'a mut T) -> PinMut<'a, T> { - PinMut { inner: reference } - } - - /// Reborrow a `PinMut` for a shorter lifetime. - /// - /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a - /// short-lived mutable reference reborrowing from `x`. - #[unstable(feature = "pin", issue = "49150")] - pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> { - PinMut { inner: self.inner } - } - - /// Get a mutable reference to the data inside of this `PinMut`. - /// - /// This function is unsafe. You must guarantee that you will never move - /// the data out of the mutable reference you receive when you call this - /// function. - #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T { - this.inner - } - - /// Construct a new pin by mapping the interior value. - /// - /// For example, if you wanted to get a `PinMut` of a field of something, - /// you could use this to get access to that field in one line of code. - /// - /// This function is unsafe. You must guarantee that the data you return - /// will not move so long as the argument value does not move (for example, - /// because it is one of the fields of that value), and also that you do - /// not move out of the argument you receive to the interior function. - #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn map_unchecked(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where - F: FnOnce(&mut T) -> &mut U - { - PinMut { inner: f(this.inner) } - } - - /// Assign a new value to the memory behind the pinned reference. - #[unstable(feature = "pin", issue = "49150")] - pub fn set(this: PinMut<'a, T>, value: T) - where T: Sized, - { - *this.inner = value; - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Deref for PinMut<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - &*self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> { - fn deref_mut(&mut self) -> &mut T { - self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Pointer::fmt(&(&*self.inner as *const T), f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for PinMut<'a, T> {} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {} - -#[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinMut<'a, F> - where F: Future + 'a -{ - fn into_raw(self) -> *mut () { - unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () } - } - - unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) - } - - unsafe fn drop(_ptr: *mut ()) {} -} diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index cc36ea7f71..30067d7e16 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -14,7 +14,8 @@ use ops::CoerceUnsized; /// A wrapper type for raw pointers and integers that will never be /// NULL or 0 that might allow certain optimizations. -#[lang = "non_zero"] +#[cfg_attr(stage0, lang = "non_zero")] +#[cfg_attr(not(stage0), rustc_layout_scalar_valid_range_start(1))] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] pub(crate) struct NonZero(pub(crate) T); diff --git a/src/libcore/num/dec2flt/parse.rs b/src/libcore/num/dec2flt/parse.rs index 69418434eb..e7ed94d4d9 100644 --- a/src/libcore/num/dec2flt/parse.rs +++ b/src/libcore/num/dec2flt/parse.rs @@ -40,7 +40,7 @@ pub struct Decimal<'a> { impl<'a> Decimal<'a> { pub fn new(integral: &'a [u8], fractional: &'a [u8], exp: i64) -> Decimal<'a> { - Decimal { integral: integral, fractional: fractional, exp: exp } + Decimal { integral, fractional, exp } } } diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs index 456d0e956d..38f4e4687a 100644 --- a/src/libcore/num/dec2flt/rawfp.rs +++ b/src/libcore/num/dec2flt/rawfp.rs @@ -45,7 +45,7 @@ pub struct Unpacked { impl Unpacked { pub fn new(sig: u64, k: i16) -> Self { - Unpacked { sig: sig, k: k } + Unpacked { sig, k } } } @@ -317,13 +317,13 @@ pub fn big_to_fp(f: &Big) -> Fp { // We cut off all bits prior to the index `start`, i.e., we effectively right-shift by // an amount of `start`, so this is also the exponent we need. let e = start as i16; - let rounded_down = Fp { f: leading, e: e }.normalize(); + let rounded_down = Fp { f: leading, e }.normalize(); // Round (half-to-even) depending on the truncated bits. match num::compare_with_half_ulp(f, start) { Less => rounded_down, Equal if leading % 2 == 0 => rounded_down, Equal | Greater => match leading.checked_add(1) { - Some(f) => Fp { f: f, e: e }.normalize(), + Some(f) => Fp { f, e }.normalize(), None => Fp { f: 1 << 63, e: e + 1 }, } } diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs index 97bcba2f2f..b0561da593 100644 --- a/src/libcore/num/diy_float.rs +++ b/src/libcore/num/diy_float.rs @@ -42,7 +42,7 @@ impl Fp { let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */; let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); let e = self.e + other.e + 64; - Fp { f: f, e: e } + Fp { f, e } } /// Normalizes itself so that the resulting mantissa is at least `2^63`. @@ -74,7 +74,7 @@ impl Fp { e -= 1; } debug_assert!(f >= (1 >> 63)); - Fp { f: f, e: e } + Fp { f, e } } /// Normalizes itself to have the shared exponent. diff --git a/src/libcore/num/flt2dec/decoder.rs b/src/libcore/num/flt2dec/decoder.rs index b779eefce5..c34a56f288 100644 --- a/src/libcore/num/flt2dec/decoder.rs +++ b/src/libcore/num/flt2dec/decoder.rs @@ -77,8 +77,8 @@ 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: mant, minus: 1, plus: 1, - exp: exp, inclusive: even }) + FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1, + exp, inclusive: even }) } FpCategory::Normal => { let minnorm = ::min_pos_norm_value().integer_decode(); diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index beaa6e140a..21a2e72dac 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -424,20 +424,20 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, match full_decoded { FullDecoded::Nan => { parts[0] = Part::Copy(b"NaN"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Infinite => { parts[0] = Part::Copy(b"inf"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Zero => { if frac_digits > 0 { // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); - Formatted { sign: sign, parts: &parts[..2] } + Formatted { sign, parts: &parts[..2] } } else { parts[0] = Part::Copy(b"0"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } } FullDecoded::Finite(ref decoded) => { @@ -480,11 +480,11 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T, match full_decoded { FullDecoded::Nan => { parts[0] = Part::Copy(b"NaN"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Infinite => { parts[0] = Part::Copy(b"inf"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Zero => { parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 { @@ -492,7 +492,7 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T, } else { Part::Copy(if upper { b"0E0" } else { b"0e0" }) }; - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Finite(ref decoded) => { let (len, exp) = format_shortest(decoded, buf); @@ -502,7 +502,7 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T, } else { digits_to_exp_str(&buf[..len], exp, 0, upper, parts) }; - Formatted { sign: sign, parts: parts } + Formatted { sign, parts } } } } @@ -558,21 +558,21 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, match full_decoded { FullDecoded::Nan => { parts[0] = Part::Copy(b"NaN"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Infinite => { parts[0] = Part::Copy(b"inf"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Zero => { 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" }); - Formatted { sign: sign, parts: &parts[..3] } + Formatted { sign, parts: &parts[..3] } } else { parts[0] = Part::Copy(if upper { b"0E0" } else { b"0e0" }); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } } FullDecoded::Finite(ref decoded) => { @@ -613,20 +613,20 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, match full_decoded { FullDecoded::Nan => { parts[0] = Part::Copy(b"NaN"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Infinite => { parts[0] = Part::Copy(b"inf"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } FullDecoded::Zero => { if frac_digits > 0 { // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); - Formatted { sign: sign, parts: &parts[..2] } + Formatted { sign, parts: &parts[..2] } } else { parts[0] = Part::Copy(b"0"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } } FullDecoded::Finite(ref decoded) => { @@ -646,10 +646,10 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, if frac_digits > 0 { // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); - Formatted { sign: sign, parts: &parts[..2] } + Formatted { sign, parts: &parts[..2] } } else { parts[0] = Part::Copy(b"0"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { sign, parts: &parts[..1] } } } else { Formatted { sign, diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index f33186e59c..effe073c38 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -129,7 +129,7 @@ pub fn cached_power(alpha: i16, gamma: i16) -> (i16, Fp) { let idx = ((gamma as i32) - offset) * range / domain; let (f, e, k) = CACHED_POW10[idx as usize]; debug_assert!(alpha <= e && e <= gamma); - (k, Fp { f: f, e: e }) + (k, Fp { f, e }) } /// Given `x > 0`, returns `(k, 10^k)` such that `10^k <= x < 10^(k+1)`. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 3bc2861460..12da0455cc 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -34,22 +34,32 @@ macro_rules! impl_nonzero_fmt { } } +macro_rules! doc_comment { + ($x:expr, $($tt:tt)*) => { + #[doc = $x] + $($tt)* + }; +} + macro_rules! nonzero_integers { ( $( $Ty: ident($Int: ty); )+ ) => { $( - /// An integer that is known not to equal zero. - /// - /// This enables some memory layout optimization. - /// For example, `Option` is the same size as `u32`: - /// - /// ```rust - /// use std::mem::size_of; - /// assert_eq!(size_of::>(), size_of::()); - /// ``` - #[stable(feature = "nonzero", since = "1.28.0")] - #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] - #[repr(transparent)] - pub struct $Ty(NonZero<$Int>); + doc_comment! { + concat!("An integer that is known not to equal zero. + +This enables some memory layout optimization. +For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`: + +```rust +use std::mem::size_of; +assert_eq!(size_of::>(), size_of::<", stringify!($Int), +">()); +```"), + #[stable(feature = "nonzero", since = "1.28.0")] + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + #[repr(transparent)] + pub struct $Ty(NonZero<$Int>); + } impl $Ty { /// Create a non-zero without checking the value. @@ -112,6 +122,9 @@ nonzero_integers! { /// all standard arithmetic operations on the underlying value are /// intended to have wrapping semantics. /// +/// The underlying value can be retrieved through the `.0` index of the +/// `Wrapping` tuple. +/// /// # Examples /// /// ``` @@ -176,19 +189,13 @@ pub mod dec2flt; pub mod bignum; pub mod diy_float; -macro_rules! doc_comment { - ($x:expr, $($tt:tt)*) => { - #[doc = $x] - $($tt)* - }; -} - mod wrapping; // `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) => { + $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, + $reversed:expr, $le_bytes:expr, $be_bytes:expr) => { doc_comment! { concat!("Returns the smallest value that can be represented by this integer type. @@ -334,106 +341,127 @@ $EndFeature, " } } - /// Shifts the bits to the left by a specified amount, `n`, - /// wrapping the truncated bits to the end of the resulting integer. - /// - /// Please note this isn't the same operation as `<<`! - /// - /// # Examples - /// - /// Please note that this example is shared between integer types. - /// Which explains why `i64` is used here. - /// - /// Basic usage: - /// - /// ``` - /// let n = 0x0123456789ABCDEFi64; - /// let m = -0x76543210FEDCBA99i64; - /// - /// assert_eq!(n.rotate_left(32), m); - /// ``` + /// no docs here #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[cfg(stage0)] pub fn rotate_left(self, n: u32) -> Self { (self as $UnsignedT).rotate_left(n) as Self } - /// Shifts the bits to the right by a specified amount, `n`, - /// wrapping the truncated bits to the beginning of the resulting - /// integer. - /// - /// Please note this isn't the same operation as `>>`! - /// - /// # Examples - /// - /// Please note that this example is shared between integer types. - /// Which explains why `i64` is used here. - /// - /// Basic usage: - /// - /// ``` - /// let n = 0x0123456789ABCDEFi64; - /// let m = -0xFEDCBA987654322i64; - /// - /// assert_eq!(n.rotate_right(4), m); - /// ``` + doc_comment! { + concat!("Shifts the bits to the left by a specified amount, `n`, +wrapping the truncated bits to the end of the resulting integer. + +Please note this isn't the same operation as `<<`! + +# Examples + +Basic usage: + +``` +let n = ", $rot_op, stringify!($SelfT), "; +let m = ", $rot_result, "; + +assert_eq!(n.rotate_left(", $rot, "), m); +```"), + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_rotate")] + #[inline] + #[cfg(not(stage0))] + pub const fn rotate_left(self, n: u32) -> Self { + (self as $UnsignedT).rotate_left(n) as Self + } + } + + /// no docs here #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[cfg(stage0)] pub fn rotate_right(self, n: u32) -> Self { (self as $UnsignedT).rotate_right(n) as Self } - /// Reverses the byte order of the integer. - /// - /// # Examples - /// - /// Please note that this example is shared between integer types. - /// Which explains why `i16` is used here. - /// - /// Basic usage: - /// - /// ``` - /// let n: i16 = 0b0000000_01010101; - /// assert_eq!(n, 85); - /// - /// let m = n.swap_bytes(); - /// - /// assert_eq!(m, 0b01010101_00000000); - /// assert_eq!(m, 21760); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_ops")] - #[inline] - pub const fn swap_bytes(self) -> Self { - (self as $UnsignedT).swap_bytes() as Self + doc_comment! { + concat!("Shifts the bits to the right by a specified amount, `n`, +wrapping the truncated bits to the beginning of the resulting +integer. + +Please note this isn't the same operation as `>>`! + +# Examples + +Basic usage: + +``` +let n = ", $rot_result, stringify!($SelfT), "; +let m = ", $rot_op, "; + +assert_eq!(n.rotate_right(", $rot, "), m); +```"), + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_rotate")] + #[inline] + #[cfg(not(stage0))] + pub const fn rotate_right(self, n: u32) -> Self { + (self as $UnsignedT).rotate_right(n) as Self + } } - /// Reverses the bit pattern of the integer. - /// - /// # Examples - /// - /// Please note that this example is shared between integer types. - /// Which explains why `i16` is used here. - /// - /// Basic usage: - /// - /// ``` - /// #![feature(reverse_bits)] - /// - /// let n: i16 = 0b0000000_01010101; - /// assert_eq!(n, 85); - /// - /// let m = n.reverse_bits(); - /// - /// assert_eq!(m as u16, 0b10101010_00000000); - /// assert_eq!(m, -22016); - /// ``` + doc_comment! { + concat!("Reverses the byte order of the integer. + +# Examples + +Basic usage: + +``` +let n = ", $swap_op, stringify!($SelfT), "; + +let m = n.swap_bytes(); + +assert_eq!(m, ", $swapped, "); +```"), + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_ops")] + #[inline] + pub const fn swap_bytes(self) -> Self { + (self as $UnsignedT).swap_bytes() as Self + } + } + + /// no docs here #[unstable(feature = "reverse_bits", issue = "48763")] #[inline] + #[cfg(stage0)] pub fn reverse_bits(self) -> Self { (self as $UnsignedT).reverse_bits() as Self } + doc_comment! { + concat!("Reverses the bit pattern of the integer. + +# Examples + +Basic usage: + +``` +#![feature(reverse_bits)] + +let n = ", $swap_op, stringify!($SelfT), "; +let m = n.reverse_bits(); + +assert_eq!(m, ", $reversed, "); +```"), + #[unstable(feature = "reverse_bits", issue = "48763")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn reverse_bits(self) -> Self { + (self as $UnsignedT).reverse_bits() as Self + } + } + doc_comment! { concat!("Converts an integer from big endian to the target's endianness. @@ -979,6 +1007,16 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_add(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_add(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the type. @@ -994,14 +1032,26 @@ assert_eq!(", stringify!($SelfT), "::max_value().wrapping_add(2), ", stringify!( $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_add(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_add(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_add(self, rhs) } } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_sub(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_sub(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the boundary of the type. @@ -1017,14 +1067,26 @@ stringify!($SelfT), "::max_value());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_sub(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_sub(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_sub(self, rhs) } } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_mul(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_mul(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at the boundary of the type. @@ -1039,8 +1101,10 @@ assert_eq!(11i8.wrapping_mul(12), -124);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_mul(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_mul(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_mul(self, rhs) } @@ -1183,6 +1247,16 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_shl(self, rhs: u32) -> Self { + unsafe { + intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + doc_comment! { concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. @@ -1202,14 +1276,26 @@ assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_shl(self, rhs: u32) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_shl(self, rhs: u32) -> Self { unsafe { intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) } } } + /// no docs here + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_shr(self, rhs: u32) -> Self { + unsafe { + intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + doc_comment! { concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` removes any high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. @@ -1229,8 +1315,10 @@ assert_eq!((-128i16).wrapping_shr(64), -128);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_shr(self, rhs: u32) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_shr(self, rhs: u32) -> Self { unsafe { intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) } @@ -1308,6 +1396,18 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::add_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates `self` + `rhs` @@ -1325,9 +1425,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), "::MIN, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT) @@ -1336,6 +1438,18 @@ assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($Sel } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::sub_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates `self` - `rhs` @@ -1353,9 +1467,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT) @@ -1364,6 +1480,18 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($Sel } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::mul_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates the multiplication of `self` and `rhs`. @@ -1379,9 +1507,11 @@ Basic usage: assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT) @@ -1551,6 +1681,14 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($Self } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) + } + doc_comment! { concat!("Shifts self left by `rhs` bits. @@ -1567,13 +1705,23 @@ Basic usage: assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) + } + doc_comment! { concat!("Shifts self right by `rhs` bits. @@ -1590,9 +1738,11 @@ Basic usage: assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) } } @@ -1856,6 +2006,12 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn is_positive(self) -> bool { self > 0 } + doc_comment! { concat!("Returns `true` if `self` is positive and `false` if the number is zero or negative. @@ -1870,10 +2026,18 @@ assert!(!(-10", stringify!($SelfT), ").is_positive());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_sign")] #[inline] - pub fn is_positive(self) -> bool { self > 0 } + #[cfg(not(stage0))] + pub const fn is_positive(self) -> bool { self > 0 } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn is_negative(self) -> bool { self < 0 } + doc_comment! { concat!("Returns `true` if `self` is negative and `false` if the number is zero or positive. @@ -1888,98 +2052,273 @@ assert!(!10", stringify!($SelfT), ".is_negative());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_sign")] #[inline] - pub fn is_negative(self) -> bool { self < 0 } + #[cfg(not(stage0))] + pub const fn is_negative(self) -> bool { self < 0 } } - /// Return the memory representation of this integer as a byte array. - /// - /// The target platform’s native endianness is used. - /// Portable code likely wants to use this after [`to_be`] or [`to_le`]. - /// - /// [`to_be`]: #method.to_be - /// [`to_le`]: #method.to_le - /// - /// # Examples - /// - /// ``` - /// #![feature(int_to_from_bytes)] - /// - /// let bytes = i32::min_value().to_be().to_bytes(); - /// assert_eq!(bytes, [0x80, 0, 0, 0]); - /// ``` - #[unstable(feature = "int_to_from_bytes", issue = "49792")] + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() + } + + doc_comment! { + concat!("Return the memory representation of this integer as a byte array in +big-endian (network) byte order. + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); +assert_eq!(bytes, ", $be_bytes, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + +doc_comment! { + concat!("Return the memory representation of this integer as a byte array in +little-endian byte order. + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); +assert_eq!(bytes, ", $le_bytes, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] #[inline] - pub fn to_bytes(self) -> [u8; mem::size_of::()] { + #[cfg(stage0)] + pub fn to_ne_bytes(self) -> [u8; mem::size_of::()] { unsafe { mem::transmute(self) } } - /// Create an integer value from its memory representation as a byte array. - /// - /// The target platform’s native endianness is used. - /// Portable code likely wants to use [`from_be`] or [`from_le`] after this. - /// - /// [`from_be`]: #method.from_be - /// [`from_le`]: #method.from_le - /// - /// # Examples - /// - /// ``` - /// #![feature(int_to_from_bytes)] - /// - /// let int = i32::from_be(i32::from_bytes([0x80, 0, 0, 0])); - /// assert_eq!(int, i32::min_value()); - /// ``` - #[unstable(feature = "int_to_from_bytes", issue = "49792")] + doc_comment! { + concat!(" +Return the memory representation of this integer as a byte array in +native byte order. + +As the target platform's native endianness is used, portable code +should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, +instead. + +[`to_be_bytes`]: #method.to_be_bytes +[`to_le_bytes`]: #method.to_le_bytes + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes(); +assert_eq!(bytes, if cfg!(target_endian = \"big\") { + ", $be_bytes, " + } else { + ", $le_bytes, " + }); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + unsafe { mem::transmute(self) } + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + +doc_comment! { + concat!("Create an integer value from its representation as a byte array in +big endian. + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); +assert_eq!(value, ", $swap_op, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] #[inline] - pub fn from_bytes(bytes: [u8; mem::size_of::()]) -> Self { + #[cfg(stage0)] + pub fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + +doc_comment! { + concat!(" +Create an integer value from its representation as a byte array in +little endian. + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); +assert_eq!(value, ", $swap_op, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { unsafe { mem::transmute(bytes) } } + + doc_comment! { + concat!("Create an integer value from its memory representation as a byte +array in native endianness. + +As the target platform's native endianness is used, portable code +likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as +appropriate instead. + +[`from_be_bytes`]: #method.from_be_bytes +[`from_le_bytes`]: #method.from_le_bytes + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") { + ", $be_bytes, " + } else { + ", $le_bytes, " + }); +assert_eq!(value, ", $swap_op, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + unsafe { mem::transmute(bytes) } + } + } } } #[lang = "i8"] impl i8 { - int_impl! { i8, i8, u8, 8, -128, 127, "", "" } + int_impl! { i8, i8, u8, 8, -128, 127, "", "", 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", + "[0x12]", "[0x12]" } } #[lang = "i16"] impl i16 { - int_impl! { i16, i16, u16, 16, -32768, 32767, "", "" } + int_impl! { i16, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", + "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]" } } #[lang = "i32"] impl i32 { - int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "" } + int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", + "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78]" } } #[lang = "i64"] impl i64 { - int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "" } + 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]" } } #[lang = "i128"] impl i128 { int_impl! { i128, i128, u128, 128, -170141183460469231731687303715884105728, - 170141183460469231731687303715884105727, "", "" } + 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, "", "" } + int_impl! { isize, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", + "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]" } } #[cfg(target_pointer_width = "32")] #[lang = "isize"] impl isize { - int_impl! { isize, i32, u32, 32, -2147483648, 2147483647, "", "" } + int_impl! { isize, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", + "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78]" } } #[cfg(target_pointer_width = "64")] #[lang = "isize"] impl isize { - int_impl! { isize, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "" } + 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]" } } // Emits the correct `cttz` call, depending on the size of the type. @@ -1997,7 +2336,9 @@ macro_rules! uint_cttz_call { // `Int` + `UnsignedInt` implemented for unsigned integers macro_rules! uint_impl { - ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr) => { + ($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, + $reversed:expr, $le_bytes:expr, $be_bytes:expr) => { doc_comment! { concat!("Returns the smallest value that can be represented by this integer type. @@ -2138,110 +2479,131 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, " } } - /// Shifts the bits to the left by a specified amount, `n`, - /// wrapping the truncated bits to the end of the resulting integer. - /// - /// Please note this isn't the same operation as `<<`! - /// - /// # Examples - /// - /// Basic usage: - /// - /// Please note that this example is shared between integer types. - /// Which explains why `u64` is used here. - /// - /// ``` - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0x3456789ABCDEF012u64; - /// - /// assert_eq!(n.rotate_left(12), m); - /// ``` + /// no docs here #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[cfg(stage0)] pub fn rotate_left(self, n: u32) -> Self { // Protect against undefined behaviour for over-long bit shifts let n = n % $BITS; (self << n) | (self >> (($BITS - n) % $BITS)) } - /// Shifts the bits to the right by a specified amount, `n`, - /// wrapping the truncated bits to the beginning of the resulting - /// integer. - /// - /// Please note this isn't the same operation as `>>`! - /// - /// # Examples - /// - /// Basic usage: - /// - /// Please note that this example is shared between integer types. - /// Which explains why `u64` is used here. - /// - /// ``` - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0xDEF0123456789ABCu64; - /// - /// assert_eq!(n.rotate_right(12), m); - /// ``` + doc_comment! { + concat!("Shifts the bits to the left by a specified amount, `n`, +wrapping the truncated bits to the end of the resulting integer. + +Please note this isn't the same operation as `<<`! + +# Examples + +Basic usage: + +``` +let n = ", $rot_op, stringify!($SelfT), "; +let m = ", $rot_result, "; + +assert_eq!(n.rotate_left(", $rot, "), m); +```"), + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_rotate")] + #[inline] + #[cfg(not(stage0))] + pub const fn rotate_left(self, n: u32) -> Self { + (self << (n % $BITS)) | (self >> (($BITS - (n % $BITS)) % $BITS)) + } + } + + /// no docs here #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[cfg(stage0)] pub fn rotate_right(self, n: u32) -> Self { // Protect against undefined behaviour for over-long bit shifts let n = n % $BITS; (self >> n) | (self << (($BITS - n) % $BITS)) } - /// Reverses the byte order of the integer. - /// - /// # Examples - /// - /// Basic usage: - /// - /// Please note that this example is shared between integer types. - /// Which explains why `u16` is used here. - /// - /// ``` - /// let n: u16 = 0b0000000_01010101; - /// assert_eq!(n, 85); - /// - /// let m = n.swap_bytes(); - /// - /// assert_eq!(m, 0b01010101_00000000); - /// assert_eq!(m, 21760); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_ops")] - #[inline] - pub const fn swap_bytes(self) -> Self { - unsafe { intrinsics::bswap(self as $ActualT) as Self } + doc_comment! { + concat!("Shifts the bits to the right by a specified amount, `n`, +wrapping the truncated bits to the beginning of the resulting +integer. + +Please note this isn't the same operation as `>>`! + +# Examples + +Basic usage: + +``` +let n = ", $rot_result, stringify!($SelfT), "; +let m = ", $rot_op, "; + +assert_eq!(n.rotate_right(", $rot, "), m); +```"), + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_rotate")] + #[inline] + #[cfg(not(stage0))] + pub const fn rotate_right(self, n: u32) -> Self { + (self >> (n % $BITS)) | (self << (($BITS - (n % $BITS)) % $BITS)) + } } - /// Reverses the bit pattern of the integer. - /// - /// # Examples - /// - /// Basic usage: - /// - /// Please note that this example is shared between integer types. - /// Which explains why `u16` is used here. - /// - /// ``` - /// #![feature(reverse_bits)] - /// - /// let n: u16 = 0b0000000_01010101; - /// assert_eq!(n, 85); - /// - /// let m = n.reverse_bits(); - /// - /// assert_eq!(m, 0b10101010_00000000); - /// assert_eq!(m, 43520); - /// ``` + doc_comment! { + concat!(" +Reverses the byte order of the integer. + +# Examples + +Basic usage: + +``` +let n = ", $swap_op, stringify!($SelfT), "; +let m = n.swap_bytes(); + +assert_eq!(m, ", $swapped, "); +```"), + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_ops")] + #[inline] + pub const fn swap_bytes(self) -> Self { + unsafe { intrinsics::bswap(self as $ActualT) as Self } + } + } + + /// no docs here #[unstable(feature = "reverse_bits", issue = "48763")] #[inline] + #[cfg(stage0)] pub fn reverse_bits(self) -> Self { unsafe { intrinsics::bitreverse(self as $ActualT) as Self } } + doc_comment! { + concat!("Reverses the bit pattern of the integer. + +# Examples + +Basic usage: + +``` +#![feature(reverse_bits)] + +let n = ", $swap_op, stringify!($SelfT), "; +let m = n.reverse_bits(); + +assert_eq!(m, ", $reversed, "); +```"), + #[unstable(feature = "reverse_bits", issue = "48763")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn reverse_bits(self) -> Self { + unsafe { intrinsics::bitreverse(self as $ActualT) as Self } + } + } + doc_comment! { concat!("Converts an integer from big endian to the target's endianness. @@ -2725,6 +3087,16 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_add(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_add(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the type. @@ -2739,14 +3111,26 @@ assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::ma $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_add(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_add(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_add(self, rhs) } } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_sub(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_sub(self, rhs) + } + } + doc_comment! { concat!("Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the boundary of the type. @@ -2761,14 +3145,26 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::ma $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_sub(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_sub(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_sub(self, rhs) } } } + /// no docs here + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_mul(self, rhs: Self) -> Self { + unsafe { + intrinsics::overflowing_mul(self, rhs) + } + } + /// Wrapping (modular) multiplication. Computes `self * /// rhs`, wrapping around at the boundary of the type. /// @@ -2784,8 +3180,10 @@ $EndFeature, " /// assert_eq!(25u8.wrapping_mul(12), 44); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_mul(self, rhs: Self) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_mul(self, rhs: Self) -> Self { unsafe { intrinsics::overflowing_mul(self, rhs) } @@ -2906,6 +3304,16 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); self.overflowing_neg().0 } + /// no docs here + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_shl(self, rhs: u32) -> Self { + unsafe { + intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + doc_comment! { concat!("Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes any high-order bits of `rhs` that @@ -2927,14 +3335,26 @@ Basic usage: assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_shl(self, rhs: u32) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_shl(self, rhs: u32) -> Self { unsafe { intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) } } } + /// no docs here + #[stable(feature = "num_wrapping", since = "1.2.0")] + #[inline] + #[cfg(stage0)] + pub fn wrapping_shr(self, rhs: u32) -> Self { + unsafe { + intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) + } + } + doc_comment! { concat!("Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` removes any high-order bits of `rhs` that @@ -2956,8 +3376,10 @@ Basic usage: assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[rustc_const_unstable(feature = "const_int_wrapping")] #[inline] - pub fn wrapping_shr(self, rhs: u32) -> Self { + #[cfg(not(stage0))] + pub const fn wrapping_shr(self, rhs: u32) -> Self { unsafe { intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) } @@ -3002,6 +3424,18 @@ assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::add_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates `self` + `rhs` @@ -3019,9 +3453,11 @@ Basic usage assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_add(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT) @@ -3030,6 +3466,18 @@ assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndF } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::sub_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + doc_comment! { concat!("Calculates `self` - `rhs` @@ -3048,9 +3496,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false)); assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT) @@ -3059,6 +3509,18 @@ $EndFeature, " } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let (a, b) = unsafe { + intrinsics::mul_with_overflow(self as $ActualT, + rhs as $ActualT) + }; + (a as Self, b) + } + /// Calculates the multiplication of `self` and `rhs`. /// /// Returns a tuple of the multiplication along with a boolean @@ -3076,9 +3538,11 @@ $EndFeature, " /// assert_eq!(5u32.overflowing_mul(2), (10, false)); /// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true)); /// ``` - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) { let (a, b) = unsafe { intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT) @@ -3216,6 +3680,14 @@ assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!( } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) + } + doc_comment! { concat!("Shifts self left by `rhs` bits. @@ -3233,13 +3705,23 @@ Basic usage ", $Feature, "assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false)); assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) { (self.wrapping_shl(rhs), (rhs > ($BITS - 1))) } } + /// no docs here + #[stable(feature = "wrapping", since = "1.7.0")] + #[inline] + #[cfg(stage0)] + pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) + } + doc_comment! { concat!("Shifts self right by `rhs` bits. @@ -3257,9 +3739,11 @@ Basic usage ", $Feature, "assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false)); assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, " ```"), - #[inline] #[stable(feature = "wrapping", since = "1.7.0")] - pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) { + #[rustc_const_unstable(feature = "const_int_overflowing")] + #[inline] + #[cfg(not(stage0))] + pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) { (self.wrapping_shr(rhs), (rhs > ($BITS - 1))) } } @@ -3501,55 +3985,210 @@ $EndFeature, " } } - /// Return the memory representation of this integer as a byte array. - /// - /// The target platform’s native endianness is used. - /// Portable code likely wants to use this after [`to_be`] or [`to_le`]. - /// - /// [`to_be`]: #method.to_be - /// [`to_le`]: #method.to_le - /// - /// # Examples - /// - /// ``` - /// #![feature(int_to_from_bytes)] - /// - /// let bytes = 0x1234_5678_u32.to_be().to_bytes(); - /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]); - /// ``` - #[unstable(feature = "int_to_from_bytes", issue = "49792")] + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() + } + + doc_comment! { + concat!("Return the memory representation of this integer as a byte array in +big-endian (network) byte order. + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); +assert_eq!(bytes, ", $be_bytes, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { + self.to_be().to_ne_bytes() + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + + doc_comment! { + concat!("Return the memory representation of this integer as a byte array in +little-endian byte order. + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); +assert_eq!(bytes, ", $le_bytes, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { + self.to_le().to_ne_bytes() + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] #[inline] - pub fn to_bytes(self) -> [u8; mem::size_of::()] { + #[cfg(stage0)] + pub fn to_ne_bytes(self) -> [u8; mem::size_of::()] { unsafe { mem::transmute(self) } } - /// Create an integer value from its memory representation as a byte array. - /// - /// The target platform’s native endianness is used. - /// Portable code likely wants to use [`to_be`] or [`to_le`] after this. - /// - /// [`to_be`]: #method.to_be - /// [`to_le`]: #method.to_le - /// - /// # Examples - /// - /// ``` - /// #![feature(int_to_from_bytes)] - /// - /// let int = u32::from_be(u32::from_bytes([0x12, 0x34, 0x56, 0x78])); - /// assert_eq!(int, 0x1234_5678_u32); - /// ``` - #[unstable(feature = "int_to_from_bytes", issue = "49792")] + doc_comment! { + concat!(" +Return the memory representation of this integer as a byte array in +native byte order. + +As the target platform's native endianness is used, portable code +should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, +instead. + +[`to_be_bytes`]: #method.to_be_bytes +[`to_le_bytes`]: #method.to_le_bytes + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes(); +assert_eq!(bytes, if cfg!(target_endian = \"big\") { + ", $be_bytes, " + } else { + ", $le_bytes, " + }); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + unsafe { mem::transmute(self) } + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + + doc_comment! { + concat!("Create an integer value from its representation as a byte array in +big endian. + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, "); +assert_eq!(value, ", $swap_op, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_be(Self::from_ne_bytes(bytes)) + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[inline] + #[cfg(stage0)] + pub fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + + doc_comment! { + concat!(" +Create an integer value from its representation as a byte array in +little endian. + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, "); +assert_eq!(value, ", $swap_op, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { + Self::from_le(Self::from_ne_bytes(bytes)) + } + } + + /// no docs here + #[unstable(feature = "int_to_from_bytes", issue = "52963")] #[inline] - pub fn from_bytes(bytes: [u8; mem::size_of::()]) -> Self { + #[cfg(stage0)] + pub fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { unsafe { mem::transmute(bytes) } } + + doc_comment! { + concat!("Create an integer value from its memory representation as a byte +array in native endianness. + +As the target platform's native endianness is used, portable code +likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as +appropriate instead. + +[`from_be_bytes`]: #method.from_be_bytes +[`from_le_bytes`]: #method.from_le_bytes + +# Examples + +``` +#![feature(int_to_from_bytes)] + +let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") { + ", $be_bytes, " + } else { + ", $le_bytes, " + }); +assert_eq!(value, ", $swap_op, "); +```"), + #[unstable(feature = "int_to_from_bytes", issue = "52963")] + #[rustc_const_unstable(feature = "const_int_conversion")] + #[inline] + #[cfg(not(stage0))] + pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + unsafe { mem::transmute(bytes) } + } + } } } #[lang = "u8"] impl u8 { - uint_impl! { u8, u8, 8, 255, "", "" } + uint_impl! { u8, u8, 8, 255, "", "", 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", + "[0x12]" } /// Checks if the value is within the ASCII range. @@ -3689,8 +4328,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -3727,8 +4364,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -3765,8 +4400,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -3806,8 +4439,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -3844,8 +4475,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -3885,8 +4514,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -3927,8 +4554,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -3965,8 +4590,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -4020,8 +4643,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -4060,8 +4681,6 @@ impl u8 { /// # Examples /// /// ``` - /// #![feature(ascii_ctype)] - /// /// let uppercase_a = b'A'; /// let uppercase_g = b'G'; /// let a = b'a'; @@ -4095,39 +4714,55 @@ impl u8 { #[lang = "u16"] impl u16 { - uint_impl! { u16, u16, 16, 65535, "", "" } + uint_impl! { u16, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + "[0x34, 0x12]", "[0x12, 0x34]" } } #[lang = "u32"] impl u32 { - uint_impl! { u32, u32, 32, 4294967295, "", "" } + uint_impl! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", + "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]" } } #[lang = "u64"] impl u64 { - uint_impl! { u64, u64, 64, 18446744073709551615, "", "" } + 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]" } } #[lang = "u128"] impl u128 { - uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, "", "" } + 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]" } } #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { - uint_impl! { usize, u16, 16, 65536, "", "" } + uint_impl! { usize, u16, 16, 65536, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + "[0x34, 0x12]", "[0x12, 0x34]" } } #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { - uint_impl! { usize, u32, 32, 4294967295, "", "" } + uint_impl! { usize, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", + "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]" } } #[cfg(target_pointer_width = "64")] #[lang = "usize"] impl usize { - uint_impl! { usize, u64, 64, 18446744073709551615, "", "" } + 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]" } } /// A classification of floating point numbers. @@ -4195,7 +4830,7 @@ 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. #[unstable(feature = "try_from", issue = "33417")] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct TryFromIntError(()); impl TryFromIntError { diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index d10fcb86b2..3ebd10a920 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -66,6 +66,11 @@ #[lang = "fn"] #[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}`", +)] #[fundamental] // so that regex can rely that `&str: !FnMut` pub trait Fn : FnMut { /// Performs the call operation. @@ -139,6 +144,11 @@ pub trait Fn : FnMut { #[lang = "fn_mut"] #[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 `{FnMut}<{Args}>` closure, found `{Self}`", + label="expected an `FnMut<{Args}>` closure, found `{Self}`", +)] #[fundamental] // so that regex can rely that `&str: !FnMut` pub trait FnMut : FnOnce { /// Performs the call operation. @@ -212,6 +222,11 @@ pub trait FnMut : FnOnce { #[lang = "fn_once"] #[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}`", +)] #[fundamental] // so that regex can rely that `&str: !FnMut` pub trait FnOnce { /// The returned type after the call operator is used. diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs index cd896859b1..da72f37484 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -13,7 +13,7 @@ use marker::Unsize; /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. /// -/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] +/// See the [DST coercion RFC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] /// for more details. /// /// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize` diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 9f9dbd0777..dfdc375765 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -146,8 +146,8 @@ #![stable(feature = "rust1", since = "1.0.0")] use iter::{FromIterator, FusedIterator, TrustedLen}; -use {hint, mem, ops}; -use mem::PinMut; +use {hint, mem, ops::{self, Deref}}; +use pin::PinMut; // 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 @@ -953,6 +953,17 @@ impl Option { } } +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Option { + /// Converts from `&Option` to `Option<&T::Target>`. + /// + /// Leaves the original Option in-place, creating a new one with a reference + /// to the original one, additionally coercing the contents via `Deref`. + pub fn deref(&self) -> Option<&T::Target> { + self.as_ref().map(|t| t.deref()) + } +} + impl Option> { /// Transposes an `Option` of a `Result` into a `Result` of an `Option`. /// @@ -989,16 +1000,13 @@ fn expect_failed(msg: &str) -> ! { panic!("{}", msg) } - ///////////////////////////////////////////////////////////////////////////// // Trait implementations ///////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] impl Default for Option { - /// Returns [`None`]. - /// - /// [`None`]: #variant.None + /// Returns [`None`][Option::None]. #[inline] fn default() -> Option { None } } @@ -1054,6 +1062,20 @@ impl From for Option { } } +#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] +impl<'a, T> From<&'a Option> for Option<&'a T> { + fn from(o: &'a Option) -> Option<&'a T> { + o.as_ref() + } +} + +#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] +impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { + fn from(o: &'a mut Option) -> Option<&'a mut T> { + o.as_mut() + } +} + ///////////////////////////////////////////////////////////////////////////// // The Option Iterators ///////////////////////////////////////////////////////////////////////////// @@ -1131,6 +1153,7 @@ unsafe impl<'a, A> TrustedLen for Iter<'a, A> {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> Clone for Iter<'a, A> { + #[inline] fn clone(&self) -> Iter<'a, A> { Iter { inner: self.inner.clone() } } @@ -1217,9 +1240,10 @@ unsafe impl TrustedLen for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] impl> FromIterator> for Option { - /// Takes each element in the [`Iterator`]: if it is [`None`], no further - /// elements are taken, and the [`None`] is returned. Should no [`None`] occur, a - /// container with the values of each `Option` is returned. + /// Takes each element in the [`Iterator`]: if it is [`None`][Option::None], + /// no further elements are taken, and the [`None`][Option::None] is + /// returned. Should no [`None`][Option::None] occur, a container with the + /// values of each [`Option`] is returned. /// /// Here is an example which increments every integer in a vector, /// checking for overflow: @@ -1236,7 +1260,6 @@ impl> FromIterator> for Option { /// ``` /// /// [`Iterator`]: ../iter/trait.Iterator.html - /// [`None`]: enum.Option.html#variant.None #[inline] fn from_iter>>(iter: I) -> Option { // FIXME(#11084): This could be replaced with Iterator::scan when this @@ -1297,14 +1320,17 @@ impl ops::Try for Option { type Ok = T; type Error = NoneError; + #[inline] fn into_result(self) -> Result { self.ok_or(NoneError) } + #[inline] fn from_ok(v: T) -> Self { Some(v) } + #[inline] fn from_error(_: NoneError) -> Self { None } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs new file mode 100644 index 0000000000..e9001f86b3 --- /dev/null +++ b/src/libcore/pin.rs @@ -0,0 +1,160 @@ +//! Types which pin data to its location in memory +//! +//! See the [standard library module] for more information. +//! +//! [standard library module]: ../../std/pin/index.html + +#![unstable(feature = "pin", issue = "49150")] + +use fmt; +use future::{Future, UnsafeFutureObj}; +use marker::{Sized, Unpin, Unsize}; +use task::{Context, Poll}; +use ops::{Deref, DerefMut, CoerceUnsized}; + +/// A pinned reference. +/// +/// This type is similar to a mutable reference, except that it pins its value, +/// which prevents it from moving out of the reference, unless it implements [`Unpin`]. +/// +/// See the [`pin` module] documentation for furthur explanation on pinning. +/// +/// [`Unpin`]: ../../std/marker/trait.Unpin.html +/// [`pin` module]: ../../std/pin/index.html +#[unstable(feature = "pin", issue = "49150")] +#[fundamental] +pub struct PinMut<'a, T: ?Sized + 'a> { + inner: &'a mut T, +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized + Unpin> PinMut<'a, T> { + /// Construct a new `PinMut` around a reference to some data of a type that + /// implements `Unpin`. + #[unstable(feature = "pin", issue = "49150")] + pub fn new(reference: &'a mut T) -> PinMut<'a, T> { + PinMut { inner: reference } + } + + /// Get a mutable reference to the data inside of this `PinMut`. + #[unstable(feature = "pin", issue = "49150")] + pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T { + this.inner + } +} + + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> PinMut<'a, T> { + /// Construct a new `PinMut` around a reference to some data of a type that + /// may or may not implement `Unpin`. + /// + /// This constructor is unsafe because we do not know what will happen with + /// that data after the lifetime of the reference ends. If you cannot guarantee that the + /// data will never move again, calling this constructor is invalid. + #[unstable(feature = "pin", issue = "49150")] + pub unsafe fn new_unchecked(reference: &'a mut T) -> PinMut<'a, T> { + PinMut { inner: reference } + } + + /// Reborrow a `PinMut` for a shorter lifetime. + /// + /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a + /// short-lived mutable reference reborrowing from `x`. + #[unstable(feature = "pin", issue = "49150")] + pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> { + PinMut { inner: self.inner } + } + + /// Get a mutable reference to the data inside of this `PinMut`. + /// + /// This function is unsafe. You must guarantee that you will never move + /// the data out of the mutable reference you receive when you call this + /// function. + #[unstable(feature = "pin", issue = "49150")] + pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T { + this.inner + } + + /// Construct a new pin by mapping the interior value. + /// + /// For example, if you wanted to get a `PinMut` of a field of something, + /// you could use this to get access to that field in one line of code. + /// + /// This function is unsafe. You must guarantee that the data you return + /// will not move so long as the argument value does not move (for example, + /// because it is one of the fields of that value), and also that you do + /// not move out of the argument you receive to the interior function. + #[unstable(feature = "pin", issue = "49150")] + pub unsafe fn map_unchecked(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where + F: FnOnce(&mut T) -> &mut U + { + PinMut { inner: f(this.inner) } + } + + /// Assign a new value to the memory behind the pinned reference. + #[unstable(feature = "pin", issue = "49150")] + pub fn set(this: PinMut<'a, T>, value: T) + where T: Sized, + { + *this.inner = value; + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> Deref for PinMut<'a, T> { + type Target = T; + + fn deref(&self) -> &T { + &*self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> { + fn deref_mut(&mut self) -> &mut T { + self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Pointer::fmt(&(&*self.inner as *const T), f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for PinMut<'a, T> {} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {} + +#[unstable(feature = "futures_api", issue = "50547")] +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinMut<'a, F> + where F: Future + 'a +{ + fn into_raw(self) -> *mut () { + unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () } + } + + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) + } + + unsafe fn drop(_ptr: *mut ()) {} +} diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index fe5914c72e..57351822cc 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -226,8 +226,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { // Declaring `t` here avoids aligning the stack when this loop is unused let mut t: Block = mem::uninitialized(); let t = &mut t as *mut _ as *mut u8; - let x = x.offset(i as isize); - let y = y.offset(i as isize); + let x = x.add(i); + let y = y.add(i); // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available @@ -243,8 +243,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { let rem = len - i; let t = &mut t as *mut _ as *mut u8; - let x = x.offset(i as isize); - let y = y.offset(i as isize); + let x = x.add(i); + let y = y.add(i); copy_nonoverlapping(x, t, rem); copy_nonoverlapping(y, x, rem); @@ -448,6 +448,12 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use /// because it will attempt to drop the value previously at `*src`. /// +/// Just like in C, whether an operation is volatile has no bearing whatsoever +/// on questions involving concurrent access from multiple threads. Volatile +/// accesses behave exactly like non-atomic accesses in that regard. In particular, +/// a race between a `read_volatile` and any write operation to the same location +/// is undefined behavior. +/// /// # Examples /// /// Basic usage: @@ -498,6 +504,12 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. /// +/// Just like in C, whether an operation is volatile has no bearing whatsoever +/// on questions involving concurrent access from multiple threads. Volatile +/// accesses behave exactly like non-atomic accesses in that regard. In particular, +/// a race between a `write_volatile` and any other operation (reading or writing) +/// on the same location is undefined behavior. +/// /// # Examples /// /// Basic usage: @@ -570,6 +582,21 @@ impl *const T { /// } /// } /// ``` + /// + /// # Null-unchecked version + /// + /// If you are sure the pointer can never be null and are looking for some kind of + /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>, know that you can + /// dereference the pointer directly. + /// + /// ``` + /// let ptr: *const u8 = &10u8 as *const u8; + /// + /// unsafe { + /// let val_back = &*ptr; + /// println!("We got back the value: {}!", val_back); + /// } + /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { @@ -601,7 +628,7 @@ impl *const T { /// The compiler and standard library generally tries to ensure allocations /// never reach a size where an offset is a concern. For instance, `Vec` /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().offset(vec.len() as isize)` is always safe. + /// `vec.as_ptr().add(vec.len())` is always safe. /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request @@ -680,46 +707,6 @@ impl *const T { } } - /// Calculates the distance between two pointers. The returned value is in - /// units of T: the distance in bytes is divided by `mem::size_of::()`. - /// - /// If the address different between the two pointers ia not a multiple of - /// `mem::size_of::()` then the result of the division is rounded towards - /// zero. - /// - /// This function returns `None` if `T` is a zero-sized type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(offset_to)] - /// #![allow(deprecated)] - /// - /// fn main() { - /// let a = [0; 5]; - /// let ptr1: *const i32 = &a[1]; - /// let ptr2: *const i32 = &a[3]; - /// assert_eq!(ptr1.offset_to(ptr2), Some(2)); - /// assert_eq!(ptr2.offset_to(ptr1), Some(-2)); - /// assert_eq!(unsafe { ptr1.offset(2) }, ptr2); - /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1); - /// } - /// ``` - #[unstable(feature = "offset_to", issue = "41079")] - #[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \ - opposite argument order. If you're writing unsafe code, consider `offset_from`.")] - #[inline] - pub fn offset_to(self, other: *const T) -> Option where T: Sized { - let size = mem::size_of::(); - if size == 0 { - None - } else { - Some(other.wrapping_offset_from(self)) - } - } - /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// @@ -1097,6 +1084,12 @@ impl *const T { /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// + /// Just like in C, whether an operation is volatile has no bearing whatsoever + /// on questions involving concurrent access from multiple threads. Volatile + /// accesses behave exactly like non-atomic accesses in that regard. In particular, + /// a race between a `read_volatile` and any write operation to the same location + /// is undefined behavior. + /// /// # Examples /// /// Basic usage: @@ -1253,7 +1246,7 @@ impl *const T { /// let ptr = &x[n] as *const u8; /// let offset = ptr.align_offset(align_of::()); /// if offset < x.len() - n - 1 { - /// let u16_ptr = ptr.offset(offset as isize) as *const u16; + /// let u16_ptr = ptr.add(offset) as *const u16; /// assert_ne!(*u16_ptr, 500); /// } else { /// // while the pointer can be aligned via `offset`, it would point @@ -1325,6 +1318,21 @@ impl *mut T { /// } /// } /// ``` + /// + /// # Null-unchecked version + /// + /// If you are sure the pointer can never be null and are looking for some kind of + /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>, know that you can + /// dereference the pointer directly. + /// + /// ``` + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; + /// + /// unsafe { + /// let val_back = &*ptr; + /// println!("We got back the value: {}!", val_back); + /// } + /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { @@ -1356,7 +1364,7 @@ impl *mut T { /// The compiler and standard library generally tries to ensure allocations /// never reach a size where an offset is a concern. For instance, `Vec` /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so - /// `vec.as_ptr().offset(vec.len() as isize)` is always safe. + /// `vec.as_ptr().add(vec.len())` is always safe. /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request @@ -1464,46 +1472,6 @@ impl *mut T { } } - /// Calculates the distance between two pointers. The returned value is in - /// units of T: the distance in bytes is divided by `mem::size_of::()`. - /// - /// If the address different between the two pointers ia not a multiple of - /// `mem::size_of::()` then the result of the division is rounded towards - /// zero. - /// - /// This function returns `None` if `T` is a zero-sized type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(offset_to)] - /// #![allow(deprecated)] - /// - /// fn main() { - /// let mut a = [0; 5]; - /// let ptr1: *mut i32 = &mut a[1]; - /// let ptr2: *mut i32 = &mut a[3]; - /// assert_eq!(ptr1.offset_to(ptr2), Some(2)); - /// assert_eq!(ptr2.offset_to(ptr1), Some(-2)); - /// assert_eq!(unsafe { ptr1.offset(2) }, ptr2); - /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1); - /// } - /// ``` - #[unstable(feature = "offset_to", issue = "41079")] - #[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \ - opposite argument order. If you're writing unsafe code, consider `offset_from`.")] - #[inline] - pub fn offset_to(self, other: *const T) -> Option where T: Sized { - let size = mem::size_of::(); - if size == 0 { - None - } else { - Some(other.wrapping_offset_from(self)) - } - } - /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// @@ -1870,6 +1838,12 @@ impl *mut T { /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// + /// Just like in C, whether an operation is volatile has no bearing whatsoever + /// on questions involving concurrent access from multiple threads. Volatile + /// accesses behave exactly like non-atomic accesses in that regard. In particular, + /// a race between a `read_volatile` and any write operation to the same location + /// is undefined behavior. + /// /// # Examples /// /// Basic usage: @@ -2185,6 +2159,12 @@ impl *mut T { /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. /// + /// Just like in C, whether an operation is volatile has no bearing whatsoever + /// on questions involving concurrent access from multiple threads. Volatile + /// accesses behave exactly like non-atomic accesses in that regard. In particular, + /// a race between a `write_volatile` and any other operation (reading or writing) + /// on the same location is undefined behavior. + /// /// # Examples /// /// Basic usage: @@ -2311,7 +2291,7 @@ impl *mut T { /// let ptr = &x[n] as *const u8; /// let offset = ptr.align_offset(align_of::()); /// if offset < x.len() - n - 1 { - /// let u16_ptr = ptr.offset(offset as isize) as *const u16; + /// let u16_ptr = ptr.add(offset) as *const u16; /// assert_ne!(*u16_ptr, 500); /// } else { /// // while the pointer can be aligned via `offset`, it would point @@ -2341,7 +2321,7 @@ impl *mut T { /// /// If we ever decide to make it possible to call the intrinsic with `a` that is not a /// power-of-two, it will probably be more prudent to just change to a naive implementation rather -/// than trying to adapt this to accomodate that change. +/// than trying to adapt this to accommodate that change. /// /// Any questions go to @nagisa. #[lang="align_offset"] @@ -2368,7 +2348,7 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1]; if m <= INV_TABLE_MOD { - return table_inverse & (m - 1); + table_inverse & (m - 1) } else { // We iterate "up" using the following formula: // @@ -2455,7 +2435,7 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { } // Cannot be aligned at all. - return usize::max_value(); + usize::max_value() } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index e0cc669d03..93ee11aac3 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -242,7 +242,7 @@ use fmt; use iter::{FromIterator, FusedIterator, TrustedLen}; -use ops; +use ops::{self, Deref}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). /// @@ -470,6 +470,36 @@ impl Result { } } + /// Maps a `Result` to `U` by applying a function to a + /// contained [`Ok`] value, or a fallback function to a + /// contained [`Err`] value. + /// + /// This function can be used to unpack a successful result + /// while handling an error. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(result_map_or_else)] + /// let k = 21; + /// + /// let x : Result<_, &str> = Ok("foo"); + /// assert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 3); + /// + /// let x : Result<&str, _> = Err("bar"); + /// 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) + } + /// Maps a `Result` to `Result` by applying a function to a /// contained [`Err`] value, leaving an [`Ok`] value untouched. /// @@ -507,7 +537,7 @@ impl Result { /// Returns an iterator over the possibly contained value. /// - /// The iterator yields one value if the result is [`Ok`], otherwise none. + /// The iterator yields one value if the result is [`Result::Ok`], otherwise none. /// /// # Examples /// @@ -520,8 +550,6 @@ impl Result { /// let x: Result = Err("nothing!"); /// assert_eq!(x.iter().next(), None); /// ``` - /// - /// [`Ok`]: enum.Result.html#variant.Ok #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { @@ -530,7 +558,7 @@ impl Result { /// Returns a mutable iterator over the possibly contained value. /// - /// The iterator yields one value if the result is [`Ok`], otherwise none. + /// The iterator yields one value if the result is [`Result::Ok`], otherwise none. /// /// # Examples /// @@ -547,8 +575,6 @@ impl Result { /// let mut x: Result = Err("nothing!"); /// assert_eq!(x.iter_mut().next(), None); /// ``` - /// - /// [`Ok`]: enum.Result.html#variant.Ok #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut { @@ -909,6 +935,44 @@ impl Result { } } +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `&Result` to `Result<&T::Target, &E>`. + /// + /// Leaves the original Result in-place, creating a new one with a reference + /// to the original one, additionally coercing the `Ok` arm of the Result via + /// `Deref`. + pub fn deref_ok(&self) -> Result<&T::Target, &E> { + self.as_ref().map(|t| t.deref()) + } +} + +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `&Result` to `Result<&T, &E::Target>`. + /// + /// Leaves the original Result in-place, creating a new one with a reference + /// to the original one, additionally coercing the `Err` arm of the Result via + /// `Deref`. + pub fn deref_err(&self) -> Result<&T, &E::Target> + { + self.as_ref().map_err(|e| e.deref()) + } +} + +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `&Result` to `Result<&T::Target, &E::Target>`. + /// + /// Leaves the original Result in-place, creating a new one with a reference + /// to the original one, additionally coercing both the `Ok` and `Err` arms + /// of the Result via `Deref`. + pub fn deref(&self) -> Result<&T::Target, &E::Target> + { + self.as_ref().map(|t| t.deref()).map_err(|e| e.deref()) + } +} + impl Result, E> { /// Transposes a `Result` of an `Option` into an `Option` of a `Result`. /// @@ -956,7 +1020,7 @@ impl IntoIterator for Result { /// Returns a consuming iterator over the possibly contained value. /// - /// The iterator yields one value if the result is [`Ok`], otherwise none. + /// The iterator yields one value if the result is [`Result::Ok`], otherwise none. /// /// # Examples /// @@ -971,8 +1035,6 @@ impl IntoIterator for Result { /// let v: Vec = x.into_iter().collect(); /// assert_eq!(v, []); /// ``` - /// - /// [`Ok`]: enum.Result.html#variant.Ok #[inline] fn into_iter(self) -> IntoIter { IntoIter { inner: self.ok() } @@ -1046,6 +1108,7 @@ unsafe impl<'a, A> TrustedLen for Iter<'a, A> {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { + #[inline] fn clone(&self) -> Iter<'a, T> { Iter { inner: self.inner } } } @@ -1197,14 +1260,17 @@ impl ops::Try for Result { type Ok = T; type Error = E; + #[inline] fn into_result(self) -> Self { self } + #[inline] fn from_ok(v: T) -> Self { Ok(v) } + #[inline] fn from_error(v: E) -> Self { Err(v) } diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs index 72e7b57a6c..cf95333af9 100644 --- a/src/libcore/slice/memchr.rs +++ b/src/libcore/slice/memchr.rs @@ -72,8 +72,8 @@ pub fn memchr(x: u8, text: &[u8]) -> Option { if len >= 2 * usize_bytes { while offset <= len - 2 * usize_bytes { unsafe { - let u = *(ptr.offset(offset as isize) as *const usize); - let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize); + let u = *(ptr.add(offset) as *const usize); + let v = *(ptr.add(offset + usize_bytes) as *const usize); // break if there is a matching byte let zu = contains_zero_byte(u ^ repeated_x); @@ -100,24 +100,30 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { // - the first remaining bytes, < 2 word size let len = text.len(); let ptr = text.as_ptr(); - let usize_bytes = mem::size_of::(); + type Chunk = usize; - let mut offset = { - // We call this just to obtain the length of the suffix - let (_, _, suffix) = unsafe { text.align_to::() }; - len - suffix.len() + let (min_aligned_offset, max_aligned_offset) = { + // We call this just to obtain the length of the prefix and suffix. + // In the middle we always process two chunks at once. + let (prefix, _, suffix) = unsafe { text.align_to::<(Chunk, Chunk)>() }; + (prefix.len(), len - suffix.len()) }; + + let mut offset = max_aligned_offset; if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) { return Some(offset + index); } - // search the body of the text + // search the body of the text, make sure we don't cross min_aligned_offset. + // offset is always aligned, so just testing `>` is sufficient and avoids possible + // overflow. let repeated_x = repeat_byte(x); + let chunk_bytes = mem::size_of::(); - while offset >= 2 * usize_bytes { + while offset > min_aligned_offset { unsafe { - let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize); - let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize); + let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk); + let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk); // break if there is a matching byte let zu = contains_zero_byte(u ^ repeated_x); @@ -126,7 +132,7 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { break; } } - offset -= 2 * usize_bytes; + offset -= 2 * chunk_bytes; } // find the byte before the point the body loop stopped diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index b766140ffe..da4a56cfec 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -21,14 +21,9 @@ // The library infrastructure for slices is fairly messy. There's // a lot of stuff defined here. Let's keep it clean. // -// Since slices don't support inherent methods; all operations -// on them are defined on traits, which are then re-exported from -// the prelude for convenience. So there are a lot of traits here. -// // The layout of this file is thus: // -// * Slice-specific 'extension' traits and their implementations. This -// is where most of the slice API resides. +// * Inherent methods. This is where most of the slice API resides. // * Implementations of a few common traits with important slice ops. // * Definitions of a bunch of iterators. // * Free functions. @@ -75,44 +70,6 @@ struct FatPtr { // Extension traits // -// Use macros to be generic over const/mut -macro_rules! slice_offset { - ($ptr:expr, $by:expr) => {{ - let ptr = $ptr; - if size_from_ptr(ptr) == 0 { - (ptr as *mut i8).wrapping_offset($by) as _ - } else { - ptr.offset($by) - } - }}; -} - -// make a &T from a *const T -macro_rules! make_ref { - ($ptr:expr) => {{ - let ptr = $ptr; - if size_from_ptr(ptr) == 0 { - // Use a non-null pointer value - &*(1 as *mut _) - } else { - &*ptr - } - }}; -} - -// make a &mut T from a *mut T -macro_rules! make_ref_mut { - ($ptr:expr) => {{ - let ptr = $ptr; - if size_from_ptr(ptr) == 0 { - // Use a non-null pointer value - &mut *(1 as *mut _) - } else { - &mut *ptr - } - }}; -} - #[lang = "slice"] #[cfg(not(test))] impl [T] { @@ -421,7 +378,7 @@ impl [T] { /// /// unsafe { /// for i in 0..x.len() { - /// assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize)); + /// assert_eq!(x.get_unchecked(i), &*x_ptr.add(i)); /// } /// } /// ``` @@ -448,7 +405,7 @@ impl [T] { /// /// unsafe { /// for i in 0..x.len() { - /// *x_ptr.offset(i as isize) += 2; + /// *x_ptr.add(i) += 2; /// } /// } /// assert_eq!(x, &[3, 4, 6]); @@ -580,17 +537,18 @@ impl [T] { #[inline] pub fn iter(&self) -> Iter { unsafe { - let p = if mem::size_of::() == 0 { - 1 as *const _ + let ptr = self.as_ptr(); + assume(!ptr.is_null()); + + let end = if mem::size_of::() == 0 { + (ptr as *const u8).wrapping_add(self.len()) as *const T } else { - let p = self.as_ptr(); - assume(!p.is_null()); - p + ptr.add(self.len()) }; Iter { - ptr: p, - end: slice_offset!(p, self.len() as isize), + ptr, + end, _marker: marker::PhantomData } } @@ -611,17 +569,18 @@ impl [T] { #[inline] pub fn iter_mut(&mut self) -> IterMut { unsafe { - let p = if mem::size_of::() == 0 { - 1 as *mut _ + let ptr = self.as_mut_ptr(); + assume(!ptr.is_null()); + + let end = if mem::size_of::() == 0 { + (ptr as *mut u8).wrapping_add(self.len()) as *mut T } else { - let p = self.as_mut_ptr(); - assume(!p.is_null()); - p + ptr.add(self.len()) }; IterMut { - ptr: p, - end: slice_offset!(p, self.len() as isize), + ptr, + end, _marker: marker::PhantomData } } @@ -657,7 +616,7 @@ impl [T] { #[inline] pub fn windows(&self, size: usize) -> Windows { assert!(size != 0); - Windows { v: self, size: size } + Windows { v: self, size } } /// Returns an iterator over `chunk_size` elements of the slice at a @@ -688,7 +647,7 @@ impl [T] { #[inline] pub fn chunks(&self, chunk_size: usize) -> Chunks { assert!(chunk_size != 0); - Chunks { v: self, chunk_size: chunk_size } + Chunks { v: self, chunk_size } } /// Returns an iterator over `chunk_size` elements of the slice at a time. @@ -723,7 +682,7 @@ impl [T] { #[inline] pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut { assert!(chunk_size != 0); - ChunksMut { v: self, chunk_size: chunk_size } + ChunksMut { v: self, chunk_size } } /// Returns an iterator over `chunk_size` elements of the slice at a @@ -760,7 +719,7 @@ impl [T] { let rem = self.len() % chunk_size; let len = self.len() - rem; let (fst, snd) = self.split_at(len); - ExactChunks { v: fst, rem: snd, chunk_size: chunk_size} + ExactChunks { v: fst, rem: snd, chunk_size } } /// Returns an iterator over `chunk_size` elements of the slice at a time. @@ -802,7 +761,7 @@ impl [T] { let rem = self.len() % chunk_size; let len = self.len() - rem; let (fst, snd) = self.split_at_mut(len); - ExactChunksMut { v: fst, rem: snd, chunk_size: chunk_size} + ExactChunksMut { v: fst, rem: snd, chunk_size } } /// Divides one slice into two at an index. @@ -878,7 +837,7 @@ impl [T] { assert!(mid <= len); (from_raw_parts_mut(ptr, mid), - from_raw_parts_mut(ptr.offset(mid as isize), len - mid)) + from_raw_parts_mut(ptr.add(mid), len - mid)) } } @@ -952,7 +911,7 @@ impl [T] { pub fn split_mut(&mut self, pred: F) -> SplitMut where F: FnMut(&T) -> bool { - SplitMut { v: self, pred: pred, finished: false } + SplitMut { v: self, pred, finished: false } } /// Returns an iterator over subslices separated by elements that match @@ -1480,7 +1439,7 @@ impl [T] { unsafe { let p = self.as_mut_ptr(); - rotate::ptr_rotate(mid, p.offset(mid as isize), k); + rotate::ptr_rotate(mid, p.add(mid), k); } } @@ -1521,7 +1480,7 @@ impl [T] { unsafe { let p = self.as_mut_ptr(); - rotate::ptr_rotate(mid, p.offset(mid as isize), k); + rotate::ptr_rotate(mid, p.add(mid), k); } } @@ -1716,7 +1675,7 @@ impl [T] { } } - /// Function to calculate lenghts of the middle and trailing slice for `align_to{,_mut}`. + /// Function to calculate lengths of the middle and trailing slice for `align_to{,_mut}`. fn align_to_offsets(&self) -> (usize, usize) { // What we gonna do about `rest` is figure out what multiple of `U`s we can put in a // lowest number of `T`s. And how many `T`s we need for each such "multiple". @@ -1763,7 +1722,7 @@ impl [T] { ctz_b = ::intrinsics::cttz_nonzero(b); } } - return a << k; + a << k } let gcd: usize = gcd(::mem::size_of::(), ::mem::size_of::()); let ts: usize = ::mem::size_of::() / gcd; @@ -1773,15 +1732,16 @@ impl [T] { let us_len = self.len() / ts * us; // And how many `T`s will be in the trailing slice! let ts_len = self.len() % ts; - return (us_len, ts_len); + (us_len, ts_len) } - /// Transmute the slice to a slice of another type, ensuring aligment of the types is + /// Transmute the slice to a slice of another type, ensuring alignment of the types is /// maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. The middle slice will have the greatest length - /// possible for a given type and input slice. + /// slice of a new type, and the suffix slice. The method does a best effort to make the + /// middle slice the greatest length possible for a given type and input slice, but only + /// your algorithm's performance should depend on that, not its correctness. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. @@ -1796,7 +1756,6 @@ impl [T] { /// Basic usage: /// /// ``` - /// # #![feature(slice_align_to)] /// unsafe { /// let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7]; /// let (prefix, shorts, suffix) = bytes.align_to::(); @@ -1805,7 +1764,7 @@ impl [T] { /// // less_efficient_algorithm_for_bytes(suffix); /// } /// ``` - #[unstable(feature = "slice_align_to", issue = "44488")] + #[stable(feature = "slice_align_to", since = "1.30.0")] pub unsafe fn align_to(&self) -> (&[T], &[U], &[T]) { // Note that most of this function will be constant-evaluated, if ::mem::size_of::() == 0 || ::mem::size_of::() == 0 { @@ -1818,22 +1777,24 @@ impl [T] { let ptr = self.as_ptr(); let offset = ::ptr::align_offset(ptr, ::mem::align_of::()); if offset > self.len() { - return (self, &[], &[]); + (self, &[], &[]) } else { let (left, rest) = self.split_at(offset); + // now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay let (us_len, ts_len) = rest.align_to_offsets::(); - return (left, - from_raw_parts(rest.as_ptr() as *const U, us_len), - from_raw_parts(rest.as_ptr().offset((rest.len() - ts_len) as isize), ts_len)) + (left, + from_raw_parts(rest.as_ptr() as *const U, us_len), + from_raw_parts(rest.as_ptr().add(rest.len() - ts_len), ts_len)) } } - /// Transmute the slice to a slice of another type, ensuring aligment of the types is + /// Transmute the slice to a slice of another type, ensuring alignment of the types is /// maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. The middle slice will have the greatest length - /// possible for a given type and input slice. + /// slice of a new type, and the suffix slice. The method does a best effort to make the + /// middle slice the greatest length possible for a given type and input slice, but only + /// your algorithm's performance should depend on that, not its correctness. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. @@ -1848,7 +1809,6 @@ impl [T] { /// Basic usage: /// /// ``` - /// # #![feature(slice_align_to)] /// unsafe { /// let mut bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7]; /// let (prefix, shorts, suffix) = bytes.align_to_mut::(); @@ -1857,7 +1817,7 @@ impl [T] { /// // less_efficient_algorithm_for_bytes(suffix); /// } /// ``` - #[unstable(feature = "slice_align_to", issue = "44488")] + #[stable(feature = "slice_align_to", since = "1.30.0")] pub unsafe fn align_to_mut(&mut self) -> (&mut [T], &mut [U], &mut [T]) { // Note that most of this function will be constant-evaluated, if ::mem::size_of::() == 0 || ::mem::size_of::() == 0 { @@ -1870,14 +1830,15 @@ impl [T] { let ptr = self.as_ptr(); let offset = ::ptr::align_offset(ptr, ::mem::align_of::()); if offset > self.len() { - return (self, &mut [], &mut []); + (self, &mut [], &mut []) } else { let (left, rest) = self.split_at_mut(offset); + // now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay let (us_len, ts_len) = rest.align_to_offsets::(); let mut_ptr = rest.as_mut_ptr(); - return (left, - from_raw_parts_mut(mut_ptr as *mut U, us_len), - from_raw_parts_mut(mut_ptr.offset((rest.len() - ts_len) as isize), ts_len)) + (left, + from_raw_parts_mut(mut_ptr as *mut U, us_len), + from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len)) } } } @@ -2043,7 +2004,7 @@ pub trait SliceIndex: private_slice_index::Sealed { fn index_mut(self, slice: &mut T) -> &mut Self::Output; } -#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] impl SliceIndex<[T]> for usize { type Output = T; @@ -2071,12 +2032,12 @@ impl SliceIndex<[T]> for usize { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &T { - &*slice.as_ptr().offset(self as isize) + &*slice.as_ptr().add(self) } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut T { - &mut *slice.as_mut_ptr().offset(self as isize) + &mut *slice.as_mut_ptr().add(self) } #[inline] @@ -2092,7 +2053,7 @@ impl SliceIndex<[T]> for usize { } } -#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] impl SliceIndex<[T]> for ops::Range { type Output = [T]; @@ -2120,12 +2081,12 @@ impl SliceIndex<[T]> for ops::Range { #[inline] unsafe fn get_unchecked(self, slice: &[T]) -> &[T] { - from_raw_parts(slice.as_ptr().offset(self.start as isize), self.end - self.start) + from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] { - from_raw_parts_mut(slice.as_mut_ptr().offset(self.start as isize), self.end - self.start) + from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) } #[inline] @@ -2153,7 +2114,7 @@ impl SliceIndex<[T]> for ops::Range { } } -#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] impl SliceIndex<[T]> for ops::RangeTo { type Output = [T]; @@ -2188,7 +2149,7 @@ impl SliceIndex<[T]> for ops::RangeTo { } } -#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] impl SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; @@ -2223,7 +2184,7 @@ impl SliceIndex<[T]> for ops::RangeFrom { } } -#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] +#[stable(feature = "slice_get_slice_impls", since = "1.15.0")] impl SliceIndex<[T]> for ops::RangeFull { type Output = [T]; @@ -2373,14 +2334,88 @@ impl<'a, T> IntoIterator for &'a mut [T] { } } -#[inline] +// Macro helper functions +#[inline(always)] fn size_from_ptr(_: *const T) -> usize { mem::size_of::() } +// Inlining is_empty and len makes a huge performance difference +macro_rules! is_empty { + // The way we encode the length of a ZST iterator, this works both for ZST + // and non-ZST. + ($self: ident) => {$self.ptr == $self.end} +} +// To get rid of some bounds checks (see `position`), we compute the length in a somewhat +// unexpected way. (Tested by `codegen/slice-position-bounds-check`.) +macro_rules! len { + ($self: ident) => {{ + let start = $self.ptr; + let diff = ($self.end as usize).wrapping_sub(start as usize); + let size = size_from_ptr(start); + if size == 0 { + diff + } else { + // Using division instead of `offset_from` helps LLVM remove bounds checks + diff / size + } + }} +} + // The shared definition of the `Iter` and `IterMut` iterators macro_rules! iterator { - (struct $name:ident -> $ptr:ty, $elem:ty, $mkref:ident) => { + (struct $name:ident -> $ptr:ty, $elem:ty, $raw_mut:tt, $( $mut_:tt )*) => { + impl<'a, T> $name<'a, T> { + // Helper function for creating a slice from the iterator. + #[inline(always)] + fn make_slice(&self) -> &'a [T] { + unsafe { from_raw_parts(self.ptr, len!(self)) } + } + + // Helper function for moving the start of the iterator forwards by `offset` elements, + // returning the old start. + // Unsafe because the offset must be in-bounds or one-past-the-end. + #[inline(always)] + unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T { + if mem::size_of::() == 0 { + // This is *reducing* the length. `ptr` never changes with ZST. + self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T; + self.ptr + } else { + let old = self.ptr; + self.ptr = self.ptr.offset(offset); + old + } + } + + // Helper function for moving the end of the iterator backwards by `offset` elements, + // returning the new end. + // Unsafe because the offset must be in-bounds or one-past-the-end. + #[inline(always)] + unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T { + if mem::size_of::() == 0 { + self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T; + self.ptr + } else { + self.end = self.end.offset(-offset); + self.end + } + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T> ExactSizeIterator for $name<'a, T> { + #[inline(always)] + fn len(&self) -> usize { + len!(self) + } + + #[inline(always)] + fn is_empty(&self) -> bool { + is_empty!(self) + } + } + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for $name<'a, T> { type Item = $elem; @@ -2389,33 +2424,48 @@ macro_rules! iterator { fn next(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks unsafe { + assume(!self.ptr.is_null()); if mem::size_of::() != 0 { - assume(!self.ptr.is_null()); assume(!self.end.is_null()); } - if self.ptr == self.end { + if is_empty!(self) { None } else { - Some($mkref!(self.ptr.post_inc())) + Some(& $( $mut_ )* *self.post_inc_start(1)) } } } #[inline] fn size_hint(&self) -> (usize, Option) { - let exact = unsafe { ptrdistance(self.ptr, self.end) }; + let exact = len!(self); (exact, Some(exact)) } #[inline] fn count(self) -> usize { - self.len() + len!(self) } #[inline] fn nth(&mut self, n: usize) -> Option<$elem> { - // Call helper method. Can't put the definition here because mut versus const. - self.iter_nth(n) + if n >= len!(self) { + // This iterator is now empty. + if mem::size_of::() == 0 { + // We have to do it this way as `ptr` may never be 0, but `end` + // could be (due to wrapping). + self.end = self.ptr; + } else { + self.ptr = self.end; + } + return None; + } + // We are in bounds. `offset` does the right thing even for ZSTs. + unsafe { + let elem = Some(& $( $mut_ )* *self.ptr.add(n)); + self.post_inc_start((n as isize).wrapping_add(1)); + elem + } } #[inline] @@ -2430,14 +2480,14 @@ macro_rules! iterator { // manual unrolling is needed when there are conditional exits from the loop let mut accum = init; unsafe { - while ptrdistance(self.ptr, self.end) >= 4 { - accum = f(accum, $mkref!(self.ptr.post_inc()))?; - accum = f(accum, $mkref!(self.ptr.post_inc()))?; - accum = f(accum, $mkref!(self.ptr.post_inc()))?; - accum = f(accum, $mkref!(self.ptr.post_inc()))?; + while len!(self) >= 4 { + accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; + accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; + accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; + accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; } - while self.ptr != self.end { - accum = f(accum, $mkref!(self.ptr.post_inc()))?; + while !is_empty!(self) { + accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; } } Try::from_ok(accum) @@ -2462,9 +2512,8 @@ macro_rules! iterator { Self: Sized, P: FnMut(Self::Item) -> bool, { - // The addition might panic on overflow - // Use the len of the slice to hint optimizer to remove result index bounds check. - let n = make_slice!(self.ptr, self.end).len(); + // The addition might panic on overflow. + let n = len!(self); self.try_fold(0, move |i, x| { if predicate(x) { Err(i) } else { Ok(i + 1) } @@ -2481,9 +2530,7 @@ macro_rules! iterator { Self: Sized + ExactSizeIterator + DoubleEndedIterator { // No need for an overflow check here, because `ExactSizeIterator` - // implies that the number of elements fits into a `usize`. - // Use the len of the slice to hint optimizer to remove result index bounds check. - let n = make_slice!(self.ptr, self.end).len(); + let n = len!(self); self.try_rfold(n, move |i, x| { let i = i - 1; if predicate(x) { Err(i) } @@ -2502,14 +2549,14 @@ macro_rules! iterator { fn next_back(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks unsafe { + assume(!self.ptr.is_null()); if mem::size_of::() != 0 { - assume(!self.ptr.is_null()); assume(!self.end.is_null()); } - if self.end == self.ptr { + if is_empty!(self) { None } else { - Some($mkref!(self.end.pre_dec())) + Some(& $( $mut_ )* *self.pre_dec_end(1)) } } } @@ -2521,14 +2568,15 @@ macro_rules! iterator { // manual unrolling is needed when there are conditional exits from the loop let mut accum = init; unsafe { - while ptrdistance(self.ptr, self.end) >= 4 { - accum = f(accum, $mkref!(self.end.pre_dec()))?; - accum = f(accum, $mkref!(self.end.pre_dec()))?; - accum = f(accum, $mkref!(self.end.pre_dec()))?; - accum = f(accum, $mkref!(self.end.pre_dec()))?; + while len!(self) >= 4 { + accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; + accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; + accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; + accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; } - while self.ptr != self.end { - accum = f(accum, $mkref!(self.end.pre_dec()))?; + // inlining is_empty everywhere makes a huge performance difference + while !is_empty!(self) { + accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; } } Try::from_ok(accum) @@ -2556,34 +2604,6 @@ macro_rules! iterator { } } -macro_rules! make_slice { - ($start: expr, $end: expr) => {{ - let start = $start; - let diff = ($end as usize).wrapping_sub(start as usize); - if size_from_ptr(start) == 0 { - // use a non-null pointer value - unsafe { from_raw_parts(1 as *const _, diff) } - } else { - let len = diff / size_from_ptr(start); - unsafe { from_raw_parts(start, len) } - } - }} -} - -macro_rules! make_mut_slice { - ($start: expr, $end: expr) => {{ - let start = $start; - let diff = ($end as usize).wrapping_sub(start as usize); - if size_from_ptr(start) == 0 { - // use a non-null pointer value - unsafe { from_raw_parts_mut(1 as *mut _, diff) } - } else { - let len = diff / size_from_ptr(start); - unsafe { from_raw_parts_mut(start, len) } - } - }} -} - /// Immutable slice iterator /// /// This struct is created by the [`iter`] method on [slices]. @@ -2607,7 +2627,9 @@ macro_rules! make_mut_slice { #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { ptr: *const T, - end: *const T, + end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that + // ptr == end is a quick test for the Iterator being empty, that works + // for both ZST and non-ZST. _marker: marker::PhantomData<&'a T>, } @@ -2652,32 +2674,11 @@ impl<'a, T> Iter<'a, T> { /// ``` #[stable(feature = "iter_to_slice", since = "1.4.0")] pub fn as_slice(&self) -> &'a [T] { - make_slice!(self.ptr, self.end) - } - - // Helper function for Iter::nth - fn iter_nth(&mut self, n: usize) -> Option<&'a T> { - match self.as_slice().get(n) { - Some(elem_ref) => unsafe { - self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1)); - Some(elem_ref) - }, - None => { - self.ptr = self.end; - None - } - } + self.make_slice() } } -iterator!{struct Iter -> *const T, &'a T, make_ref} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> ExactSizeIterator for Iter<'a, T> { - fn is_empty(&self) -> bool { - self.ptr == self.end - } -} +iterator!{struct Iter -> *const T, &'a T, const, /* no mut */} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { @@ -2718,7 +2719,9 @@ impl<'a, T> AsRef<[T]> for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { ptr: *mut T, - end: *mut T, + end: *mut T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that + // ptr == end is a quick test for the Iterator being empty, that works + // for both ZST and non-ZST. _marker: marker::PhantomData<&'a mut T>, } @@ -2726,7 +2729,7 @@ pub struct IterMut<'a, T: 'a> { impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("IterMut") - .field(&make_slice!(self.ptr, self.end)) + .field(&self.make_slice()) .finish() } } @@ -2772,77 +2775,11 @@ impl<'a, T> IterMut<'a, T> { /// ``` #[stable(feature = "iter_to_slice", since = "1.4.0")] pub fn into_slice(self) -> &'a mut [T] { - make_mut_slice!(self.ptr, self.end) - } - - // Helper function for IterMut::nth - fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> { - match make_mut_slice!(self.ptr, self.end).get_mut(n) { - Some(elem_ref) => unsafe { - self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1)); - Some(elem_ref) - }, - None => { - self.ptr = self.end; - None - } - } - } -} - -iterator!{struct IterMut -> *mut T, &'a mut T, make_ref_mut} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> ExactSizeIterator for IterMut<'a, T> { - fn is_empty(&self) -> bool { - self.ptr == self.end - } -} - -// Return the number of elements of `T` from `start` to `end`. -// Return the arithmetic difference if `T` is zero size. -#[inline(always)] -unsafe fn ptrdistance(start: *const T, end: *const T) -> usize { - if mem::size_of::() == 0 { - (end as usize).wrapping_sub(start as usize) - } else { - end.offset_from(start) as usize - } -} - -// Extension methods for raw pointers, used by the iterators -trait PointerExt : Copy { - unsafe fn slice_offset(self, i: isize) -> Self; - - /// Increments `self` by 1, but returns the old value. - #[inline(always)] - unsafe fn post_inc(&mut self) -> Self { - let current = *self; - *self = self.slice_offset(1); - current - } - - /// Decrements `self` by 1, and returns the new value. - #[inline(always)] - unsafe fn pre_dec(&mut self) -> Self { - *self = self.slice_offset(-1); - *self + unsafe { from_raw_parts_mut(self.ptr, len!(self)) } } } -impl PointerExt for *const T { - #[inline(always)] - unsafe fn slice_offset(self, i: isize) -> Self { - slice_offset!(self, i) - } -} - -impl PointerExt for *mut T { - #[inline(always)] - unsafe fn slice_offset(self, i: isize) -> Self { - slice_offset!(self, i) - } -} +iterator!{struct IterMut -> *mut T, &'a mut T, mut, mut} /// An internal abstraction over the splitting iterators, so that /// splitn, splitn_mut etc can be implemented once. @@ -3405,7 +3342,7 @@ impl<'a, T> FusedIterator for Windows<'a, T> {} #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { - from_raw_parts(self.v.as_ptr().offset(i as isize), self.size) + from_raw_parts(self.v.as_ptr().add(i), self.size) } fn may_have_side_effect() -> bool { false } } @@ -3532,7 +3469,7 @@ unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> { None => self.v.len(), Some(end) => cmp::min(end, self.v.len()), }; - from_raw_parts(self.v.as_ptr().offset(start as isize), end - start) + from_raw_parts(self.v.as_ptr().add(start), end - start) } fn may_have_side_effect() -> bool { false } } @@ -3651,7 +3588,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> { None => self.v.len(), Some(end) => cmp::min(end, self.v.len()), }; - from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), end - start) + from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) } fn may_have_side_effect() -> bool { false } } @@ -3774,7 +3711,7 @@ impl<'a, T> FusedIterator for ExactChunks<'a, T> {} unsafe impl<'a, T> TrustedRandomAccess for ExactChunks<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { let start = i * self.chunk_size; - from_raw_parts(self.v.as_ptr().offset(start as isize), self.chunk_size) + from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) } fn may_have_side_effect() -> bool { false } } @@ -3889,7 +3826,7 @@ impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {} unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] { let start = i * self.chunk_size; - from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), self.chunk_size) + from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) } fn may_have_side_effect() -> bool { false } } @@ -3927,31 +3864,35 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// ``` /// use std::slice; /// -/// // manifest a slice out of thin air! -/// let ptr = 0x1234 as *const usize; -/// let amt = 10; -/// unsafe { -/// let slice = slice::from_raw_parts(ptr, amt); -/// } +/// // manifest a slice for a single element +/// let x = 42; +/// let ptr = &x as *const _; +/// let slice = unsafe { slice::from_raw_parts(ptr, 1) }; +/// assert_eq!(slice[0], 42); /// ``` /// /// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { + debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); 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 [`from_raw_parts`], except that a +/// mutable slice is returned. /// -/// This function is unsafe for the same reasons as `from_raw_parts`, as well +/// 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`. +/// slices as with [`from_raw_parts`]. See the documentation of +/// [`from_raw_parts`] for more details. +/// +/// [`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!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); Repr { raw: FatPtr { data, len} }.rust_mut } @@ -4173,7 +4114,7 @@ impl_marker_for!(BytewiseEquality, #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { - &*self.ptr.offset(i as isize) + &*self.ptr.add(i) } fn may_have_side_effect() -> bool { false } } @@ -4181,7 +4122,7 @@ unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> { #[doc(hidden)] unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { - &mut *self.ptr.offset(i as isize) + &mut *self.ptr.add(i) } fn may_have_side_effect() -> bool { false } } diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index 28ef53ccb5..0d182b8497 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -77,8 +77,8 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { } ptr::swap_nonoverlapping( - mid.offset(-(left as isize)), - mid.offset((right-delta) as isize), + mid.sub(left), + mid.add(right - delta), delta); if left <= right { @@ -91,15 +91,15 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { let rawarray = RawArray::new(); let buf = rawarray.ptr(); - let dim = mid.offset(-(left as isize)).offset(right as isize); + let dim = mid.sub(left).add(right); if left <= right { - ptr::copy_nonoverlapping(mid.offset(-(left as isize)), buf, left); - ptr::copy(mid, mid.offset(-(left as isize)), right); + ptr::copy_nonoverlapping(mid.sub(left), buf, left); + ptr::copy(mid, mid.sub(left), right); ptr::copy_nonoverlapping(buf, dim, left); } else { ptr::copy_nonoverlapping(mid, buf, right); - ptr::copy(mid.offset(-(left as isize)), dim, left); - ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right); + ptr::copy(mid.sub(left), dim, left); + ptr::copy_nonoverlapping(buf, mid.sub(left), right); } } diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 518d56095d..e4c1fd03f9 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -221,15 +221,15 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize // 3. `end` - End pointer into the `offsets` array. // 4. `offsets - Indices of out-of-order elements within the block. - // The current block on the left side (from `l` to `l.offset(block_l)`). + // The current block on the left side (from `l` to `l.add(block_l)`). let mut l = v.as_mut_ptr(); let mut block_l = BLOCK; let mut start_l = ptr::null_mut(); let mut end_l = ptr::null_mut(); let mut offsets_l: [u8; BLOCK] = unsafe { mem::uninitialized() }; - // The current block on the right side (from `r.offset(-block_r)` to `r`). - let mut r = unsafe { l.offset(v.len() as isize) }; + // The current block on the right side (from `r.sub(block_r)` to `r`). + let mut r = unsafe { l.add(v.len()) }; let mut block_r = BLOCK; let mut start_r = ptr::null_mut(); let mut end_r = ptr::null_mut(); diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs index 5cfb36d3b1..186d6adbc9 100644 --- a/src/libcore/str/lossy.rs +++ b/src/libcore/str/lossy.rs @@ -146,7 +146,7 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { broken: &[], }; self.source = &[]; - return Some(r); + Some(r) } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 86b8349fa3..2c941c28d4 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -59,7 +59,7 @@ pub mod lossy; /// /// fn from_str(s: &str) -> Result { /// let coords: Vec<&str> = s.trim_matches(|p| p == '(' || p == ')' ) -/// .split(",") +/// .split(',') /// .collect(); /// /// let x_fromstr = coords[0].parse::()?; @@ -244,7 +244,10 @@ impl Utf8Error { /// The length provided is that of the invalid byte sequence /// that starts at the index given by `valid_up_to()`. /// Decoding should resume after that sequence - /// (after inserting a U+FFFD REPLACEMENT CHARACTER) in case of lossy decoding. + /// (after inserting a [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]) in case of + /// lossy decoding. + /// + /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html #[stable(feature = "utf8_error_error_len", since = "1.20.0")] pub fn error_len(&self) -> Option { self.error_len.map(|len| len as usize) @@ -1515,12 +1518,12 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { let ptr = v.as_ptr(); let align = unsafe { // the offset is safe, because `index` is guaranteed inbounds - ptr.offset(index as isize).align_offset(usize_bytes) + ptr.add(index).align_offset(usize_bytes) }; if align == 0 { while index < blocks_end { unsafe { - let block = ptr.offset(index as isize) as *const usize; + let block = ptr.add(index) as *const usize; // break if there is a nonascii byte let zu = contains_nonascii(*block); let zv = contains_nonascii(*block.offset(1)); @@ -1567,7 +1570,7 @@ static UTF8_CHAR_WIDTH: [u8; 256] = [ #[unstable(feature = "str_internals", issue = "0")] #[inline] pub fn utf8_char_width(b: u8) -> usize { - return UTF8_CHAR_WIDTH[b as usize] as usize; + UTF8_CHAR_WIDTH[b as usize] as usize } /// Mask of the value bits of a continuation byte. @@ -1875,13 +1878,13 @@ mod traits { } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { - let ptr = slice.as_ptr().offset(self.start as isize); + let ptr = slice.as_ptr().add(self.start); let len = self.end - self.start; super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { - let ptr = slice.as_ptr().offset(self.start as isize); + let ptr = slice.as_ptr().add(self.start); let len = self.end - self.start; super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len)) } @@ -1970,13 +1973,13 @@ mod traits { } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { - let ptr = slice.as_ptr().offset(self.start as isize); + let ptr = slice.as_ptr().add(self.start); let len = slice.len() - self.start; super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { - let ptr = slice.as_ptr().offset(self.start as isize); + let ptr = slice.as_ptr().add(self.start); let len = slice.len() - self.start; super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len)) } @@ -2117,8 +2120,6 @@ impl str { /// This length is in bytes, not [`char`]s or graphemes. In other words, /// it may not be what a human considers the length of the string. /// - /// [`char`]: primitive.char.html - /// /// # Examples /// /// Basic usage: @@ -2572,7 +2573,7 @@ impl str { unsafe { (from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)), from_utf8_unchecked_mut(slice::from_raw_parts_mut( - ptr.offset(mid as isize), + ptr.add(mid), len - mid ))) } @@ -2590,8 +2591,6 @@ impl str { /// Value, and may not match your idea of what a 'character' is. Iteration /// over grapheme clusters may be what you actually want. /// - /// [`char`]: primitive.char.html - /// /// # Examples /// /// Basic usage: @@ -2643,8 +2642,6 @@ impl str { /// The iterator yields tuples. The position is first, the [`char`] is /// second. /// - /// [`char`]: primitive.char.html - /// /// # Examples /// /// Basic usage: @@ -2946,7 +2943,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines if /// a character matches. /// - /// [`char`]: primitive.char.html /// [`None`]: option/enum.Option.html#variant.None /// /// # Examples @@ -2994,7 +2990,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines if /// a character matches. /// - /// [`char`]: primitive.char.html /// [`None`]: option/enum.Option.html#variant.None /// /// # Examples @@ -3050,7 +3045,6 @@ impl str { /// If the pattern allows a reverse search but its results might differ /// from a forward search, the [`rsplit`] method can be used. /// - /// [`char`]: primitive.char.html /// [`rsplit`]: #method.rsplit /// /// # Examples @@ -3157,8 +3151,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines the /// split. /// - /// [`char`]: primitive.char.html - /// /// # Iterator behavior /// /// The returned iterator requires that the pattern supports a reverse @@ -3224,7 +3216,6 @@ impl str { /// elements. This is true for, eg, [`char`] but not for `&str`. /// /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// [`char`]: primitive.char.html /// /// If the pattern allows a reverse search but its results might differ /// from a forward search, the [`rsplit_terminator`] method can be used. @@ -3259,8 +3250,6 @@ impl str { /// Additional libraries might provide more complex patterns like /// regular expressions. /// - /// [`char`]: primitive.char.html - /// /// Equivalent to [`split`], except that the trailing substring is /// skipped if empty. /// @@ -3306,8 +3295,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines the /// split. /// - /// [`char`]: primitive.char.html - /// /// # Iterator behavior /// /// The returned iterator will not be double ended, because it is @@ -3361,8 +3348,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that /// determines the split. /// - /// [`char`]: primitive.char.html - /// /// # Iterator behavior /// /// The returned iterator will not be double ended, because it is not @@ -3407,8 +3392,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that /// determines if a character matches. /// - /// [`char`]: primitive.char.html - /// /// # Iterator behavior /// /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern @@ -3416,7 +3399,6 @@ impl str { /// elements. This is true for, eg, [`char`] but not for `&str`. /// /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// [`char`]: primitive.char.html /// /// If the pattern allows a reverse search but its results might differ /// from a forward search, the [`rmatches`] method can be used. @@ -3446,8 +3428,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines if /// a character matches. /// - /// [`char`]: primitive.char.html - /// /// # Iterator behavior /// /// The returned iterator requires that the pattern supports a reverse @@ -3488,8 +3468,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines /// if a character matches. /// - /// [`char`]: primitive.char.html - /// /// # Iterator behavior /// /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern @@ -3532,8 +3510,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines if a /// character matches. /// - /// [`char`]: primitive.char.html - /// /// # Iterator behavior /// /// The returned iterator requires that the pattern supports a reverse @@ -3587,6 +3563,76 @@ impl str { self.trim_matches(|c: char| c.is_whitespace()) } + /// Returns a string slice with leading whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. `start` in this context means the first + /// position of that byte string; for a left-to-right language like English or + /// Russian, this will be left side; and for right-to-left languages like + /// like Arabic or Hebrew, this will be the right side. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!("Hello\tworld\t", s.trim_start()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = " English "; + /// assert!(Some('E') == s.trim_start().chars().next()); + /// + /// let s = " עברית "; + /// assert!(Some('×¢') == s.trim_start().chars().next()); + /// ``` + #[stable(feature = "trim_direction", since = "1.30.0")] + pub fn trim_start(&self) -> &str { + self.trim_start_matches(|c: char| c.is_whitespace()) + } + + /// Returns a string slice with trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. `end` in this context means the last + /// position of that byte string; for a left-to-right language like English or + /// Russian, this will be right side; and for right-to-left languages like + /// like Arabic or Hebrew, this will be the left side. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(" Hello\tworld", s.trim_end()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = " English "; + /// assert!(Some('h') == s.trim_end().chars().rev().next()); + /// + /// let s = " עברית "; + /// assert!(Some('ת') == s.trim_end().chars().rev().next()); + /// ``` + #[stable(feature = "trim_direction", since = "1.30.0")] + pub fn trim_end(&self) -> &str { + self.trim_end_matches(|c: char| c.is_whitespace()) + } + /// Returns a string slice with leading whitespace removed. /// /// 'Whitespace' is defined according to the terms of the Unicode Derived @@ -3619,8 +3665,9 @@ impl str { /// assert!(Some('×¢') == s.trim_left().chars().next()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(reason = "superseded by `trim_start`", since = "1.33.0")] pub fn trim_left(&self) -> &str { - self.trim_left_matches(|c: char| c.is_whitespace()) + self.trim_start() } /// Returns a string slice with trailing whitespace removed. @@ -3655,8 +3702,9 @@ impl str { /// assert!(Some('ת') == s.trim_right().chars().rev().next()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(reason = "superseded by `trim_end`", since = "1.33.0")] pub fn trim_right(&self) -> &str { - self.trim_right_matches(|c: char| c.is_whitespace()) + self.trim_end() } /// Returns a string slice with all prefixes and suffixes that match a @@ -3665,8 +3713,6 @@ impl str { /// The pattern can be a [`char`] or a closure that determines if a /// character matches. /// - /// [`char`]: primitive.char.html - /// /// # Examples /// /// Simple patterns: @@ -3711,8 +3757,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines if /// a character matches. /// - /// [`char`]: primitive.char.html - /// /// # Text directionality /// /// A string is a sequence of bytes. 'Left' in this context means the first @@ -3725,14 +3769,14 @@ impl str { /// Basic usage: /// /// ``` - /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); - /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); + /// assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11"); + /// assert_eq!("123foo1bar123".trim_start_matches(char::is_numeric), "foo1bar123"); /// /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12"); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { + #[stable(feature = "trim_direction", since = "1.30.0")] + pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { let mut i = self.len(); let mut matcher = pat.into_searcher(self); if let Some((a, _)) = matcher.next_reject() { @@ -3750,8 +3794,6 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that /// determines if a character matches. /// - /// [`char`]: primitive.char.html - /// /// # Text directionality /// /// A string is a sequence of bytes. 'Right' in this context means the last @@ -3764,20 +3806,20 @@ impl str { /// Simple patterns: /// /// ``` - /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); - /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); + /// assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar"); + /// assert_eq!("123foo1bar123".trim_end_matches(char::is_numeric), "123foo1bar"); /// /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// assert_eq!("12foo1bar12".trim_end_matches(x), "12foo1bar"); /// ``` /// /// A more complex pattern, using a closure: /// /// ``` - /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo"); + /// assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo"); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + #[stable(feature = "trim_direction", since = "1.30.0")] + pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str where P::Searcher: ReverseSearcher<'a> { let mut j = 0; @@ -3791,6 +3833,78 @@ impl str { } } + /// Returns a string slice with all prefixes that match a pattern + /// repeatedly removed. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(reason = "superseded by `trim_start_matches`", since = "1.33.0")] + pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { + self.trim_start_matches(pat) + } + + /// Returns a string slice with all suffixes that match a pattern + /// repeatedly removed. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(reason = "superseded by `trim_end_matches`", since = "1.33.0")] + pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a> + { + self.trim_end_matches(pat) + } + /// Parses this string slice into another type. /// /// Because `parse` is so general, it can cause problems with type diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index e9d1fb8911..602f8d4ee7 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -29,7 +29,7 @@ //! //! [`Ordering`]: enum.Ordering.html //! -//! [1]: http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations +//! [1]: https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations //! [2]: ../../../nomicon/atomics.html //! //! Atomic variables are safe to share between threads (they implement [`Sync`]) @@ -176,53 +176,85 @@ unsafe impl Sync for AtomicPtr {} /// "relaxed" atomics allow all reorderings. /// /// Rust's memory orderings are [the same as -/// LLVM's](http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations). +/// LLVM's](https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations). /// /// For more information see the [nomicon]. /// /// [nomicon]: ../../../nomicon/atomics.html #[stable(feature = "rust1", since = "1.0.0")] #[derive(Copy, Clone, Debug)] +#[non_exhaustive] pub enum Ordering { /// No ordering constraints, only atomic operations. /// /// Corresponds to LLVM's [`Monotonic`] ordering. /// - /// [`Monotonic`]: http://llvm.org/docs/Atomics.html#monotonic + /// [`Monotonic`]: https://llvm.org/docs/Atomics.html#monotonic #[stable(feature = "rust1", since = "1.0.0")] Relaxed, - /// When coupled with a store, all previous writes become visible - /// to the other threads that perform a load with [`Acquire`] ordering - /// on the same value. + /// When coupled with a store, all previous operations become ordered + /// before any load of this value with [`Acquire`] (or stronger) ordering. + /// In particular, all previous writes become visible to all threads + /// that perform an [`Acquire`] (or stronger) load of this value. /// - /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire + /// Notice that using this ordering for an operation that combines loads + /// and stores leads to a [`Relaxed`] load operation! + /// + /// This ordering is only applicable for operations that can perform a store. + /// + /// Corresponds to LLVM's [`Release`] ordering. + /// + /// [`Release`]: https://llvm.org/docs/Atomics.html#release + /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire + /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic #[stable(feature = "rust1", since = "1.0.0")] Release, - /// When coupled with a load, all subsequent loads will see data - /// written before a store with [`Release`] ordering on the same value - /// in other threads. + /// When coupled with a load, if the loaded value was written by a store operation with + /// [`Release`] (or stronger) ordering, then all subsequent operations + /// become ordered after that store. In particular, all subsequent loads will see data + /// written before the store. + /// + /// Notice that using this ordering for an operation that combines loads + /// and stores leads to a [`Relaxed`] store operation! + /// + /// This ordering is only applicable for operations that can perform a load. /// - /// [`Release`]: http://llvm.org/docs/Atomics.html#release + /// Corresponds to LLVM's [`Acquire`] ordering. + /// + /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire + /// [`Release`]: https://llvm.org/docs/Atomics.html#release + /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic #[stable(feature = "rust1", since = "1.0.0")] Acquire, - /// Has the effects of both [`Acquire`] and [`Release`] together. + /// Has the effects of both [`Acquire`] and [`Release`] together: + /// For loads it uses [`Acquire`] ordering. For stores it uses the [`Release`] ordering. + /// + /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up + /// not performing any store and hence it has just `Acquire` ordering. However, + /// `AcqRel` will never perform [`Relaxed`] accesses. /// /// This ordering is only applicable for operations that combine both loads and stores. /// - /// For loads it uses [`Acquire`] ordering. For stores it uses the [`Release`] ordering. + /// Corresponds to LLVM's [`AcquireRelease`] ordering. /// - /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire - /// [`Release`]: http://llvm.org/docs/Atomics.html#release + /// [`AcquireRelease`]: https://llvm.org/docs/Atomics.html#acquirerelease + /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire + /// [`Release`]: https://llvm.org/docs/Atomics.html#release + /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic #[stable(feature = "rust1", since = "1.0.0")] AcqRel, - /// Like `AcqRel` with the additional guarantee that all threads see all + /// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store + /// operations, respectively) with the additional guarantee that all threads see all /// sequentially consistent operations in the same order. + /// + /// Corresponds to LLVM's [`SequentiallyConsistent`] ordering. + /// + /// [`SequentiallyConsistent`]: https://llvm.org/docs/Atomics.html#sequentiallyconsistent + /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire + /// [`Release`]: https://llvm.org/docs/Atomics.html#release + /// [`AcqRel`]: https://llvm.org/docs/Atomics.html#acquirerelease #[stable(feature = "rust1", since = "1.0.0")] SeqCst, - // Prevent exhaustive matching to allow for future extension - #[doc(hidden)] - #[unstable(feature = "future_atomic_orderings", issue = "0")] - __Nonexhaustive, } /// An [`AtomicBool`] initialized to `false`. @@ -295,15 +327,18 @@ impl AtomicBool { /// Loads a value from the bool. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering - /// of this operation. + /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Release`] or [`AcqRel`]. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel + /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst /// /// # Examples /// @@ -323,9 +358,18 @@ impl AtomicBool { /// Stores a value into the bool. /// /// `store` takes an [`Ordering`] argument which describes the memory ordering - /// of this operation. + /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Acquire`] or [`AcqRel`]. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel + /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst /// /// # Examples /// @@ -337,13 +381,6 @@ impl AtomicBool { /// some_bool.store(false, Ordering::Relaxed); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// ``` - /// - /// # Panics - /// - /// Panics if `order` is [`Acquire`] or [`AcqRel`]. - /// - /// [`Acquire`]: enum.Ordering.html#variant.Acquire - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, val: bool, order: Ordering) { @@ -355,9 +392,14 @@ impl AtomicBool { /// Stores a value into the bool, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering - /// of this operation. + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire /// /// # Examples /// @@ -371,7 +413,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn swap(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 } } @@ -382,9 +424,16 @@ impl AtomicBool { /// was updated. /// /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory - /// ordering of this operation. + /// ordering of this operation. Notice that even when using [`AcqRel`], the operation + /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics. + /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it + /// happens, and using [`Release`] makes the load part [`Relaxed`]. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// [`bool`]: ../../../std/primitive.bool.html /// /// # Examples @@ -402,7 +451,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -418,13 +467,18 @@ impl AtomicBool { /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. The first describes the required ordering if the /// operation succeeds while the second describes the required ordering when the - /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must - /// be equivalent or weaker than the success ordering. + /// operation fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] + /// and must be equivalent to or weaker than the success ordering. + /// /// /// [`bool`]: ../../../std/primitive.bool.html /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst /// /// # Examples /// @@ -448,7 +502,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange(&self, current: bool, new: bool, @@ -471,16 +525,20 @@ impl AtomicBool { /// previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if the operation - /// succeeds while the second describes the required ordering when the operation fails. The - /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or - /// weaker than the success ordering. + /// ordering of this operation. The first describes the required ordering if the + /// operation succeeds while the second describes the required ordering when the + /// operation fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] + /// and must be equivalent to or weaker than the success ordering. /// /// [`bool`]: ../../../std/primitive.bool.html /// [`compare_exchange`]: #method.compare_exchange /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst /// /// # Examples /// @@ -521,6 +579,16 @@ impl AtomicBool { /// /// Returns the previous value. /// + /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// /// # Examples /// /// ``` @@ -540,7 +608,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_and(self.v.get(), val as u8, order) != 0 } } @@ -552,6 +620,16 @@ impl AtomicBool { /// /// Returns the previous value. /// + /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// /// # Examples /// /// ``` @@ -572,7 +650,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { // We can't use atomic_nand here because it can result in a bool with // an invalid value. This happens because the atomic operation is done @@ -596,6 +674,16 @@ impl AtomicBool { /// /// Returns the previous value. /// + /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// /// # Examples /// /// ``` @@ -615,7 +703,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_or(self.v.get(), val as u8, order) != 0 } } @@ -627,6 +715,16 @@ impl AtomicBool { /// /// Returns the previous value. /// + /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// /// # Examples /// /// ``` @@ -646,7 +744,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } } @@ -712,15 +810,18 @@ impl AtomicPtr { /// Loads a value from the pointer. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering - /// of this operation. + /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Release`] or [`AcqRel`]. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel + /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst /// /// # Examples /// @@ -741,9 +842,18 @@ impl AtomicPtr { /// Stores a value into the pointer. /// /// `store` takes an [`Ordering`] argument which describes the memory ordering - /// of this operation. + /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. + /// + /// # Panics + /// + /// Panics if `order` is [`Acquire`] or [`AcqRel`]. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel + /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst /// /// # Examples /// @@ -757,13 +867,6 @@ impl AtomicPtr { /// /// some_ptr.store(other_ptr, Ordering::Relaxed); /// ``` - /// - /// # Panics - /// - /// Panics if `order` is [`Acquire`] or [`AcqRel`]. - /// - /// [`Acquire`]: enum.Ordering.html#variant.Acquire - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, ptr: *mut T, order: Ordering) { @@ -775,9 +878,14 @@ impl AtomicPtr { /// Stores a value into the pointer, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering - /// of this operation. + /// of this operation. All ordering modes are possible. Note that using + /// [`Acquire`] makes the store part of this operation [`Relaxed`], and + /// using [`Release`] makes the load part [`Relaxed`]. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire /// /// # Examples /// @@ -793,7 +901,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T } } @@ -804,9 +912,16 @@ impl AtomicPtr { /// was updated. /// /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory - /// ordering of this operation. + /// ordering of this operation. Notice that even when using [`AcqRel`], the operation + /// might fail and hence just perform an `Acquire` load, but not have `Release` semantics. + /// Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it + /// happens, and using [`Release`] makes the load part [`Relaxed`]. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -823,7 +938,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -837,14 +952,18 @@ impl AtomicPtr { /// the previous value. On success this value is guaranteed to be equal to `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if - /// the operation succeeds while the second describes the required ordering when - /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] - /// and must be equivalent or weaker than the success ordering. + /// ordering of this operation. The first describes the required ordering if the + /// operation succeeds while the second describes the required ordering when the + /// operation fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] + /// and must be equivalent to or weaker than the success ordering. /// /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst /// /// # Examples /// @@ -862,7 +981,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange(&self, current: *mut T, new: *mut T, @@ -890,15 +1009,19 @@ impl AtomicPtr { /// previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if the operation - /// succeeds while the second describes the required ordering when the operation fails. The - /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or - /// weaker than the success ordering. + /// ordering of this operation. The first describes the required ordering if the + /// operation succeeds while the second describes the required ordering when the + /// operation fails. Using [`Acquire`] as success ordering makes the store part + /// of this operation [`Relaxed`], and using [`Release`] makes the successful load + /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] + /// and must be equivalent to or weaker than the success ordering. /// /// [`compare_exchange`]: #method.compare_exchange /// [`Ordering`]: enum.Ordering.html + /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel + /// [`Acquire`]: enum.Ordering.html#variant.Acquire + /// [`SeqCst`]: enum.Ordering.html#variant.SeqCst /// /// # Examples /// @@ -1074,14 +1197,18 @@ assert_eq!(some_var.into_inner(), 5); concat!("Loads a value from the atomic integer. `load` takes an [`Ordering`] argument which describes the memory ordering of this operation. +Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. # Panics Panics if `order` is [`Release`] or [`AcqRel`]. [`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed [`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire [`AcqRel`]: enum.Ordering.html#variant.AcqRel +[`SeqCst`]: enum.Ordering.html#variant.SeqCst # Examples @@ -1103,8 +1230,18 @@ assert_eq!(some_var.load(Ordering::Relaxed), 5); concat!("Stores a value into the atomic integer. `store` takes an [`Ordering`] argument which describes the memory ordering of this operation. + Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. + +# Panics + +Panics if `order` is [`Acquire`] or [`AcqRel`]. [`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire +[`AcqRel`]: enum.Ordering.html#variant.AcqRel +[`SeqCst`]: enum.Ordering.html#variant.SeqCst # Examples @@ -1115,14 +1252,7 @@ let some_var = ", stringify!($atomic_type), "::new(5); some_var.store(10, Ordering::Relaxed); assert_eq!(some_var.load(Ordering::Relaxed), 10); -``` - -# Panics - -Panics if `order` is [`Acquire`] or [`AcqRel`]. - -[`Acquire`]: enum.Ordering.html#variant.Acquire -[`AcqRel`]: enum.Ordering.html#variant.AcqRel"), +```"), #[inline] #[$stable] pub fn store(&self, val: $int_type, order: Ordering) { @@ -1133,9 +1263,15 @@ Panics if `order` is [`Acquire`] or [`AcqRel`]. doc_comment! { concat!("Stores a value into the atomic integer, returning the previous value. -`swap` takes an [`Ordering`] argument which describes the memory ordering of this operation. +`swap` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. [`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire # Examples @@ -1148,7 +1284,7 @@ assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); ```"), #[inline] #[$stable] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -1162,9 +1298,16 @@ The return value is always the previous value. If it is equal to `current`, then value was updated. `compare_and_swap` also takes an [`Ordering`] argument which describes the memory -ordering of this operation. +ordering of this operation. Notice that even when using [`AcqRel`], the operation +might fail and hence just perform an `Acquire` load, but not have `Release` semantics. +Using [`Acquire`] makes the store part of this operation [`Relaxed`] if it +happens, and using [`Release`] makes the load part [`Relaxed`]. [`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire +[`AcqRel`]: enum.Ordering.html#variant.AcqRel # Examples @@ -1181,7 +1324,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[$stable] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn compare_and_swap(&self, current: $int_type, new: $int_type, @@ -1205,14 +1348,18 @@ containing the previous value. On success this value is guaranteed to be equal t `current`. `compare_exchange` takes two [`Ordering`] arguments to describe the memory -ordering of this operation. The first describes the required ordering if -the operation succeeds while the second describes the required ordering when -the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and -must be equivalent or weaker than the success ordering. +ordering of this operation. The first describes the required ordering if the +operation succeeds while the second describes the required ordering when the +operation fails. Using [`Acquire`] as success ordering makes the store part +of this operation [`Relaxed`], and using [`Release`] makes the successful load +[`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] +and must be equivalent to or weaker than the success ordering. [`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed [`Release`]: enum.Ordering.html#variant.Release -[`AcqRel`]: enum.Ordering.html#variant.AcqRel +[`Acquire`]: enum.Ordering.html#variant.Acquire +[`SeqCst`]: enum.Ordering.html#variant.SeqCst # Examples @@ -1235,7 +1382,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[$stable_cxchg] - #[cfg(any(stage0, target_has_atomic = "cas"))] + #[cfg(target_has_atomic = "cas")] pub fn compare_exchange(&self, current: $int_type, new: $int_type, @@ -1257,13 +1404,17 @@ written and containing the previous value. `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory ordering of this operation. The first describes the required ordering if the operation succeeds while the second describes the required ordering when the -operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and -must be equivalent or weaker than the success ordering. +operation fails. Using [`Acquire`] as success ordering makes the store part +of this operation [`Relaxed`], and using [`Release`] makes the successful load +[`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] +and must be equivalent to or weaker than the success ordering. [`compare_exchange`]: #method.compare_exchange [`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed [`Release`]: enum.Ordering.html#variant.Release -[`AcqRel`]: enum.Ordering.html#variant.AcqRel +[`Acquire`]: enum.Ordering.html#variant.Acquire +[`SeqCst`]: enum.Ordering.html#variant.SeqCst # Examples @@ -1299,6 +1450,16 @@ loop { This operation wraps around on overflow. +`fetch_add` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. + +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire + # Examples ``` @@ -1320,6 +1481,16 @@ assert_eq!(foo.load(Ordering::SeqCst), 10); This operation wraps around on overflow. +`fetch_sub` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. + +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire + # Examples ``` @@ -1344,6 +1515,16 @@ sets the new value to the result. Returns the previous value. +`fetch_and` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. + +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire + # Examples ``` @@ -1368,6 +1549,16 @@ sets the new value to the result. Returns the previous value. +`fetch_nand` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. + +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire + # Examples ``` @@ -1393,6 +1584,16 @@ sets the new value to the result. Returns the previous value. +`fetch_or` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. + +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire + # Examples ``` @@ -1417,6 +1618,16 @@ sets the new value to the result. Returns the previous value. +`fetch_xor` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. + +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire + # Examples ``` @@ -1442,6 +1653,25 @@ Note: This may call the function multiple times if the value has been changed fr the meantime, as long as the function returns `Some(_)`, but the function will have been applied but once to the stored value. +`fetch_update` takes two [`Ordering`] arguments to describe the memory +ordering of this operation. The first describes the required ordering for loads +and failed updates while the second describes the required ordering when the +operation finally succeeds. Beware that this is different from the two +modes in [`compare_exchange`]! + +Using [`Acquire`] as success ordering makes the store part +of this operation [`Relaxed`], and using [`Release`] makes the final successful load +[`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] +and must be equivalent to or weaker than the success ordering. + +[`bool`]: ../../../std/primitive.bool.html +[`compare_exchange`]: #method.compare_exchange +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire +[`SeqCst`]: enum.Ordering.html#variant.SeqCst + # Examples ```rust @@ -1482,6 +1712,16 @@ sets the new value to the result. Returns the previous value. +`fetch_max` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. + +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire + # Examples ``` @@ -1521,6 +1761,16 @@ sets the new value to the result. Returns the previous value. +`fetch_min` takes an [`Ordering`] argument which describes the memory ordering +of this operation. All ordering modes are possible. Note that using +[`Acquire`] makes the store part of this operation [`Relaxed`], and +using [`Release`] makes the load part [`Relaxed`]. + +[`Ordering`]: enum.Ordering.html +[`Relaxed`]: enum.Ordering.html#variant.Relaxed +[`Release`]: enum.Ordering.html#variant.Release +[`Acquire`]: enum.Ordering.html#variant.Acquire + # Examples ``` @@ -1690,7 +1940,7 @@ atomic_int!{ } #[inline] -#[cfg(any(stage0, target_has_atomic = "cas"))] +#[cfg(target_has_atomic = "cas")] fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release => Relaxed, @@ -1698,7 +1948,6 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering { SeqCst => SeqCst, Acquire => Acquire, AcqRel => Acquire, - __Nonexhaustive => __Nonexhaustive, } } @@ -1710,7 +1959,6 @@ unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { SeqCst => intrinsics::atomic_store(dst, val), Acquire => panic!("there is no such thing as an acquire store"), AcqRel => panic!("there is no such thing as an acquire/release store"), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1722,12 +1970,11 @@ unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { SeqCst => intrinsics::atomic_load(dst), Release => panic!("there is no such thing as a release load"), AcqRel => panic!("there is no such thing as an acquire/release load"), - __Nonexhaustive => panic!("invalid memory ordering"), } } #[inline] -#[cfg(any(stage0, target_has_atomic = "cas"))] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), @@ -1735,7 +1982,6 @@ unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), SeqCst => intrinsics::atomic_xchg(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1748,7 +1994,6 @@ unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), Relaxed => intrinsics::atomic_xadd_relaxed(dst, val), SeqCst => intrinsics::atomic_xadd(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1761,12 +2006,11 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), Relaxed => intrinsics::atomic_xsub_relaxed(dst, val), SeqCst => intrinsics::atomic_xsub(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } #[inline] -#[cfg(any(stage0, target_has_atomic = "cas"))] +#[cfg(target_has_atomic = "cas")] unsafe fn atomic_compare_exchange(dst: *mut T, old: T, new: T, @@ -1783,8 +2027,6 @@ unsafe fn atomic_compare_exchange(dst: *mut T, (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), - (__Nonexhaustive, _) => panic!("invalid memory ordering"), - (_, __Nonexhaustive) => panic!("invalid memory ordering"), (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), (_, Release) => panic!("there is no such thing as a release failure ordering"), _ => panic!("a failure ordering can't be stronger than a success ordering"), @@ -1809,8 +2051,6 @@ unsafe fn atomic_compare_exchange_weak(dst: *mut T, (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new), (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new), - (__Nonexhaustive, _) => panic!("invalid memory ordering"), - (_, __Nonexhaustive) => panic!("invalid memory ordering"), (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), (_, Release) => panic!("there is no such thing as a release failure ordering"), _ => panic!("a failure ordering can't be stronger than a success ordering"), @@ -1826,7 +2066,6 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_and_acqrel(dst, val), Relaxed => intrinsics::atomic_and_relaxed(dst, val), SeqCst => intrinsics::atomic_and(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1838,7 +2077,6 @@ unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_nand_acqrel(dst, val), Relaxed => intrinsics::atomic_nand_relaxed(dst, val), SeqCst => intrinsics::atomic_nand(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1850,7 +2088,6 @@ unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_or_acqrel(dst, val), Relaxed => intrinsics::atomic_or_relaxed(dst, val), SeqCst => intrinsics::atomic_or(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1862,7 +2099,6 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_xor_acqrel(dst, val), Relaxed => intrinsics::atomic_xor_relaxed(dst, val), SeqCst => intrinsics::atomic_xor(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1875,7 +2111,6 @@ unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_max_acqrel(dst, val), Relaxed => intrinsics::atomic_max_relaxed(dst, val), SeqCst => intrinsics::atomic_max(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1888,7 +2123,6 @@ unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_min_acqrel(dst, val), Relaxed => intrinsics::atomic_min_relaxed(dst, val), SeqCst => intrinsics::atomic_min(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1901,7 +2135,6 @@ unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_umax_acqrel(dst, val), Relaxed => intrinsics::atomic_umax_relaxed(dst, val), SeqCst => intrinsics::atomic_umax(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -1914,7 +2147,6 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { AcqRel => intrinsics::atomic_umin_acqrel(dst, val), Relaxed => intrinsics::atomic_umin_relaxed(dst, val), SeqCst => intrinsics::atomic_umin(dst, val), - __Nonexhaustive => panic!("invalid memory ordering"), } } @@ -2004,7 +2236,6 @@ pub fn fence(order: Ordering) { AcqRel => intrinsics::atomic_fence_acqrel(), SeqCst => intrinsics::atomic_fence(), Relaxed => panic!("there is no such thing as a relaxed fence"), - __Nonexhaustive => panic!("invalid memory ordering"), } } } @@ -2094,7 +2325,6 @@ pub fn compiler_fence(order: Ordering) { AcqRel => intrinsics::atomic_singlethreadfence_acqrel(), SeqCst => intrinsics::atomic_singlethreadfence(), Relaxed => panic!("there is no such thing as a relaxed compiler fence"), - __Nonexhaustive => panic!("invalid memory ordering"), } } } diff --git a/src/libcore/task/context.rs b/src/libcore/task/context.rs index 1fc975cb17..5a29c8528e 100644 --- a/src/libcore/task/context.rs +++ b/src/libcore/task/context.rs @@ -13,7 +13,7 @@ issue = "50547")] use fmt; -use super::{Executor, Waker, LocalWaker}; +use super::{Spawn, Waker, LocalWaker}; /// Information about the currently-running task. /// @@ -21,7 +21,7 @@ use super::{Executor, Waker, LocalWaker}; /// when performing a single `poll` step on a task. pub struct Context<'a> { local_waker: &'a LocalWaker, - executor: &'a mut dyn Executor, + spawner: &'a mut dyn Spawn, } impl<'a> fmt::Debug for Context<'a> { @@ -32,13 +32,14 @@ impl<'a> fmt::Debug for Context<'a> { } impl<'a> Context<'a> { - /// Create a new task `Context` with the provided `local_waker`, `waker`, and `executor`. + /// Create a new task `Context` with the provided `local_waker`, `waker`, + /// and `spawner`. #[inline] - pub fn new(local_waker: &'a LocalWaker, executor: &'a mut dyn Executor) -> Context<'a> { - Context { - local_waker, - executor, - } + pub fn new( + local_waker: &'a LocalWaker, + spawner: &'a mut dyn Spawn, + ) -> Context<'a> { + Context { local_waker, spawner } } /// Get the `LocalWaker` associated with the current task. @@ -53,40 +54,45 @@ impl<'a> Context<'a> { unsafe { &*(self.local_waker as *const LocalWaker as *const Waker) } } - /// Get the default executor associated with this task. + /// Get the spawner associated with this task. /// /// This method is useful primarily if you want to explicitly handle /// spawn failures. #[inline] - pub fn executor(&mut self) -> &mut dyn Executor { - self.executor + pub fn spawner(&mut self) -> &mut dyn Spawn { + self.spawner } - /// Produce a context like the current one, but using the given waker instead. + /// Produce a context like the current one, but using the given waker + /// instead. /// /// This advanced method is primarily used when building "internal /// schedulers" within a task, where you want to provide some customized /// wakeup logic. #[inline] - pub fn with_waker<'b>(&'b mut self, local_waker: &'b LocalWaker) -> Context<'b> { + pub fn with_waker<'b>( + &'b mut self, + local_waker: &'b LocalWaker, + ) -> Context<'b> { Context { local_waker, - executor: self.executor, + spawner: self.spawner, } } - /// Produce a context like the current one, but using the given executor + /// Produce a context like the current one, but using the given spawner /// instead. /// /// This advanced method is primarily used when building "internal /// schedulers" within a task. #[inline] - pub fn with_executor<'b, E>(&'b mut self, executor: &'b mut E) -> Context<'b> - where E: Executor - { + pub fn with_spawner<'b, Sp: Spawn>( + &'b mut self, + spawner: &'b mut Sp, + ) -> Context<'b> { Context { local_waker: self.local_waker, - executor: executor, + spawner, } } } diff --git a/src/libcore/task/executor.rs b/src/libcore/task/executor.rs deleted file mode 100644 index affcbf464d..0000000000 --- a/src/libcore/task/executor.rs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![unstable(feature = "futures_api", - reason = "futures in libcore are unstable", - issue = "50547")] - -use fmt; -use future::{FutureObj, LocalFutureObj}; - -/// A task executor. -/// -/// Futures are polled until completion by tasks, a kind of lightweight -/// "thread". A *task executor* is responsible for the creation of these tasks -/// and the coordination of their execution on real operating system threads. In -/// particular, whenever a task signals that it can make further progress via a -/// wake-up notification, it is the responsibility of the task executor to put -/// the task into a queue to continue executing it, i.e. polling the future in -/// it, later. -pub trait Executor { - /// Spawns a new task with the given future. The future will be polled until - /// completion. - /// - /// # Errors - /// - /// The executor may be unable to spawn tasks, either because it has - /// been shut down or is resource-constrained. - fn spawn_obj( - &mut self, - future: FutureObj<'static, ()>, - ) -> Result<(), SpawnObjError>; - - /// Determines whether the executor is able to spawn new tasks. - /// - /// # Returns - /// - /// An `Ok` return means the executor is *likely* (but not guaranteed) - /// to accept a subsequent spawn attempt. Likewise, an `Err` return - /// means that `spawn` is likely, but not guaranteed, to yield an error. - #[inline] - fn status(&self) -> Result<(), SpawnErrorKind> { - Ok(()) - } -} - -/// Provides the reason that an executor was unable to spawn. -pub struct SpawnErrorKind { - _hidden: (), -} - -impl fmt::Debug for SpawnErrorKind { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("SpawnErrorKind") - .field(&"shutdown") - .finish() - } -} - -impl SpawnErrorKind { - /// Spawning is failing because the executor has been shut down. - pub fn shutdown() -> SpawnErrorKind { - SpawnErrorKind { _hidden: () } - } - - /// Check whether this error is the `shutdown` error. - pub fn is_shutdown(&self) -> bool { - true - } -} - -/// The result of a failed spawn -#[derive(Debug)] -pub struct SpawnObjError { - /// The kind of error - pub kind: SpawnErrorKind, - - /// The future for which spawning inside a task was attempted - pub future: FutureObj<'static, ()>, -} - -/// The result of a failed spawn -#[derive(Debug)] -pub struct SpawnLocalObjError { - /// The kind of error - pub kind: SpawnErrorKind, - - /// The future for which spawning inside a task was attempted - pub future: LocalFutureObj<'static, ()>, -} diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index c4f0753616..f51e5f7ce0 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -17,10 +17,8 @@ mod context; pub use self::context::Context; -mod executor; -pub use self::executor::{ - Executor, SpawnErrorKind, SpawnObjError, SpawnLocalObjError -}; +mod spawn; +pub use self::spawn::{Spawn, SpawnErrorKind, SpawnObjError, SpawnLocalObjError}; mod poll; pub use self::poll::Poll; diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs new file mode 100644 index 0000000000..58ee85d232 --- /dev/null +++ b/src/libcore/task/spawn.rs @@ -0,0 +1,93 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![unstable(feature = "futures_api", + reason = "futures in libcore are unstable", + issue = "50547")] + +use fmt; +use future::{FutureObj, LocalFutureObj}; + +/// Spawns tasks that poll futures to completion onto its associated task +/// executor. +/// +/// The term "task" refers to a kind of lightweight "thread". Task executors +/// are responsible for scheduling the execution of tasks on operating system +/// threads. +pub trait Spawn { + /// Spawns a new task with the given future. The future will be polled until + /// completion. + /// + /// # Errors + /// + /// The executor may be unable to spawn tasks, either because it has + /// been shut down or is resource-constrained. + fn spawn_obj( + &mut self, + future: FutureObj<'static, ()>, + ) -> Result<(), SpawnObjError>; + + /// Determines whether the executor is able to spawn new tasks. + /// + /// # Returns + /// + /// An `Ok` return means the executor is *likely* (but not guaranteed) + /// to accept a subsequent spawn attempt. Likewise, an `Err` return + /// means that `spawn` is likely, but not guaranteed, to yield an error. + #[inline] + fn status(&self) -> Result<(), SpawnErrorKind> { + Ok(()) + } +} + +/// Provides the reason that an executor was unable to spawn. +pub struct SpawnErrorKind { + _hidden: (), +} + +impl fmt::Debug for SpawnErrorKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("SpawnErrorKind") + .field(&"shutdown") + .finish() + } +} + +impl SpawnErrorKind { + /// Spawning is failing because the executor has been shut down. + pub fn shutdown() -> SpawnErrorKind { + SpawnErrorKind { _hidden: () } + } + + /// Check whether this error is the `shutdown` error. + pub fn is_shutdown(&self) -> bool { + true + } +} + +/// The result of a failed spawn +#[derive(Debug)] +pub struct SpawnObjError { + /// The kind of error + pub kind: SpawnErrorKind, + + /// The future for which spawning inside a task was attempted + pub future: FutureObj<'static, ()>, +} + +/// The result of a failed spawn +#[derive(Debug)] +pub struct SpawnLocalObjError { + /// The kind of error + pub kind: SpawnErrorKind, + + /// The future for which spawning inside a task was attempted + pub future: LocalFutureObj<'static, ()>, +} diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 321b432d3f..d770536ef4 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -42,7 +42,7 @@ impl Waker { /// `Arc` type and the safe `Wake` trait. #[inline] pub unsafe fn new(inner: NonNull) -> Self { - Waker { inner: inner } + Waker { inner } } /// Wake up the task associated with this `Waker`. @@ -120,7 +120,7 @@ impl LocalWaker { /// on the current thread. #[inline] pub unsafe fn new(inner: NonNull) -> Self { - LocalWaker { inner: inner } + LocalWaker { inner } } /// Wake up the task associated with this `LocalWaker`. @@ -159,7 +159,9 @@ impl LocalWaker { impl From for Waker { #[inline] fn from(local_waker: LocalWaker) -> Self { - Waker { inner: local_waker.inner } + let inner = local_waker.inner; + mem::forget(local_waker); + Waker { inner } } } diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs index d2a9ed75be..3d99c8ea9e 100644 --- a/src/libcore/tests/char.rs +++ b/src/libcore/tests/char.rs @@ -148,9 +148,10 @@ fn test_is_control() { } #[test] -fn test_is_digit() { +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()); @@ -363,54 +364,3 @@ fn eu_iterator_specializations() { check('\u{12340}'); check('\u{10FFFF}'); } - -#[test] -#[allow(deprecated)] -fn test_decode_utf8() { - macro_rules! assert_decode_utf8 { - ($input_bytes: expr, $expected_str: expr) => { - let input_bytes: &[u8] = &$input_bytes; - let s = char::decode_utf8(input_bytes.iter().cloned()) - .map(|r_b| r_b.unwrap_or('\u{FFFD}')) - .collect::(); - assert_eq!(s, $expected_str, - "input bytes: {:?}, expected str: {:?}, result: {:?}", - input_bytes, $expected_str, s); - assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str); - } - } - - assert_decode_utf8!([], ""); - assert_decode_utf8!([0x41], "A"); - assert_decode_utf8!([0xC1, 0x81], "��"); - assert_decode_utf8!([0xE2, 0x99, 0xA5], "♥"); - assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A"); - assert_decode_utf8!([0xE2, 0x99], "�"); - assert_decode_utf8!([0xE2, 0x99, 0x41], "�A"); - assert_decode_utf8!([0xC0], "�"); - assert_decode_utf8!([0xC0, 0x41], "�A"); - assert_decode_utf8!([0x80], "�"); - assert_decode_utf8!([0x80, 0x41], "�A"); - assert_decode_utf8!([0xFE], "�"); - assert_decode_utf8!([0xFE, 0x41], "�A"); - assert_decode_utf8!([0xFF], "�"); - assert_decode_utf8!([0xFF, 0x41], "�A"); - assert_decode_utf8!([0xC0, 0x80], "��"); - - // Surrogates - assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}"); - assert_decode_utf8!([0xED, 0xA0, 0x80], "���"); - assert_decode_utf8!([0xED, 0xBF, 0x80], "���"); - assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}"); - - // char::MAX - assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}"); - assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "�A"); - assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "����"); - - // 5 and 6 bytes sequence - // Part of the original design of UTF-8, - // but invalid now that UTF-8 is artificially restricted to match the range of UTF-16. - assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "�����"); - assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "������"); -} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 6fcfaae453..4f3086575c 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -8,18 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(ascii_ctype)] #![feature(box_syntax)] #![feature(cell_update)] -#![feature(core_float)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] -#![feature(decode_utf8)] #![feature(euclidean_division)] #![feature(exact_size_is_empty)] #![feature(fixed_size_array)] -#![feature(float_internals)] #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(hashmap_internals)] @@ -29,7 +25,6 @@ #![feature(refcell_map_split)] #![feature(refcell_replace_swap)] #![feature(slice_patterns)] -#![feature(slice_rotate)] #![feature(sort_internals)] #![feature(specialization)] #![feature(step_trait)] @@ -39,10 +34,9 @@ #![feature(try_from)] #![feature(try_trait)] #![feature(exact_chunks)] -#![feature(slice_align_to)] #![feature(align_offset)] #![feature(reverse_bits)] -#![feature(iterator_find_map)] +#![feature(inner_deref)] #![feature(slice_internals)] #![feature(option_replace)] diff --git a/src/libcore/tests/manually_drop.rs b/src/libcore/tests/manually_drop.rs index 96bc9247da..82dfb8d4c0 100644 --- a/src/libcore/tests/manually_drop.rs +++ b/src/libcore/tests/manually_drop.rs @@ -21,4 +21,9 @@ fn smoke() { let x = ManuallyDrop::new(TypeWithDrop); drop(x); + + // also test unsizing + let x : Box> = + Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop])); + drop(x); } diff --git a/src/libcore/tests/num/flt2dec/random.rs b/src/libcore/tests/num/flt2dec/random.rs index a1928657da..ab619093d9 100644 --- a/src/libcore/tests/num/flt2dec/random.rs +++ b/src/libcore/tests/num/flt2dec/random.rs @@ -18,8 +18,8 @@ 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 rand::{self, Rand, XorShiftRng}; -use rand::distributions::{IndependentSample, Range}; +use rand::{FromEntropy, XorShiftRng}; +use rand::distributions::{Distribution, Uniform}; pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { @@ -71,10 +71,10 @@ fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V 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) { - let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); - let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000); + let mut rng = XorShiftRng::from_entropy(); + let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000); iterate("f32_random_equivalence_test", k, n, f, g, |_| { - let x = f32::from_bits(f32_range.ind_sample(&mut rng)); + let x = f32::from_bits(f32_range.sample(&mut rng)); decode_finite(x) }); } @@ -82,10 +82,10 @@ 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) { - let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); - let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); + let mut rng = XorShiftRng::from_entropy(); + let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); iterate("f64_random_equivalence_test", k, n, f, g, |_| { - let x = f64::from_bits(f64_range.ind_sample(&mut rng)); + let x = f64::from_bits(f64_range.sample(&mut rng)); decode_finite(x) }); } diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index 324ebf4356..1324ba2d9a 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -298,6 +298,23 @@ fn test_try() { assert_eq!(try_option_err(), Err(NoneError)); } +#[test] +fn test_option_deref() { + // Some: &Option::Some(T) -> Option<&T::Deref::Target>::Some(&*T) + let ref_option = &Some(&42); + assert_eq!(ref_option.deref(), Some(&42)); + + let ref_option = &Some(String::from("a result")); + assert_eq!(ref_option.deref(), Some("a result")); + + let ref_option = &Some(vec![1, 2, 3, 4, 5]); + assert_eq!(ref_option.deref(), Some(&[1, 2, 3, 4, 5][..])); + + // None: &Option>::None -> None + let ref_option: &Option<&i32> = &None; + assert_eq!(ref_option.deref(), None); +} + #[test] fn test_replace() { let mut x = Some(2); diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs index 0616252c82..0c00992ffd 100644 --- a/src/libcore/tests/result.rs +++ b/src/libcore/tests/result.rs @@ -233,3 +233,96 @@ fn test_try() { } assert_eq!(try_result_err(), Err(1)); } + +#[test] +fn test_result_deref() { + // &Result::Ok(T).deref_ok() -> + // Result<&T::Deref::Target, &E>::Ok(&*T) + let ref_ok = &Result::Ok::<&i32, u8>(&42); + let expected_result = Result::Ok::<&i32, &u8>(&42); + assert_eq!(ref_ok.deref_ok(), expected_result); + + let ref_ok = &Result::Ok::(String::from("a result")); + let expected_result = Result::Ok::<&str, &u32>("a result"); + assert_eq!(ref_ok.deref_ok(), expected_result); + + let ref_ok = &Result::Ok::, u32>(vec![1, 2, 3, 4, 5]); + let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]); + assert_eq!(ref_ok.deref_ok(), expected_result); + + // &Result::Ok(T).deref() -> + // Result<&T::Deref::Target, &E::Deref::Target>::Ok(&*T) + let ref_ok = &Result::Ok::<&i32, &u8>(&42); + let expected_result = Result::Ok::<&i32, &u8>(&42); + assert_eq!(ref_ok.deref(), expected_result); + + let ref_ok = &Result::Ok::(String::from("a result")); + let expected_result = Result::Ok::<&str, &u32>("a result"); + assert_eq!(ref_ok.deref(), expected_result); + + let ref_ok = &Result::Ok::, &u32>(vec![1, 2, 3, 4, 5]); + let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]); + assert_eq!(ref_ok.deref(), expected_result); + + // &Result::Err(T).deref_err() -> + // Result<&T, &E::Deref::Target>::Err(&*E) + let ref_err = &Result::Err::(&41); + let expected_result = Result::Err::<&u8, &i32>(&41); + assert_eq!(ref_err.deref_err(), expected_result); + + let ref_err = &Result::Err::(String::from("an error")); + let expected_result = Result::Err::<&u32, &str>("an error"); + assert_eq!(ref_err.deref_err(), expected_result); + + let ref_err = &Result::Err::>(vec![5, 4, 3, 2, 1]); + let expected_result = Result::Err::<&u32, &[i32]>(&[5, 4, 3, 2, 1][..]); + assert_eq!(ref_err.deref_err(), expected_result); + + // &Result::Err(T).deref_err() -> + // Result<&T, &E::Deref::Target>::Err(&*E) + let ref_err = &Result::Err::<&u8, &i32>(&41); + let expected_result = Result::Err::<&u8, &i32>(&41); + assert_eq!(ref_err.deref(), expected_result); + + let ref_err = &Result::Err::<&u32, String>(String::from("an error")); + let expected_result = Result::Err::<&u32, &str>("an error"); + assert_eq!(ref_err.deref(), expected_result); + + let ref_err = &Result::Err::<&u32, Vec>(vec![5, 4, 3, 2, 1]); + let expected_result = Result::Err::<&u32, &[i32]>(&[5, 4, 3, 2, 1][..]); + assert_eq!(ref_err.deref(), expected_result); + + // The following cases test calling deref_* with the wrong variant (i.e. + // `deref_ok()` with a `Result::Err()`, or `deref_err()` with a `Result::Ok()`. + // While unusual, these cases are supported to ensure that an `inner_deref` + // call can still be made even when one of the Result types does not implement + // `Deref` (for example, std::io::Error). + + // &Result::Ok(T).deref_err() -> + // Result<&T, &E::Deref::Target>::Ok(&T) + let ref_ok = &Result::Ok::(42); + let expected_result = Result::Ok::<&i32, &u8>(&42); + assert_eq!(ref_ok.deref_err(), expected_result); + + let ref_ok = &Result::Ok::<&str, &u32>("a result"); + let expected_result = Result::Ok::<&&str, &u32>(&"a result"); + assert_eq!(ref_ok.deref_err(), expected_result); + + let ref_ok = &Result::Ok::<[i32; 5], &u32>([1, 2, 3, 4, 5]); + let expected_result = Result::Ok::<&[i32; 5], &u32>(&[1, 2, 3, 4, 5]); + assert_eq!(ref_ok.deref_err(), expected_result); + + // &Result::Err(E).deref_ok() -> + // Result<&T::Deref::Target, &E>::Err(&E) + let ref_err = &Result::Err::<&u8, i32>(41); + let expected_result = Result::Err::<&u8, &i32>(&41); + assert_eq!(ref_err.deref_ok(), expected_result); + + let ref_err = &Result::Err::<&u32, &str>("an error"); + let expected_result = Result::Err::<&u32, &&str>(&"an error"); + assert_eq!(ref_err.deref_ok(), expected_result); + + let ref_err = &Result::Err::<&u32, [i32; 5]>([5, 4, 3, 2, 1]); + let expected_result = Result::Err::<&u32, &[i32; 5]>(&[5, 4, 3, 2, 1]); + assert_eq!(ref_err.deref_ok(), expected_result); +} diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 2b37acdfe3..012dc9bf5e 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -390,6 +390,132 @@ fn test_windows_zip() { assert_eq!(res, [14, 18, 22, 26]); } +#[test] +#[allow(const_err)] +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 { + [ref v1, ref v2, ref v3] => [v1 as *const _, v2 as *const _, v3 as *const _], + _ => unreachable!() + }; + let len = v.len(); + + // nth(i) + for i in 0..len { + assert_eq!(&v[i] as *const _, v_ptrs[i]); // check the v_ptrs array, just to be sure + let nth = v.iter().nth(i).unwrap(); + assert_eq!(nth as *const _, v_ptrs[i]); + } + assert_eq!(v.iter().nth(len), None, "nth(len) should return None"); + + // stepping through with nth(0) + { + let mut it = v.iter(); + for i in 0..len { + let next = it.nth(0).unwrap(); + assert_eq!(next as *const _, v_ptrs[i]); + } + assert_eq!(it.nth(0), None); + } + + // next() + { + let mut it = v.iter(); + for i in 0..len { + let remaining = len - i; + assert_eq!(it.size_hint(), (remaining, Some(remaining))); + + let next = it.next().unwrap(); + assert_eq!(next as *const _, v_ptrs[i]); + } + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None, "The final call to next() should return None"); + } + + // next_back() + { + let mut it = v.iter(); + for i in 0..len { + let remaining = len - i; + 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!(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!() + }; + let len = v.len(); + + // nth(i) + for i in 0..len { + assert_eq!(&mut v[i] as *mut _, v_ptrs[i]); // check the v_ptrs array, just to be sure + let nth = v.iter_mut().nth(i).unwrap(); + assert_eq!(nth as *mut _, v_ptrs[i]); + } + assert_eq!(v.iter().nth(len), None, "nth(len) should return None"); + + // stepping through with nth(0) + { + let mut it = v.iter(); + for i in 0..len { + let next = it.nth(0).unwrap(); + assert_eq!(next as *const _, v_ptrs[i]); + } + assert_eq!(it.nth(0), None); + } + + // next() + { + let mut it = v.iter_mut(); + for i in 0..len { + let remaining = len - i; + assert_eq!(it.size_hint(), (remaining, Some(remaining))); + + let next = it.next().unwrap(); + assert_eq!(next as *mut _, v_ptrs[i]); + } + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None, "The final call to next() should return None"); + } + + // next_back() + { + let mut it = v.iter_mut(); + for i in 0..len { + let remaining = len - i; + 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!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next_back(), None, "The final call to next_back() should return None"); + } + } + + // Make sure iterators and slice patterns yield consistent addresses for various types, + // including ZSTs. + test(0u32); + test(()); + test([0u32; 0]); // ZST with alignment > 0 + test_mut(0u32); + test_mut(()); + test_mut([0u32; 0]); // ZST with alignment > 0 +} + // The current implementation of SliceIndex fails to handle methods // orthogonally from range types; therefore, it is worth testing // all of the indexing operations on each input. @@ -676,11 +802,11 @@ fn test_rotate_right() { fn sort_unstable() { use core::cmp::Ordering::{Equal, Greater, Less}; use core::slice::heapsort; - use rand::{Rng, XorShiftRng}; + use rand::{FromEntropy, Rng, XorShiftRng}; let mut v = [0; 600]; let mut tmp = [0; 600]; - let mut rng = XorShiftRng::new_unseeded(); + let mut rng = XorShiftRng::from_entropy(); for len in (2..25).chain(500..510) { let v = &mut v[0..len]; @@ -860,3 +986,17 @@ fn test_align_to_non_trivial() { assert_eq!(aligned.len(), 4); assert_eq!(prefix.len() + suffix.len(), 2); } + +#[test] +fn test_align_to_empty_mid() { + use core::mem; + + // Make sure that we do not create empty unaligned slices for the mid part, even when the + // overall slice is too short to contain an aligned address. + 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::() }; + assert_eq!(mid.as_ptr() as usize % mem::align_of::(), 0); + } +} diff --git a/src/libcore/time.rs b/src/libcore/time.rs index 54973b7b77..b58920224e 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -91,7 +91,7 @@ impl Duration { let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64) .expect("overflow in Duration::new"); let nanos = nanos % NANOS_PER_SEC; - Duration { secs: secs, nanos: nanos } + Duration { secs, nanos } } /// Creates a new `Duration` from the specified number of whole seconds. @@ -109,7 +109,7 @@ impl Duration { #[stable(feature = "duration", since = "1.3.0")] #[inline] pub const fn from_secs(secs: u64) -> Duration { - Duration { secs: secs, nanos: 0 } + Duration { secs, nanos: 0 } } /// Creates a new `Duration` from the specified number of milliseconds. @@ -387,7 +387,7 @@ impl Duration { } }; debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { secs: secs, nanos: nanos }) + Some(Duration { secs, nanos }) } else { None } @@ -453,7 +453,7 @@ impl Duration { let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); let nanos = self.nanos / rhs + (extra_nanos as u32); debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { secs: secs, nanos: nanos }) + Some(Duration { secs, nanos }) } else { None } diff --git a/src/libcore/unicode/tables.rs b/src/libcore/unicode/tables.rs index 32668ea93d..3de855ac94 100644 --- a/src/libcore/unicode/tables.rs +++ b/src/libcore/unicode/tables.rs @@ -40,7 +40,7 @@ pub mod general_category { pub const N_table: &super::BoolTrie = &super::BoolTrie { r1: [ - 0x03ff000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x03ff000000000000, 0x0000000000000000, 0x720c000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, @@ -50,12 +50,14 @@ pub mod general_category { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x00000000000003ff ], r2: [ - 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 2, 3, - 0, 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5, 0, 0, 0, 3, 2, 0, 0, 0, 0, 6, 0, 2, 0, 0, 7, 0, 0, 2, 8, 0, 0, 7, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 2, 0, 1, 0, 1, 0, 3, 0, 4, 0, 5, 0, 1, 0, 6, 0, 1, 0, 7, 0, 7, 8, + 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 0, 0, 0, 12, 7, 0, 0, 0, 0, 13, 0, 14, 0, 0, 15, 0, 0, 7, 16, 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 9, 0, 0, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 27, 0, 28, + 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -69,10 +71,10 @@ pub mod general_category { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, + 0, 0, 1, 0, 0, 0, 0, 31, 0, 0, 7, 9, 0, 0, 32, 0, 7, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 2, 4, 0, 0, 12, 0, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -82,18 +84,21 @@ pub mod general_category { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0 ], r3: &[ - 0x0000000000000000, 0x0000ffc000000000, 0x0000000003ff0000, 0x000003ff00000000, - 0x00000000000003ff, 0x0001c00000000000, 0x000000000000ffc0, 0x0000000003ff03ff, - 0x03ff000000000000, 0xffffffff00000000, 0x00000000000001e7, 0x070003fe00000080, + 0x0000000000000000, 0x0000ffc000000000, 0x03f0ffc000000000, 0x00fcffc000000000, + 0x0007ffc000000000, 0x7f00ffc000000000, 0x01ffffc07f000000, 0x0000000003ff0000, + 0x000fffff00000000, 0x00000000000003ff, 0x1ffffe0000000000, 0x0001c00000000000, + 0x03ff03ff00000000, 0x000000000000ffc0, 0x0000000007ff0000, 0x0000000003ff03ff, + 0x03ff000000000000, 0x03f1000000000000, 0xffffffffffff0000, 0x00000000000003e7, + 0xffffffff00000000, 0x000000000fffffff, 0xfffffc0000000000, 0xffc0000000000000, + 0x00000000000fffff, 0x2000000000000000, 0x070003fe00000080, 0x00000000003c0000, + 0x000003ff00000000, 0x00000000fffeff00, 0xfffe0000000003ff, 0x003f000000000000, 0x03ff000003ff0000 ], r4: [ - 0, 1, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 5, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0, 1, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, @@ -104,28 +109,37 @@ pub mod general_category { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ], r5: &[ - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 6, 0, 5, 7, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0, - 0, 0, 8, 0, 9, 5, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, - 0, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, - 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 10, 11, 12, 0, 13, 14, 0, 15, 16, 17, 0, 18, 19, 0, 0, 0, 0, 20, 21, 0, + 0, 0, 0, 22, 0, 0, 23, 24, 0, 0, 0, 25, 0, 21, 26, 0, 0, 27, 0, 0, 0, 21, 0, 0, 0, 0, 0, + 28, 0, 28, 0, 0, 0, 0, 0, 28, 0, 29, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32, 0, 0, 0, 28, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 28, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], r6: &[ - 0x0000000000000000, 0x001fffffffffffff, 0x0000000000000402, 0x00000000003e0000, - 0x000003ff00000000, 0x03ff000000000000, 0x0000ffc000000000, 0xffc0000000000000, - 0x0000000003ff0000, 0x00000000000003ff, 0xffffffffffffffff, 0x00007fffffffffff, - 0xffffffffffffc000 + 0x0000000000000000, 0x000fffffffffff80, 0x01ffffffffffffff, 0x0000000000000c00, + 0x0ffffffe00000000, 0x0000000f00000000, 0x0000000000000402, 0x00000000003e0000, + 0x000003ff00000000, 0xfe000000ff000000, 0x0000ff8000000000, 0xf800000000000000, + 0x000000000fc00000, 0x3000000000000000, 0xfffffffffffcffff, 0x60000000000001ff, + 0x00000000e0000000, 0x0000f80000000000, 0xff000000ff000000, 0x0000fe0000000000, + 0xfc00000000000000, 0x03ff000000000000, 0x7fffffff00000000, 0x0000007fe0000000, + 0x00000000001e0000, 0x0000fffffffc0000, 0xffc0000000000000, 0x001ffffe03ff0000, + 0x0000000003ff0000, 0x00000000000003ff, 0x0fff000000000000, 0x0007ffff00000000, + 0x00001fffffff0000, 0xffffffffffffffff, 0x00007fffffffffff, 0x00000003fbff0000, + 0x00000000007fffff, 0x000fffff00000000, 0x01ffffff00000000, 0xffffffffffffc000, + 0x000000000000ff80, 0xfffe000000000000, 0x001eefffffffffff, 0x0000000000001fff ], }; diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index be0970b544..28a1e01805 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -52,7 +52,7 @@ expanded_categories = { 'Lu': ['LC', 'L'], 'Ll': ['LC', 'L'], 'Lt': ['LC', 'L'], 'Lm': ['L'], 'Lo': ['L'], 'Mn': ['M'], 'Mc': ['M'], 'Me': ['M'], - 'Nd': ['N'], 'Nl': ['N'], 'No': ['No'], + 'Nd': ['N'], 'Nl': ['N'], 'No': ['N'], 'Pc': ['P'], 'Pd': ['P'], 'Ps': ['P'], 'Pe': ['P'], 'Pi': ['P'], 'Pf': ['P'], 'Po': ['P'], 'Sm': ['S'], 'Sc': ['S'], 'Sk': ['S'], 'So': ['S'], diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 373db1f166..1bac6d22d3 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -20,6 +20,8 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] +#![cfg_attr(not(stage0), feature(nll))] + pub use self::Piece::*; pub use self::Position::*; pub use self::Alignment::*; @@ -152,7 +154,7 @@ pub struct Parser<'a> { style: Option, /// How many newlines have been seen in the string so far, to adjust the error spans seen_newlines: usize, - /// Start and end byte offset of every successfuly parsed argument + /// Start and end byte offset of every successfully parsed argument pub arg_places: Vec<(usize, usize)>, } @@ -409,7 +411,7 @@ impl<'a> Parser<'a> { // fill character if let Some(&(_, c)) = self.cur.peek() { - match self.cur.clone().skip(1).next() { + match self.cur.clone().nth(1) { Some((_, '>')) | Some((_, '<')) | Some((_, '^')) => { spec.fill = Some(c); self.cur.next(); @@ -502,13 +504,11 @@ impl<'a> Parser<'a> { if word.is_empty() { self.cur = tmp; CountImplied + } else if self.consume('$') { + CountIsName(word) } else { - if self.consume('$') { - CountIsName(word) - } else { - self.cur = tmp; - CountImplied - } + self.cur = tmp; + CountImplied } } } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 158d010151..9fa48adebd 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -288,6 +288,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(allow(unused_variables), deny(warnings))))] +#![cfg_attr(not(stage0), feature(nll))] #![feature(str_escape)] use self::LabelText::*; @@ -419,7 +420,8 @@ impl<'a> Id<'a> { if !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' ) { return Err(()); } - return Ok(Id { name: name }); + + Ok(Id { name }) } pub fn as_slice(&'a self) -> &'a str { @@ -532,10 +534,10 @@ impl<'a> LabelText<'a> { /// Renders text as string suitable for a label in a .dot file. /// This includes quotes or suitable delimiters. pub fn to_dot_string(&self) -> String { - match self { - &LabelStr(ref s) => format!("\"{}\"", s.escape_default()), - &EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s)), - &HtmlStr(ref s) => format!("<{}>", s), + match *self { + LabelStr(ref s) => format!("\"{}\"", s.escape_default()), + EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s)), + HtmlStr(ref s) => format!("<{}>", s), } } diff --git a/src/liblibc/.travis.yml b/src/liblibc/.travis.yml index da3124db08..1905b0d4fb 100644 --- a/src/liblibc/.travis.yml +++ b/src/liblibc/.travis.yml @@ -21,9 +21,6 @@ env: global: secure: "e2/3QjgRN9atOuSHp22TrYG7QVKcYUWY48Hi9b60w+r1+BhPkTseIJLte7WefRhdXtqpjjUJTooKDhnurFOeHaCT+nmBgiv+FPU893sBl4bhesY4m0vgUJVbNZcs6lTImYekWVb+aqjGdgV/XAgCw7c3kPmrZV0MzGDWL64Xaps=" matrix: - allow_failures: - # FIXME(#987) move back to include once 404 is fixed - - env: TARGET=s390x-unknown-linux-gnu include: # 1.13.0 compat - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 @@ -41,10 +38,10 @@ matrix: - env: TARGET=i686-unknown-linux-gnu - os: osx env: TARGET=x86_64-apple-darwin NO_ADD=1 - osx_image: xcode8.3 + osx_image: xcode9.4 - os: osx env: TARGET=i686-apple-darwin - osx_image: xcode8.3 + osx_image: xcode9.4 - env: TARGET=arm-linux-androideabi - env: TARGET=aarch64-linux-android # FIXME(#826) should reenable @@ -59,14 +56,14 @@ matrix: # FIXME(#856) rust: 1.22.1 - os: osx - osx_image: xcode8.2 + osx_image: xcode9.4 env: TARGET=i386-apple-ios CARGO_TARGET_I386_APPLE_IOS_RUNNER=$HOME/runtest RUSTFLAGS=-Clink-arg=-mios-simulator-version-min=7.0 before_install: rustc ./ci/ios/deploy_and_run_on_ios_simulator.rs -o $HOME/runtest - os: osx - osx_image: xcode8.2 + osx_image: xcode9.4 env: TARGET=x86_64-apple-ios CARGO_TARGET_X86_64_APPLE_IOS_RUNNER=$HOME/runtest RUSTFLAGS=-Clink-arg=-mios-simulator-version-min=7.0 @@ -91,7 +88,7 @@ matrix: rust: beta - os: osx env: TARGET=x86_64-apple-darwin NO_ADD=1 - osx_image: xcode8.3 + osx_image: xcode9.4 rust: beta # nightly @@ -99,7 +96,7 @@ matrix: rust: nightly - os: osx env: TARGET=x86_64-apple-darwin NO_ADD=1 - osx_image: xcode8.3 + osx_image: xcode9.4 rust: nightly # not available on stable # without --release the build fails @@ -109,6 +106,13 @@ matrix: # QEMU based targets that compile in an emulator - env: TARGET=x86_64-unknown-freebsd + allow_failures: + - env: TARGET=i386-apple-ios + CARGO_TARGET_I386_APPLE_IOS_RUNNER=$HOME/runtest + RUSTFLAGS=-Clink-arg=-mios-simulator-version-min=7.0 + - env: TARGET=x86_64-apple-ios + CARGO_TARGET_X86_64_APPLE_IOS_RUNNER=$HOME/runtest + RUSTFLAGS=-Clink-arg=-mios-simulator-version-min=7.0 notifications: email: diff --git a/src/liblibc/Cargo.lock b/src/liblibc/Cargo.lock index 5c02a4eabf..c47d80d81f 100644 --- a/src/liblibc/Cargo.lock +++ b/src/liblibc/Cargo.lock @@ -10,26 +10,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ctest" -version = "0.1.7" -source = "git+https://github.com/alexcrichton/ctest#482c7f0643942174a802d89ad7d460e89b576ed3" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_syntax 0.59.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "dtoa" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -37,11 +37,11 @@ name = "extprim" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -60,7 +60,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itoa" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -74,19 +74,19 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.41" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.2.43" [[package]] name = "libc" -version = "0.2.42" +version = "0.2.43" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc-test" version = "0.1.0" dependencies = [ - "ctest 0.1.7 (git+https://github.com/alexcrichton/ctest)", - "libc 0.2.42", + "ctest 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43", ] [[package]] @@ -94,25 +94,25 @@ name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.4" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -120,10 +120,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -132,13 +132,13 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc_version" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -159,39 +159,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.64" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.64" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.14.1" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -200,9 +200,9 @@ name = "syntex_errors" version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.59.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -213,8 +213,8 @@ name = "syntex_pos" version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -225,9 +225,9 @@ dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "extprim 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.59.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.59.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -254,7 +254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -279,36 +279,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" -"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d" -"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" -"checksum ctest 0.1.7 (git+https://github.com/alexcrichton/ctest)" = "" -"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275" +"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" +"checksum ctest 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb5b62c8bba3ca51cb21a3d3f8506074d1364ca5f53cf28ed1c07311bb1080c" +"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum extprim 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "054bc2552b3f66fa8097e29e47255bfff583c08e737a67cbbb54b817ddaa5206" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" +"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" -"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" -"checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46" -"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" +"checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2" +"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" +"checksum proc-macro2 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7a17a4d77bc20d344179de803a34694c0ac7a0b3fb4384bee99783215a8e0410" +"checksum quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ed7d650913520df631972f21e104a4fa2f9c82a14afc65d17b388a2e29731e7c" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91" -"checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8" -"checksum serde_json 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "93aee34bb692dde91e602871bc792dd319e489c7308cdbbe5f27cf27c64280f5" -"checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101" +"checksum serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfad05c8854584e5f72fb859385ecdfa03af69c3fd0572f0da2d4c95f060bdb" +"checksum serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)" = "b719c6d5e9f73fbc37892246d5852333f040caa617b8873c6aced84bcb28e7bb" +"checksum serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2" +"checksum syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b7bfcbb0c068d0f642a0ffbd5c604965a360a61f99e8add013cef23a838614f3" "checksum syntex_errors 0.59.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3133289179676c9f5c5b2845bf5a2e127769f4889fcbada43035ef6bd662605e" "checksum syntex_pos 0.59.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30ab669fa003d208c681f874bbc76d91cc3d32550d16b5d9d2087cf477316470" "checksum syntex_syntax 0.59.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03815b9f04d95828770d9c974aa39c6e1f6ef3114eb77a3ce09008a0d15dd142" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/src/liblibc/Cargo.toml b/src/liblibc/Cargo.toml index 662d0ad657..a9f0f59603 100644 --- a/src/liblibc/Cargo.toml +++ b/src/liblibc/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libc" -version = "0.2.42" +version = "0.2.43" authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" @@ -20,6 +20,7 @@ appveyor = { repository = "rust-lang/libc", project_name = "rust-lang-libs/libc" [features] default = ["use_std"] use_std = [] +align = [] [workspace] members = ["libc-test"] diff --git a/src/liblibc/README.md b/src/liblibc/README.md index 9afd7b5cdc..a19a56ee0f 100644 --- a/src/liblibc/README.md +++ b/src/liblibc/README.md @@ -6,8 +6,10 @@ various systems, including libc. [![Build Status](https://travis-ci.org/rust-lang/libc.svg?branch=master)](https://travis-ci.org/rust-lang/libc) [![Build status](https://ci.appveyor.com/api/projects/status/github/rust-lang/libc?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/libc) +[![Latest version](https://img.shields.io/crates/v/libc.svg)](https://crates.io/crates/libc) +[![Documentation](https://docs.rs/libc/badge.svg)](https://docs.rs/libc) +![License](https://img.shields.io/crates/l/libc.svg) -[Documentation](#platforms-and-documentation) ## Usage @@ -33,6 +35,16 @@ this via: libc = { version = "0.2", default-features = false } ``` +By default libc uses private fields in structs in order to enforce a certain +memory alignment on them. These structs can be hard to instantiate outside of +libc. To make libc use `#[repr(align(x))]`, instead of the private fields, +activate the *align* feature. This requires Rust 1.25 or newer: + +```toml +[dependencies] +libc = { version = "0.2", features = ["align"] } +``` + ## What is libc? The primary purpose of this crate is to provide all of the definitions necessary diff --git a/src/liblibc/ci/docker/aarch64-unknown-linux-musl/Dockerfile b/src/liblibc/ci/docker/aarch64-unknown-linux-musl/Dockerfile index e86c4c0ae3..caec1572cb 100644 --- a/src/liblibc/ci/docker/aarch64-unknown-linux-musl/Dockerfile +++ b/src/liblibc/ci/docker/aarch64-unknown-linux-musl/Dockerfile @@ -3,21 +3,21 @@ FROM ubuntu:17.10 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc make libc6-dev git curl ca-certificates \ gcc-aarch64-linux-gnu qemu-user -RUN curl https://www.musl-libc.org/releases/musl-1.1.16.tar.gz | \ +RUN curl https://www.musl-libc.org/releases/musl-1.1.19.tar.gz | \ tar xzf - && \ - cd musl-1.1.16 && \ + cd musl-1.1.19 && \ CC=aarch64-linux-gnu-gcc \ ./configure --prefix=/musl-aarch64 --enable-wrapper=yes && \ make install -j4 && \ cd .. && \ - rm -rf musl-1.1.16 && \ + rm -rf musl-1.1.19 # Install linux kernel headers sanitized for use with musl - curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \ +RUN curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-6.tar.gz | \ tar xzf - && \ - cd kernel-headers-3.12.6-5 && \ + cd kernel-headers-3.12.6-6 && \ make ARCH=arm64 prefix=/musl-aarch64 install -j4 && \ cd .. && \ - rm -rf kernel-headers-3.12.6-5 + rm -rf kernel-headers-3.12.6-6 # FIXME: shouldn't need the `-lgcc` here, shouldn't that be in libstd? ENV PATH=$PATH:/musl-aarch64/bin:/rust/bin \ diff --git a/src/liblibc/ci/docker/arm-unknown-linux-musleabihf/Dockerfile b/src/liblibc/ci/docker/arm-unknown-linux-musleabihf/Dockerfile index 130730b997..86304130fe 100644 --- a/src/liblibc/ci/docker/arm-unknown-linux-musleabihf/Dockerfile +++ b/src/liblibc/ci/docker/arm-unknown-linux-musleabihf/Dockerfile @@ -4,21 +4,21 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gcc make libc6-dev git curl ca-certificates \ gcc-arm-linux-gnueabihf qemu-user -RUN curl https://www.musl-libc.org/releases/musl-1.1.16.tar.gz | tar xzf - -WORKDIR /musl-1.1.16 +RUN curl https://www.musl-libc.org/releases/musl-1.1.19.tar.gz | tar xzf - +WORKDIR /musl-1.1.19 RUN CC=arm-linux-gnueabihf-gcc \ CFLAGS="-march=armv6 -marm" \ ./configure --prefix=/musl-arm --enable-wrapper=yes RUN make install -j4 # Install linux kernel headers sanitized for use with musl -RUN \ - curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \ +RUN curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-6.tar.gz | \ tar xzf - && \ - cd kernel-headers-3.12.6-5 && \ + cd kernel-headers-3.12.6-6 && \ make ARCH=arm prefix=/musl-arm install -j4 && \ cd .. && \ - rm -rf kernel-headers-3.12.6-5 + rm -rf kernel-headers-3.12.6-6 + ENV PATH=$PATH:/musl-arm/bin:/rust/bin \ CC_arm_unknown_linux_musleabihf=musl-gcc \ CARGO_TARGET_ARM_UNKNOWN_LINUX_MUSLEABIHF_LINKER=musl-gcc \ diff --git a/src/liblibc/ci/docker/i686-unknown-linux-musl/Dockerfile b/src/liblibc/ci/docker/i686-unknown-linux-musl/Dockerfile index 3adb920040..49f37d70f2 100644 --- a/src/liblibc/ci/docker/i686-unknown-linux-musl/Dockerfile +++ b/src/liblibc/ci/docker/i686-unknown-linux-musl/Dockerfile @@ -12,19 +12,20 @@ RUN apt-get install -y --no-install-recommends \ # since otherwise the script will fail to find a compiler. # * We manually unset CROSS_COMPILE when running make; otherwise the makefile # will call the non-existent binary 'i686-ar'. -RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \ +RUN curl https://www.musl-libc.org/releases/musl-1.1.19.tar.gz | \ tar xzf - && \ - cd musl-1.1.15 && \ + cd musl-1.1.19 && \ CC=gcc CFLAGS=-m32 ./configure --prefix=/musl-i686 --disable-shared --target=i686 && \ make CROSS_COMPILE= install -j4 && \ cd .. && \ - rm -rf musl-1.1.15 && \ + rm -rf musl-1.1.19 # Install linux kernel headers sanitized for use with musl - curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \ +RUN curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-6.tar.gz | \ tar xzf - && \ - cd kernel-headers-3.12.6-5 && \ + cd kernel-headers-3.12.6-6 && \ make ARCH=i386 prefix=/musl-i686 install -j4 && \ cd .. && \ - rm -rf kernel-headers-3.12.6-5 + rm -rf kernel-headers-3.12.6-6 + ENV PATH=$PATH:/musl-i686/bin:/rust/bin \ CC_i686_unknown_linux_musl=musl-gcc diff --git a/src/liblibc/ci/docker/sparc64-unknown-linux-gnu/Dockerfile b/src/liblibc/ci/docker/sparc64-unknown-linux-gnu/Dockerfile index 90b5ea9bda..d9edaab426 100644 --- a/src/liblibc/ci/docker/sparc64-unknown-linux-gnu/Dockerfile +++ b/src/liblibc/ci/docker/sparc64-unknown-linux-gnu/Dockerfile @@ -5,7 +5,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gcc libc6-dev \ gcc-sparc64-linux-gnu libc6-dev-sparc64-cross \ qemu-system-sparc64 openbios-sparc seabios ipxe-qemu \ - p7zip-full cpio + p7zip-full cpio linux-libc-dev-sparc64-cross linux-headers-4.9.0-3-common + +# Put linux/module.h into the right spot as it is not shipped by debian +RUN cp /usr/src/linux-headers-4.9.0-3-common/include/uapi/linux/module.h /usr/sparc64-linux-gnu/include/linux/ COPY linux-sparc64.sh / RUN bash /linux-sparc64.sh diff --git a/src/liblibc/ci/docker/x86_64-unknown-linux-musl/Dockerfile b/src/liblibc/ci/docker/x86_64-unknown-linux-musl/Dockerfile index d9d6511386..6e2b7d9e5e 100644 --- a/src/liblibc/ci/docker/x86_64-unknown-linux-musl/Dockerfile +++ b/src/liblibc/ci/docker/x86_64-unknown-linux-musl/Dockerfile @@ -3,18 +3,18 @@ FROM ubuntu:17.10 RUN apt-get update RUN apt-get install -y --no-install-recommends \ gcc make libc6-dev git curl ca-certificates -RUN curl https://www.musl-libc.org/releases/musl-1.1.15.tar.gz | \ +RUN curl https://www.musl-libc.org/releases/musl-1.1.19.tar.gz | \ tar xzf - && \ - cd musl-1.1.15 && \ + cd musl-1.1.19 && \ ./configure --prefix=/musl-x86_64 && \ make install -j4 && \ cd .. && \ - rm -rf musl-1.1.15 && \ + rm -rf musl-1.1.19 # Install linux kernel headers sanitized for use with musl - curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-5.tar.gz | \ +RUN curl -L https://github.com/sabotage-linux/kernel-headers/archive/v3.12.6-6.tar.gz | \ tar xzf - && \ - cd kernel-headers-3.12.6-5 && \ + cd kernel-headers-3.12.6-6 && \ make ARCH=x86_64 prefix=/musl-x86_64 install -j4 && \ cd .. && \ - rm -rf kernel-headers-3.12.6-5 + rm -rf kernel-headers-3.12.6-6 ENV PATH=$PATH:/musl-x86_64/bin:/rust/bin diff --git a/src/liblibc/ci/ios/deploy_and_run_on_ios_simulator.rs b/src/liblibc/ci/ios/deploy_and_run_on_ios_simulator.rs index b14615036d..95df52d76d 100644 --- a/src/liblibc/ci/ios/deploy_and_run_on_ios_simulator.rs +++ b/src/liblibc/ci/ios/deploy_and_run_on_ios_simulator.rs @@ -123,6 +123,7 @@ fn run_app_on_simulator() { .arg("com.rust.unittests") .output()); + println!("status: {}", output.status); println!("stdout --\n{}\n", String::from_utf8_lossy(&output.stdout)); println!("stderr --\n{}\n", String::from_utf8_lossy(&output.stderr)); diff --git a/src/liblibc/ci/run.sh b/src/liblibc/ci/run.sh index ff74899cbb..27ffc054a0 100755 --- a/src/liblibc/ci/run.sh +++ b/src/liblibc/ci/run.sh @@ -79,12 +79,20 @@ if [ "$QEMU" != "" ]; then exec grep "^PASSED .* tests" $CARGO_TARGET_DIR/out.log fi -# FIXME: x86_64-unknown-linux-gnux32 fail to compile wihout --release +# FIXME: x86_64-unknown-linux-gnux32 fail to compile without --release # See https://github.com/rust-lang/rust/issues/45417 opt= if [ "$TARGET" = "x86_64-unknown-linux-gnux32" ]; then opt="--release" fi -cargo test $opt --no-default-features --manifest-path libc-test/Cargo.toml --target $TARGET +# Building with --no-default-features is currently broken on rumprun because we +# need cfg(target_vendor), which is currently unstable. +if [ "$TARGET" != "x86_64-rumprun-netbsd" ]; then + cargo test $opt --no-default-features --manifest-path libc-test/Cargo.toml --target $TARGET +fi +# Test the #[repr(align(x))] feature if this is building on Rust >= 1.25 +if [ $(rustc --version | sed -E 's/^rustc 1\.([0-9]*)\..*/\1/') -ge 25 ]; then + cargo test $opt --features align --manifest-path libc-test/Cargo.toml --target $TARGET +fi exec cargo test $opt --manifest-path libc-test/Cargo.toml --target $TARGET diff --git a/src/liblibc/libc-test/Cargo.toml b/src/liblibc/libc-test/Cargo.toml index 8d0f9d34e6..79fcf5f01e 100644 --- a/src/liblibc/libc-test/Cargo.toml +++ b/src/liblibc/libc-test/Cargo.toml @@ -9,11 +9,12 @@ path = ".." default-features = false [build-dependencies] -ctest = { git = "https://github.com/alexcrichton/ctest" } +ctest = "0.2" [features] default = [ "use_std" ] use_std = [ "libc/use_std" ] +align = [ "libc/align" ] [[test]] name = "main" diff --git a/src/liblibc/libc-test/build.rs b/src/liblibc/libc-test/build.rs index b76b6f09ce..d46372b44b 100644 --- a/src/liblibc/libc-test/build.rs +++ b/src/liblibc/libc-test/build.rs @@ -15,6 +15,7 @@ fn main() { let linux = target.contains("unknown-linux"); let android = target.contains("android"); let apple = target.contains("apple"); + let ios = target.contains("apple-ios"); let emscripten = target.contains("asm"); let musl = target.contains("musl") || emscripten; let uclibc = target.contains("uclibc"); @@ -84,8 +85,10 @@ fn main() { cfg.header("sys/socket.h"); } cfg.header("net/if.h"); - cfg.header("net/route.h"); - cfg.header("net/if_arp.h"); + if !ios { + cfg.header("net/route.h"); + cfg.header("net/if_arp.h"); + } cfg.header("netdb.h"); cfg.header("netinet/in.h"); cfg.header("netinet/ip.h"); @@ -113,7 +116,7 @@ fn main() { cfg.header("pwd.h"); cfg.header("grp.h"); cfg.header("sys/utsname.h"); - if !solaris { + if !solaris && !ios { cfg.header("sys/ptrace.h"); } cfg.header("sys/mount.h"); @@ -175,19 +178,22 @@ fn main() { cfg.header("util.h"); cfg.header("xlocale.h"); cfg.header("sys/xattr.h"); - cfg.header("sys/sys_domain.h"); - cfg.header("net/if_utun.h"); - cfg.header("net/bpf.h"); - if target.starts_with("x86") { + if target.starts_with("x86") && !ios { cfg.header("crt_externs.h"); } - cfg.header("net/route.h"); - cfg.header("netinet/if_ether.h"); cfg.header("netinet/in.h"); - cfg.header("sys/proc_info.h"); - cfg.header("sys/kern_control.h"); cfg.header("sys/ipc.h"); cfg.header("sys/shm.h"); + + if !ios { + cfg.header("sys/sys_domain.h"); + cfg.header("net/if_utun.h"); + cfg.header("net/bpf.h"); + cfg.header("net/route.h"); + cfg.header("netinet/if_ether.h"); + cfg.header("sys/proc_info.h"); + cfg.header("sys/kern_control.h"); + } } if bsdlike { @@ -272,6 +278,7 @@ fn main() { if linux || android { cfg.header("sys/fsuid.h"); + cfg.header("linux/module.h"); cfg.header("linux/seccomp.h"); cfg.header("linux/if_ether.h"); cfg.header("linux/if_tun.h"); @@ -343,7 +350,7 @@ fn main() { } } - cfg.type_name(move |ty, is_struct| { + cfg.type_name(move |ty, is_struct, is_union| { match ty { // Just pass all these through, no need for a "struct" prefix "FILE" | @@ -360,6 +367,10 @@ fn main() { // OSX calls this something else "sighandler_t" if bsdlike => "sig_t".to_string(), + t if is_union => { + format!("union {}", t) + } + t if t.ends_with("_t") => t.to_string(), // Windows uppercase structs don't have `struct` in front, there's a @@ -444,6 +455,17 @@ fn main() { // header conflicts when including them with all the other structs. "termios2" => true, + // Present on historical versions of iOS but missing in more recent + // SDKs + "bpf_hdr" | + "proc_taskinfo" | + "proc_taskallinfo" | + "proc_bsdinfo" | + "proc_threadinfo" | + "sockaddr_inarp" | + "sockaddr_ctl" | + "arphdr" if ios => true, + _ => false } }); @@ -538,12 +560,6 @@ fn main() { "KERN_USERMOUNT" | "KERN_ARND" if openbsd => true, - // These constants were added in OpenBSD 6.2 - "EV_RECEIPT" | "EV_DISPATCH" if openbsd => true, - - // These constants were added in OpenBSD 6.3 - "MAP_STACK" if openbsd => true, - // These are either unimplemented or optionally built into uClibc "LC_CTYPE_MASK" | "LC_NUMERIC_MASK" | "LC_TIME_MASK" | "LC_COLLATE_MASK" | "LC_MONETARY_MASK" | "LC_MESSAGES_MASK" | "MADV_MERGEABLE" | "MADV_UNMERGEABLE" | "MADV_HWPOISON" | "IPV6_ADD_MEMBERSHIP" | "IPV6_DROP_MEMBERSHIP" | "IPV6_MULTICAST_LOOP" | "IPV6_V6ONLY" | @@ -560,7 +576,7 @@ fn main() { // Defined by libattr not libc on linux (hard to test). // See constant definition for more details. - "ENOATTR" if linux => true, + "ENOATTR" if android || linux => true, // On mips*-unknown-linux-gnu* CMSPAR cannot be included with the set of headers we // want to use here for testing. It's originally defined in asm/termbits.h, which is @@ -595,6 +611,30 @@ fn main() { // shouldn't be used in code anyway... "AF_MAX" | "PF_MAX" => true, + // Present on historical versions of iOS, but now removed in more + // recent SDKs + "ARPOP_REQUEST" | + "ARPOP_REPLY" | + "ATF_COM" | + "ATF_PERM" | + "ATF_PUBL" | + "ATF_USETRAILERS" | + "AF_SYS_CONTROL" | + "SYSPROTO_EVENT" | + "PROC_PIDTASKALLINFO" | + "PROC_PIDTASKINFO" | + "PROC_PIDTHREADINFO" | + "UTUN_OPT_FLAGS" | + "UTUN_OPT_IFNAME" | + "BPF_ALIGNMENT" | + "SYSPROTO_CONTROL" if ios => true, + s if ios && s.starts_with("RTF_") => true, + s if ios && s.starts_with("RTM_") => true, + s if ios && s.starts_with("RTA_") => true, + s if ios && s.starts_with("RTAX_") => true, + s if ios && s.starts_with("RTV_") => true, + s if ios && s.starts_with("DLT_") => true, + _ => false, } }); @@ -737,6 +777,10 @@ fn main() { // FIXME: mincore is defined with caddr_t on Solaris. "mincore" if solaris => true, + // These were all included in historical versions of iOS but appear + // to be removed now + "system" | "ptrace" if ios => true, + _ => false, } }); @@ -822,9 +866,10 @@ fn main() { cfg.skip_struct(|s| { s != "termios2" }); - cfg.type_name(move |ty, is_struct| { + cfg.type_name(move |ty, is_struct, is_union| { match ty { t if is_struct => format!("struct {}", t), + t if is_union => format!("union {}", t), t => t.to_string(), } }); diff --git a/src/liblibc/src/fuchsia/aarch64.rs b/src/liblibc/src/fuchsia/aarch64.rs index 157d3d6e9e..572f8c1ce3 100644 --- a/src/liblibc/src/fuchsia/aarch64.rs +++ b/src/liblibc/src/fuchsia/aarch64.rs @@ -1,8 +1,8 @@ pub type c_char = u8; pub type __u64 = ::c_ulonglong; pub type wchar_t = u32; -pub type nlink_t = u32; -pub type blksize_t = ::c_int; +pub type nlink_t = ::c_ulong; +pub type blksize_t = ::c_long; s! { pub struct stat { diff --git a/src/liblibc/src/fuchsia/mod.rs b/src/liblibc/src/fuchsia/mod.rs index 0aac98531a..0b93d84af3 100644 --- a/src/liblibc/src/fuchsia/mod.rs +++ b/src/liblibc/src/fuchsia/mod.rs @@ -97,16 +97,13 @@ s! { pub tv_usec: suseconds_t, } - // linux x32 compatibility - // See https://sourceware.org/bugzilla/show_bug.cgi?id=16437 pub struct timespec { pub tv_sec: time_t, - #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] - pub tv_nsec: i64, - #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub tv_nsec: ::c_long, } + // FIXME: the rlimit and rusage related functions and types don't exist + // within zircon. Are there reasons for keeping them around? pub struct rlimit { pub rlim_cur: rlim_t, pub rlim_max: rlim_t, @@ -168,7 +165,6 @@ s! { pub struct in6_addr { pub s6_addr: [u8; 16], - __align: [u32; 0], } pub struct ip_mreq { @@ -178,9 +174,6 @@ s! { pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, - #[cfg(target_os = "android")] - pub ipv6mr_interface: ::c_int, - #[cfg(not(target_os = "android"))] pub ipv6mr_interface: ::c_uint, } @@ -398,13 +391,9 @@ s! { pub struct sched_param { pub sched_priority: ::c_int, - #[cfg(target_env = "musl")] pub sched_ss_low_priority: ::c_int, - #[cfg(target_env = "musl")] pub sched_ss_repl_period: ::timespec, - #[cfg(target_env = "musl")] pub sched_ss_init_budget: ::timespec, - #[cfg(target_env = "musl")] pub sched_ss_max_repl: ::c_int, } @@ -415,11 +404,6 @@ s! { pub dli_saddr: *mut ::c_void, } - #[cfg_attr(any(all(target_arch = "x86", - not(target_env = "musl"), - not(target_os = "android")), - target_arch = "x86_64"), - repr(packed))] pub struct epoll_event { pub events: ::uint32_t, pub u64: ::uint64_t, @@ -465,13 +449,9 @@ s! { pub sigev_value: ::sigval, pub sigev_signo: ::c_int, pub sigev_notify: ::c_int, - // Actually a union. We only expose sigev_notify_thread_id because it's - // the most useful member - pub sigev_notify_thread_id: ::c_int, - #[cfg(target_pointer_width = "64")] - __unused1: [::c_int; 11], - #[cfg(target_pointer_width = "32")] - __unused1: [::c_int; 12] + pub sigev_notify_function: fn(::sigval), + pub sigev_notify_attributes: *mut pthread_attr_t, + pub __pad: [::c_char; 56 - 3 * 8 /* 8 == sizeof(long) */], } pub struct dirent { @@ -518,71 +498,118 @@ s! { pub ifa_data: *mut ::c_void } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "arm", + target_arch = "x86_64")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "arm", + target_arch = "x86_64")))), + repr(align(8)))] pub struct pthread_mutex_t { - #[cfg(any(target_arch = "mips", - target_arch = "arm", - target_arch = "powerpc", - all(target_arch = "x86_64", - target_pointer_width = "32")))] + #[cfg(all(not(feature = "align"), + any(target_arch = "arm", + all(target_arch = "x86_64", + target_pointer_width = "32"))))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", + #[cfg(not(any(feature = "align", target_arch = "arm", - target_arch = "powerpc", all(target_arch = "x86_64", target_pointer_width = "32"))))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "arm", + target_arch = "x86_64")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "arm", + target_arch = "x86_64")))), + repr(align(8)))] pub struct pthread_rwlock_t { - #[cfg(any(target_arch = "mips", - target_arch = "arm", - target_arch = "powerpc", - all(target_arch = "x86_64", - target_pointer_width = "32")))] + #[cfg(all(not(feature = "align"), + any(target_arch = "arm", + all(target_arch = "x86_64", + target_pointer_width = "32"))))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", + #[cfg(not(any(feature = "align", target_arch = "arm", - target_arch = "powerpc", all(target_arch = "x86_64", target_pointer_width = "32"))))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], } + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "32", + target_arch = "x86_64", + all(target_arch = "aarch64", target_env = "musl"))), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(any(target_pointer_width = "32", + target_arch = "x86_64", + all(target_arch = "aarch64", target_env = "musl")))), + repr(align(8)))] pub struct pthread_mutexattr_t { - #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", - target_arch = "mips64", target_arch = "s390x", - target_arch = "sparc64"))] + #[cfg(all(not(features = "align"), + any(target_arch = "x86_64", + all(target_arch = "aarch64", target_env = "musl"))))] __align: [::c_int; 0], - #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", - target_arch = "mips64", target_arch = "s390x", - target_arch = "sparc64", target_arch = "aarch64")))] - __align: [::c_long; 0], - #[cfg(all(target_arch = "aarch64", target_env = "gnu"))] + #[cfg(all(not(features = "align"), + not(any(target_arch = "x86_64", + all(target_arch = "aarch64", target_env = "musl")))))] __align: [::c_long; 0], - #[cfg(all(target_arch = "aarch64", target_env = "musl"))] - __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } + #[cfg_attr(all(feature = "align", + any(target_env = "musl", target_pointer_width = "32")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(target_env = "musl"), + target_pointer_width = "64"), + repr(align(8)))] pub struct pthread_rwlockattr_t { - #[cfg(any(target_env = "musl"))] + #[cfg(all(not(feature = "align"), target_env = "musl"))] __align: [::c_int; 0], - #[cfg(not(any(target_env = "musl")))] + #[cfg(all(not(feature = "align"), not(target_env = "musl")))] __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T], } + #[cfg_attr(all(feature = "align", + target_env = "musl", + target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + target_env = "musl", + target_pointer_width = "64"), + repr(align(8)))] + #[cfg_attr(all(feature = "align", + not(target_env = "musl"), + target_arch = "x86"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(target_env = "musl"), + not(target_arch = "x86")), + repr(align(8)))] pub struct pthread_cond_t { - #[cfg(any(target_env = "musl"))] + #[cfg(all(not(feature = "align"), target_env = "musl"))] __align: [*const ::c_void; 0], - #[cfg(not(any(target_env = "musl")))] + #[cfg(not(any(feature = "align", target_env = "musl")))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_COND_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_condattr_t { + #[cfg(not(feature = "align"))] __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], } @@ -2004,18 +2031,17 @@ pub const RTLD_NOW: ::c_int = 0x2; pub const TCP_MD5SIG: ::c_int = 14; -pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_MUTEX_T], -}; -pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_COND_T], -}; -pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_RWLOCK_T], -}; +align_const! { + pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + size: [0; __SIZEOF_PTHREAD_MUTEX_T], + }; + pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + size: [0; __SIZEOF_PTHREAD_COND_T], + }; + pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], + }; +} pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; @@ -3915,9 +3941,6 @@ cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; - } else if #[cfg(any(target_arch = "powerpc64"))] { - mod powerpc64; - pub use self::powerpc64::*; } else if #[cfg(any(target_arch = "x86_64"))] { mod x86_64; pub use self::x86_64::*; diff --git a/src/liblibc/src/fuchsia/powerpc64.rs b/src/liblibc/src/fuchsia/powerpc64.rs deleted file mode 100644 index 112cd43514..0000000000 --- a/src/liblibc/src/fuchsia/powerpc64.rs +++ /dev/null @@ -1,79 +0,0 @@ -pub type c_char = u8; -pub type wchar_t = i32; -pub type __u64 = ::c_ulong; -pub type nlink_t = u64; -pub type blksize_t = ::c_long; - -s! { - pub struct stat { - pub st_dev: ::dev_t, - pub st_ino: ::ino_t, - pub st_nlink: ::nlink_t, - pub st_mode: ::mode_t, - pub st_uid: ::uid_t, - pub st_gid: ::gid_t, - __pad0: ::c_int, - pub st_rdev: ::dev_t, - pub st_size: ::off_t, - pub st_blksize: ::blksize_t, - pub st_blocks: ::blkcnt_t, - pub st_atime: ::time_t, - pub st_atime_nsec: ::c_long, - pub st_mtime: ::time_t, - pub st_mtime_nsec: ::c_long, - pub st_ctime: ::time_t, - pub st_ctime_nsec: ::c_long, - __unused: [::c_long; 3], - } - - pub struct stat64 { - pub st_dev: ::dev_t, - pub st_ino: ::ino64_t, - pub st_nlink: ::nlink_t, - pub st_mode: ::mode_t, - pub st_uid: ::uid_t, - pub st_gid: ::gid_t, - __pad0: ::c_int, - pub st_rdev: ::dev_t, - pub st_size: ::off_t, - pub st_blksize: ::blksize_t, - pub st_blocks: ::blkcnt64_t, - pub st_atime: ::time_t, - pub st_atime_nsec: ::c_long, - pub st_mtime: ::time_t, - pub st_mtime_nsec: ::c_long, - pub st_ctime: ::time_t, - pub st_ctime_nsec: ::c_long, - __reserved: [::c_long; 3], - } - - pub struct ipc_perm { - pub __ipc_perm_key: ::key_t, - pub uid: ::uid_t, - pub gid: ::gid_t, - pub cuid: ::uid_t, - pub cgid: ::gid_t, - pub mode: ::mode_t, - pub __seq: ::c_int, - __unused1: ::c_long, - __unused2: ::c_long - } -} - -pub const SYS_pivot_root: ::c_long = 203; -pub const SYS_gettid: ::c_long = 207; -pub const SYS_perf_event_open: ::c_long = 319; -pub const SYS_memfd_create: ::c_long = 360; - -pub const MAP_32BIT: ::c_int = 0x0040; - -pub const SIGSTKSZ: ::size_t = 8192; -pub const MINSIGSTKSZ: ::size_t = 2048; - -#[doc(hidden)] -pub const AF_MAX: ::c_int = 42; -#[doc(hidden)] -pub const PF_MAX: ::c_int = AF_MAX; - -// Syscall table -pub const SYS_renameat2: ::c_long = 357; diff --git a/src/liblibc/src/lib.rs b/src/liblibc/src/lib.rs index f7efb6002e..7f8e907aaf 100644 --- a/src/liblibc/src/lib.rs +++ b/src/liblibc/src/lib.rs @@ -86,7 +86,7 @@ ))] // Attributes needed when building as part of the standard library -#![cfg_attr(feature = "stdbuild", feature(staged_api, custom_attribute, cfg_target_vendor))] +#![cfg_attr(feature = "stdbuild", feature(staged_api, cfg_target_vendor))] #![cfg_attr(feature = "stdbuild", feature(link_cfg, repr_packed))] #![cfg_attr(feature = "stdbuild", allow(warnings))] #![cfg_attr(feature = "stdbuild", unstable(feature = "libc", @@ -104,6 +104,9 @@ mod dox; cfg_if! { if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { // empty ... + } else if #[cfg(target_os = "switch")] { + // On the Switch, we only define some useful universal types for + // convenience. Those can be found in the switch.rs file. } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable @@ -296,6 +299,9 @@ cfg_if! { } else if #[cfg(target_os = "fuchsia")] { mod fuchsia; pub use fuchsia::*; + } else if #[cfg(target_os = "switch")] { + mod switch; + pub use switch::*; } else if #[cfg(unix)] { mod unix; pub use unix::*; diff --git a/src/liblibc/src/macros.rs b/src/liblibc/src/macros.rs index 0e13bfcf46..f48ad45941 100644 --- a/src/liblibc/src/macros.rs +++ b/src/liblibc/src/macros.rs @@ -35,11 +35,11 @@ macro_rules! __cfg_if_apply { } macro_rules! s { - ($($(#[$attr:meta])* pub struct $i:ident { $($field:tt)* })*) => ($( + ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($( __item! { #[repr(C)] $(#[$attr])* - pub struct $i { $($field)* } + pub $t $i { $($field)* } } impl ::dox::Copy for $i {} impl ::dox::Clone for $i { @@ -69,3 +69,20 @@ macro_rules! f { macro_rules! __item { ($i:item) => ($i) } + +#[allow(unused_macros)] +macro_rules! align_const { + ($($(#[$attr:meta])* pub const $name:ident : $t1:ty = $t2:ident { $($field:tt)* };)*) => ($( + #[cfg(feature = "align")] + $(#[$attr])* + pub const $name : $t1 = $t2 { + $($field)* + }; + #[cfg(not(feature = "align"))] + $(#[$attr])* + pub const $name : $t1 = $t2 { + $($field)* + __align: [], + }; + )*) +} diff --git a/src/liblibc/src/redox/net.rs b/src/liblibc/src/redox/net.rs index a545ba4795..fcbb181c32 100644 --- a/src/liblibc/src/redox/net.rs +++ b/src/liblibc/src/redox/net.rs @@ -9,8 +9,10 @@ s! { pub s_addr: in_addr_t, } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct in6_addr { pub s6_addr: [u8; 16], + #[cfg(not(feature = "align"))] __align: [u32; 0], } diff --git a/src/liblibc/src/switch.rs b/src/liblibc/src/switch.rs new file mode 100644 index 0000000000..c11379541e --- /dev/null +++ b/src/liblibc/src/switch.rs @@ -0,0 +1,48 @@ +//! Switch C type definitions + +// Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable +// more optimization opportunities around it recognizing things like +// malloc/free. +#[repr(u8)] +pub enum c_void { + // Two dummy variants so the #[repr] attribute can be used. + #[doc(hidden)] + __variant1, + #[doc(hidden)] + __variant2, +} + +pub type int8_t = i8; +pub type int16_t = i16; +pub type int32_t = i32; +pub type int64_t = i64; +pub type uint8_t = u8; +pub type uint16_t = u16; +pub type uint32_t = u32; +pub type uint64_t = u64; + +pub type c_schar = i8; +pub type c_uchar = u8; +pub type c_short = i16; +pub type c_ushort = u16; +pub type c_int = i32; +pub type c_uint = u32; +pub type c_float = f32; +pub type c_double = f64; +pub type c_longlong = i64; +pub type c_ulonglong = u64; +pub type intmax_t = i64; +pub type uintmax_t = u64; + +pub type size_t = usize; +pub type ptrdiff_t = isize; +pub type intptr_t = isize; +pub type uintptr_t = usize; +pub type ssize_t = isize; + +// Arch specific +pub type off_t = i64; +pub type c_char = u8; +pub type c_long = i64; +pub type c_ulong = u64; +pub type wchar_t = u32; diff --git a/src/liblibc/src/unix/bsd/apple/b32.rs b/src/liblibc/src/unix/bsd/apple/b32.rs index 5dea472ccb..907ab02df4 100644 --- a/src/liblibc/src/unix/bsd/apple/b32.rs +++ b/src/liblibc/src/unix/bsd/apple/b32.rs @@ -58,3 +58,9 @@ pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 12; pub const TIOCTIMESTAMP: ::c_ulong = 0x40087459; pub const TIOCDCDTIMESTAMP: ::c_ulong = 0x40087458; + +extern { + pub fn exchangedata(path1: *const ::c_char, + path2: *const ::c_char, + options: ::c_ulong) -> ::c_int; +} diff --git a/src/liblibc/src/unix/bsd/apple/b64.rs b/src/liblibc/src/unix/bsd/apple/b64.rs index 2b34f85345..8e8c87dd28 100644 --- a/src/liblibc/src/unix/bsd/apple/b64.rs +++ b/src/liblibc/src/unix/bsd/apple/b64.rs @@ -64,4 +64,8 @@ pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 16; pub const TIOCTIMESTAMP: ::c_ulong = 0x40107459; pub const TIOCDCDTIMESTAMP: ::c_ulong = 0x40107458; -pub const FIONREAD: ::c_ulong = 0x4004667f; +extern { + pub fn exchangedata(path1: *const ::c_char, + path2: *const ::c_char, + options: ::c_uint) -> ::c_int; +} diff --git a/src/liblibc/src/unix/bsd/apple/mod.rs b/src/liblibc/src/unix/bsd/apple/mod.rs index 4abe466a0e..cf48528b4a 100644 --- a/src/liblibc/src/unix/bsd/apple/mod.rs +++ b/src/liblibc/src/unix/bsd/apple/mod.rs @@ -765,16 +765,8 @@ pub const VM_FLAGS_SUPERPAGE_MASK: ::c_int = 0x70000; pub const VM_FLAGS_RETURN_DATA_ADDR: ::c_int = 0x100000; pub const VM_FLAGS_RETURN_4K_DATA_ADDR: ::c_int = 0x800000; pub const VM_FLAGS_ALIAS_MASK: ::c_int = 0xFF000000; -pub const VM_FLAGS_USER_ALLOCATE: ::c_int = VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE | - VM_FLAGS_PURGABLE | - VM_FLAGS_RANDOM_ADDR | - VM_FLAGS_NO_CACHE | - VM_FLAGS_OVERWRITE | - VM_FLAGS_SUPERPAGE_MASK | - VM_FLAGS_ALIAS_MASK; -pub const VM_FLAGS_USER_MAP: ::c_int = VM_FLAGS_USER_ALLOCATE | - VM_FLAGS_RETURN_4K_DATA_ADDR | - VM_FLAGS_RETURN_DATA_ADDR; +pub const VM_FLAGS_USER_ALLOCATE: ::c_int = 0xff07401b; +pub const VM_FLAGS_USER_MAP: ::c_int = 0xff97401b; pub const VM_FLAGS_USER_REMAP: ::c_int = VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR | VM_FLAGS_OVERWRITE | @@ -1085,6 +1077,13 @@ pub const TIOCPTYGRANT: ::c_uint = 0x20007454; pub const TIOCPTYGNAME: ::c_uint = 0x40807453; pub const TIOCPTYUNLK: ::c_uint = 0x20007452; +pub const FIONCLEX: ::c_uint = 0x20006602; +pub const FIONREAD: ::c_ulong = 0x4004667f; +pub const FIOASYNC: ::c_ulong = 0x8004667d; +pub const FIOSETOWN: ::c_ulong = 0x8004667c; +pub const FIOGETOWN: ::c_ulong = 0x4004667b; +pub const FIODTYPE: ::c_ulong = 0x4004667a; + pub const B0: speed_t = 0; pub const B50: speed_t = 50; pub const B75: speed_t = 75; @@ -2253,10 +2252,14 @@ pub const DLT_LOOP: ::c_uint = 108; // sizeof(int32_t) pub const BPF_ALIGNMENT: ::c_int = 4; +// sys/spawn.h: pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02; pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x04; pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x08; +pub const POSIX_SPAWN_SETEXEC: ::c_int = 0x40; +pub const POSIX_SPAWN_START_SUSPENDED: ::c_int = 0x80; +pub const POSIX_SPAWN_CLOEXEC_DEFAULT: ::c_int = 0x4000; // sys/ipc.h: pub const IPC_CREAT: ::c_int = 0x200; diff --git a/src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs index f399f27ccb..9e1082e53b 100644 --- a/src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs +++ b/src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs @@ -115,6 +115,27 @@ s! { pub f_uid_uuid: ::uuid_t, } + pub struct statfs { + pub f_bsize: ::c_long, + pub f_iosize: ::c_long, + pub f_blocks: ::c_long, + pub f_bfree: ::c_long, + pub f_bavail: ::c_long, + pub f_files: ::c_long, + pub f_ffree: ::c_long, + pub f_fsid: ::fsid_t, + pub f_owner: ::uid_t, + pub f_type: ::int32_t, + pub f_flags: ::int32_t, + pub f_syncwrites: ::c_long, + pub f_asyncwrites: ::c_long, + pub f_fstypename: [::c_char; 16], + pub f_mntonname: [::c_char; 90], + pub f_syncreads: ::c_long, + pub f_asyncreads: ::c_long, + pub f_mntfromname: [::c_char; 90], + } + pub struct stat { pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, @@ -760,4 +781,7 @@ extern { pub fn lwp_rtprio(function: ::c_int, pid: ::pid_t, lwpid: lwpid_t, rtp: *mut super::rtprio) -> ::c_int; + + pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; + pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; } diff --git a/src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs b/src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs index def81dfe2e..a64dbc468f 100644 --- a/src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs +++ b/src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs @@ -99,6 +99,31 @@ s! { pub f_namemax: ::c_ulong, } + pub struct statfs { + pub f_version: ::uint32_t, + pub f_type: ::uint32_t, + pub f_flags: ::uint64_t, + pub f_bsize: ::uint64_t, + pub f_iosize: ::uint64_t, + pub f_blocks: ::uint64_t, + pub f_bfree: ::uint64_t, + pub f_bavail: ::int64_t, + pub f_files: ::uint64_t, + pub f_ffree: ::int64_t, + pub f_syncwrites: ::uint64_t, + pub f_asyncwrites: ::uint64_t, + pub f_syncreads: ::uint64_t, + pub f_asyncreads: ::uint64_t, + f_spare: [::uint64_t; 10], + pub f_namemax: ::uint32_t, + pub f_owner: ::uid_t, + pub f_fsid: ::fsid_t, + f_charspare: [::c_char; 80], + pub f_fstypename: [::c_char; 16], + pub f_mntfromname: [::c_char; 88], + pub f_mntonname: [::c_char; 88], + } + // internal structure has changed over time pub struct _sem { data: [u32; 4], @@ -994,6 +1019,9 @@ extern { fd: ::c_int, newfd: ::c_int, ) -> ::c_int; + + pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; + pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; } cfg_if! { diff --git a/src/liblibc/src/unix/bsd/mod.rs b/src/liblibc/src/unix/bsd/mod.rs index 47f82bdf59..03ab319269 100644 --- a/src/liblibc/src/unix/bsd/mod.rs +++ b/src/liblibc/src/unix/bsd/mod.rs @@ -444,6 +444,7 @@ extern { flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__futimes50")] pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/mod.rs index 1b7576e768..6384a29f8c 100644 --- a/src/liblibc/src/unix/bsd/netbsdlike/mod.rs +++ b/src/liblibc/src/unix/bsd/netbsdlike/mod.rs @@ -57,15 +57,6 @@ s! { pub l_type: ::c_short, pub l_whence: ::c_short, } - - #[repr(packed)] - pub struct arphdr { - pub ar_hrd: u16, - pub ar_pro: u16, - pub ar_hln: u8, - pub ar_pln: u8, - pub ar_op: u16, - } } pub const D_T_FMT: ::nl_item = 0; @@ -430,10 +421,6 @@ pub const IPV6_RECVPKTINFO: ::c_int = 36; pub const IPV6_PKTINFO: ::c_int = 46; pub const TCP_NODELAY: ::c_int = 0x01; -pub const TCP_KEEPIDLE: ::c_int = 3; -pub const TCP_KEEPINTVL: ::c_int = 5; -pub const TCP_KEEPCNT: ::c_int = 6; -pub const TCP_KEEPINIT: ::c_int = 7; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_DEBUG: ::c_int = 0x01; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/aarch64.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/aarch64.rs new file mode 100644 index 0000000000..6aa9950ed1 --- /dev/null +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/aarch64.rs @@ -0,0 +1,3 @@ +pub type c_long = i64; +pub type c_ulong = u64; +pub type c_char = u8; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/arm.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/arm.rs new file mode 100644 index 0000000000..377e05be07 --- /dev/null +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/arm.rs @@ -0,0 +1,3 @@ +pub type c_long = i32; +pub type c_ulong = u32; +pub type c_char = u8; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/mod.rs index 01dd188495..b343c3a197 100644 --- a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/mod.rs +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/mod.rs @@ -1,6 +1,5 @@ use dox::mem; -pub type c_char = i8; pub type clock_t = ::c_uint; pub type suseconds_t = ::c_int; pub type dev_t = u64; @@ -318,6 +317,15 @@ s! { pub ipi_addr: ::in_addr, pub ipi_ifindex: ::c_uint, } + + #[repr(packed)] + pub struct arphdr { + pub ar_hrd: u16, + pub ar_pro: u16, + pub ar_hln: u8, + pub ar_pln: u8, + pub ar_op: u16, + } } pub const AT_FDCWD: ::c_int = -100; @@ -381,6 +389,11 @@ pub const IP_RECVPKTINFO: ::c_int = 26; pub const IPV6_JOIN_GROUP: ::c_int = 12; pub const IPV6_LEAVE_GROUP: ::c_int = 13; +pub const TCP_KEEPIDLE: ::c_int = 3; +pub const TCP_KEEPINTVL: ::c_int = 5; +pub const TCP_KEEPCNT: ::c_int = 6; +pub const TCP_KEEPINIT: ::c_int = 7; + pub const SOCK_CONN_DGRAM: ::c_int = 6; pub const SOCK_DCCP: ::c_int = SOCK_CONN_DGRAM; pub const SOCK_NOSIGPIPE: ::c_int = 0x40000000; @@ -991,6 +1004,7 @@ extern { pub fn lio_listio(mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent) -> ::c_int; + #[link_name = "__lutimes50"] pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, @@ -1042,11 +1056,13 @@ extern { pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; + #[link_name = "__mq_timedreceive50"] pub fn mq_timedreceive(mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msq_prio: *mut ::c_uint, abs_timeout: *const ::timespec) -> ::ssize_t; + #[link_name = "__mq_timedsend50"] pub fn mq_timedsend(mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, @@ -1096,5 +1112,26 @@ extern { result: *mut *mut ::group) -> ::c_int; } -mod other; -pub use self::other::*; +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + pub use self::aarch64::*; + } else if #[cfg(target_arch = "arm")] { + mod arm; + pub use self::arm::*; + } else if #[cfg(target_arch = "powerpc")] { + mod powerpc; + pub use self::powerpc::*; + } else if #[cfg(target_arch = "sparc64")] { + mod sparc64; + pub use self::sparc64::*; + } else if #[cfg(target_arch = "x86_64")] { + mod x86_64; + pub use self::x86_64::*; + } else if #[cfg(target_arch = "x86")] { + mod x86; + pub use self::x86::*; + } else { + // Unknown target_arch + } +} diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/b32/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/b32/mod.rs deleted file mode 100644 index 9b0b338b91..0000000000 --- a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/b32/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub type c_long = i32; -pub type c_ulong = u32; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/b64/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/b64/mod.rs deleted file mode 100644 index b07c476aa4..0000000000 --- a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/b64/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub type c_long = i64; -pub type c_ulong = u64; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/mod.rs deleted file mode 100644 index 3a9bf0866c..0000000000 --- a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -cfg_if! { - if #[cfg(any(target_arch = "sparc64", - target_arch = "x86_64"))] { - mod b64; - pub use self::b64::*; - } else if #[cfg(any(target_arch = "arm", - target_arch = "powerpc", - target_arch = "x86"))] { - mod b32; - pub use self::b32::*; - } else { - // Unknown target_arch - } -} diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/powerpc.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/powerpc.rs new file mode 100644 index 0000000000..377e05be07 --- /dev/null +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/powerpc.rs @@ -0,0 +1,3 @@ +pub type c_long = i32; +pub type c_ulong = u32; +pub type c_char = u8; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/sparc64.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/sparc64.rs new file mode 100644 index 0000000000..27b9412668 --- /dev/null +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/sparc64.rs @@ -0,0 +1,3 @@ +pub type c_long = i64; +pub type c_ulong = u64; +pub type c_char = i8; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/x86.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/x86.rs new file mode 100644 index 0000000000..a00e3337ef --- /dev/null +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/x86.rs @@ -0,0 +1,3 @@ +pub type c_long = i32; +pub type c_ulong = u32; +pub type c_char = i8; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/x86_64.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/x86_64.rs new file mode 100644 index 0000000000..27b9412668 --- /dev/null +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/x86_64.rs @@ -0,0 +1,3 @@ +pub type c_long = i64; +pub type c_ulong = u64; +pub type c_char = i8; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs index e44bfca61c..bf5ddd2e7a 100644 --- a/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs +++ b/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/mod.rs @@ -193,6 +193,14 @@ s! { pub gid: ::gid_t, pub pid: ::pid_t, } + + pub struct arphdr { + pub ar_hrd: u16, + pub ar_pro: u16, + pub ar_hln: u8, + pub ar_pln: u8, + pub ar_op: u16, + } } pub const UT_NAMESIZE: usize = 32; @@ -579,6 +587,7 @@ pub const CTL_MACHDEP: ::c_int = 7; pub const CTL_DDB: ::c_int = 9; pub const CTL_VFS: ::c_int = 10; pub const CTL_MAXID: ::c_int = 11; +pub const HW_NCPUONLINE: ::c_int = 25; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; @@ -653,7 +662,8 @@ pub const KERN_PROC_VMMAP: ::c_int = 80; pub const KERN_GLOBAL_PTRACE: ::c_int = 81; pub const KERN_CONSBUFSIZE: ::c_int = 82; pub const KERN_CONSBUF: ::c_int = 83; -pub const KERN_MAXID: ::c_int = 84; +pub const KERN_AUDIO: ::c_int = 84; +pub const KERN_MAXID: ::c_int = 85; pub const KERN_PROC_ALL: ::c_int = 0; pub const KERN_PROC_PID: ::c_int = 1; pub const KERN_PROC_PGRP: ::c_int = 2; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs index cca8a47ae0..5e6948115f 100644 --- a/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs +++ b/src/liblibc/src/unix/bsd/netbsdlike/openbsdlike/openbsd/mod.rs @@ -25,8 +25,207 @@ s! { pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } + + pub struct statfs { + pub f_flags: ::uint32_t, + pub f_bsize: ::uint32_t, + pub f_iosize: ::uint32_t, + pub f_blocks: ::uint64_t, + pub f_bfree: ::uint64_t, + pub f_bavail: ::int64_t, + pub f_files: ::uint64_t, + pub f_ffree: ::uint64_t, + pub f_favail: ::int64_t, + pub f_syncwrites: ::uint64_t, + pub f_syncreads: ::uint64_t, + pub f_asyncwrites: ::uint64_t, + pub f_asyncreads: ::uint64_t, + pub f_fsid: ::fsid_t, + pub f_namemax: ::uint32_t, + pub f_owner: ::uid_t, + pub f_ctime: ::uint64_t, + pub f_fstypename: [::c_char; 16], + pub f_mntonname: [::c_char; 90], + pub f_mntfromname: [::c_char; 90], + pub f_mntfromspec: [::c_char; 90], + pub mount_info: mount_info, + } + + pub union mount_info { + pub ufs_args: ufs_args, + pub mfs_args: mfs_args, + pub nfs_args: nfs_args, + pub iso_args: iso_args, + pub msdosfs_args: msdosfs_args, + pub ntfs_args: ntfs_args, + pub tmpfs_args: tmpfs_args, + align: [::c_char; 160], + } + + pub struct ufs_args { + pub fspec: *mut ::c_char, + pub export_info: export_args, + } + + pub struct mfs_args { + pub fspec: *mut ::c_char, + pub export_info: export_args, + // https://github.com/openbsd/src/blob/master/sys/sys/types.h#L134 + pub base: *mut ::c_char, + pub size: ::c_ulong, + } + + pub struct iso_args { + pub fspec: *mut ::c_char, + pub export_info: export_args, + pub flags: ::c_int, + pub sess: ::c_int, + } + + pub struct nfs_args { + pub version: ::c_int, + pub addr: *mut ::sockaddr, + pub addrlen: ::c_int, + pub sotype: ::c_int, + pub proto: ::c_int, + pub fh: *mut ::c_uchar, + pub fhsize: ::c_int, + pub flags: ::c_int, + pub wsize: ::c_int, + pub rsize: ::c_int, + pub readdirsize: ::c_int, + pub timeo: ::c_int, + pub retrans: ::c_int, + pub maxgrouplist: ::c_int, + pub readahead: ::c_int, + pub leaseterm: ::c_int, + pub deadthresh: ::c_int, + pub hostname: *mut ::c_char, + pub acregmin: ::c_int, + pub acregmax: ::c_int, + pub acdirmin: ::c_int, + pub acdirmax: ::c_int, + } + + pub struct msdosfs_args { + pub fspec: *mut ::c_char, + pub export_info: export_args, + pub uid: ::uid_t, + pub gid: ::gid_t, + pub mask: ::mode_t, + pub flags: ::c_int, + } + + pub struct ntfs_args { + pub fspec: *mut ::c_char, + pub export_info: export_args, + pub uid: ::uid_t, + pub gid: ::gid_t, + pub mode: ::mode_t, + pub flag: ::c_ulong, + } + + pub struct udf_args { + pub fspec: *mut ::c_char, + pub lastblock: ::uint32_t, + } + + pub struct tmpfs_args { + pub ta_version: ::c_int, + pub ta_nodes_max: ::ino_t, + pub ta_size_max: ::off_t, + pub ta_root_uid: ::uid_t, + pub ta_root_gid: ::gid_t, + pub ta_root_mode: ::mode_t, + } + + pub struct fusefs_args { + pub name: *mut ::c_char, + pub fd: ::c_int, + pub max_read: ::c_int, + pub allow_other: ::c_int, + } + + pub struct xucred { + pub cr_uid: ::uid_t, + pub cr_gid: ::gid_t, + pub cr_ngroups: ::c_short, + //https://github.com/openbsd/src/blob/master/sys/sys/syslimits.h#L44 + pub cr_groups: [::gid_t; 16], + } + + pub struct export_args { + pub ex_flags: ::c_int, + pub ex_root: ::uid_t, + pub ex_anon: xucred, + pub ex_addr: *mut ::sockaddr, + pub ex_addrlen: ::c_int, + pub ex_mask: *mut ::sockaddr, + pub ex_masklen: ::c_int, + } } +//https://github.com/openbsd/src/blob/master/sys/sys/mount.h +pub const ISOFSMNT_NORRIP: ::c_int = 0x1; // disable Rock Ridge Ext +pub const ISOFSMNT_GENS: ::c_int = 0x2; // enable generation numbers +pub const ISOFSMNT_EXTATT: ::c_int = 0x4; // enable extended attr +pub const ISOFSMNT_NOJOLIET: ::c_int = 0x8; // disable Joliet Ext +pub const ISOFSMNT_SESS: ::c_int = 0x10; // use iso_args.sess + +pub const NFS_ARGSVERSION: ::c_int = 4; // change when nfs_args changes + +pub const NFSMNT_RESVPORT: ::c_int = 0; // always use reserved ports +pub const NFSMNT_SOFT: ::c_int = 0x1; // soft mount (hard is default) +pub const NFSMNT_WSIZE: ::c_int = 0x2; // set write size +pub const NFSMNT_RSIZE: ::c_int = 0x4; // set read size +pub const NFSMNT_TIMEO: ::c_int = 0x8; // set initial timeout +pub const NFSMNT_RETRANS: ::c_int = 0x10; // set number of request retries +pub const NFSMNT_MAXGRPS: ::c_int = 0x20; // set maximum grouplist size +pub const NFSMNT_INT: ::c_int = 0x40; // allow interrupts on hard mount +pub const NFSMNT_NOCONN: ::c_int = 0x80; // Don't Connect the socket +pub const NFSMNT_NQNFS: ::c_int = 0x100; // Use Nqnfs protocol +pub const NFSMNT_NFSV3: ::c_int = 0x200; // Use NFS Version 3 protocol +pub const NFSMNT_KERB: ::c_int = 0x400; // Use Kerberos authentication +pub const NFSMNT_DUMBTIMR: ::c_int = 0x800; // Don't estimate rtt dynamically +pub const NFSMNT_LEASETERM: ::c_int = 0x1000; // set lease term (nqnfs) +pub const NFSMNT_READAHEAD: ::c_int = 0x2000; // set read ahead +pub const NFSMNT_DEADTHRESH: ::c_int = 0x4000; // set dead server retry thresh +pub const NFSMNT_NOAC: ::c_int = 0x8000; // disable attribute cache +pub const NFSMNT_RDIRPLUS: ::c_int = 0x10000; // Use Readdirplus for V3 +pub const NFSMNT_READDIRSIZE: ::c_int = 0x20000; // Set readdir size + +/* Flags valid only in mount syscall arguments */ +pub const NFSMNT_ACREGMIN: ::c_int = 0x40000; // acregmin field valid +pub const NFSMNT_ACREGMAX: ::c_int = 0x80000; // acregmax field valid +pub const NFSMNT_ACDIRMIN: ::c_int = 0x100000; // acdirmin field valid +pub const NFSMNT_ACDIRMAX: ::c_int = 0x200000; // acdirmax field valid + +/* Flags valid only in kernel */ +pub const NFSMNT_INTERNAL: ::c_int = 0xfffc0000; // Bits set internally +pub const NFSMNT_HASWRITEVERF: ::c_int = 0x40000; // Has write verifier for V3 +pub const NFSMNT_GOTPATHCONF: ::c_int = 0x80000; // Got the V3 pathconf info +pub const NFSMNT_GOTFSINFO: ::c_int = 0x100000; // Got the V3 fsinfo +pub const NFSMNT_MNTD: ::c_int = 0x200000; // Mnt server for mnt point +pub const NFSMNT_DISMINPROG: ::c_int = 0x400000; // Dismount in progress +pub const NFSMNT_DISMNT: ::c_int = 0x800000; // Dismounted +pub const NFSMNT_SNDLOCK: ::c_int = 0x1000000; // Send socket lock +pub const NFSMNT_WANTSND: ::c_int = 0x2000000; // Want above +pub const NFSMNT_RCVLOCK: ::c_int = 0x4000000; // Rcv socket lock +pub const NFSMNT_WANTRCV: ::c_int = 0x8000000; // Want above +pub const NFSMNT_WAITAUTH: ::c_int = 0x10000000; // Wait for authentication +pub const NFSMNT_HASAUTH: ::c_int = 0x20000000; // Has authenticator +pub const NFSMNT_WANTAUTH: ::c_int = 0x40000000; // Wants an authenticator +pub const NFSMNT_AUTHERR: ::c_int = 0x80000000; // Authentication error + +pub const MSDOSFSMNT_SHORTNAME: ::c_int = 0x1; // Force old DOS short names only +pub const MSDOSFSMNT_LONGNAME: ::c_int = 0x2; // Force Win'95 long names +pub const MSDOSFSMNT_NOWIN95: ::c_int = 0x4; // Completely ignore Win95 entries + +pub const NTFS_MFLAG_CASEINS: ::c_int = 0x1; +pub const NTFS_MFLAG_ALLNAMES: ::c_int = 0x2; + +pub const TMPFS_ARGS_VERSION: ::c_int = 1; + pub const MAP_STACK : ::c_int = 0x4000; // https://github.com/openbsd/src/blob/master/sys/net/if.h#L187 @@ -47,7 +246,7 @@ pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast -pub const SIGSTKSZ : ::size_t = 24576; +pub const SIGSTKSZ : ::size_t = 28672; extern { pub fn accept4(s: ::c_int, addr: *mut ::sockaddr, @@ -59,6 +258,9 @@ extern { pub fn strtonum(nptr: *const ::c_char, minval: ::c_longlong, maxval: ::c_longlong, errstr: *mut *const ::c_char) -> ::c_longlong; + + pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; + pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; } cfg_if! { diff --git a/src/liblibc/src/unix/hermit/aarch64.rs b/src/liblibc/src/unix/hermit/aarch64.rs new file mode 100644 index 0000000000..1a92e3b4fa --- /dev/null +++ b/src/liblibc/src/unix/hermit/aarch64.rs @@ -0,0 +1,2 @@ +pub type c_char = u8; +pub type wchar_t = u32; diff --git a/src/liblibc/src/unix/hermit/mod.rs b/src/liblibc/src/unix/hermit/mod.rs new file mode 100644 index 0000000000..bed6f7ae7f --- /dev/null +++ b/src/liblibc/src/unix/hermit/mod.rs @@ -0,0 +1,736 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// liblibc port for HermitCore (https://hermitcore.org) +// HermitCore is a unikernel based on lwIP, newlib, and +// pthread-embedded. +// Consider these definitions when porting liblibc to another +// lwIP/newlib/pte-based target. +// +// Ported by Colin Finck + +pub type c_long = i64; +pub type c_ulong = u64; + +pub type uid_t = u16; +pub type gid_t = u16; +pub type speed_t = ::c_uint; +pub type mode_t = u32; +pub type dev_t = i16; +pub type nfds_t = ::c_ulong; +pub type socklen_t = u32; +pub type sa_family_t = u8; +pub type clock_t = c_ulong; +pub type time_t = c_long; +pub type suseconds_t = c_long; +pub type off_t = i64; +pub type rlim_t = ::c_ulonglong; +pub type sigset_t = ::c_ulong; +pub type ino_t = u16; +pub type nlink_t = u16; +pub type blksize_t = c_long; +pub type blkcnt_t = c_long; +pub type stat64 = stat; +pub type clockid_t = c_ulong; +pub type pthread_t = pte_handle_t; +pub type pthread_attr_t = usize; +pub type pthread_cond_t = usize; +pub type pthread_condattr_t = usize; +pub type pthread_key_t = usize; +pub type pthread_mutex_t = usize; +pub type pthread_mutexattr_t = usize; +pub type pthread_rwlock_t = usize; +pub type pthread_rwlockattr_t = usize; + +s! { + pub struct addrinfo { + pub ai_flags: ::c_int, + pub ai_family: ::c_int, + pub ai_socktype: ::c_int, + pub ai_protocol: ::c_int, + pub ai_addrlen: socklen_t, + pub ai_addr: *mut ::sockaddr, + pub ai_canonname: *mut c_char, + pub ai_next: *mut addrinfo, + } + + pub struct dirent { + pub d_ino: ::c_long, + pub d_off: off_t, + pub d_reclen: u16, + pub d_name: [::c_char; 256], + } + + pub struct Dl_info {} + + pub struct fd_set { + fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE], + } + + pub struct lconv { + pub decimal_point: *mut ::c_char, + pub thousands_sep: *mut ::c_char, + pub grouping: *mut ::c_char, + pub int_curr_symbol: *mut ::c_char, + pub currency_symbol: *mut ::c_char, + pub mon_decimal_point: *mut ::c_char, + pub mon_thousands_sep: *mut ::c_char, + pub mon_grouping: *mut ::c_char, + pub positive_sign: *mut ::c_char, + pub negative_sign: *mut ::c_char, + pub int_frac_digits: ::c_char, + pub frac_digits: ::c_char, + pub p_cs_precedes: ::c_char, + pub p_sep_by_space: ::c_char, + pub n_cs_precedes: ::c_char, + pub n_sep_by_space: ::c_char, + pub p_sign_posn: ::c_char, + pub n_sign_posn: ::c_char, + pub int_p_cs_precedes: ::c_char, + pub int_p_sep_by_space: ::c_char, + pub int_n_cs_precedes: ::c_char, + pub int_n_sep_by_space: ::c_char, + pub int_p_sign_posn: ::c_char, + pub int_n_sign_posn: ::c_char, + } + + pub struct passwd { // Unverified + pub pw_name: *mut ::c_char, + pub pw_passwd: *mut ::c_char, + pub pw_uid: ::uid_t, + pub pw_gid: ::gid_t, + pub pw_gecos: *mut ::c_char, + pub pw_dir: *mut ::c_char, + pub pw_shell: *mut ::c_char, + } + + pub struct pte_handle_t { + pub p: usize, + pub x: ::c_uint, + } + + pub struct sched_param { + pub sched_priority: ::c_int, + } + + pub struct sem_t { + pub value: i32, + pub lock: usize, + pub sem: usize, + } + + pub struct sigaction { + pub sa_flags: ::c_int, + pub sa_mask: sigset_t, + pub sa_handler: usize, + } + + pub struct sockaddr { + pub sa_len: u8, + pub sa_family: sa_family_t, + pub sa_data: [::c_char; 14], + } + + pub struct sockaddr_in { + pub sin_len: u8, + pub sin_family: sa_family_t, + pub sin_port: ::in_port_t, + pub sin_addr: ::in_addr, + pub sin_zero: [::c_char; 8], + } + + pub struct sockaddr_in6 { + pub sin6_len: u8, + pub sin6_family: sa_family_t, + pub sin6_port: ::in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: ::in6_addr, + pub sin6_scope_id: u32, + } + + pub struct sockaddr_storage { + pub s2_len: u8, + pub ss_family: sa_family_t, + pub s2_data1: [::c_char; 2], + pub s2_data2: [u32; 3], + pub s2_data3: [u32; 3], + } + + // Dummy + pub struct sockaddr_un { + pub sun_family: sa_family_t, + pub sun_path: [::c_char; 108], + } + + pub struct stat { + pub st_dev: ::dev_t, + pub st_ino: ::ino_t, + pub st_mode: ::mode_t, + pub st_nlink: ::nlink_t, + pub st_uid: ::uid_t, + pub st_gid: ::gid_t, + pub st_rdev: dev_t, + pub st_size: off_t, + pub st_atime: time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: time_t, + pub st_ctime_nsec: ::c_long, + pub st_blksize: blksize_t, + pub st_blocks: blkcnt_t, + pub st_spare4: [::c_long; 2], + } + + pub struct statvfs {} + + pub struct tm { + pub tm_sec: ::c_int, + pub tm_min: ::c_int, + pub tm_hour: ::c_int, + pub tm_mday: ::c_int, + pub tm_mon: ::c_int, + pub tm_year: ::c_int, + pub tm_wday: ::c_int, + pub tm_yday: ::c_int, + pub tm_isdst: ::c_int, + } + + pub struct tms { + pub tms_utime: ::clock_t, + pub tms_stime: ::clock_t, + pub tms_cutime: ::clock_t, + pub tms_cstime: ::clock_t, + } + + pub struct termios {} + + pub struct utsname {} +} + +pub const AF_UNSPEC: ::c_int = 0; +pub const AF_INET: ::c_int = 2; +pub const AF_INET6: ::c_int = 10; + +// Dummy +pub const AF_UNIX: ::c_int = 1; + +pub const CLOCK_REALTIME: ::clockid_t = 1; +pub const CLOCK_MONOTONIC: ::clockid_t = 4; + +// Dummy +pub const EAI_SYSTEM: ::c_int = -11; + +pub const EPERM: ::c_int = 1; +pub const ENOENT: ::c_int = 2; +pub const ESRCH: ::c_int = 3; +pub const EINTR: ::c_int = 4; +pub const EIO: ::c_int = 5; +pub const ENXIO: ::c_int = 6; +pub const E2BIG: ::c_int = 7; +pub const ENOEXEC: ::c_int = 8; +pub const EBADF: ::c_int = 9; +pub const ECHILD: ::c_int = 10; +pub const EAGAIN: ::c_int = 11; +pub const ENOMEM: ::c_int = 12; +pub const EACCES: ::c_int = 13; +pub const EFAULT: ::c_int = 14; +pub const EBUSY: ::c_int = 16; +pub const EEXIST: ::c_int = 17; +pub const EXDEV: ::c_int = 18; +pub const ENODEV: ::c_int = 19; +pub const ENOTDIR: ::c_int = 20; +pub const EISDIR: ::c_int = 21; +pub const EINVAL: ::c_int = 22; +pub const ENFILE: ::c_int = 23; +pub const EMFILE: ::c_int = 24; +pub const ENOTTY: ::c_int = 25; +pub const ETXTBSY: ::c_int = 26; +pub const EFBIG: ::c_int = 27; +pub const ENOSPC: ::c_int = 28; +pub const ESPIPE: ::c_int = 29; +pub const EROFS: ::c_int = 30; +pub const EMLINK: ::c_int = 31; +pub const EPIPE: ::c_int = 32; +pub const EDOM: ::c_int = 33; +pub const ERANGE: ::c_int = 34; +pub const EDEADLK: ::c_int = 35; +pub const ENAMETOOLONG: ::c_int = 36; +pub const ENOLCK: ::c_int = 37; +pub const ENOSYS: ::c_int = 38; +pub const ENOTEMPTY: ::c_int = 39; +pub const ELOOP: ::c_int = 40; +pub const EWOULDBLOCK: ::c_int = EAGAIN; +pub const ENOMSG: ::c_int = 42; +pub const EIDRM: ::c_int = 43; +pub const ECHRNG: ::c_int = 44; +pub const EL2NSYNC: ::c_int = 45; +pub const EL3HLT: ::c_int = 46; +pub const EL3RST: ::c_int = 47; +pub const ELNRNG: ::c_int = 48; +pub const EUNATCH: ::c_int = 49; +pub const ENOCSI: ::c_int = 50; +pub const EL2HLT: ::c_int = 51; +pub const EBADE: ::c_int = 52; +pub const EBADR: ::c_int = 53; +pub const EXFULL: ::c_int = 54; +pub const ENOANO: ::c_int = 55; +pub const EBADRQC: ::c_int = 56; +pub const EBADSLT: ::c_int = 57; +pub const EDEADLOCK: ::c_int = EDEADLK; +pub const EBFONT: ::c_int = 59; +pub const ENOSTR: ::c_int = 60; +pub const ENODATA: ::c_int = 61; +pub const ETIME: ::c_int = 62; +pub const ENOSR: ::c_int = 63; +pub const ENONET: ::c_int = 64; +pub const ENOPKG: ::c_int = 65; +pub const EREMOTE: ::c_int = 66; +pub const ENOLINK: ::c_int = 67; +pub const EADV: ::c_int = 68; +pub const ESRMNT: ::c_int = 69; +pub const ECOMM: ::c_int = 70; +pub const EPROTO: ::c_int = 71; +pub const EMULTIHOP: ::c_int = 72; +pub const EDOTDOT: ::c_int = 73; +pub const EBADMSG: ::c_int = 74; +pub const EOVERFLOW: ::c_int = 75; +pub const ENOTUNIQ: ::c_int = 76; +pub const EBADFD: ::c_int = 77; +pub const EREMCHG: ::c_int = 78; +pub const ELIBACC: ::c_int = 79; +pub const ELIBBAD: ::c_int = 80; +pub const ELIBSCN: ::c_int = 81; +pub const ELIBMAX: ::c_int = 82; +pub const ELIBEXEC: ::c_int = 83; +pub const EILSEQ: ::c_int = 84; +pub const ERESTART: ::c_int = 85; +pub const ESTRPIPE: ::c_int = 86; +pub const EUSERS: ::c_int = 87; +pub const ENOTSOCK: ::c_int = 88; +pub const EDESTADDRREQ: ::c_int = 89; +pub const EMSGSIZE: ::c_int = 90; +pub const EPROTOTYPE: ::c_int = 91; +pub const ENOPROTOOPT: ::c_int = 92; +pub const EPROTONOSUPPORT: ::c_int = 93; +pub const ESOCKTNOSUPPORT: ::c_int = 94; +pub const EOPNOTSUPP: ::c_int = 95; +pub const EPFNOSUPPORT: ::c_int = 96; +pub const EAFNOSUPPORT: ::c_int = 97; +pub const EADDRINUSE: ::c_int = 98; +pub const EADDRNOTAVAIL: ::c_int = 99; +pub const ENETDOWN: ::c_int = 100; +pub const ENETUNREACH: ::c_int = 101; +pub const ENETRESET: ::c_int = 102; +pub const ECONNABORTED: ::c_int = 103; +pub const ECONNRESET: ::c_int = 104; +pub const ENOBUFS: ::c_int = 105; +pub const EISCONN: ::c_int = 106; +pub const ENOTCONN: ::c_int = 107; +pub const ESHUTDOWN: ::c_int = 108; +pub const ETOOMANYREFS: ::c_int = 109; +pub const ETIMEDOUT: ::c_int = 110; +pub const ECONNREFUSED: ::c_int = 111; +pub const EHOSTDOWN: ::c_int = 112; +pub const EHOSTUNREACH: ::c_int = 113; +pub const EALREADY: ::c_int = 114; +pub const EINPROGRESS: ::c_int = 115; +pub const ESTALE: ::c_int = 116; +pub const EUCLEAN: ::c_int = 117; +pub const ENOTNAM: ::c_int = 118; +pub const ENAVAIL: ::c_int = 119; +pub const EISNAM: ::c_int = 120; +pub const EREMOTEIO: ::c_int = 121; +pub const EDQUOT: ::c_int = 122; +pub const ENOMEDIUM: ::c_int = 123; +pub const EMEDIUMTYPE: ::c_int = 124; +pub const ECANCELED: ::c_int = 125; +pub const ENOKEY: ::c_int = 126; +pub const EKEYEXPIRED: ::c_int = 127; +pub const EKEYREVOKED: ::c_int = 128; +pub const EKEYREJECTED: ::c_int = 129; +pub const EOWNERDEAD: ::c_int = 130; +pub const ENOTRECOVERABLE: ::c_int = 131; +pub const ERFKILL: ::c_int = 132; +pub const EHWPOISON: ::c_int = 133; + +pub const EXIT_FAILURE: ::c_int = 1; +pub const EXIT_SUCCESS: ::c_int = 0; + +pub const F_DUPFD: ::c_int = 0; +pub const F_GETFD: ::c_int = 1; +pub const F_SETFD: ::c_int = 2; +pub const F_GETFL: ::c_int = 3; +pub const F_SETFL: ::c_int = 4; +pub const F_GETOWN: ::c_int = 5; +pub const F_SETOWN: ::c_int = 6; +pub const F_GETLK: ::c_int = 7; +pub const F_SETLK: ::c_int = 8; +pub const F_SETLKW: ::c_int = 9; +pub const F_RGETLK: ::c_int = 10; +pub const F_RSETLK: ::c_int = 11; +pub const F_CNVT: ::c_int = 12; +pub const F_RSETLKW: ::c_int = 13; +pub const F_DUPFD_CLOEXEC: ::c_int = 14; + +pub const FD_SETSIZE: usize = 1024; + +// Dummy +pub const FIOCLEX: ::c_int = 0x5451; + +pub const FIONBIO: ::c_int = 0x8004667e; +pub const FIONREAD: ::c_int = 0x4004667f; + +pub const IP_ADD_MEMBERSHIP: ::c_int = 3; +pub const IP_DROP_MEMBERSHIP: ::c_int = 4; + +pub const IP_TOS: ::c_int = 1; +pub const IP_TTL: ::c_int = 2; + +pub const IP_MULTICAST_TTL: ::c_int = 5; +pub const IP_MULTICAST_IF: ::c_int = 6; +pub const IP_MULTICAST_LOOP: ::c_int = 7; + +pub const IPV6_JOIN_GROUP: ::c_int = 12; +pub const IPV6_ADD_MEMBERSHIP: ::c_int = 12; +pub const IPV6_LEAVE_GROUP: ::c_int = 13; +pub const IPV6_DROP_MEMBERSHIP: ::c_int = 13; +pub const IPV6_V6ONLY: ::c_int = 27; + +// Dummy +pub const IPV6_MULTICAST_LOOP: ::c_int = 7; + +pub const MSG_PEEK: ::c_int = 0x01; +pub const MSG_WAITALL: ::c_int = 0x02; +pub const MSG_OOB: ::c_int = 0x04; +pub const MSG_DONTWAIT: ::c_int = 0x08; +pub const MSG_MORE: ::c_int = 0x10; + +pub const O_ACCMODE: ::c_int = 3; +pub const O_RDONLY: ::c_int = 0; +pub const O_WRONLY: ::c_int = 1; +pub const O_RDWR: ::c_int = 2; +pub const O_APPEND: ::c_int = 1024; +pub const O_CREAT: ::c_int = 64; +pub const O_EXCL: ::c_int = 128; +pub const O_NOCTTY: ::c_int = 256; +pub const O_NONBLOCK: ::c_int = 2048; +pub const O_TRUNC: ::c_int = 512; +pub const O_CLOEXEC: ::c_int = 524288; + +pub const POLLIN: ::c_short = 0x1; +pub const POLLPRI: ::c_short = 0x2; +pub const POLLOUT: ::c_short = 0x4; +pub const POLLERR: ::c_short = 0x8; +pub const POLLHUP: ::c_short = 0x10; +pub const POLLNVAL: ::c_short = 0x20; + +pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = usize::max_value(); +pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = usize::max_value(); +pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = usize::max_value(); + +pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; +pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; +pub const PTHREAD_STACK_MIN: ::size_t = 0; + +// Dummy +pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; + +pub const _SC_ARG_MAX: ::c_int = 0; +pub const _SC_CHILD_MAX: ::c_int = 1; +pub const _SC_CLK_TCK: ::c_int = 2; +pub const _SC_NGROUPS_MAX: ::c_int = 3; +pub const _SC_OPEN_MAX: ::c_int = 4; +pub const _SC_JOB_CONTROL: ::c_int = 5; +pub const _SC_SAVED_IDS: ::c_int = 6; +pub const _SC_VERSION: ::c_int = 7; +pub const _SC_PAGESIZE: ::c_int = 8; +pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; +pub const _SC_NPROCESSORS_CONF: ::c_int = 9; +pub const _SC_NPROCESSORS_ONLN: ::c_int = 10; +pub const _SC_PHYS_PAGES: ::c_int = 11; +pub const _SC_AVPHYS_PAGES: ::c_int = 12; +pub const _SC_MQ_OPEN_MAX: ::c_int = 13; +pub const _SC_MQ_PRIO_MAX: ::c_int = 14; +pub const _SC_RTSIG_MAX: ::c_int = 15; +pub const _SC_SEM_NSEMS_MAX: ::c_int = 16; +pub const _SC_SEM_VALUE_MAX: ::c_int = 17; +pub const _SC_SIGQUEUE_MAX: ::c_int = 18; +pub const _SC_TIMER_MAX: ::c_int = 19; +pub const _SC_TZNAME_MAX: ::c_int = 20; +pub const _SC_ASYNCHRONOUS_IO: ::c_int = 21; +pub const _SC_FSYNC: ::c_int = 22; +pub const _SC_MAPPED_FILES: ::c_int = 23; +pub const _SC_MEMLOCK: ::c_int = 24; +pub const _SC_MEMLOCK_RANGE: ::c_int = 25; +pub const _SC_MEMORY_PROTECTION: ::c_int = 26; +pub const _SC_MESSAGE_PASSING: ::c_int = 27; +pub const _SC_PRIORITIZED_IO: ::c_int = 28; +pub const _SC_REALTIME_SIGNALS: ::c_int = 29; +pub const _SC_SEMAPHORES: ::c_int = 30; +pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 31; +pub const _SC_SYNCHRONIZED_IO: ::c_int = 32; +pub const _SC_TIMERS: ::c_int = 33; +pub const _SC_AIO_LISTIO_MAX: ::c_int = 34; +pub const _SC_AIO_MAX: ::c_int = 35; +pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 36; +pub const _SC_DELAYTIMER_MAX: ::c_int = 37; +pub const _SC_THREAD_KEYS_MAX: ::c_int = 38; +pub const _SC_THREAD_STACK_MIN: ::c_int = 39; +pub const _SC_THREAD_THREADS_MAX: ::c_int = 40; +pub const _SC_TTY_NAME_MAX: ::c_int = 41; +pub const _SC_THREADS: ::c_int = 42; +pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 43; +pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 44; +pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 45; +pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 46; +pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 47; +pub const _SC_THREAD_PRIO_CEILING: ::c_int = _SC_THREAD_PRIO_PROTECT; +pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 48; +pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 49; +pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 50; +pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51; +pub const _SC_LOGIN_NAME_MAX: ::c_int = 52; +pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 53; +pub const _SC_ADVISORY_INFO: ::c_int = 54; +pub const _SC_ATEXIT_MAX: ::c_int = 55; +pub const _SC_BARRIERS: ::c_int = 56; +pub const _SC_BC_BASE_MAX: ::c_int = 57; +pub const _SC_BC_DIM_MAX: ::c_int = 58; +pub const _SC_BC_SCALE_MAX: ::c_int = 59; +pub const _SC_BC_STRING_MAX: ::c_int = 60; +pub const _SC_CLOCK_SELECTION: ::c_int = 61; +pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 62; +pub const _SC_CPUTIME: ::c_int = 63; +pub const _SC_EXPR_NEST_MAX: ::c_int = 64; +pub const _SC_HOST_NAME_MAX: ::c_int = 65; +pub const _SC_IOV_MAX: ::c_int = 66; +pub const _SC_IPV6: ::c_int = 67; +pub const _SC_LINE_MAX: ::c_int = 68; +pub const _SC_MONOTONIC_CLOCK: ::c_int = 69; +pub const _SC_RAW_SOCKETS: ::c_int = 70; +pub const _SC_READER_WRITER_LOCKS: ::c_int = 71; +pub const _SC_REGEXP: ::c_int = 72; +pub const _SC_RE_DUP_MAX: ::c_int = 73; +pub const _SC_SHELL: ::c_int = 74; +pub const _SC_SPAWN: ::c_int = 75; +pub const _SC_SPIN_LOCKS: ::c_int = 76; +pub const _SC_SPORADIC_SERVER: ::c_int = 77; +pub const _SC_SS_REPL_MAX: ::c_int = 78; +pub const _SC_SYMLOOP_MAX: ::c_int = 79; +pub const _SC_THREAD_CPUTIME: ::c_int = 80; +pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 81; +pub const _SC_TIMEOUTS: ::c_int = 82; +pub const _SC_TRACE: ::c_int = 83; +pub const _SC_TRACE_EVENT_FILTER: ::c_int = 84; +pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 85; +pub const _SC_TRACE_INHERIT: ::c_int = 86; +pub const _SC_TRACE_LOG: ::c_int = 87; +pub const _SC_TRACE_NAME_MAX: ::c_int = 88; +pub const _SC_TRACE_SYS_MAX: ::c_int = 89; +pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 90; +pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 91; +pub const _SC_V7_ILP32_OFF32: ::c_int = 92; +pub const _SC_V6_ILP32_OFF32: ::c_int =_SC_V7_ILP32_OFF32; +pub const _SC_XBS5_ILP32_OFF32: ::c_int = _SC_V7_ILP32_OFF32; +pub const _SC_V7_ILP32_OFFBIG: ::c_int = 93; +pub const _SC_V6_ILP32_OFFBIG: ::c_int = _SC_V7_ILP32_OFFBIG; +pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = _SC_V7_ILP32_OFFBIG; +pub const _SC_V7_LP64_OFF64: ::c_int = 94; +pub const _SC_V6_LP64_OFF64: ::c_int = _SC_V7_LP64_OFF64; +pub const _SC_XBS5_LP64_OFF64: ::c_int = _SC_V7_LP64_OFF64; +pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 95; +pub const _SC_V6_LPBIG_OFFBIG: ::c_int = _SC_V7_LPBIG_OFFBIG; +pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = _SC_V7_LPBIG_OFFBIG; +pub const _SC_XOPEN_CRYPT: ::c_int = 96; +pub const _SC_XOPEN_ENH_I18N: ::c_int = 97; +pub const _SC_XOPEN_LEGACY: ::c_int = 98; +pub const _SC_XOPEN_REALTIME: ::c_int = 99; +pub const _SC_STREAM_MAX: ::c_int = 100; +pub const _SC_PRIORITY_SCHEDULING: ::c_int = 101; +pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 102; +pub const _SC_XOPEN_SHM: ::c_int = 103; +pub const _SC_XOPEN_STREAMS: ::c_int = 104; +pub const _SC_XOPEN_UNIX: ::c_int = 105; +pub const _SC_XOPEN_VERSION: ::c_int = 106; +pub const _SC_2_CHAR_TERM: ::c_int = 107; +pub const _SC_2_C_BIND: ::c_int = 108; +pub const _SC_2_C_DEV: ::c_int = 109; +pub const _SC_2_FORT_DEV: ::c_int = 110; +pub const _SC_2_FORT_RUN: ::c_int = 111; +pub const _SC_2_LOCALEDEF: ::c_int = 112; +pub const _SC_2_PBS: ::c_int = 113; +pub const _SC_2_PBS_ACCOUNTING: ::c_int = 114; +pub const _SC_2_PBS_CHECKPOINT: ::c_int = 115; +pub const _SC_2_PBS_LOCATE: ::c_int = 116; +pub const _SC_2_PBS_MESSAGE: ::c_int = 117; +pub const _SC_2_PBS_TRACK: ::c_int = 118; +pub const _SC_2_SW_DEV: ::c_int = 119; +pub const _SC_2_UPE: ::c_int = 120; +pub const _SC_2_VERSION: ::c_int = 121; +pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 122; +pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 123; +pub const _SC_XOPEN_UUCP: ::c_int = 124; +pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 125; +pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 126; +pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 127; +pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 128; +pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 129; +pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 130; +pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 131; +pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 132; +pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 133; +pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 134; +pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 135; +pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 136; +pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 137; +pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 138; +pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 139; + +pub const S_BLKSIZE: ::mode_t = 1024; +pub const S_IREAD: ::mode_t = 256; +pub const S_IWRITE: ::mode_t = 128; +pub const S_IEXEC: ::mode_t = 64; +pub const S_ENFMT: ::mode_t = 1024; +pub const S_IFMT: ::mode_t = 61440; +pub const S_IFDIR: ::mode_t = 16384; +pub const S_IFCHR: ::mode_t = 8192; +pub const S_IFBLK: ::mode_t = 24576; +pub const S_IFREG: ::mode_t = 32768; +pub const S_IFLNK: ::mode_t = 40960; +pub const S_IFSOCK: ::mode_t = 49152; +pub const S_IFIFO: ::mode_t = 4096; +pub const S_IRUSR: ::mode_t = 256; +pub const S_IWUSR: ::mode_t = 128; +pub const S_IXUSR: ::mode_t = 64; +pub const S_IRGRP: ::mode_t = 32; +pub const S_IWGRP: ::mode_t = 16; +pub const S_IXGRP: ::mode_t = 8; +pub const S_IROTH: ::mode_t = 4; +pub const S_IWOTH: ::mode_t = 2; +pub const S_IXOTH: ::mode_t = 1; + +pub const SEEK_SET: ::c_int = 0; +pub const SEEK_CUR: ::c_int = 1; +pub const SEEK_END: ::c_int = 2; + +pub const SHUT_RD: ::c_int = 0; +pub const SHUT_WR: ::c_int = 1; +pub const SHUT_RDWR: ::c_int = 2; + +pub const SIG_SETMASK: ::c_int = 0; + +pub const SIGHUP: ::c_int = 1; +pub const SIGINT: ::c_int = 2; +pub const SIGQUIT: ::c_int = 3; +pub const SIGILL: ::c_int = 4; +pub const SIGABRT: ::c_int = 6; +pub const SIGEMT: ::c_int = 7; +pub const SIGFPE: ::c_int = 8; +pub const SIGKILL: ::c_int = 9; +pub const SIGSEGV: ::c_int = 11; +pub const SIGPIPE: ::c_int = 13; +pub const SIGALRM: ::c_int = 14; +pub const SIGTERM: ::c_int = 15; + +pub const SO_DEBUG: ::c_int = 0x0001; +pub const SO_ACCEPTCONN: ::c_int = 0x0002; +pub const SO_REUSEADDR: ::c_int = 0x0004; +pub const SO_KEEPALIVE: ::c_int = 0x0008; +pub const SO_DONTROUTE: ::c_int = 0x0010; +pub const SO_BROADCAST: ::c_int = 0x0020; +pub const SO_USELOOPBACK: ::c_int = 0x0040; +pub const SO_LINGER: ::c_int = 0x0080; +pub const SO_OOBINLINE: ::c_int = 0x0100; +pub const SO_REUSEPORT: ::c_int = 0x0200; +pub const SO_SNDBUF: ::c_int = 0x1001; +pub const SO_RCVBUF: ::c_int = 0x1002; +pub const SO_SNDLOWAT: ::c_int = 0x1003; +pub const SO_RCVLOWAT: ::c_int = 0x1004; +pub const SO_SNDTIMEO: ::c_int = 0x1005; +pub const SO_RCVTIMEO: ::c_int = 0x1006; +pub const SO_ERROR: ::c_int = 0x1007; +pub const SO_TYPE: ::c_int = 0x1008; +pub const SO_CONTIMEO: ::c_int = 0x1009; +pub const SO_NO_CHECK: ::c_int = 0x100a; + +pub const SOCK_STREAM: ::c_int = 1; +pub const SOCK_DGRAM: ::c_int = 2; +pub const SOCK_RAW: ::c_int = 3; + +pub const SOL_SOCKET: ::c_int = 0xfff; + +pub const STDIN_FILENO: ::c_int = 0; +pub const STDOUT_FILENO: ::c_int = 1; +pub const STDERR_FILENO: ::c_int = 2; + +pub const TCP_NODELAY: ::c_int = 0x01; +pub const TCP_KEEPALIVE: ::c_int = 0x02; +pub const TCP_KEEPIDLE: ::c_int = 0x03; +pub const TCP_KEEPINTVL: ::c_int = 0x04; +pub const TCP_KEEPCNT: ::c_int = 0x05; + +const ULONG_SIZE: usize = 64; + +pub const WNOHANG: ::c_int = 0x00000001; + +f! { + pub fn WEXITSTATUS(status: ::c_int) -> ::c_int { + (status >> 8) & 0xff + } + + pub fn WIFEXITED(status: ::c_int) -> bool { + (status & 0xff) == 0 + } + + pub fn WTERMSIG(status: ::c_int) -> ::c_int { + status & 0x7f + } +} + +extern { + pub fn bind(s: ::c_int, name: *const ::sockaddr, namelen: ::socklen_t) + -> ::c_int; + + pub fn clock_gettime(clock_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; + + pub fn getpwuid_r(uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, + buflen: ::size_t, result: *mut *mut passwd) -> ::c_int; + + // Dummy + pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; + + pub fn memalign(align: ::size_t, nbytes: ::size_t) -> *mut ::c_void; + + pub fn pthread_create(tid: *mut ::pthread_t, attr: *const ::pthread_attr_t, + start: extern fn(*mut ::c_void) -> *mut ::c_void, arg: *mut ::c_void) + -> ::c_int; + + pub fn pthread_sigmask(how: ::c_int, set: *const ::sigset_t, + oset: *mut ::sigset_t) -> ::c_int; + + pub fn recvfrom(s: ::c_int, mem: *mut ::c_void, len: ::size_t, + flags: ::c_int, from: *mut ::sockaddr, fromlen: *mut ::socklen_t) + -> ::c_int; + + pub fn setgroups(ngroups: ::c_int, grouplist: *const ::gid_t) -> ::c_int; +} + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + pub use self::aarch64::*; + } else if #[cfg(target_arch = "x86_64")] { + mod x86_64; + pub use self::x86_64::*; + } else { + // Unknown target_arch + } +} diff --git a/src/liblibc/src/unix/hermit/x86_64.rs b/src/liblibc/src/unix/hermit/x86_64.rs new file mode 100644 index 0000000000..76ec3ce823 --- /dev/null +++ b/src/liblibc/src/unix/hermit/x86_64.rs @@ -0,0 +1,2 @@ +pub type c_char = i8; +pub type wchar_t = i32; diff --git a/src/liblibc/src/unix/mod.rs b/src/liblibc/src/unix/mod.rs index 15c7821fa1..9c68178ad1 100644 --- a/src/liblibc/src/unix/mod.rs +++ b/src/liblibc/src/unix/mod.rs @@ -104,8 +104,10 @@ s! { pub s_addr: in_addr_t, } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct in6_addr { pub s6_addr: [u8; 16], + #[cfg(not(feature = "align"))] __align: [u32; 0], } @@ -294,11 +296,11 @@ cfg_if! { } else if #[cfg(target_os = "emscripten")] { #[link(name = "c")] extern {} - } else if #[cfg(all(target_os = "netbsd"))] { + } else if #[cfg(all(target_os = "netbsd", + feature = "stdbuild", target_vendor = "rumprun"))] { // Since we don't use -nodefaultlibs on Rumprun, libc is always pulled // in automatically by the linker. We avoid passing it explicitly, as it // causes some versions of binutils to crash with an assertion failure. - #[cfg_attr(feature = "stdbuild", target_vendor = "rumprun")] #[link(name = "m")] extern {} } else if #[cfg(any(target_os = "macos", @@ -321,6 +323,11 @@ cfg_if! { #[link(name = "c")] #[link(name = "m")] extern {} + } else if #[cfg(target_os = "hermit")] { + // no_default_libraries is set to false for HermitCore, so only a link + // to "pthread" needs to be added. + #[link(name = "pthread")] + extern {} } else { #[link(name = "c")] #[link(name = "m")] @@ -929,6 +936,7 @@ extern { pub fn openlog(ident: *const ::c_char, logopt: ::c_int, facility: ::c_int); pub fn closelog(); pub fn setlogmask(maskpri: ::c_int) -> ::c_int; + #[cfg_attr(target_os = "macos", link_name = "syslog$DARWIN_EXTSN")] pub fn syslog(priority: ::c_int, message: *const ::c_char, ...); #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "nice$UNIX2003")] @@ -968,6 +976,9 @@ cfg_if! { } else if #[cfg(target_os = "haiku")] { mod haiku; pub use self::haiku::*; + } else if #[cfg(target_os = "hermit")] { + mod hermit; + pub use self::hermit::*; } else { // Unknown target_os } diff --git a/src/liblibc/src/unix/newlib/mod.rs b/src/liblibc/src/unix/newlib/mod.rs index 6cf8633e6b..9968d36685 100644 --- a/src/liblibc/src/unix/newlib/mod.rs +++ b/src/liblibc/src/unix/newlib/mod.rs @@ -238,34 +238,80 @@ s! { __size: [u64; 7] } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))), + repr(align(8)))] pub struct pthread_mutex_t { // Unverified - #[cfg(any(target_arch = "mips", target_arch = "arm", - target_arch = "powerpc"))] + #[cfg(all(not(feature = "align"), + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", target_arch = "arm", + #[cfg(not(any(feature = "align", + target_arch = "mips", + target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))), + repr(align(8)))] pub struct pthread_rwlock_t { // Unverified - #[cfg(any(target_arch = "mips", target_arch = "arm", - target_arch = "powerpc"))] + #[cfg(all(not(feature = "align"), + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", target_arch = "arm", + #[cfg(not(any(feature = "align", + target_arch = "mips", + target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], } + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "32", + target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(any(target_pointer_width = "32", + target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))), + repr(align(8)))] pub struct pthread_mutexattr_t { // Unverified - #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", - target_arch = "mips64", target_arch = "s390x", - target_arch = "sparc64"))] - __align: [::c_int; 0], - #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + #[cfg(all(not(feature = "align"), + any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64")))] + __align: [::c_int; 0], + #[cfg(all(not(feature = "align"), + not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))))] __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } @@ -275,12 +321,16 @@ s! { __pshared: ::c_int, } + #[cfg_attr(feature = "align", repr(align(8)))] pub struct pthread_cond_t { // Unverified + #[cfg(not(feature = "align"))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_COND_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_condattr_t { // Unverified + #[cfg(not(feature = "align"))] __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], } @@ -288,18 +338,17 @@ s! { } // unverified constants -pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_MUTEX_T], -}; -pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_COND_T], -}; -pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_RWLOCK_T], -}; +align_const! { + pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + size: [0; __SIZEOF_PTHREAD_MUTEX_T], + }; + pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + size: [0; __SIZEOF_PTHREAD_COND_T], + }; + pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], + }; +} pub const NCCS: usize = 32; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 56; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; diff --git a/src/liblibc/src/unix/notbsd/android/mod.rs b/src/liblibc/src/unix/notbsd/android/mod.rs index 53f957d3e8..3e10acd505 100644 --- a/src/liblibc/src/unix/notbsd/android/mod.rs +++ b/src/liblibc/src/unix/notbsd/android/mod.rs @@ -1458,6 +1458,13 @@ pub const SIOCSRARP: ::c_ulong = 0x00008962; pub const SIOCGIFMAP: ::c_ulong = 0x00008970; pub const SIOCSIFMAP: ::c_ulong = 0x00008971; +// linux/module.h +pub const MODULE_INIT_IGNORE_MODVERSIONS: ::c_uint = 0x0001; +pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002; + +// Similarity to Linux it's not used but defined for compatibility. +pub const ENOATTR: ::c_int = ::ENODATA; + f! { pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.__bits.iter_mut() { diff --git a/src/liblibc/src/unix/notbsd/emscripten.rs b/src/liblibc/src/unix/notbsd/emscripten.rs index 6216947ee5..b30fee3232 100644 --- a/src/liblibc/src/unix/notbsd/emscripten.rs +++ b/src/liblibc/src/unix/notbsd/emscripten.rs @@ -72,32 +72,47 @@ s! { __unused5: *mut ::c_void, } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_mutex_t { + #[cfg(not(feature = "align"))] __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_rwlock_t { + #[cfg(not(feature = "align"))] __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_mutexattr_t { + #[cfg(not(feature = "align"))] __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_rwlockattr_t { + #[cfg(not(feature = "align"))] __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T], } + #[cfg_attr(all(feature = "align", target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", target_pointer_width = "64"), + repr(align(8)))] pub struct pthread_cond_t { + #[cfg(not(feature = "align"))] __align: [*const ::c_void; 0], size: [u8; __SIZEOF_PTHREAD_COND_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_condattr_t { + #[cfg(not(feature = "align"))] __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], } @@ -747,18 +762,18 @@ pub const RTLD_NOW: ::c_int = 0x2; pub const TCP_MD5SIG: ::c_int = 14; -pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_MUTEX_T], -}; -pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_COND_T], -}; -pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_RWLOCK_T], -}; +align_const! { + pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + size: [0; __SIZEOF_PTHREAD_MUTEX_T], + }; + pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + size: [0; __SIZEOF_PTHREAD_COND_T], + }; + pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], + }; +} + pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs b/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs index d9d5035bf2..a6c08a5ad7 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs @@ -1,3 +1,5 @@ +use pthread_mutex_t; + pub type c_char = i8; pub type c_long = i32; pub type c_ulong = u32; @@ -278,60 +280,56 @@ pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; -#[cfg(target_endian = "little")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; +align_const! { + #[cfg(target_endian = "little")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; +} pub const O_LARGEFILE: ::c_int = 0x2000; diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs b/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs index 747b97bd0b..e8b02a36b0 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs @@ -1,3 +1,5 @@ +use pthread_mutex_t; + pub type blkcnt_t = i64; pub type blksize_t = i64; pub type c_char = i8; @@ -262,60 +264,56 @@ pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; -#[cfg(target_endian = "little")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; +align_const! { + #[cfg(target_endian = "little")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; +} pub const O_LARGEFILE: ::c_int = 0; diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mod.rs b/src/liblibc/src/unix/notbsd/linux/mips/mod.rs index 833a3210cc..4c14d12ebc 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mod.rs @@ -21,11 +21,16 @@ s! { } // FIXME this is actually a union + #[cfg_attr(all(feature = "align", target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", target_pointer_width = "64"), + repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], + #[cfg(not(feature = "align"))] __align: [::c_long; 0], } diff --git a/src/liblibc/src/unix/notbsd/linux/mod.rs b/src/liblibc/src/unix/notbsd/linux/mod.rs index fdd26f8409..6bc7db191c 100644 --- a/src/liblibc/src/unix/notbsd/linux/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/mod.rs @@ -71,14 +71,32 @@ s! { __unused5: *mut ::c_void, } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "x86_64", + target_arch = "x86")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "x86_64", + target_arch = "x86")))), + repr(align(8)))] pub struct pthread_mutex_t { - #[cfg(any(target_arch = "mips", - target_arch = "arm", - target_arch = "powerpc", - all(target_arch = "x86_64", - target_pointer_width = "32")))] + #[cfg(all(not(feature = "align"), + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc", + all(target_arch = "x86_64", + target_pointer_width = "32"))))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", + #[cfg(not(any(feature = "align", + target_arch = "mips", target_arch = "arm", target_arch = "powerpc", all(target_arch = "x86_64", @@ -87,14 +105,32 @@ s! { size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "x86_64", + target_arch = "x86")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "x86_64", + target_arch = "x86")))), + repr(align(8)))] pub struct pthread_rwlock_t { - #[cfg(any(target_arch = "mips", - target_arch = "arm", - target_arch = "powerpc", - all(target_arch = "x86_64", - target_pointer_width = "32")))] + #[cfg(all(not(feature = "align"), + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc", + all(target_arch = "x86_64", + target_pointer_width = "32"))))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", + #[cfg(not(any(feature = "align", + target_arch = "mips", target_arch = "arm", target_arch = "powerpc", all(target_arch = "x86_64", @@ -103,39 +139,78 @@ s! { size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], } + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "32", + target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64", + all(target_arch = "aarch64", target_env = "musl"))), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(any(target_pointer_width = "32", + target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64", + all(target_arch = "aarch64", target_env = "musl")))), + repr(align(8)))] pub struct pthread_mutexattr_t { - #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", - target_arch = "mips64", target_arch = "s390x", - target_arch = "sparc64"))] - __align: [::c_int; 0], - #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + #[cfg(all(not(features = "align"), + any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", - target_arch = "sparc64", target_arch = "aarch64")))] - __align: [::c_long; 0], - #[cfg(all(target_arch = "aarch64", target_env = "gnu"))] - __align: [::c_long; 0], - #[cfg(all(target_arch = "aarch64", target_env = "musl"))] + target_arch = "sparc64", + all(target_arch = "aarch64", target_env = "musl"))))] __align: [::c_int; 0], + #[cfg(all(not(features = "align"), + not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64", + all(target_arch = "aarch64", target_env = "musl")))))] + __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } + #[cfg_attr(all(feature = "align", + any(target_env = "musl", target_pointer_width = "32")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(target_env = "musl"), + target_pointer_width = "64"), + repr(align(8)))] pub struct pthread_rwlockattr_t { - #[cfg(any(target_env = "musl"))] + #[cfg(all(not(feature = "align"), target_env = "musl"))] __align: [::c_int; 0], - #[cfg(not(any(target_env = "musl")))] + #[cfg(all(not(feature = "align"), not(target_env = "musl")))] __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T], } + #[cfg_attr(all(feature = "align", + target_env = "musl", + target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + target_env = "musl", + target_pointer_width = "64"), + repr(align(8)))] + #[cfg_attr(all(feature = "align", + not(target_env = "musl"), + target_arch = "x86"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(target_env = "musl"), + not(target_arch = "x86")), + repr(align(8)))] pub struct pthread_cond_t { - #[cfg(any(target_env = "musl"))] + #[cfg(all(not(feature = "align"), target_env = "musl"))] __align: [*const ::c_void; 0], - #[cfg(not(any(target_env = "musl")))] + #[cfg(not(any(feature = "align", target_env = "musl")))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_COND_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_condattr_t { + #[cfg(not(feature = "align"))] __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], } @@ -229,6 +304,13 @@ s! { pad: [::c_long; 4], } + pub struct packet_mreq { + pub mr_ifindex: ::c_int, + pub mr_type: ::c_ushort, + pub mr_alen: ::c_ushort, + pub mr_address: [::c_uchar; 8], + } + pub struct cpu_set_t { #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] @@ -785,18 +867,17 @@ pub const RTLD_NOW: ::c_int = 0x2; pub const TCP_MD5SIG: ::c_int = 14; -pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_MUTEX_T], -}; -pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_COND_T], -}; -pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_RWLOCK_T], -}; +align_const! { + pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + size: [0; __SIZEOF_PTHREAD_MUTEX_T], + }; + pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + size: [0; __SIZEOF_PTHREAD_COND_T], + }; + pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], + }; +} pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; @@ -1300,6 +1381,15 @@ pub const CTRL_ATTR_MCAST_GRP_UNSPEC: ::c_int = 0; pub const CTRL_ATTR_MCAST_GRP_NAME: ::c_int = 1; pub const CTRL_ATTR_MCAST_GRP_ID: ::c_int = 2; +// linux/if_packet.h +pub const PACKET_ADD_MEMBERSHIP: ::c_int = 1; +pub const PACKET_DROP_MEMBERSHIP: ::c_int = 2; + +pub const PACKET_MR_MULTICAST: ::c_int = 0; +pub const PACKET_MR_PROMISC: ::c_int = 1; +pub const PACKET_MR_ALLMULTI: ::c_int = 2; +pub const PACKET_MR_UNICAST: ::c_int = 3; + // linux/netfilter.h pub const NF_DROP: ::c_int = 0; pub const NF_ACCEPT: ::c_int = 1; @@ -1482,6 +1572,10 @@ pub const ARPD_LOOKUP: ::c_ushort = 0x02; pub const ARPD_FLUSH: ::c_ushort = 0x03; pub const ATF_MAGIC: ::c_int = 0x80; +// linux/module.h +pub const MODULE_INIT_IGNORE_MODVERSIONS: ::c_uint = 0x0001; +pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002; + f! { pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { diff --git a/src/liblibc/src/unix/notbsd/linux/musl/b32/arm.rs b/src/liblibc/src/unix/notbsd/linux/musl/b32/arm.rs index 22bf16c1fd..20fa33a3f7 100644 --- a/src/liblibc/src/unix/notbsd/linux/musl/b32/arm.rs +++ b/src/liblibc/src/unix/notbsd/linux/musl/b32/arm.rs @@ -52,6 +52,18 @@ s! { pub ss_size: ::size_t } + pub struct ipc_perm { + pub __ipc_perm_key: ::key_t, + pub uid: ::uid_t, + pub gid: ::gid_t, + pub cuid: ::uid_t, + pub cgid: ::gid_t, + pub mode: ::mode_t, + pub __seq: ::c_int, + __unused1: ::c_long, + __unused2: ::c_long + } + pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, @@ -151,6 +163,9 @@ s! { } } +pub const SIGSTKSZ: ::size_t = 8192; +pub const MINSIGSTKSZ: ::size_t = 2048; + pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; @@ -165,6 +180,76 @@ pub const RLIMIT_NOFILE: ::c_int = 7; pub const RLIMIT_AS: ::c_int = 9; pub const RLIMIT_NPROC: ::c_int = 6; pub const RLIMIT_MEMLOCK: ::c_int = 8; +pub const RLIMIT_NLIMITS: ::c_int = 16; + +pub const MCL_CURRENT: ::c_int = 0x0001; +pub const MCL_FUTURE: ::c_int = 0x0002; +pub const CBAUD: ::tcflag_t = 0o0010017; +pub const TAB1: ::c_int = 0x00000800; +pub const TAB2: ::c_int = 0x00001000; +pub const TAB3: ::c_int = 0x00001800; +pub const CR1: ::c_int = 0x00000200; +pub const CR2: ::c_int = 0x00000400; +pub const CR3: ::c_int = 0x00000600; +pub const FF1: ::c_int = 0x00008000; +pub const BS1: ::c_int = 0x00002000; +pub const VT1: ::c_int = 0x00004000; +pub const VWERASE: usize = 14; +pub const VREPRINT: usize = 12; +pub const VSUSP: usize = 10; +pub const VSTART: usize = 8; +pub const VSTOP: usize = 9; +pub const VDISCARD: usize = 13; +pub const VTIME: usize = 5; +pub const IXON: ::tcflag_t = 0x00000400; +pub const IXOFF: ::tcflag_t = 0x00001000; +pub const ONLCR: ::tcflag_t = 0x4; +pub const CSIZE: ::tcflag_t = 0x00000030; +pub const CS6: ::tcflag_t = 0x00000010; +pub const CS7: ::tcflag_t = 0x00000020; +pub const CS8: ::tcflag_t = 0x00000030; +pub const CSTOPB: ::tcflag_t = 0x00000040; +pub const CREAD: ::tcflag_t = 0x00000080; +pub const PARENB: ::tcflag_t = 0x00000100; +pub const PARODD: ::tcflag_t = 0x00000200; +pub const HUPCL: ::tcflag_t = 0x00000400; +pub const CLOCAL: ::tcflag_t = 0x00000800; +pub const ECHOKE: ::tcflag_t = 0x00000800; +pub const ECHOE: ::tcflag_t = 0x00000010; +pub const ECHOK: ::tcflag_t = 0x00000020; +pub const ECHONL: ::tcflag_t = 0x00000040; +pub const ECHOPRT: ::tcflag_t = 0x00000400; +pub const ECHOCTL: ::tcflag_t = 0x00000200; +pub const ISIG: ::tcflag_t = 0x00000001; +pub const ICANON: ::tcflag_t = 0x00000002; +pub const PENDIN: ::tcflag_t = 0x00004000; +pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; +pub const B57600: ::speed_t = 0o010001; +pub const B115200: ::speed_t = 0o010002; +pub const B230400: ::speed_t = 0o010003; +pub const B460800: ::speed_t = 0o010004; +pub const B500000: ::speed_t = 0o010005; +pub const B576000: ::speed_t = 0o010006; +pub const B921600: ::speed_t = 0o010007; +pub const B1000000: ::speed_t = 0o010010; +pub const B1152000: ::speed_t = 0o010011; +pub const B1500000: ::speed_t = 0o010012; +pub const B2000000: ::speed_t = 0o010013; +pub const B2500000: ::speed_t = 0o010014; +pub const B3000000: ::speed_t = 0o010015; +pub const B3500000: ::speed_t = 0o010016; +pub const B4000000: ::speed_t = 0o010017; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; diff --git a/src/liblibc/src/unix/notbsd/linux/musl/b32/mips.rs b/src/liblibc/src/unix/notbsd/linux/musl/b32/mips.rs index 89231a0c75..bfde73c563 100644 --- a/src/liblibc/src/unix/notbsd/linux/musl/b32/mips.rs +++ b/src/liblibc/src/unix/notbsd/linux/musl/b32/mips.rs @@ -54,6 +54,18 @@ s! { pub ss_flags: ::c_int, } + pub struct ipc_perm { + pub __ipc_perm_key: ::key_t, + pub uid: ::uid_t, + pub gid: ::gid_t, + pub cuid: ::uid_t, + pub cgid: ::gid_t, + pub mode: ::mode_t, + pub __seq: ::c_int, + __unused1: ::c_long, + __unused2: ::c_long + } + pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, @@ -162,6 +174,9 @@ s! { } } +pub const SIGSTKSZ: ::size_t = 8192; +pub const MINSIGSTKSZ: ::size_t = 2048; + pub const O_DIRECT: ::c_int = 0o100000; pub const O_DIRECTORY: ::c_int = 0o200000; pub const O_NOFOLLOW: ::c_int = 0o400000; @@ -176,6 +191,76 @@ pub const RLIMIT_NOFILE: ::c_int = 5; pub const RLIMIT_AS: ::c_int = 6; pub const RLIMIT_NPROC: ::c_int = 8; pub const RLIMIT_MEMLOCK: ::c_int = 9; +pub const RLIMIT_NLIMITS: ::c_int = 16; + +pub const MCL_CURRENT: ::c_int = 0x0001; +pub const MCL_FUTURE: ::c_int = 0x0002; +pub const CBAUD: ::tcflag_t = 0o0010017; +pub const TAB1: ::c_int = 0x00000800; +pub const TAB2: ::c_int = 0x00001000; +pub const TAB3: ::c_int = 0x00001800; +pub const CR1: ::c_int = 0x00000200; +pub const CR2: ::c_int = 0x00000400; +pub const CR3: ::c_int = 0x00000600; +pub const FF1: ::c_int = 0x00008000; +pub const BS1: ::c_int = 0x00002000; +pub const VT1: ::c_int = 0x00004000; +pub const VWERASE: usize = 14; +pub const VREPRINT: usize = 12; +pub const VSUSP: usize = 10; +pub const VSTART: usize = 8; +pub const VSTOP: usize = 9; +pub const VDISCARD: usize = 13; +pub const VTIME: usize = 5; +pub const IXON: ::tcflag_t = 0x00000400; +pub const IXOFF: ::tcflag_t = 0x00001000; +pub const ONLCR: ::tcflag_t = 0x4; +pub const CSIZE: ::tcflag_t = 0x00000030; +pub const CS6: ::tcflag_t = 0x00000010; +pub const CS7: ::tcflag_t = 0x00000020; +pub const CS8: ::tcflag_t = 0x00000030; +pub const CSTOPB: ::tcflag_t = 0x00000040; +pub const CREAD: ::tcflag_t = 0x00000080; +pub const PARENB: ::tcflag_t = 0x00000100; +pub const PARODD: ::tcflag_t = 0x00000200; +pub const HUPCL: ::tcflag_t = 0x00000400; +pub const CLOCAL: ::tcflag_t = 0x00000800; +pub const ECHOKE: ::tcflag_t = 0x00000800; +pub const ECHOE: ::tcflag_t = 0x00000010; +pub const ECHOK: ::tcflag_t = 0x00000020; +pub const ECHONL: ::tcflag_t = 0x00000040; +pub const ECHOPRT: ::tcflag_t = 0x00000400; +pub const ECHOCTL: ::tcflag_t = 0x00000200; +pub const ISIG: ::tcflag_t = 0x00000001; +pub const ICANON: ::tcflag_t = 0x00000002; +pub const PENDIN: ::tcflag_t = 0x00004000; +pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; +pub const B57600: ::speed_t = 0o010001; +pub const B115200: ::speed_t = 0o010002; +pub const B230400: ::speed_t = 0o010003; +pub const B460800: ::speed_t = 0o010004; +pub const B500000: ::speed_t = 0o010005; +pub const B576000: ::speed_t = 0o010006; +pub const B921600: ::speed_t = 0o010007; +pub const B1000000: ::speed_t = 0o010010; +pub const B1152000: ::speed_t = 0o010011; +pub const B1500000: ::speed_t = 0o010012; +pub const B2000000: ::speed_t = 0o010013; +pub const B2500000: ::speed_t = 0o010014; +pub const B3000000: ::speed_t = 0o010015; +pub const B3500000: ::speed_t = 0o010016; +pub const B4000000: ::speed_t = 0o010017; pub const O_APPEND: ::c_int = 0o010; pub const O_CREAT: ::c_int = 0o400; diff --git a/src/liblibc/src/unix/notbsd/linux/musl/b32/mod.rs b/src/liblibc/src/unix/notbsd/linux/musl/b32/mod.rs index b4a0f76163..4128a8e4da 100644 --- a/src/liblibc/src/unix/notbsd/linux/musl/b32/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/musl/b32/mod.rs @@ -32,96 +32,13 @@ s! { pub struct sem_t { __val: [::c_int; 4], } - - pub struct ipc_perm { - pub __ipc_perm_key: ::key_t, - pub uid: ::uid_t, - pub gid: ::gid_t, - pub cuid: ::uid_t, - pub cgid: ::gid_t, - pub mode: ::mode_t, - pub __seq: ::c_int, - __unused1: ::c_long, - __unused2: ::c_long - } } -pub const SIGSTKSZ: ::size_t = 8192; -pub const MINSIGSTKSZ: ::size_t = 2048; - pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; -pub const RLIMIT_NLIMITS: ::c_int = 16; pub const TIOCINQ: ::c_int = ::FIONREAD; -pub const MCL_CURRENT: ::c_int = 0x0001; -pub const MCL_FUTURE: ::c_int = 0x0002; -pub const CBAUD: ::tcflag_t = 0o0010017; -pub const TAB1: ::c_int = 0x00000800; -pub const TAB2: ::c_int = 0x00001000; -pub const TAB3: ::c_int = 0x00001800; -pub const CR1: ::c_int = 0x00000200; -pub const CR2: ::c_int = 0x00000400; -pub const CR3: ::c_int = 0x00000600; -pub const FF1: ::c_int = 0x00008000; -pub const BS1: ::c_int = 0x00002000; -pub const VT1: ::c_int = 0x00004000; -pub const VWERASE: usize = 14; -pub const VREPRINT: usize = 12; -pub const VSUSP: usize = 10; -pub const VSTART: usize = 8; -pub const VSTOP: usize = 9; -pub const VDISCARD: usize = 13; -pub const VTIME: usize = 5; -pub const IXON: ::tcflag_t = 0x00000400; -pub const IXOFF: ::tcflag_t = 0x00001000; -pub const ONLCR: ::tcflag_t = 0x4; -pub const CSIZE: ::tcflag_t = 0x00000030; -pub const CS6: ::tcflag_t = 0x00000010; -pub const CS7: ::tcflag_t = 0x00000020; -pub const CS8: ::tcflag_t = 0x00000030; -pub const CSTOPB: ::tcflag_t = 0x00000040; -pub const CREAD: ::tcflag_t = 0x00000080; -pub const PARENB: ::tcflag_t = 0x00000100; -pub const PARODD: ::tcflag_t = 0x00000200; -pub const HUPCL: ::tcflag_t = 0x00000400; -pub const CLOCAL: ::tcflag_t = 0x00000800; -pub const ECHOKE: ::tcflag_t = 0x00000800; -pub const ECHOE: ::tcflag_t = 0x00000010; -pub const ECHOK: ::tcflag_t = 0x00000020; -pub const ECHONL: ::tcflag_t = 0x00000040; -pub const ECHOPRT: ::tcflag_t = 0x00000400; -pub const ECHOCTL: ::tcflag_t = 0x00000200; -pub const ISIG: ::tcflag_t = 0x00000001; -pub const ICANON: ::tcflag_t = 0x00000002; -pub const PENDIN: ::tcflag_t = 0x00004000; -pub const NOFLSH: ::tcflag_t = 0x00000080; -pub const CIBAUD: ::tcflag_t = 0o02003600000; -pub const CBAUDEX: ::tcflag_t = 0o010000; -pub const VSWTC: usize = 7; -pub const OLCUC: ::tcflag_t = 0o000002; -pub const NLDLY: ::tcflag_t = 0o000400; -pub const CRDLY: ::tcflag_t = 0o003000; -pub const TABDLY: ::tcflag_t = 0o014000; -pub const BSDLY: ::tcflag_t = 0o020000; -pub const FFDLY: ::tcflag_t = 0o100000; -pub const VTDLY: ::tcflag_t = 0o040000; -pub const XTABS: ::tcflag_t = 0o014000; -pub const B57600: ::speed_t = 0o010001; -pub const B115200: ::speed_t = 0o010002; -pub const B230400: ::speed_t = 0o010003; -pub const B460800: ::speed_t = 0o010004; -pub const B500000: ::speed_t = 0o010005; -pub const B576000: ::speed_t = 0o010006; -pub const B921600: ::speed_t = 0o010007; -pub const B1000000: ::speed_t = 0o010010; -pub const B1152000: ::speed_t = 0o010011; -pub const B1500000: ::speed_t = 0o010012; -pub const B2000000: ::speed_t = 0o010013; -pub const B2500000: ::speed_t = 0o010014; -pub const B3000000: ::speed_t = 0o010015; -pub const B3500000: ::speed_t = 0o010016; -pub const B4000000: ::speed_t = 0o010017; + extern { pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; } @@ -136,6 +53,9 @@ cfg_if! { } else if #[cfg(any(target_arch = "arm"))] { mod arm; pub use self::arm::*; + } else if #[cfg(any(target_arch = "powerpc"))] { + mod powerpc; + pub use self::powerpc::*; } else { // Unknown target_arch } diff --git a/src/liblibc/src/unix/notbsd/linux/musl/b32/powerpc.rs b/src/liblibc/src/unix/notbsd/linux/musl/b32/powerpc.rs new file mode 100644 index 0000000000..50b6b57ef1 --- /dev/null +++ b/src/liblibc/src/unix/notbsd/linux/musl/b32/powerpc.rs @@ -0,0 +1,866 @@ +pub type c_char = u8; +pub type wchar_t = i32; + +s! { + pub struct stat { + pub st_dev: ::dev_t, + pub st_ino: ::ino_t, + pub st_mode: ::mode_t, + pub st_nlink: ::nlink_t, + pub st_uid: ::uid_t, + pub st_gid: ::gid_t, + pub st_rdev: ::dev_t, + __st_rdev_padding: ::c_short, + pub st_size: ::off_t, + pub st_blksize: ::blksize_t, + pub st_blocks: ::blkcnt_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + __unused: [::c_long; 2], + } + + pub struct stat64 { + pub st_dev: ::dev_t, + pub st_ino: ::ino_t, + pub st_mode: ::mode_t, + pub st_nlink: ::nlink_t, + pub st_uid: ::uid_t, + pub st_gid: ::gid_t, + pub st_rdev: ::dev_t, + __st_rdev_padding: ::c_short, + pub st_size: ::off_t, + pub st_blksize: ::blksize_t, + pub st_blocks: ::blkcnt_t, + pub st_atime: ::time_t, + pub st_atime_nsec: ::c_long, + pub st_mtime: ::time_t, + pub st_mtime_nsec: ::c_long, + pub st_ctime: ::time_t, + pub st_ctime_nsec: ::c_long, + __unused: [::c_long; 2], + } + + pub struct stack_t { + pub ss_sp: *mut ::c_void, + pub ss_flags: ::c_int, + pub ss_size: ::size_t + } + + pub struct ipc_perm { + pub __ipc_perm_key: ::key_t, + pub uid: ::uid_t, + pub gid: ::gid_t, + pub cuid: ::uid_t, + pub cgid: ::gid_t, + pub mode: ::mode_t, + pub __seq: ::c_int, + __pad1: ::c_int, + __pad2: ::c_longlong, + __pad3: ::c_longlong + } + + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + __unused1: ::c_int, + pub shm_atime: ::time_t, + __unused2: ::c_int, + pub shm_dtime: ::time_t, + __unused3: ::c_int, + pub shm_ctime: ::time_t, + __unused4: ::c_int, + pub shm_segsz: ::size_t, + pub shm_cpid: ::pid_t, + pub shm_lpid: ::pid_t, + pub shm_nattch: ::c_ulong, + __pad1: ::c_ulong, + __pad2: ::c_ulong, + } + + pub struct msqid_ds { + pub msg_perm: ::ipc_perm, + __unused1: ::c_int, + pub msg_stime: ::time_t, + __unused2: ::c_int, + pub msg_rtime: ::time_t, + __unused3: ::c_int, + pub msg_ctime: ::time_t, + __msg_cbytes: ::c_ulong, + pub msg_qnum: ::msgqnum_t, + pub msg_qbytes: ::msglen_t, + pub msg_lspid: ::pid_t, + pub msg_lrpid: ::pid_t, + __pad1: ::c_ulong, + __pad2: ::c_ulong, + } + + pub struct statfs { + pub f_type: ::c_ulong, + pub f_bsize: ::c_ulong, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_fsid: ::fsid_t, + pub f_namelen: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_flags: ::c_ulong, + pub f_spare: [::c_ulong; 4], + } + + pub struct siginfo_t { + pub si_signo: ::c_int, + pub si_errno: ::c_int, + pub si_code: ::c_int, + pub _pad: [::c_int; 29], + _align: [usize; 0], + } + + pub struct statfs64 { + pub f_type: ::c_ulong, + pub f_bsize: ::c_ulong, + pub f_blocks: ::fsblkcnt_t, + pub f_bfree: ::fsblkcnt_t, + pub f_bavail: ::fsblkcnt_t, + pub f_files: ::fsfilcnt_t, + pub f_ffree: ::fsfilcnt_t, + pub f_fsid: ::fsid_t, + pub f_namelen: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_flags: ::c_ulong, + pub f_spare: [::c_ulong; 4], + } + + pub struct statvfs64 { + pub f_bsize: ::c_ulong, + pub f_frsize: ::c_ulong, + pub f_blocks: u64, + pub f_bfree: u64, + pub f_bavail: u64, + pub f_files: u64, + pub f_ffree: u64, + pub f_favail: u64, + #[cfg(target_endian = "little")] + pub f_fsid: ::c_ulong, + __f_unused: ::c_int, + #[cfg(target_endian = "big")] + pub f_fsid: ::c_ulong, + pub f_flag: ::c_ulong, + pub f_namemax: ::c_ulong, + __f_spare: [::c_int; 6], + } + + pub struct termios2 { + pub c_iflag: ::tcflag_t, + pub c_oflag: ::tcflag_t, + pub c_cflag: ::tcflag_t, + pub c_lflag: ::tcflag_t, + pub c_cc: [::cc_t; 19], + pub c_line: ::cc_t, + pub c_ispeed: ::speed_t, + pub c_ospeed: ::speed_t, + } +} + +pub const SIGSTKSZ: ::size_t = 10240; +pub const MINSIGSTKSZ: ::size_t = 4096; + +pub const O_DIRECT: ::c_int = 0x20000; +pub const O_DIRECTORY: ::c_int = 0x4000; +pub const O_NOFOLLOW: ::c_int = 0x8000; +pub const O_ASYNC: ::c_int = 0x2000; +pub const O_LARGEFILE: ::c_int = 0x10000; + +pub const FIOCLEX: ::c_int = 0x20006601; +pub const FIONBIO: ::c_int = 0x8004667E; + +pub const RLIMIT_RSS: ::c_int = 5; +pub const RLIMIT_NOFILE: ::c_int = 7; +pub const RLIMIT_AS: ::c_int = 9; +pub const RLIMIT_NPROC: ::c_int = 6; +pub const RLIMIT_MEMLOCK: ::c_int = 8; +pub const RLIMIT_NLIMITS: ::c_int = 15; + +pub const MCL_CURRENT: ::c_int = 0x2000; +pub const MCL_FUTURE: ::c_int = 0x4000; +pub const CBAUD: ::tcflag_t = 0o0000377; +pub const TAB1: ::c_int = 0x00000400; +pub const TAB2: ::c_int = 0x00000800; +pub const TAB3: ::c_int = 0x00000C00; +pub const CR1: ::c_int = 0x00001000; +pub const CR2: ::c_int = 0x00002000; +pub const CR3: ::c_int = 0x00003000; +pub const FF1: ::c_int = 0x00004000; +pub const BS1: ::c_int = 0x00008000; +pub const VT1: ::c_int = 0x00010000; +pub const VWERASE: usize = 10; +pub const VREPRINT: usize = 11; +pub const VSUSP: usize = 12; +pub const VSTART: usize = 13; +pub const VSTOP: usize = 14; +pub const VDISCARD: usize = 16; +pub const VTIME: usize = 7; +pub const IXON: ::tcflag_t = 0x00000200; +pub const IXOFF: ::tcflag_t = 0x00000400; +pub const ONLCR: ::tcflag_t = 0x00000002; +pub const CSIZE: ::tcflag_t = 0x00000300; +pub const CS6: ::tcflag_t = 0x00000100; +pub const CS7: ::tcflag_t = 0x00000200; +pub const CS8: ::tcflag_t = 0x00000300; +pub const CSTOPB: ::tcflag_t = 0x00000400; +pub const CREAD: ::tcflag_t = 0x00000800; +pub const PARENB: ::tcflag_t = 0x00001000; +pub const PARODD: ::tcflag_t = 0x00002000; +pub const HUPCL: ::tcflag_t = 0x00004000; +pub const CLOCAL: ::tcflag_t = 0x00008000; +pub const ECHOKE: ::tcflag_t = 0x00000001; +pub const ECHOE: ::tcflag_t = 0x00000002; +pub const ECHOK: ::tcflag_t = 0x00000004; +pub const ECHONL: ::tcflag_t = 0x00000010; +pub const ECHOPRT: ::tcflag_t = 0x00000020; +pub const ECHOCTL: ::tcflag_t = 0x00000040; +pub const ISIG: ::tcflag_t = 0x00000080; +pub const ICANON: ::tcflag_t = 0x00000100; +pub const PENDIN: ::tcflag_t = 0x20000000; +pub const NOFLSH: ::tcflag_t = 0x80000000; +pub const CIBAUD: ::tcflag_t = 0o00077600000; +pub const CBAUDEX: ::tcflag_t = 0o000020; +pub const VSWTC: usize = 9; +pub const OLCUC: ::tcflag_t = 0o000004; +pub const NLDLY: ::tcflag_t = 0o001400; +pub const CRDLY: ::tcflag_t = 0o030000; +pub const TABDLY: ::tcflag_t = 0o006000; +pub const BSDLY: ::tcflag_t = 0o100000; +pub const FFDLY: ::tcflag_t = 0o040000; +pub const VTDLY: ::tcflag_t = 0o200000; +pub const XTABS: ::tcflag_t = 0o006000; +pub const B57600: ::speed_t = 0o000020; +pub const B115200: ::speed_t = 0o000021; +pub const B230400: ::speed_t = 0o000022; +pub const B460800: ::speed_t = 0o000023; +pub const B500000: ::speed_t = 0o000024; +pub const B576000: ::speed_t = 0o000025; +pub const B921600: ::speed_t = 0o000026; +pub const B1000000: ::speed_t = 0o000027; +pub const B1152000: ::speed_t = 0o000030; +pub const B1500000: ::speed_t = 0o000031; +pub const B2000000: ::speed_t = 0o000032; +pub const B2500000: ::speed_t = 0o000033; +pub const B3000000: ::speed_t = 0o000034; +pub const B3500000: ::speed_t = 0o000035; +pub const B4000000: ::speed_t = 0o000036; + +pub const O_APPEND: ::c_int = 1024; +pub const O_CREAT: ::c_int = 64; +pub const O_EXCL: ::c_int = 128; +pub const O_NOCTTY: ::c_int = 256; +pub const O_NONBLOCK: ::c_int = 2048; +pub const O_SYNC: ::c_int = 1052672; +pub const O_RSYNC: ::c_int = 1052672; +pub const O_DSYNC: ::c_int = 4096; + +pub const SOCK_NONBLOCK: ::c_int = 2048; + +pub const MAP_ANON: ::c_int = 0x0020; +pub const MAP_GROWSDOWN: ::c_int = 0x0100; +pub const MAP_DENYWRITE: ::c_int = 0x0800; +pub const MAP_EXECUTABLE: ::c_int = 0x01000; +pub const MAP_LOCKED: ::c_int = 0x00080; +pub const MAP_NORESERVE: ::c_int = 0x00040; +pub const MAP_POPULATE: ::c_int = 0x08000; +pub const MAP_NONBLOCK: ::c_int = 0x010000; +pub const MAP_STACK: ::c_int = 0x020000; + +pub const SOCK_STREAM: ::c_int = 1; +pub const SOCK_DGRAM: ::c_int = 2; +pub const SOCK_SEQPACKET: ::c_int = 5; + +pub const SOL_SOCKET: ::c_int = 1; + +pub const EDEADLK: ::c_int = 35; +pub const ENAMETOOLONG: ::c_int = 36; +pub const ENOLCK: ::c_int = 37; +pub const ENOSYS: ::c_int = 38; +pub const ENOTEMPTY: ::c_int = 39; +pub const ELOOP: ::c_int = 40; +pub const ENOMSG: ::c_int = 42; +pub const EIDRM: ::c_int = 43; +pub const ECHRNG: ::c_int = 44; +pub const EL2NSYNC: ::c_int = 45; +pub const EL3HLT: ::c_int = 46; +pub const EL3RST: ::c_int = 47; +pub const ELNRNG: ::c_int = 48; +pub const EUNATCH: ::c_int = 49; +pub const ENOCSI: ::c_int = 50; +pub const EL2HLT: ::c_int = 51; +pub const EBADE: ::c_int = 52; +pub const EBADR: ::c_int = 53; +pub const EXFULL: ::c_int = 54; +pub const ENOANO: ::c_int = 55; +pub const EBADRQC: ::c_int = 56; +pub const EBADSLT: ::c_int = 57; +pub const EDEADLOCK: ::c_int = 58; +pub const EMULTIHOP: ::c_int = 72; +pub const EBADMSG: ::c_int = 74; +pub const EOVERFLOW: ::c_int = 75; +pub const ENOTUNIQ: ::c_int = 76; +pub const EBADFD: ::c_int = 77; +pub const EREMCHG: ::c_int = 78; +pub const ELIBACC: ::c_int = 79; +pub const ELIBBAD: ::c_int = 80; +pub const ELIBSCN: ::c_int = 81; +pub const ELIBMAX: ::c_int = 82; +pub const ELIBEXEC: ::c_int = 83; +pub const EILSEQ: ::c_int = 84; +pub const ERESTART: ::c_int = 85; +pub const ESTRPIPE: ::c_int = 86; +pub const EUSERS: ::c_int = 87; +pub const ENOTSOCK: ::c_int = 88; +pub const EDESTADDRREQ: ::c_int = 89; +pub const EMSGSIZE: ::c_int = 90; +pub const EPROTOTYPE: ::c_int = 91; +pub const ENOPROTOOPT: ::c_int = 92; +pub const EPROTONOSUPPORT: ::c_int = 93; +pub const ESOCKTNOSUPPORT: ::c_int = 94; +pub const EOPNOTSUPP: ::c_int = 95; +pub const ENOTSUP: ::c_int = EOPNOTSUPP; +pub const EPFNOSUPPORT: ::c_int = 96; +pub const EAFNOSUPPORT: ::c_int = 97; +pub const EADDRINUSE: ::c_int = 98; +pub const EADDRNOTAVAIL: ::c_int = 99; +pub const ENETDOWN: ::c_int = 100; +pub const ENETUNREACH: ::c_int = 101; +pub const ENETRESET: ::c_int = 102; +pub const ECONNABORTED: ::c_int = 103; +pub const ECONNRESET: ::c_int = 104; +pub const ENOBUFS: ::c_int = 105; +pub const EISCONN: ::c_int = 106; +pub const ENOTCONN: ::c_int = 107; +pub const ESHUTDOWN: ::c_int = 108; +pub const ETOOMANYREFS: ::c_int = 109; +pub const ETIMEDOUT: ::c_int = 110; +pub const ECONNREFUSED: ::c_int = 111; +pub const EHOSTDOWN: ::c_int = 112; +pub const EHOSTUNREACH: ::c_int = 113; +pub const EALREADY: ::c_int = 114; +pub const EINPROGRESS: ::c_int = 115; +pub const ESTALE: ::c_int = 116; +pub const EUCLEAN: ::c_int = 117; +pub const ENOTNAM: ::c_int = 118; +pub const ENAVAIL: ::c_int = 119; +pub const EISNAM: ::c_int = 120; +pub const EREMOTEIO: ::c_int = 121; +pub const EDQUOT: ::c_int = 122; +pub const ENOMEDIUM: ::c_int = 123; +pub const EMEDIUMTYPE: ::c_int = 124; +pub const ECANCELED: ::c_int = 125; +pub const ENOKEY: ::c_int = 126; +pub const EKEYEXPIRED: ::c_int = 127; +pub const EKEYREVOKED: ::c_int = 128; +pub const EKEYREJECTED: ::c_int = 129; +pub const EOWNERDEAD: ::c_int = 130; +pub const ENOTRECOVERABLE: ::c_int = 131; +pub const ERFKILL: ::c_int = 132; +pub const EHWPOISON: ::c_int = 133; + +pub const SO_REUSEADDR: ::c_int = 2; +pub const SO_TYPE: ::c_int = 3; +pub const SO_ERROR: ::c_int = 4; +pub const SO_DONTROUTE: ::c_int = 5; +pub const SO_BROADCAST: ::c_int = 6; +pub const SO_SNDBUF: ::c_int = 7; +pub const SO_RCVBUF: ::c_int = 8; +pub const SO_KEEPALIVE: ::c_int = 9; +pub const SO_OOBINLINE: ::c_int = 10; +pub const SO_NO_CHECK: ::c_int = 11; +pub const SO_PRIORITY: ::c_int = 12; +pub const SO_LINGER: ::c_int = 13; +pub const SO_BSDCOMPAT: ::c_int = 14; +pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_RCVLOWAT: ::c_int = 16; +pub const SO_SNDLOWAT: ::c_int = 17; +pub const SO_RCVTIMEO: ::c_int = 18; +pub const SO_SNDTIMEO: ::c_int = 19; +pub const SO_PASSCRED: ::c_int = 20; +pub const SO_PEERCRED: ::c_int = 21; +pub const SO_ACCEPTCONN: ::c_int = 30; +pub const SO_SNDBUFFORCE: ::c_int = 32; +pub const SO_RCVBUFFORCE: ::c_int = 33; +pub const SO_PROTOCOL: ::c_int = 38; +pub const SO_DOMAIN: ::c_int = 39; + +pub const SA_ONSTACK: ::c_int = 0x08000000; +pub const SA_SIGINFO: ::c_int = 0x00000004; +pub const SA_NOCLDWAIT: ::c_int = 0x00000002; + +pub const SIGCHLD: ::c_int = 17; +pub const SIGBUS: ::c_int = 7; +pub const SIGTTIN: ::c_int = 21; +pub const SIGTTOU: ::c_int = 22; +pub const SIGXCPU: ::c_int = 24; +pub const SIGXFSZ: ::c_int = 25; +pub const SIGVTALRM: ::c_int = 26; +pub const SIGPROF: ::c_int = 27; +pub const SIGWINCH: ::c_int = 28; +pub const SIGUSR1: ::c_int = 10; +pub const SIGUSR2: ::c_int = 12; +pub const SIGCONT: ::c_int = 18; +pub const SIGSTOP: ::c_int = 19; +pub const SIGTSTP: ::c_int = 20; +pub const SIGURG: ::c_int = 23; +pub const SIGIO: ::c_int = 29; +pub const SIGSYS: ::c_int = 31; +pub const SIGSTKFLT: ::c_int = 16; +pub const SIGPOLL: ::c_int = 29; +pub const SIGPWR: ::c_int = 30; +pub const SIG_SETMASK: ::c_int = 2; +pub const SIG_BLOCK: ::c_int = 0x000000; +pub const SIG_UNBLOCK: ::c_int = 0x01; + +pub const EXTPROC: ::tcflag_t = 0x10000000; + +pub const MAP_HUGETLB: ::c_int = 0x040000; + +pub const F_GETLK: ::c_int = 12; +pub const F_GETOWN: ::c_int = 9; +pub const F_SETLK: ::c_int = 13; +pub const F_SETLKW: ::c_int = 14; +pub const F_SETOWN: ::c_int = 8; + +pub const VEOF: usize = 4; +pub const VEOL: usize = 6; +pub const VEOL2: usize = 8; +pub const VMIN: usize = 5; +pub const IEXTEN: ::tcflag_t = 0x00000400; +pub const TOSTOP: ::tcflag_t = 0x00400000; +pub const FLUSHO: ::tcflag_t = 0x00800000; + +pub const TCGETS: ::c_int = 0x402C7413; +pub const TCSETS: ::c_int = 0x802C7414; +pub const TCSETSW: ::c_int = 0x802C7415; +pub const TCSETSF: ::c_int = 0x802C7416; +pub const TCGETA: ::c_int = 0x40147417; +pub const TCSETA: ::c_int = 0x80147418; +pub const TCSETAW: ::c_int = 0x80147419; +pub const TCSETAF: ::c_int = 0x8014741C; +pub const TCSBRK: ::c_int = 0x2000741D; +pub const TCXONC: ::c_int = 0x2000741E; +pub const TCFLSH: ::c_int = 0x2000741F; +pub const TIOCGSOFTCAR: ::c_int = 0x5419; +pub const TIOCSSOFTCAR: ::c_int = 0x541A; +pub const TIOCLINUX: ::c_int = 0x541C; +pub const TIOCGSERIAL: ::c_int = 0x541E; +pub const TIOCEXCL: ::c_int = 0x540C; +pub const TIOCNXCL: ::c_int = 0x540D; +pub const TIOCSCTTY: ::c_int = 0x540E; +pub const TIOCGPGRP: ::c_int = 0x40047477; +pub const TIOCSPGRP: ::c_int = 0x80047476; +pub const TIOCOUTQ: ::c_int = 0x40047473; +pub const TIOCSTI: ::c_int = 0x5412; +pub const TIOCGWINSZ: ::c_int = 0x40087468; +pub const TIOCSWINSZ: ::c_int = 0x80087467; +pub const TIOCMGET: ::c_int = 0x5415; +pub const TIOCMBIS: ::c_int = 0x5416; +pub const TIOCMBIC: ::c_int = 0x5417; +pub const TIOCMSET: ::c_int = 0x5418; +pub const FIONREAD: ::c_int = 0x4004667F; +pub const TIOCCONS: ::c_int = 0x541D; + +pub const POLLWRNORM: ::c_short = 0x100; +pub const POLLWRBAND: ::c_short = 0x200; + +pub const TIOCM_LE: ::c_int = 0x001; +pub const TIOCM_DTR: ::c_int = 0x002; +pub const TIOCM_RTS: ::c_int = 0x004; +pub const TIOCM_ST: ::c_int = 0x008; +pub const TIOCM_SR: ::c_int = 0x010; +pub const TIOCM_CTS: ::c_int = 0x020; +pub const TIOCM_CAR: ::c_int = 0x040; +pub const TIOCM_RNG: ::c_int = 0x080; +pub const TIOCM_DSR: ::c_int = 0x100; +pub const TIOCM_CD: ::c_int = TIOCM_CAR; +pub const TIOCM_RI: ::c_int = TIOCM_RNG; + +// Syscall table +pub const SYS_restart_syscall: ::c_long = 0; +pub const SYS_exit: ::c_long = 1; +pub const SYS_fork: ::c_long = 2; +pub const SYS_read: ::c_long = 3; +pub const SYS_write: ::c_long = 4; +pub const SYS_open: ::c_long = 5; +pub const SYS_close: ::c_long = 6; +pub const SYS_waitpid: ::c_long = 7; +pub const SYS_creat: ::c_long = 8; +pub const SYS_link: ::c_long = 9; +pub const SYS_unlink: ::c_long = 10; +pub const SYS_execve: ::c_long = 11; +pub const SYS_chdir: ::c_long = 12; +pub const SYS_time: ::c_long = 13; +pub const SYS_mknod: ::c_long = 14; +pub const SYS_chmod: ::c_long = 15; +pub const SYS_lchown: ::c_long = 16; +pub const SYS_break: ::c_long = 17; +pub const SYS_oldstat: ::c_long = 18; +pub const SYS_lseek: ::c_long = 19; +pub const SYS_getpid: ::c_long = 20; +pub const SYS_mount: ::c_long = 21; +pub const SYS_umount: ::c_long = 22; +pub const SYS_setuid: ::c_long = 23; +pub const SYS_getuid: ::c_long = 24; +pub const SYS_stime: ::c_long = 25; +pub const SYS_ptrace: ::c_long = 26; +pub const SYS_alarm: ::c_long = 27; +pub const SYS_oldfstat: ::c_long = 28; +pub const SYS_pause: ::c_long = 29; +pub const SYS_utime: ::c_long = 30; +pub const SYS_stty: ::c_long = 31; +pub const SYS_gtty: ::c_long = 32; +pub const SYS_access: ::c_long = 33; +pub const SYS_nice: ::c_long = 34; +pub const SYS_ftime: ::c_long = 35; +pub const SYS_sync: ::c_long = 36; +pub const SYS_kill: ::c_long = 37; +pub const SYS_rename: ::c_long = 38; +pub const SYS_mkdir: ::c_long = 39; +pub const SYS_rmdir: ::c_long = 40; +pub const SYS_dup: ::c_long = 41; +pub const SYS_pipe: ::c_long = 42; +pub const SYS_times: ::c_long = 43; +pub const SYS_prof: ::c_long = 44; +pub const SYS_brk: ::c_long = 45; +pub const SYS_setgid: ::c_long = 46; +pub const SYS_getgid: ::c_long = 47; +pub const SYS_signal: ::c_long = 48; +pub const SYS_geteuid: ::c_long = 49; +pub const SYS_getegid: ::c_long = 50; +pub const SYS_acct: ::c_long = 51; +pub const SYS_umount2: ::c_long = 52; +pub const SYS_lock: ::c_long = 53; +pub const SYS_ioctl: ::c_long = 54; +pub const SYS_fcntl: ::c_long = 55; +pub const SYS_mpx: ::c_long = 56; +pub const SYS_setpgid: ::c_long = 57; +pub const SYS_ulimit: ::c_long = 58; +pub const SYS_oldolduname: ::c_long = 59; +pub const SYS_umask: ::c_long = 60; +pub const SYS_chroot: ::c_long = 61; +pub const SYS_ustat: ::c_long = 62; +pub const SYS_dup2: ::c_long = 63; +pub const SYS_getppid: ::c_long = 64; +pub const SYS_getpgrp: ::c_long = 65; +pub const SYS_setsid: ::c_long = 66; +pub const SYS_sigaction: ::c_long = 67; +pub const SYS_sgetmask: ::c_long = 68; +pub const SYS_ssetmask: ::c_long = 69; +pub const SYS_setreuid: ::c_long = 70; +pub const SYS_setregid: ::c_long = 71; +pub const SYS_sigsuspend: ::c_long = 72; +pub const SYS_sigpending: ::c_long = 73; +pub const SYS_sethostname: ::c_long = 74; +pub const SYS_setrlimit: ::c_long = 75; +pub const SYS_getrlimit: ::c_long = 76; +pub const SYS_getrusage: ::c_long = 77; +pub const SYS_gettimeofday: ::c_long = 78; +pub const SYS_settimeofday: ::c_long = 79; +pub const SYS_getgroups: ::c_long = 80; +pub const SYS_setgroups: ::c_long = 81; +pub const SYS_select: ::c_long = 82; +pub const SYS_symlink: ::c_long = 83; +pub const SYS_oldlstat: ::c_long = 84; +pub const SYS_readlink: ::c_long = 85; +pub const SYS_uselib: ::c_long = 86; +pub const SYS_swapon: ::c_long = 87; +pub const SYS_reboot: ::c_long = 88; +pub const SYS_readdir: ::c_long = 89; +pub const SYS_mmap: ::c_long = 90; +pub const SYS_munmap: ::c_long = 91; +pub const SYS_truncate: ::c_long = 92; +pub const SYS_ftruncate: ::c_long = 93; +pub const SYS_fchmod: ::c_long = 94; +pub const SYS_fchown: ::c_long = 95; +pub const SYS_getpriority: ::c_long = 96; +pub const SYS_setpriority: ::c_long = 97; +pub const SYS_profil: ::c_long = 98; +pub const SYS_statfs: ::c_long = 99; +pub const SYS_fstatfs: ::c_long = 100; +pub const SYS_ioperm: ::c_long = 101; +pub const SYS_socketcall: ::c_long = 102; +pub const SYS_syslog: ::c_long = 103; +pub const SYS_setitimer: ::c_long = 104; +pub const SYS_getitimer: ::c_long = 105; +pub const SYS_stat: ::c_long = 106; +pub const SYS_lstat: ::c_long = 107; +pub const SYS_fstat: ::c_long = 108; +pub const SYS_olduname: ::c_long = 109; +pub const SYS_iopl: ::c_long = 110; +pub const SYS_vhangup: ::c_long = 111; +pub const SYS_idle: ::c_long = 112; +pub const SYS_vm86: ::c_long = 113; +pub const SYS_wait4: ::c_long = 114; +pub const SYS_swapoff: ::c_long = 115; +pub const SYS_sysinfo: ::c_long = 116; +pub const SYS_ipc: ::c_long = 117; +pub const SYS_fsync: ::c_long = 118; +pub const SYS_sigreturn: ::c_long = 119; +pub const SYS_clone: ::c_long = 120; +pub const SYS_setdomainname: ::c_long = 121; +pub const SYS_uname: ::c_long = 122; +pub const SYS_modify_ldt: ::c_long = 123; +pub const SYS_adjtimex: ::c_long = 124; +pub const SYS_mprotect: ::c_long = 125; +pub const SYS_sigprocmask: ::c_long = 126; +pub const SYS_create_module: ::c_long = 127; +pub const SYS_init_module: ::c_long = 128; +pub const SYS_delete_module: ::c_long = 129; +pub const SYS_get_kernel_syms: ::c_long = 130; +pub const SYS_quotactl: ::c_long = 131; +pub const SYS_getpgid: ::c_long = 132; +pub const SYS_fchdir: ::c_long = 133; +pub const SYS_bdflush: ::c_long = 134; +pub const SYS_sysfs: ::c_long = 135; +pub const SYS_personality: ::c_long = 136; +pub const SYS_afs_syscall: ::c_long = 137; +pub const SYS_setfsuid: ::c_long = 138; +pub const SYS_setfsgid: ::c_long = 139; +pub const SYS__llseek: ::c_long = 140; +pub const SYS_getdents: ::c_long = 141; +pub const SYS__newselect: ::c_long = 142; +pub const SYS_flock: ::c_long = 143; +pub const SYS_msync: ::c_long = 144; +pub const SYS_readv: ::c_long = 145; +pub const SYS_writev: ::c_long = 146; +pub const SYS_getsid: ::c_long = 147; +pub const SYS_fdatasync: ::c_long = 148; +pub const SYS__sysctl: ::c_long = 149; +pub const SYS_mlock: ::c_long = 150; +pub const SYS_munlock: ::c_long = 151; +pub const SYS_mlockall: ::c_long = 152; +pub const SYS_munlockall: ::c_long = 153; +pub const SYS_sched_setparam: ::c_long = 154; +pub const SYS_sched_getparam: ::c_long = 155; +pub const SYS_sched_setscheduler: ::c_long = 156; +pub const SYS_sched_getscheduler: ::c_long = 157; +pub const SYS_sched_yield: ::c_long = 158; +pub const SYS_sched_get_priority_max: ::c_long = 159; +pub const SYS_sched_get_priority_min: ::c_long = 160; +pub const SYS_sched_rr_get_interval: ::c_long = 161; +pub const SYS_nanosleep: ::c_long = 162; +pub const SYS_mremap: ::c_long = 163; +pub const SYS_setresuid: ::c_long = 164; +pub const SYS_getresuid: ::c_long = 165; +pub const SYS_query_module: ::c_long = 166; +pub const SYS_poll: ::c_long = 167; +pub const SYS_nfsservctl: ::c_long = 168; +pub const SYS_setresgid: ::c_long = 169; +pub const SYS_getresgid: ::c_long = 170; +pub const SYS_prctl: ::c_long = 171; +pub const SYS_rt_sigreturn: ::c_long = 172; +pub const SYS_rt_sigaction: ::c_long = 173; +pub const SYS_rt_sigprocmask: ::c_long = 174; +pub const SYS_rt_sigpending: ::c_long = 175; +pub const SYS_rt_sigtimedwait: ::c_long = 176; +pub const SYS_rt_sigqueueinfo: ::c_long = 177; +pub const SYS_rt_sigsuspend: ::c_long = 178; +pub const SYS_pread64: ::c_long = 179; +pub const SYS_pwrite64: ::c_long = 180; +pub const SYS_chown: ::c_long = 181; +pub const SYS_getcwd: ::c_long = 182; +pub const SYS_capget: ::c_long = 183; +pub const SYS_capset: ::c_long = 184; +pub const SYS_sigaltstack: ::c_long = 185; +pub const SYS_sendfile: ::c_long = 186; +pub const SYS_getpmsg: ::c_long = 187; +pub const SYS_putpmsg: ::c_long = 188; +pub const SYS_vfork: ::c_long = 189; +pub const SYS_ugetrlimit: ::c_long = 190; +pub const SYS_readahead: ::c_long = 191; +pub const SYS_mmap2: ::c_long = 192; +pub const SYS_truncate64: ::c_long = 193; +pub const SYS_ftruncate64: ::c_long = 194; +pub const SYS_stat64: ::c_long = 195; +pub const SYS_lstat64: ::c_long = 196; +pub const SYS_fstat64: ::c_long = 197; +pub const SYS_pciconfig_read: ::c_long = 198; +pub const SYS_pciconfig_write: ::c_long = 199; +pub const SYS_pciconfig_iobase: ::c_long = 200; +pub const SYS_multiplexer: ::c_long = 201; +pub const SYS_getdents64: ::c_long = 202; +pub const SYS_pivot_root: ::c_long = 203; +pub const SYS_fcntl64: ::c_long = 204; +pub const SYS_madvise: ::c_long = 205; +pub const SYS_mincore: ::c_long = 206; +pub const SYS_gettid: ::c_long = 207; +pub const SYS_tkill: ::c_long = 208; +pub const SYS_setxattr: ::c_long = 209; +pub const SYS_lsetxattr: ::c_long = 210; +pub const SYS_fsetxattr: ::c_long = 211; +pub const SYS_getxattr: ::c_long = 212; +pub const SYS_lgetxattr: ::c_long = 213; +pub const SYS_fgetxattr: ::c_long = 214; +pub const SYS_listxattr: ::c_long = 215; +pub const SYS_llistxattr: ::c_long = 216; +pub const SYS_flistxattr: ::c_long = 217; +pub const SYS_removexattr: ::c_long = 218; +pub const SYS_lremovexattr: ::c_long = 219; +pub const SYS_fremovexattr: ::c_long = 220; +pub const SYS_futex: ::c_long = 221; +pub const SYS_sched_setaffinity: ::c_long = 222; +pub const SYS_sched_getaffinity: ::c_long = 223; +pub const SYS_tuxcall: ::c_long = 225; +pub const SYS_sendfile64: ::c_long = 226; +pub const SYS_io_setup: ::c_long = 227; +pub const SYS_io_destroy: ::c_long = 228; +pub const SYS_io_getevents: ::c_long = 229; +pub const SYS_io_submit: ::c_long = 230; +pub const SYS_io_cancel: ::c_long = 231; +pub const SYS_set_tid_address: ::c_long = 232; +pub const SYS_fadvise64: ::c_long = 233; +pub const SYS_exit_group: ::c_long = 234; +pub const SYS_lookup_dcookie: ::c_long = 235; +pub const SYS_epoll_create: ::c_long = 236; +pub const SYS_epoll_ctl: ::c_long = 237; +pub const SYS_epoll_wait: ::c_long = 238; +pub const SYS_remap_file_pages: ::c_long = 239; +pub const SYS_timer_create: ::c_long = 240; +pub const SYS_timer_settime: ::c_long = 241; +pub const SYS_timer_gettime: ::c_long = 242; +pub const SYS_timer_getoverrun: ::c_long = 243; +pub const SYS_timer_delete: ::c_long = 244; +pub const SYS_clock_settime: ::c_long = 245; +pub const SYS_clock_gettime: ::c_long = 246; +pub const SYS_clock_getres: ::c_long = 247; +pub const SYS_clock_nanosleep: ::c_long = 248; +pub const SYS_swapcontext: ::c_long = 249; +pub const SYS_tgkill: ::c_long = 250; +pub const SYS_utimes: ::c_long = 251; +pub const SYS_statfs64: ::c_long = 252; +pub const SYS_fstatfs64: ::c_long = 253; +pub const SYS_fadvise64_64: ::c_long = 254; +pub const SYS_rtas: ::c_long = 255; +pub const SYS_sys_debug_setcontext: ::c_long = 256; +pub const SYS_migrate_pages: ::c_long = 258; +pub const SYS_mbind: ::c_long = 259; +pub const SYS_get_mempolicy: ::c_long = 260; +pub const SYS_set_mempolicy: ::c_long = 261; +pub const SYS_mq_open: ::c_long = 262; +pub const SYS_mq_unlink: ::c_long = 263; +pub const SYS_mq_timedsend: ::c_long = 264; +pub const SYS_mq_timedreceive: ::c_long = 265; +pub const SYS_mq_notify: ::c_long = 266; +pub const SYS_mq_getsetattr: ::c_long = 267; +pub const SYS_kexec_load: ::c_long = 268; +pub const SYS_add_key: ::c_long = 269; +pub const SYS_request_key: ::c_long = 270; +pub const SYS_keyctl: ::c_long = 271; +pub const SYS_waitid: ::c_long = 272; +pub const SYS_ioprio_set: ::c_long = 273; +pub const SYS_ioprio_get: ::c_long = 274; +pub const SYS_inotify_init: ::c_long = 275; +pub const SYS_inotify_add_watch: ::c_long = 276; +pub const SYS_inotify_rm_watch: ::c_long = 277; +pub const SYS_spu_run: ::c_long = 278; +pub const SYS_spu_create: ::c_long = 279; +pub const SYS_pselect6: ::c_long = 280; +pub const SYS_ppoll: ::c_long = 281; +pub const SYS_unshare: ::c_long = 282; +pub const SYS_splice: ::c_long = 283; +pub const SYS_tee: ::c_long = 284; +pub const SYS_vmsplice: ::c_long = 285; +pub const SYS_openat: ::c_long = 286; +pub const SYS_mkdirat: ::c_long = 287; +pub const SYS_mknodat: ::c_long = 288; +pub const SYS_fchownat: ::c_long = 289; +pub const SYS_futimesat: ::c_long = 290; +pub const SYS_fstatat64: ::c_long = 291; +pub const SYS_unlinkat: ::c_long = 292; +pub const SYS_renameat: ::c_long = 293; +pub const SYS_linkat: ::c_long = 294; +pub const SYS_symlinkat: ::c_long = 295; +pub const SYS_readlinkat: ::c_long = 296; +pub const SYS_fchmodat: ::c_long = 297; +pub const SYS_faccessat: ::c_long = 298; +pub const SYS_get_robust_list: ::c_long = 299; +pub const SYS_set_robust_list: ::c_long = 300; +pub const SYS_move_pages: ::c_long = 301; +pub const SYS_getcpu: ::c_long = 302; +pub const SYS_epoll_pwait: ::c_long = 303; +pub const SYS_utimensat: ::c_long = 304; +pub const SYS_signalfd: ::c_long = 305; +pub const SYS_timerfd_create: ::c_long = 306; +pub const SYS_eventfd: ::c_long = 307; +pub const SYS_sync_file_range2: ::c_long = 308; +pub const SYS_fallocate: ::c_long = 309; +pub const SYS_subpage_prot: ::c_long = 310; +pub const SYS_timerfd_settime: ::c_long = 311; +pub const SYS_timerfd_gettime: ::c_long = 312; +pub const SYS_signalfd4: ::c_long = 313; +pub const SYS_eventfd2: ::c_long = 314; +pub const SYS_epoll_create1: ::c_long = 315; +pub const SYS_dup3: ::c_long = 316; +pub const SYS_pipe2: ::c_long = 317; +pub const SYS_inotify_init1: ::c_long = 318; +pub const SYS_perf_event_open: ::c_long = 319; +pub const SYS_preadv: ::c_long = 320; +pub const SYS_pwritev: ::c_long = 321; +pub const SYS_rt_tgsigqueueinfo: ::c_long = 322; +pub const SYS_fanotify_init: ::c_long = 323; +pub const SYS_fanotify_mark: ::c_long = 324; +pub const SYS_prlimit64: ::c_long = 325; +pub const SYS_socket: ::c_long = 326; +pub const SYS_bind: ::c_long = 327; +pub const SYS_connect: ::c_long = 328; +pub const SYS_listen: ::c_long = 329; +pub const SYS_accept: ::c_long = 330; +pub const SYS_getsockname: ::c_long = 331; +pub const SYS_getpeername: ::c_long = 332; +pub const SYS_socketpair: ::c_long = 333; +pub const SYS_send: ::c_long = 334; +pub const SYS_sendto: ::c_long = 335; +pub const SYS_recv: ::c_long = 336; +pub const SYS_recvfrom: ::c_long = 337; +pub const SYS_shutdown: ::c_long = 338; +pub const SYS_setsockopt: ::c_long = 339; +pub const SYS_getsockopt: ::c_long = 340; +pub const SYS_sendmsg: ::c_long = 341; +pub const SYS_recvmsg: ::c_long = 342; +pub const SYS_recvmmsg: ::c_long = 343; +pub const SYS_accept4: ::c_long = 344; +pub const SYS_name_to_handle_at: ::c_long = 345; +pub const SYS_open_by_handle_at: ::c_long = 346; +pub const SYS_clock_adjtime: ::c_long = 347; +pub const SYS_syncfs: ::c_long = 348; +pub const SYS_sendmmsg: ::c_long = 349; +pub const SYS_setns: ::c_long = 350; +pub const SYS_process_vm_readv: ::c_long = 351; +pub const SYS_process_vm_writev: ::c_long = 352; +pub const SYS_finit_module: ::c_long = 353; +pub const SYS_kcmp: ::c_long = 354; +pub const SYS_sched_setattr: ::c_long = 355; +pub const SYS_sched_getattr: ::c_long = 356; +pub const SYS_renameat2: ::c_long = 357; +pub const SYS_seccomp: ::c_long = 358; +pub const SYS_getrandom: ::c_long = 359; +pub const SYS_memfd_create: ::c_long = 360; +pub const SYS_bpf: ::c_long = 361; +pub const SYS_execveat: ::c_long = 362; +pub const SYS_switch_endian: ::c_long = 363; +pub const SYS_userfaultfd: ::c_long = 364; +pub const SYS_membarrier: ::c_long = 365; +pub const SYS_mlock2: ::c_long = 378; +pub const SYS_copy_file_range: ::c_long = 379; +pub const SYS_preadv2: ::c_long = 380; +pub const SYS_pwritev2: ::c_long = 381; +pub const SYS_kexec_file_load: ::c_long = 382; +pub const SYS_statx: ::c_long = 383; +pub const SYS_pkey_alloc: ::c_long = 384; +pub const SYS_pkey_free: ::c_long = 385; +pub const SYS_pkey_mprotect: ::c_long = 386; + +#[doc(hidden)] +pub const AF_MAX: ::c_int = 43; +#[doc(hidden)] +pub const PF_MAX: ::c_int = AF_MAX; diff --git a/src/liblibc/src/unix/notbsd/linux/musl/b32/x86.rs b/src/liblibc/src/unix/notbsd/linux/musl/b32/x86.rs index fa570248c7..9f704c7fac 100644 --- a/src/liblibc/src/unix/notbsd/linux/musl/b32/x86.rs +++ b/src/liblibc/src/unix/notbsd/linux/musl/b32/x86.rs @@ -52,6 +52,18 @@ s! { pub ss_size: ::size_t } + pub struct ipc_perm { + pub __ipc_perm_key: ::key_t, + pub uid: ::uid_t, + pub gid: ::gid_t, + pub cuid: ::uid_t, + pub cgid: ::gid_t, + pub mode: ::mode_t, + pub __seq: ::c_int, + __unused1: ::c_long, + __unused2: ::c_long + } + pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, @@ -164,6 +176,9 @@ s! { } } +pub const SIGSTKSZ: ::size_t = 8192; +pub const MINSIGSTKSZ: ::size_t = 2048; + pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; @@ -178,6 +193,76 @@ pub const RLIMIT_NOFILE: ::c_int = 7; pub const RLIMIT_AS: ::c_int = 9; pub const RLIMIT_NPROC: ::c_int = 6; pub const RLIMIT_MEMLOCK: ::c_int = 8; +pub const RLIMIT_NLIMITS: ::c_int = 16; + +pub const MCL_CURRENT: ::c_int = 0x0001; +pub const MCL_FUTURE: ::c_int = 0x0002; +pub const CBAUD: ::tcflag_t = 0o0010017; +pub const TAB1: ::c_int = 0x00000800; +pub const TAB2: ::c_int = 0x00001000; +pub const TAB3: ::c_int = 0x00001800; +pub const CR1: ::c_int = 0x00000200; +pub const CR2: ::c_int = 0x00000400; +pub const CR3: ::c_int = 0x00000600; +pub const FF1: ::c_int = 0x00008000; +pub const BS1: ::c_int = 0x00002000; +pub const VT1: ::c_int = 0x00004000; +pub const VWERASE: usize = 14; +pub const VREPRINT: usize = 12; +pub const VSUSP: usize = 10; +pub const VSTART: usize = 8; +pub const VSTOP: usize = 9; +pub const VDISCARD: usize = 13; +pub const VTIME: usize = 5; +pub const IXON: ::tcflag_t = 0x00000400; +pub const IXOFF: ::tcflag_t = 0x00001000; +pub const ONLCR: ::tcflag_t = 0x4; +pub const CSIZE: ::tcflag_t = 0x00000030; +pub const CS6: ::tcflag_t = 0x00000010; +pub const CS7: ::tcflag_t = 0x00000020; +pub const CS8: ::tcflag_t = 0x00000030; +pub const CSTOPB: ::tcflag_t = 0x00000040; +pub const CREAD: ::tcflag_t = 0x00000080; +pub const PARENB: ::tcflag_t = 0x00000100; +pub const PARODD: ::tcflag_t = 0x00000200; +pub const HUPCL: ::tcflag_t = 0x00000400; +pub const CLOCAL: ::tcflag_t = 0x00000800; +pub const ECHOKE: ::tcflag_t = 0x00000800; +pub const ECHOE: ::tcflag_t = 0x00000010; +pub const ECHOK: ::tcflag_t = 0x00000020; +pub const ECHONL: ::tcflag_t = 0x00000040; +pub const ECHOPRT: ::tcflag_t = 0x00000400; +pub const ECHOCTL: ::tcflag_t = 0x00000200; +pub const ISIG: ::tcflag_t = 0x00000001; +pub const ICANON: ::tcflag_t = 0x00000002; +pub const PENDIN: ::tcflag_t = 0x00004000; +pub const NOFLSH: ::tcflag_t = 0x00000080; +pub const CIBAUD: ::tcflag_t = 0o02003600000; +pub const CBAUDEX: ::tcflag_t = 0o010000; +pub const VSWTC: usize = 7; +pub const OLCUC: ::tcflag_t = 0o000002; +pub const NLDLY: ::tcflag_t = 0o000400; +pub const CRDLY: ::tcflag_t = 0o003000; +pub const TABDLY: ::tcflag_t = 0o014000; +pub const BSDLY: ::tcflag_t = 0o020000; +pub const FFDLY: ::tcflag_t = 0o100000; +pub const VTDLY: ::tcflag_t = 0o040000; +pub const XTABS: ::tcflag_t = 0o014000; +pub const B57600: ::speed_t = 0o010001; +pub const B115200: ::speed_t = 0o010002; +pub const B230400: ::speed_t = 0o010003; +pub const B460800: ::speed_t = 0o010004; +pub const B500000: ::speed_t = 0o010005; +pub const B576000: ::speed_t = 0o010006; +pub const B921600: ::speed_t = 0o010007; +pub const B1000000: ::speed_t = 0o010010; +pub const B1152000: ::speed_t = 0o010011; +pub const B1500000: ::speed_t = 0o010012; +pub const B2000000: ::speed_t = 0o010013; +pub const B2500000: ::speed_t = 0o010014; +pub const B3000000: ::speed_t = 0o010015; +pub const B3500000: ::speed_t = 0o010016; +pub const B4000000: ::speed_t = 0o010017; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; diff --git a/src/liblibc/src/unix/notbsd/linux/musl/mod.rs b/src/liblibc/src/unix/notbsd/linux/musl/mod.rs index 0d92a4b9d1..10d61ebebe 100644 --- a/src/liblibc/src/unix/notbsd/linux/musl/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/musl/mod.rs @@ -260,7 +260,8 @@ cfg_if! { pub use self::b64::*; } else if #[cfg(any(target_arch = "x86", target_arch = "mips", - target_arch = "arm"))] { + target_arch = "arm", + target_arch = "powerpc"))] { mod b32; pub use self::b32::*; } else { } diff --git a/src/liblibc/src/unix/notbsd/linux/other/b32/mod.rs b/src/liblibc/src/unix/notbsd/linux/other/b32/mod.rs index 88a5d6cc6c..5b0142ab89 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b32/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b32/mod.rs @@ -1,5 +1,7 @@ //! 32-bit specific definitions for linux-like values +use pthread_mutex_t; + pub type c_long = i32; pub type c_ulong = u32; pub type clock_t = i32; @@ -299,60 +301,56 @@ pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; -#[cfg(target_endian = "little")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, - 0, 0, - ], - }; +align_const! { + #[cfg(target_endian = "little")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, + ], + }; +} pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; diff --git a/src/liblibc/src/unix/notbsd/linux/other/b64/aarch64.rs b/src/liblibc/src/unix/notbsd/linux/other/b64/aarch64.rs index cfa8592b20..2ba27a72b8 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/aarch64.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/aarch64.rs @@ -1,5 +1,7 @@ //! AArch64-specific definitions for 64-bit linux-like values +use pthread_mutex_t; + pub type c_long = i64; pub type c_ulong = u64; pub type c_char = u8; @@ -386,33 +388,32 @@ pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 48; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 8; -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ], - }; -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ], - }; -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ], - }; +align_const! { + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + ], + }; + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + ], + }; + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + ], + }; +} pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; diff --git a/src/liblibc/src/unix/notbsd/linux/other/b64/not_x32.rs b/src/liblibc/src/unix/notbsd/linux/other/b64/not_x32.rs index 7f42125e56..e3e449807f 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/not_x32.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/not_x32.rs @@ -1,3 +1,5 @@ +use pthread_mutex_t; + pub type c_long = i64; pub type c_ulong = u64; @@ -21,60 +23,56 @@ s! { pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; -#[cfg(target_endian = "little")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; +align_const! { + #[cfg(target_endian = "little")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; +} // Syscall table diff --git a/src/liblibc/src/unix/notbsd/linux/other/b64/powerpc64.rs b/src/liblibc/src/unix/notbsd/linux/other/b64/powerpc64.rs index 858aa243d9..9dd91f0fdd 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/powerpc64.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/powerpc64.rs @@ -1,5 +1,7 @@ //! PowerPC64-specific definitions for 64-bit linux-like values +use pthread_mutex_t; + pub type c_long = i64; pub type c_ulong = u64; pub type c_char = u8; @@ -373,60 +375,56 @@ pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; -#[cfg(target_endian = "little")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "little")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -#[cfg(target_endian = "big")] -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; +align_const! { + #[cfg(target_endian = "little")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "little")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + #[cfg(target_endian = "big")] + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; +} pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; diff --git a/src/liblibc/src/unix/notbsd/linux/other/b64/sparc64.rs b/src/liblibc/src/unix/notbsd/linux/other/b64/sparc64.rs index 8deef063cb..34438a7353 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/sparc64.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/sparc64.rs @@ -1,5 +1,7 @@ //! SPARC64-specific definitions for 64-bit linux-like values +use pthread_mutex_t; + pub type c_long = i64; pub type c_ulong = u64; pub type c_char = i8; @@ -349,30 +351,29 @@ pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; +align_const! { + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; +} pub const O_DIRECTORY: ::c_int = 0o200000; pub const O_NOFOLLOW: ::c_int = 0o400000; diff --git a/src/liblibc/src/unix/notbsd/linux/other/b64/x32.rs b/src/liblibc/src/unix/notbsd/linux/other/b64/x32.rs index 9eb30c84b7..d88dbafed8 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/x32.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/x32.rs @@ -1,3 +1,5 @@ +use pthread_mutex_t; + pub type c_long = i32; pub type c_ulong = u32; @@ -21,30 +23,29 @@ s! { pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 44; -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; +align_const! { + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; +} // Syscall table diff --git a/src/liblibc/src/unix/notbsd/linux/other/mod.rs b/src/liblibc/src/unix/notbsd/linux/other/mod.rs index 6a326dd20e..93b710b8df 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/mod.rs @@ -158,11 +158,16 @@ s! { } // FIXME this is actually a union + #[cfg_attr(all(feature = "align", target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", target_pointer_width = "64"), + repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], + #[cfg(not(feature = "align"))] __align: [::c_long; 0], } diff --git a/src/liblibc/src/unix/notbsd/linux/s390x.rs b/src/liblibc/src/unix/notbsd/linux/s390x.rs index 61745a36cf..9196f88b45 100644 --- a/src/liblibc/src/unix/notbsd/linux/s390x.rs +++ b/src/liblibc/src/unix/notbsd/linux/s390x.rs @@ -1,3 +1,5 @@ +use pthread_mutex_t; + pub type blkcnt_t = i64; pub type blksize_t = i64; pub type c_char = u8; @@ -245,8 +247,13 @@ s! { } // FIXME this is actually a union + #[cfg_attr(all(feature = "align", target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", target_pointer_width = "64"), + repr(align(8)))] pub struct sem_t { __size: [::c_char; 32], + #[cfg(not(feature = "align"))] __align: [::c_long; 0], } @@ -371,30 +378,29 @@ pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; -pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; -pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = - ::pthread_mutex_t { - __align: [], - size: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - }; +align_const! { + pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = + pthread_mutex_t { + size: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; +} pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; diff --git a/src/liblibc/src/unix/solaris/mod.rs b/src/liblibc/src/unix/solaris/mod.rs index db122dea26..697f6b07f5 100644 --- a/src/liblibc/src/unix/solaris/mod.rs +++ b/src/liblibc/src/unix/solaris/mod.rs @@ -354,6 +354,7 @@ s! { pub portev_user: *mut ::c_void, } + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed))] pub struct epoll_event { pub events: ::uint32_t, pub u64: ::uint64_t, @@ -1194,6 +1195,9 @@ pub const PORT_SOURCE_FILE: ::c_int = 7; pub const PORT_SOURCE_POSTWAIT: ::c_int = 8; pub const PORT_SOURCE_SIGNAL: ::c_int = 9; +pub const TIOCGWINSZ: ::c_int = 0x5468; +pub const TIOCSWINSZ: ::c_int = 0x5467; + pub const EPOLLIN: ::c_int = 0x1; pub const EPOLLPRI: ::c_int = 0x2; pub const EPOLLOUT: ::c_int = 0x4; diff --git a/src/liblibc/src/unix/uclibc/mips/mips32.rs b/src/liblibc/src/unix/uclibc/mips/mips32.rs index 7ad547c0ae..dcbfcf8ff2 100644 --- a/src/liblibc/src/unix/uclibc/mips/mips32.rs +++ b/src/liblibc/src/unix/uclibc/mips/mips32.rs @@ -222,11 +222,16 @@ s! { } // FIXME this is actually a union + #[cfg_attr(all(feature = "align", target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", target_pointer_width = "64"), + repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], + #[cfg(not(feature = "align"))] __align: [::c_long; 0], } } diff --git a/src/liblibc/src/unix/uclibc/mips/mips64.rs b/src/liblibc/src/unix/uclibc/mips/mips64.rs index 79bac1fa8a..e35938b1fc 100644 --- a/src/liblibc/src/unix/uclibc/mips/mips64.rs +++ b/src/liblibc/src/unix/uclibc/mips/mips64.rs @@ -188,8 +188,13 @@ s! { } // FIXME this is actually a union + #[cfg_attr(all(feature = "align", target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", target_pointer_width = "64"), + repr(align(8)))] pub struct sem_t { __size: [::c_char; 32], + #[cfg(not(feature = "align"))] __align: [::c_long; 0], } } diff --git a/src/liblibc/src/unix/uclibc/mod.rs b/src/liblibc/src/unix/uclibc/mod.rs index e9c1f21e9e..e3606c2266 100644 --- a/src/liblibc/src/unix/uclibc/mod.rs +++ b/src/liblibc/src/unix/uclibc/mod.rs @@ -224,34 +224,80 @@ s! { pub ifa_data: *mut ::c_void } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))), + repr(align(8)))] pub struct pthread_mutex_t { - #[cfg(any(target_arch = "mips", target_arch = "arm", - target_arch = "powerpc"))] + #[cfg(all(not(feature = "align"), + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", target_arch = "arm", + #[cfg(not(any(feature = "align", + target_arch = "mips", + target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))), + repr(align(8)))] pub struct pthread_rwlock_t { - #[cfg(any(target_arch = "mips", target_arch = "arm", - target_arch = "powerpc"))] + #[cfg(all(not(feature = "align"), + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", target_arch = "arm", + #[cfg(not(any(feature = "align", + target_arch = "mips", + target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], } + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "32", + target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(any(target_pointer_width = "32", + target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))), + repr(align(8)))] pub struct pthread_mutexattr_t { - #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", - target_arch = "mips64", target_arch = "s390x", - target_arch = "sparc64"))] - __align: [::c_int; 0], - #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + #[cfg(all(not(feature = "align"), + any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64")))] + __align: [::c_int; 0], + #[cfg(all(not(feature = "align"), + not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))))] __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } @@ -261,12 +307,16 @@ s! { __pshared: ::c_int, } + #[cfg_attr(feature = "align", repr(align(8)))] pub struct pthread_cond_t { + #[cfg(not(feature = "align"))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_COND_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_condattr_t { + #[cfg(not(feature = "align"))] __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], } @@ -1116,18 +1166,17 @@ pub const RTLD_NOW: ::c_int = 0x2; pub const TCP_MD5SIG: ::c_int = 14; -pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_MUTEX_T], -}; -pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_COND_T], -}; -pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { - __align: [], - size: [0; __SIZEOF_PTHREAD_RWLOCK_T], -}; +align_const! { + pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { + size: [0; __SIZEOF_PTHREAD_MUTEX_T], + }; + pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { + size: [0; __SIZEOF_PTHREAD_COND_T], + }; + pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], + }; +} pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; diff --git a/src/liblibc/src/unix/uclibc/x86_64/mod.rs b/src/liblibc/src/unix/uclibc/x86_64/mod.rs index bfd46447fd..bc6571aff9 100644 --- a/src/liblibc/src/unix/uclibc/x86_64/mod.rs +++ b/src/liblibc/src/unix/uclibc/x86_64/mod.rs @@ -133,6 +133,7 @@ s! { // // pub struct in6_addr { // pub s6_addr: [u8; 16], +// #[cfg(not(feature = "align"))] // __align: [u32; 0], // } @@ -204,51 +205,106 @@ s! { pub c_cc: [::cc_t; ::NCCS], } + #[cfg_attr(all(feature = "align", target_pointer_width = "32"), + repr(align(4)))] + #[cfg_attr(all(feature = "align", target_pointer_width = "64"), + repr(align(8)))] pub struct sem_t { // ToDo #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], + #[cfg(not(feature = "align"))] __align: [::c_long; 0], } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))), + repr(align(8)))] pub struct pthread_mutex_t { // ToDo - #[cfg(any(target_arch = "mips", target_arch = "arm", - target_arch = "powerpc"))] + #[cfg(all(not(feature = "align"), + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", target_arch = "arm", + #[cfg(not(any(feature = "align", + target_arch = "mips", + target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "32", + target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + not(any(target_pointer_width = "32", + target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))), + repr(align(8)))] pub struct pthread_mutexattr_t { // ToDo - #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", - target_arch = "mips64", target_arch = "s390x", - target_arch = "sparc64"))] - __align: [::c_int; 0], - #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", + #[cfg(all(not(feature = "align"), + any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64")))] + __align: [::c_int; 0], + #[cfg(all(not(feature = "align"), + not(any(target_arch = "x86_64", target_arch = "powerpc64", + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))))] __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } + #[cfg_attr(feature = "align", repr(align(8)))] pub struct pthread_cond_t { // ToDo + #[cfg(not(feature = "align"))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_COND_T], } + #[cfg_attr(feature = "align", repr(align(4)))] pub struct pthread_condattr_t { // ToDo + #[cfg(not(feature = "align"))] __align: [::c_int; 0], size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], } + #[cfg_attr(all(feature = "align", + target_pointer_width = "32", + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")), + repr(align(4)))] + #[cfg_attr(all(feature = "align", + any(target_pointer_width = "64", + not(any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))), + repr(align(8)))] pub struct pthread_rwlock_t { // ToDo - #[cfg(any(target_arch = "mips", target_arch = "arm", - target_arch = "powerpc"))] + #[cfg(all(not(feature = "align"), + any(target_arch = "mips", + target_arch = "arm", + target_arch = "powerpc")))] __align: [::c_long; 0], - #[cfg(not(any(target_arch = "mips", target_arch = "arm", + #[cfg(not(any(feature = "align", + target_arch = "mips", + target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 392bf17968..14221f3d79 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -24,13 +24,14 @@ #![feature(core_intrinsics)] #![feature(libc)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(panic_runtime)] #![feature(staged_api)] #![feature(rustc_attrs)] // Rust's "try" function, but if we're aborting on panics we just call the // function as there's nothing else we need to do here. -#[no_mangle] +#[cfg_attr(stage0, no_mangle)] #[rustc_std_internal_symbol] pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), data: *mut u8, @@ -50,7 +51,7 @@ pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), // which would break compat with XP. For now just use `intrinsics::abort` which // will kill us with an illegal instruction, which will do a good enough job for // now hopefully. -#[no_mangle] +#[cfg_attr(stage0, no_mangle)] #[rustc_std_internal_symbol] pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 { abort(); diff --git a/src/libpanic_unwind/wasm32.rs b/src/libpanic_unwind/dummy.rs similarity index 100% rename from src/libpanic_unwind/wasm32.rs rename to src/libpanic_unwind/dummy.rs diff --git a/src/libpanic_unwind/dwarf/mod.rs b/src/libpanic_unwind/dwarf/mod.rs index 5c05ac11d3..7e0c32fe03 100644 --- a/src/libpanic_unwind/dwarf/mod.rs +++ b/src/libpanic_unwind/dwarf/mod.rs @@ -38,7 +38,7 @@ impl DwarfReader { // telling the backend to generate "misalignment-safe" code. pub unsafe fn read(&mut self) -> T { let Unaligned(result) = *(self.ptr as *const Unaligned); - self.ptr = self.ptr.offset(mem::size_of::() as isize); + self.ptr = self.ptr.add(mem::size_of::()); result } diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 5c320bb369..9c3fc76c30 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -34,12 +34,12 @@ #![feature(core_intrinsics)] #![feature(lang_items)] #![feature(libc)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(panic_unwind)] #![feature(raw)] #![feature(staged_api)] #![feature(std_internals)] #![feature(unwind_attributes)] -#![cfg_attr(target_env = "msvc", feature(raw))] #![panic_runtime] #![feature(panic_runtime)] @@ -55,36 +55,33 @@ use core::mem; use core::raw; use core::panic::BoxMeUp; -// Rust runtime's startup objects depend on these symbols, so make them public. -#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] -pub use imp::eh_frame_registry::*; +#[macro_use] +mod macros; -// *-pc-windows-msvc -#[cfg(target_env = "msvc")] -#[path = "seh.rs"] -mod imp; - -// x86_64-pc-windows-gnu -#[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] -#[path = "seh64_gnu.rs"] -mod imp; - -// i686-pc-windows-gnu and all others -#[cfg(any(all(unix, not(target_os = "emscripten")), - target_os = "cloudabi", - target_os = "redox", - all(windows, target_arch = "x86", target_env = "gnu")))] -#[path = "gcc.rs"] -mod imp; - -// emscripten -#[cfg(target_os = "emscripten")] -#[path = "emcc.rs"] -mod imp; - -#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] -#[path = "wasm32.rs"] -mod imp; +cfg_if! { + if #[cfg(target_os = "emscripten")] { + #[path = "emcc.rs"] + mod imp; + } else if #[cfg(target_arch = "wasm32")] { + #[path = "dummy.rs"] + mod imp; + } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { + #[path = "dummy.rs"] + mod imp; + } else if #[cfg(target_env = "msvc")] { + #[path = "seh.rs"] + mod imp; + } else if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] { + #[path = "seh64_gnu.rs"] + mod imp; + } else { + // Rust runtime's startup objects depend on these symbols, so make them public. + #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] + pub use imp::eh_frame_registry::*; + #[path = "gcc.rs"] + mod imp; + } +} mod dwarf; mod windows; diff --git a/src/libpanic_unwind/macros.rs b/src/libpanic_unwind/macros.rs new file mode 100644 index 0000000000..6ea79dc862 --- /dev/null +++ b/src/libpanic_unwind/macros.rs @@ -0,0 +1,45 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// A macro for defining `#[cfg]` if-else statements. +/// +/// This is similar to the `if/elif` C preprocessor macro by allowing definition +/// of a cascade of `#[cfg]` cases, emitting the implementation which matches +/// first. +/// +/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code +/// without having to rewrite each clause multiple times. +macro_rules! cfg_if { + ($( + if #[cfg($($meta:meta),*)] { $($it:item)* } + ) else * else { + $($it2:item)* + }) => { + __cfg_if_items! { + () ; + $( ( ($($meta),*) ($($it)*) ), )* + ( () ($($it2)*) ), + } + } +} + +macro_rules! __cfg_if_items { + (($($not:meta,)*) ; ) => {}; + (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { + __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* } + __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } + } +} + +macro_rules! __cfg_if_apply { + ($m:meta, $($it:item)*) => { + $(#[$m] $it)* + } +} diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index 8cbc4a623f..832a0aff71 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -54,7 +54,7 @@ //! [win64]: http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx //! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions -#![allow(bad_style)] +#![allow(nonstandard_style)] #![allow(private_no_mangle_fns)] use alloc::boxed::Box; @@ -119,7 +119,7 @@ mod imp { } } -#[cfg(target_arch = "x86_64")] +#[cfg(any(target_arch = "x86_64", target_arch = "arm"))] #[macro_use] mod imp { pub type ptr_t = u32; @@ -142,7 +142,7 @@ mod imp { #[repr(C)] pub struct _ThrowInfo { - pub attribues: c_uint, + pub attributes: c_uint, pub pnfnUnwind: imp::ptr_t, pub pForwardCompat: imp::ptr_t, pub pCatchableTypeArray: imp::ptr_t, @@ -178,7 +178,7 @@ pub struct _TypeDescriptor { } static mut THROW_INFO: _ThrowInfo = _ThrowInfo { - attribues: 0, + attributes: 0, pnfnUnwind: ptr!(0), pForwardCompat: ptr!(0), pCatchableTypeArray: ptr!(0), diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index 0b08e54c67..c2074db003 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -11,7 +11,7 @@ //! Unwinding implementation of top of native Win64 SEH, //! however the unwind handler data (aka LSDA) uses GCC-compatible encoding. -#![allow(bad_style)] +#![allow(nonstandard_style)] #![allow(private_no_mangle_fns)] use alloc::boxed::Box; diff --git a/src/libpanic_unwind/windows.rs b/src/libpanic_unwind/windows.rs index 5f1dda36a8..0a1c9b3adf 100644 --- a/src/libpanic_unwind/windows.rs +++ b/src/libpanic_unwind/windows.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(bad_style)] +#![allow(nonstandard_style)] #![allow(dead_code)] #![cfg(windows)] diff --git a/src/libproc_macro/diagnostic.rs b/src/libproc_macro/diagnostic.rs index 51e7647f36..bf23de3943 100644 --- a/src/libproc_macro/diagnostic.rs +++ b/src/libproc_macro/diagnostic.rs @@ -11,11 +11,11 @@ use Span; use rustc_errors as errors; -use syntax_pos::MultiSpan; /// An enum representing a diagnostic level. -#[unstable(feature = "proc_macro_diagnostic", issue = "38356")] +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] #[derive(Copy, Clone, Debug)] +#[non_exhaustive] pub enum Level { /// An error. Error, @@ -25,34 +25,63 @@ pub enum Level { Note, /// A help message. Help, - #[doc(hidden)] - __Nonexhaustive, +} + +/// Trait implemented by types that can be converted into a set of `Span`s. +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] +pub trait MultiSpan { + /// Converts `self` into a `Vec`. + fn into_spans(self) -> Vec; +} + +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] +impl MultiSpan for Span { + fn into_spans(self) -> Vec { + vec![self] + } +} + +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] +impl MultiSpan for Vec { + fn into_spans(self) -> Vec { + self + } +} + +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] +impl<'a> MultiSpan for &'a [Span] { + fn into_spans(self) -> Vec { + self.to_vec() + } } /// A structure representing a diagnostic message and associated children /// messages. -#[unstable(feature = "proc_macro_diagnostic", issue = "38356")] +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] #[derive(Clone, Debug)] pub struct Diagnostic { level: Level, message: String, - span: Option, + spans: Vec, children: Vec } macro_rules! diagnostic_child_methods { ($spanned:ident, $regular:ident, $level:expr) => ( /// Add a new child diagnostic message to `self` with the level - /// identified by this methods name with the given `span` and `message`. - #[unstable(feature = "proc_macro_diagnostic", issue = "38356")] - pub fn $spanned>(mut self, span: Span, message: T) -> Diagnostic { - self.children.push(Diagnostic::spanned(span, $level, message)); + /// identified by this method's name with the given `spans` and + /// `message`. + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] + pub fn $spanned(mut self, spans: S, message: T) -> Diagnostic + where S: MultiSpan, T: Into + { + self.children.push(Diagnostic::spanned(spans, $level, message)); self } /// Add a new child diagnostic message to `self` with the level /// identified by this method's name with the given `message`. - #[unstable(feature = "proc_macro_diagnostic", issue = "38356")] + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn $regular>(mut self, message: T) -> Diagnostic { self.children.push(Diagnostic::new($level, message)); self @@ -60,26 +89,43 @@ macro_rules! diagnostic_child_methods { ) } +/// Iterator over the children diagnostics of a `Diagnostic`. +#[derive(Debug, Clone)] +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] +pub struct Children<'a>(::std::slice::Iter<'a, Diagnostic>); + +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] +impl<'a> Iterator for Children<'a> { + type Item = &'a Diagnostic; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] impl Diagnostic { /// Create a new diagnostic with the given `level` and `message`. - #[unstable(feature = "proc_macro_diagnostic", issue = "38356")] + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn new>(level: Level, message: T) -> Diagnostic { Diagnostic { level: level, message: message.into(), - span: None, + spans: vec![], children: vec![] } } /// Create a new diagnostic with the given `level` and `message` pointing to - /// the given `span`. - #[unstable(feature = "proc_macro_diagnostic", issue = "38356")] - pub fn spanned>(span: Span, level: Level, message: T) -> Diagnostic { + /// the given set of `spans`. + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] + pub fn spanned(spans: S, level: Level, message: T) -> Diagnostic + where S: MultiSpan, T: Into + { Diagnostic { level: level, message: message.into(), - span: Some(span), + spans: spans.into_spans(), children: vec![] } } @@ -90,25 +136,62 @@ impl Diagnostic { diagnostic_child_methods!(span_help, help, Level::Help); /// Returns the diagnostic `level` for `self`. - #[unstable(feature = "proc_macro_diagnostic", issue = "38356")] + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn level(&self) -> Level { self.level } + /// Sets the level in `self` to `level`. + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] + pub fn set_level(&mut self, level: Level) { + self.level = level; + } + + /// Returns the message in `self`. + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] + pub fn message(&self) -> &str { + &self.message + } + + /// Sets the message in `self` to `message`. + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] + pub fn set_message>(&mut self, message: T) { + self.message = message.into(); + } + + /// Returns the `Span`s in `self`. + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] + pub fn spans(&self) -> &[Span] { + &self.spans + } + + /// Sets the `Span`s in `self` to `spans`. + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] + pub fn set_spans(&mut self, spans: S) { + self.spans = spans.into_spans(); + } + + /// Returns an iterator over the children diagnostics of `self`. + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] + pub fn children(&self) -> Children { + Children(self.children.iter()) + } + /// Emit the diagnostic. - #[unstable(feature = "proc_macro_diagnostic", issue = "38356")] + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn emit(self) { + fn to_internal(spans: Vec) -> ::syntax_pos::MultiSpan { + let spans: Vec<_> = spans.into_iter().map(|s| s.0).collect(); + ::syntax_pos::MultiSpan::from_spans(spans) + } + let level = self.level.to_internal(); let mut diag = errors::Diagnostic::new(level, &*self.message); - - if let Some(span) = self.span { - diag.set_span(span.0); - } + diag.set_span(to_internal(self.spans)); for child in self.children { - let span = child.span.map_or(MultiSpan::new(), |s| s.0.into()); let level = child.level.to_internal(); - diag.sub(level, &*child.message, span, None); + diag.sub(level, &*child.message, to_internal(child.spans), None); } ::__internal::with_sess(move |sess, _| { diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index bf6e4a3aaa..1a0dde3ccd 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -12,13 +12,9 @@ //! //! This library, provided by the standard distribution, provides the types //! consumed in the interfaces of procedurally defined macro definitions such as -//! function-like macros `#[proc_macro]`, macro attribures `#[proc_macro_attribute]` and +//! function-like macros `#[proc_macro]`, macro attributes `#[proc_macro_attribute]` and //! custom derive attributes`#[proc_macro_derive]`. //! -//! Note that this crate is intentionally bare-bones currently. -//! This functionality is intended to be expanded over time as more surface -//! area for macro authors is stabilized. -//! //! See [the book](../book/first-edition/procedural-macros.html) for more. #![stable(feature = "proc_macro_lib", since = "1.15.0")] @@ -31,10 +27,12 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))] +#![cfg_attr(not(stage0), feature(nll))] #![feature(rustc_private)] #![feature(staged_api)] #![feature(lang_items)] #![feature(optin_builtin_traits)] +#![feature(non_exhaustive)] #![recursion_limit="256"] @@ -49,7 +47,7 @@ pub mod rustc; mod diagnostic; -#[unstable(feature = "proc_macro_diagnostic", issue = "38356")] +#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level}; use std::{ascii, fmt, iter}; @@ -60,8 +58,8 @@ use std::str::FromStr; use syntax::errors::DiagnosticBuilder; use syntax::parse::{self, token}; use syntax::symbol::Symbol; -use syntax::tokenstream; -use syntax_pos::{FileMap, Pos, FileName}; +use syntax::tokenstream::{self, DelimSpan}; +use syntax_pos::{Pos, FileName}; /// The main type provided by this crate, representing an abstract stream of /// tokens, or, more specifically, a sequence of token trees. @@ -70,9 +68,6 @@ use syntax_pos::{FileMap, Pos, FileName}; /// /// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]` /// and `#[proc_macro_derive]` definitions. -/// -/// The API of this type is intentionally bare-bones, but it'll be expanded over -/// time! #[stable(feature = "proc_macro_lib", since = "1.15.0")] #[derive(Clone)] pub struct TokenStream(tokenstream::TokenStream); @@ -179,6 +174,20 @@ impl iter::FromIterator for TokenStream { } } +#[stable(feature = "token_stream_extend", since = "1.30.0")] +impl Extend for TokenStream { + fn extend>(&mut self, trees: I) { + self.extend(trees.into_iter().map(TokenStream::from)); + } +} + +#[stable(feature = "token_stream_extend", since = "1.30.0")] +impl Extend for TokenStream { + fn extend>(&mut self, streams: I) { + self.0.extend(streams.into_iter().map(|stream| stream.0)); + } +} + /// Public implementation details for the `TokenStream` type, such as iterators. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub mod token_stream { @@ -265,7 +274,7 @@ macro_rules! diagnostic_method { ($name:ident, $level:expr) => ( /// Create a new `Diagnostic` with the given `message` at the span /// `self`. - #[unstable(feature = "proc_macro_diagnostic", issue = "38356")] + #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn $name>(self, message: T) -> Diagnostic { Diagnostic::spanned(self, $level, message) } @@ -292,7 +301,7 @@ impl Span { #[unstable(feature = "proc_macro_span", issue = "38356")] pub fn source_file(&self) -> SourceFile { SourceFile { - filemap: __internal::lookup_char_pos(self.0.lo()).file, + source_file: __internal::lookup_char_pos(self.0.lo()).file, } } @@ -403,7 +412,7 @@ impl !Sync for LineColumn {} #[unstable(feature = "proc_macro_span", issue = "38356")] #[derive(Clone)] pub struct SourceFile { - filemap: Lrc, + source_file: Lrc, } #[unstable(feature = "proc_macro_span", issue = "38356")] @@ -416,7 +425,7 @@ impl SourceFile { /// /// ### Note /// If the code span associated with this `SourceFile` was generated by an external macro, this - /// may not be an actual path on the filesystem. Use [`is_real`] to check. + /// macro, this may not be an actual path on the filesystem. Use [`is_real`] to check. /// /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on /// the command line, the path as given may not actually be valid. @@ -424,9 +433,9 @@ impl SourceFile { /// [`is_real`]: #method.is_real #[unstable(feature = "proc_macro_span", issue = "38356")] pub fn path(&self) -> PathBuf { - match self.filemap.name { + match self.source_file.name { FileName::Real(ref path) => path.clone(), - _ => PathBuf::from(self.filemap.name.to_string()) + _ => PathBuf::from(self.source_file.name.to_string()) } } @@ -437,7 +446,7 @@ impl SourceFile { // This is a hack until intercrate spans are implemented and we can have real source files // for spans generated in external macros. // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368 - self.filemap.is_real_file() + self.source_file.is_real_file() } } @@ -455,7 +464,7 @@ impl fmt::Debug for SourceFile { #[unstable(feature = "proc_macro_span", issue = "38356")] impl PartialEq for SourceFile { fn eq(&self, other: &Self) -> bool { - Lrc::ptr_eq(&self.filemap, &other.filemap) + Lrc::ptr_eq(&self.source_file, &other.source_file) } } @@ -592,7 +601,7 @@ impl fmt::Display for TokenTree { pub struct Group { delimiter: Delimiter, stream: TokenStream, - span: Span, + span: DelimSpan, } #[stable(feature = "proc_macro_lib2", since = "1.29.0")] @@ -633,7 +642,7 @@ impl Group { Group { delimiter: delimiter, stream: stream, - span: Span::call_site(), + span: DelimSpan::from_single(Span::call_site().0), } } @@ -654,9 +663,36 @@ impl Group { /// Returns the span for the delimiters of this token stream, spanning the /// entire `Group`. + /// + /// ```text + /// pub fn span(&self) -> Span { + /// ^^^^^^^ + /// ``` #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn span(&self) -> Span { - self.span + Span(self.span.entire()) + } + + /// Returns the span pointing to the opening delimiter of this group. + /// + /// ```text + /// pub fn span_open(&self) -> Span { + /// ^ + /// ``` + #[unstable(feature = "proc_macro_span", issue = "38356")] + pub fn span_open(&self) -> Span { + Span(self.span.open) + } + + /// Returns the span pointing to the closing delimiter of this group. + /// + /// ```text + /// pub fn span_close(&self) -> Span { + /// ^ + /// ``` + #[unstable(feature = "proc_macro_span", issue = "38356")] + pub fn span_close(&self) -> Span { + Span(self.span.close) } /// Configures the span for this `Group`'s delimiters, but not its internal @@ -667,7 +703,7 @@ impl Group { /// tokens at the level of the `Group`. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn set_span(&mut self, span: Span) { - self.span = span; + self.span = DelimSpan::from_single(span.0); } } @@ -1170,7 +1206,7 @@ pub mod __internal { use super::{TokenStream, LexError, Span}; pub fn lookup_char_pos(pos: BytePos) -> Loc { - with_sess(|sess, _| sess.codemap().lookup_char_pos(pos)) + with_sess(|sess, _| sess.source_map().lookup_char_pos(pos)) } pub fn new_token_stream(item: P) -> TokenStream { diff --git a/src/libproc_macro/rustc.rs b/src/libproc_macro/rustc.rs index a54c695f63..3ce02d1afb 100644 --- a/src/libproc_macro/rustc.rs +++ b/src/libproc_macro/rustc.rs @@ -64,7 +64,7 @@ impl TokenTree { tokenstream::TokenTree::Delimited(span, delimed) => { let delimiter = Delimiter::from_internal(delimed.delim); let mut g = Group::new(delimiter, ::TokenStream(delimed.tts.into())); - g.set_span(Span(span)); + g.span = span; return g.into(); } }; @@ -192,7 +192,7 @@ impl TokenTree { self::TokenTree::Punct(tt) => (tt.as_char(), tt.spacing(), tt.span()), self::TokenTree::Group(tt) => { return TokenTree::Delimited( - tt.span.0, + tt.span, Delimited { delim: tt.delimiter.to_internal(), tts: tt.stream.0.into(), @@ -278,7 +278,6 @@ impl Level { Level::Warning => errors::Level::Warning, Level::Note => errors::Level::Note, Level::Help => errors::Level::Help, - Level::__Nonexhaustive => unreachable!("Level::__Nonexhaustive"), } } } diff --git a/src/libprofiler_builtins/lib.rs b/src/libprofiler_builtins/lib.rs index 6d0d6d115b..a85593253b 100644 --- a/src/libprofiler_builtins/lib.rs +++ b/src/libprofiler_builtins/lib.rs @@ -15,4 +15,5 @@ reason = "internal implementation detail of rustc right now", issue = "0")] #![allow(unused_features)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(staged_api)] diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 457a9f2f62..6c3b52196a 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -29,9 +29,11 @@ serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } backtrace = "0.3.3" -parking_lot = "0.5.5" +parking_lot = "0.6" byteorder = { version = "1.1", features = ["i128"]} -chalk-engine = { version = "0.6.0", default-features=false } +chalk-engine = { version = "0.7.0", default-features=false } +rustc_fs_util = { path = "../librustc_fs_util" } +smallvec = { version = "0.6.5", features = ["union"] } # Note that these dependencies are a lie, they're just here to get linkage to # work. diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 98cfa094c1..6b9c0aac52 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -488,8 +488,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // expression to target let guard_start = self.add_dummy_node(&[pat_exit]); // Visit the guard expression - let guard_exit = self.expr(&guard, guard_start); - + let guard_exit = match guard { + hir::Guard::If(ref e) => self.expr(e, guard_start), + }; // #47295: We used to have very special case code // here for when a pair of arms are both formed // solely from constants, and if so, not add these @@ -555,7 +556,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { target_scope: region::Scope, to_index: CFGIndex) { let mut data = CFGEdgeData { exiting_scopes: vec![] }; - let mut scope = region::Scope::Node(from_expr.hir_id.local_id); + let mut scope = region::Scope { + id: from_expr.hir_id.local_id, + data: region::ScopeData::Node + }; let region_scope_tree = self.tcx.region_scope_tree(self.owner_def_id); while scope != target_scope { data.exiting_scopes.push(scope.item_local_id()); @@ -585,8 +589,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { Ok(loop_id) => { for b in &self.breakable_block_scopes { if b.block_expr_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { - let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id; - return (region::Scope::Node(scope_id), match scope_cf_kind { + let scope = region::Scope { + id: self.tcx.hir.node_to_hir_id(loop_id).local_id, + data: region::ScopeData::Node + }; + return (scope, match scope_cf_kind { ScopeCfKind::Break => b.break_index, ScopeCfKind::Continue => bug!("can't continue to block"), }); @@ -594,8 +601,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } for l in &self.loop_scopes { if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { - let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id; - return (region::Scope::Node(scope_id), match scope_cf_kind { + let scope = region::Scope { + id: self.tcx.hir.node_to_hir_id(loop_id).local_id, + data: region::ScopeData::Node + }; + return (scope, match scope_cf_kind { ScopeCfKind::Break => l.break_index, ScopeCfKind::Continue => l.continue_index, }); diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 14a818ddaf..d15568af6a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -75,7 +75,7 @@ use traits::query::{ CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, }; use ty::{TyCtxt, FnSig, Instance, InstanceDef, - ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty, self}; + ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty}; use ty::subst::Substs; // erase!() just makes tokens go away. It's used to specify which macro argument @@ -574,6 +574,7 @@ define_dep_nodes!( <'tcx> [] IsPanicRuntime(CrateNum), [] IsCompilerBuiltins(CrateNum), [] HasGlobalAllocator(CrateNum), + [] HasPanicHandler(CrateNum), [input] ExternCrate(DefId), [eval_always] LintLevels, [] Specializes { impl1: DefId, impl2: DefId }, @@ -615,7 +616,9 @@ define_dep_nodes!( <'tcx> [input] CrateName(CrateNum), [] ItemChildren(DefId), [] ExternModStmtCnum(DefId), - [input] GetLangItems, + [eval_always] GetLibFeatures, + [] DefinedLibFeatures(CrateNum), + [eval_always] GetLangItems, [] DefinedLangItems(CrateNum), [] MissingLangItems(CrateNum), [] VisibleParentMap, @@ -630,7 +633,6 @@ define_dep_nodes!( <'tcx> // queries). Making them anonymous avoids hashing the result, which // may save a bit of time. [anon] EraseRegionsTy { ty: Ty<'tcx> }, - [anon] ConstValueToAllocation { val: &'tcx ty::Const<'tcx> }, [input] Freevars(DefId), [input] MaybeUnusedTraitImport(DefId), diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index e308f2924a..f5a4606075 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -12,7 +12,7 @@ use errors::DiagnosticBuilder; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; use rustc_data_structures::sync::{Lrc, Lock}; use std::env; use std::hash::Hash; @@ -39,10 +39,12 @@ pub struct DepGraph { fingerprints: Lrc>> } -newtype_index!(DepNodeIndex); +newtype_index! { + pub struct DepNodeIndex { .. } +} impl DepNodeIndex { - const INVALID: DepNodeIndex = DepNodeIndex(::std::u32::MAX); + const INVALID: DepNodeIndex = DepNodeIndex::MAX; } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] @@ -878,7 +880,7 @@ pub struct WorkProduct { pub saved_files: Vec<(WorkProductFileKind, String)>, } -#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, PartialEq)] pub enum WorkProductFileKind { Object, Bytecode, @@ -1025,7 +1027,7 @@ impl CurrentDepGraph { } = task { debug_assert_eq!(node, key); let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)]; - self.alloc_node(node, SmallVec::one(krate_idx)) + self.alloc_node(node, smallvec![krate_idx]) } else { bug!("complete_eval_always_task() - Expected eval always task to be popped"); } @@ -1125,14 +1127,16 @@ impl DepNodeColorMap { match self.values[index] { COMPRESSED_NONE => None, COMPRESSED_RED => Some(DepNodeColor::Red), - value => Some(DepNodeColor::Green(DepNodeIndex(value - COMPRESSED_FIRST_GREEN))) + value => Some(DepNodeColor::Green(DepNodeIndex::from_u32( + value - COMPRESSED_FIRST_GREEN + ))) } } fn insert(&mut self, index: SerializedDepNodeIndex, color: DepNodeColor) { self.values[index] = match color { DepNodeColor::Red => COMPRESSED_RED, - DepNodeColor::Green(index) => index.0 + COMPRESSED_FIRST_GREEN, + DepNodeColor::Green(index) => index.as_u32() + COMPRESSED_FIRST_GREEN, } } } diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs index 60fc813a25..4c896a33e5 100644 --- a/src/librustc/dep_graph/serialized.rs +++ b/src/librustc/dep_graph/serialized.rs @@ -14,7 +14,9 @@ use dep_graph::DepNode; use ich::Fingerprint; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; -newtype_index!(SerializedDepNodeIndex); +newtype_index! { + pub struct SerializedDepNodeIndex { .. } +} /// Data for use when recompiling the **current crate**. #[derive(Debug, RustcEncodable, RustcDecodable)] diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 5ace8397d9..3318bbd8c8 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1232,41 +1232,54 @@ let x: i32 = "I am not a number!"; "##, E0309: 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. +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 T is not constrained, meaning the data -// stored in it is not guaranteed to last as long as the reference +// 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: &'a T + foo: >::Output, } -``` -This will compile, because it has the constraint on the type parameter: +trait SomeTrait<'a> { + type Output; +} -``` -struct Foo<'a, T: 'a> { - foo: &'a T +impl<'a, T> SomeTrait<'a> for T +where + T: 'a, +{ + type Output = u32; } ``` -To see why this is important, consider the case where `T` is itself a reference -(e.g., `T = &str`). If we don't include the restriction that `T: 'a`, the -following code would be perfectly legal: +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: -```compile_fail,E0309 -struct Foo<'a, T> { - foo: &'a T +``` +struct Foo<'a, T> +where + T: 'a, +{ + foo: >::Output } -fn main() { - let v = "42".to_string(); - let f = Foo{foo: &v}; - drop(v); - println!("{}", f.foo); // but we've already dropped v! +trait SomeTrait<'a> { + type Output; +} + +impl<'a, T> SomeTrait<'a> for T +where + T: 'a, +{ + type Output = u32; } ``` "##, @@ -1465,30 +1478,31 @@ A reference has a longer lifetime than the data it references. Erroneous code example: ```compile_fail,E0491 -// struct containing a reference requires a lifetime parameter, -// because the data the reference points to must outlive the struct (see E0106) -struct Struct<'a> { - ref_i32: &'a i32, +trait SomeTrait<'a> { + type Output; } -// However, a nested struct like this, the signature itself does not tell -// whether 'a outlives 'b or the other way around. -// So it could be possible that 'b of reference outlives 'a of the data. -struct Nested<'a, 'b> { - ref_struct: &'b Struct<'a>, // compile error E0491 +impl<'a, T> SomeTrait<'a> for T { + type Output = &'a T; // compile error E0491 } ``` -To fix this issue, you can specify a bound to the lifetime like below: +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`. ``` -struct Struct<'a> { - ref_i32: &'a i32, +trait SomeTrait<'a> { + type Output; } -// 'a: 'b means 'a outlives 'b -struct Nested<'a: 'b, 'b> { - ref_struct: &'b Struct<'a>, +impl<'a, T> SomeTrait<'a> for T +where + T: 'a, +{ + type Output = &'a T; // compile error E0491 } ``` "##, @@ -1918,6 +1932,30 @@ fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { ``` "##, +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. @@ -2138,4 +2176,5 @@ register_diagnostics! { E0708, // `async` non-`move` closures with arguments 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 } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 9ded7bc28b..298ef67923 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -125,7 +125,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { .iter() .filter(|attr| attr.name() == "repr") .filter_map(|attr| attr.meta_item_list()) - .flat_map(|hints| hints) + .flatten() .collect(); let mut int_reprs = 0; @@ -185,7 +185,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { continue } } - "i8" | "u8" | "i16" | "u16" | + "i8" | "u8" | "i16" | "u16" | "i32" | "u32" | "i64" | "u64" | "isize" | "usize" => { int_reprs += 1; diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 1c355e35fd..4286b0628f 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -28,6 +28,18 @@ pub enum CtorKind { Fictive, } +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum NonMacroAttrKind { + /// Single-segment attribute defined by the language (`#[inline]`) + Builtin, + /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`). + Tool, + /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`). + DeriveHelper, + /// Single-segment custom attribute not registered in any way (`#[my_attr]`). + Custom, +} + #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Def { // Type namespace @@ -41,7 +53,7 @@ pub enum Def { Existential(DefId), /// `type Foo = Bar;` TyAlias(DefId), - TyForeign(DefId), + ForeignTy(DefId), TraitAlias(DefId), AssociatedTy(DefId), /// `existential type Foo: Bar;` @@ -49,13 +61,15 @@ pub enum Def { PrimTy(hir::PrimTy), TyParam(DefId), SelfTy(Option /* trait */, Option /* impl */), + ToolMod, // e.g. `rustfmt` in `#[rustfmt::skip]` // Value namespace Fn(DefId), Const(DefId), Static(DefId, bool /* is_mutbl */), StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor - VariantCtor(DefId, CtorKind), + VariantCtor(DefId, CtorKind), // DefId refers to the enum variant + SelfCtor(DefId /* impl */), // DefId refers to the impl Method(DefId), AssociatedConst(DefId), @@ -67,8 +81,7 @@ pub enum Def { // Macro namespace Macro(DefId, MacroKind), - - GlobalAsm(DefId), + NonMacroAttr(NonMacroAttrKind), // e.g. `#[inline]` or `#[rustfmt::skip]` // Both namespaces Err, @@ -240,6 +253,17 @@ impl CtorKind { } } +impl NonMacroAttrKind { + fn descr(self) -> &'static str { + match self { + NonMacroAttrKind::Builtin => "built-in attribute", + NonMacroAttrKind::Tool => "tool attribute", + NonMacroAttrKind::DeriveHelper => "derive helper attribute", + NonMacroAttrKind::Custom => "custom attribute", + } + } +} + impl Def { pub fn def_id(&self) -> DefId { match *self { @@ -249,8 +273,8 @@ impl Def { Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) | Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | Def::Macro(id, ..) | - Def::Existential(id) | Def::AssociatedExistential(id) | - Def::GlobalAsm(id) | Def::TyForeign(id) => { + Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) | + Def::SelfCtor(id) => { id } @@ -259,6 +283,8 @@ impl Def { Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | + Def::ToolMod | + Def::NonMacroAttr(..) | Def::Err => { bug!("attempted .def_id() on invalid def: {:?}", self) } @@ -285,9 +311,10 @@ impl Def { Def::StructCtor(.., CtorKind::Fn) => "tuple struct", Def::StructCtor(.., CtorKind::Const) => "unit struct", Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"), + Def::SelfCtor(..) => "self constructor", Def::Union(..) => "union", Def::Trait(..) => "trait", - Def::TyForeign(..) => "foreign type", + Def::ForeignTy(..) => "foreign type", Def::Method(..) => "method", Def::Const(..) => "constant", Def::AssociatedConst(..) => "associated constant", @@ -298,7 +325,8 @@ impl Def { Def::Label(..) => "label", Def::SelfTy(..) => "self type", Def::Macro(.., macro_kind) => macro_kind.descr(), - Def::GlobalAsm(..) => "global asm", + Def::ToolMod => "tool module", + Def::NonMacroAttr(attr_kind) => attr_kind.descr(), Def::Err => "unresolved item", } } diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 7acfe68395..cd91b85689 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -9,50 +9,88 @@ // except according to those terms. use ty; - +use hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX; use rustc_data_structures::indexed_vec::Idx; use serialize; use std::fmt; use std::u32; -newtype_index!(CrateNum - { +newtype_index! { + pub struct CrateId { ENCODABLE = custom - DEBUG_FORMAT = "crate{}", + } +} - /// Item definitions in the currently-compiled crate would have the CrateNum - /// LOCAL_CRATE in their DefId. - const LOCAL_CRATE = 0, +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum CrateNum { + /// Virtual crate for builtin macros + // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get + // `CrateNum`s. + BuiltinMacros, + /// A CrateNum value that indicates that something is wrong. + Invalid, + /// A special CrateNum that we use for the tcx.rcache when decoding from + /// the incr. comp. cache. + ReservedForIncrCompCache, + Index(CrateId), +} + +impl ::std::fmt::Debug for CrateNum { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + CrateNum::Index(id) => write!(fmt, "crate{}", id.private), + CrateNum::Invalid => write!(fmt, "invalid crate"), + CrateNum::BuiltinMacros => write!(fmt, "bultin macros crate"), + CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"), + } + } +} + +/// Item definitions in the currently-compiled crate would have the CrateNum +/// LOCAL_CRATE in their DefId. +pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); - /// Virtual crate for builtin macros - // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get - // `CrateNum`s. - const BUILTIN_MACROS_CRATE = u32::MAX, - /// A CrateNum value that indicates that something is wrong. - const INVALID_CRATE = u32::MAX - 1, +impl Idx for CrateNum { + #[inline] + fn new(value: usize) -> Self { + CrateNum::Index(Idx::new(value)) + } - /// A special CrateNum that we use for the tcx.rcache when decoding from - /// the incr. comp. cache. - const RESERVED_FOR_INCR_COMP_CACHE = u32::MAX - 2, - }); + #[inline] + fn index(self) -> usize { + match self { + CrateNum::Index(idx) => Idx::index(idx), + _ => bug!("Tried to get crate index of {:?}", self), + } + } +} impl CrateNum { pub fn new(x: usize) -> CrateNum { - assert!(x < (u32::MAX as usize)); - CrateNum(x as u32) + CrateNum::from_usize(x) + } + + pub fn from_usize(x: usize) -> CrateNum { + CrateNum::Index(CrateId::from_usize(x)) } pub fn from_u32(x: u32) -> CrateNum { - CrateNum(x) + CrateNum::Index(CrateId::from_u32(x)) } - pub fn as_usize(&self) -> usize { - self.0 as usize + pub fn as_usize(self) -> usize { + match self { + CrateNum::Index(id) => id.as_usize(), + _ => bug!("tried to get index of nonstandard crate {:?}", self), + } } - pub fn as_u32(&self) -> u32 { - self.0 + pub fn as_u32(self) -> u32 { + match self { + CrateNum::Index(id) => id.as_u32(), + _ => bug!("tried to get index of nonstandard crate {:?}", self), + } } pub fn as_def_id(&self) -> DefId { DefId { krate: *self, index: CRATE_DEF_INDEX } } @@ -60,7 +98,12 @@ impl CrateNum { impl fmt::Display for CrateNum { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.0, f) + match self { + CrateNum::Index(id) => fmt::Display::fmt(&id.private, f), + CrateNum::Invalid => write!(f, "invalid crate"), + CrateNum::BuiltinMacros => write!(f, "bultin macros crate"), + CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"), + } } } @@ -125,15 +168,25 @@ impl DefIndex { // index of the macro in the CrateMetadata::proc_macros array) to the // corresponding DefIndex. pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex { - let def_index = DefIndex::from_array_index(proc_macro_index, - DefIndexAddressSpace::High); + // DefIndex for proc macros start from FIRST_FREE_HIGH_DEF_INDEX, + // because the first FIRST_FREE_HIGH_DEF_INDEX indexes are reserved + // for internal use. + let def_index = DefIndex::from_array_index( + proc_macro_index.checked_add(FIRST_FREE_HIGH_DEF_INDEX) + .expect("integer overflow adding `proc_macro_index`"), + DefIndexAddressSpace::High); assert!(def_index != CRATE_DEF_INDEX); def_index } // This function is the reverse of from_proc_macro_index() above. pub fn to_proc_macro_index(self: DefIndex) -> usize { - self.as_array_index() + assert_eq!(self.address_space(), DefIndexAddressSpace::High); + + self.as_array_index().checked_sub(FIRST_FREE_HIGH_DEF_INDEX) + .unwrap_or_else(|| { + bug!("using local index {:?} as proc-macro index", self) + }) } // Don't use this if you don't know about the DefIndex encoding. @@ -150,7 +203,7 @@ impl DefIndex { impl serialize::UseSpecializedEncodable for DefIndex {} impl serialize::UseSpecializedDecodable for DefIndex {} -#[derive(Copy, Clone, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum DefIndexAddressSpace { Low = 0, High = 1, diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 4274cd3a0a..76c2ebc0e4 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -50,7 +50,6 @@ use super::itemlikevisit::DeepVisitor; use std::cmp; use std::u32; -use std::result::Result::Err; #[derive(Copy, Clone)] pub enum FnKind<'a> { @@ -353,10 +352,10 @@ pub trait Visitor<'v> : Sized { fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { walk_lifetime(self, lifetime) } - fn visit_qpath(&mut self, qpath: &'v QPath, id: NodeId, span: Span) { + fn visit_qpath(&mut self, qpath: &'v QPath, id: HirId, span: Span) { walk_qpath(self, qpath, id, span) } - fn visit_path(&mut self, path: &'v Path, _id: NodeId) { + fn visit_path(&mut self, path: &'v Path, _id: HirId) { walk_path(self, path) } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { @@ -456,7 +455,7 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef) where V: Visitor<'v> { visitor.visit_id(trait_ref.ref_id); - visitor.visit_path(&trait_ref.path, trait_ref.ref_id) + visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id) } pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { @@ -471,7 +470,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { } ItemKind::Use(ref path, _) => { visitor.visit_id(item.id); - visitor.visit_path(path, item.id); + visitor.visit_path(path, item.hir_id); } ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => { @@ -602,7 +601,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_fn_decl(&function_declaration.decl); } TyKind::Path(ref qpath) => { - visitor.visit_qpath(qpath, typ.id, typ.span); + visitor.visit_qpath(qpath, typ.hir_id, typ.span); } TyKind::Array(ref ty, ref length) => { visitor.visit_ty(ty); @@ -621,7 +620,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { } } -pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: NodeId, span: Span) { +pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: HirId, span: Span) { match *qpath { QPath::Resolved(ref maybe_qself, ref path) => { if let Some(ref qself) = *maybe_qself { @@ -670,14 +669,14 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { visitor.visit_id(pattern.id); match pattern.node { PatKind::TupleStruct(ref qpath, ref children, _) => { - visitor.visit_qpath(qpath, pattern.id, pattern.span); + visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); walk_list!(visitor, visit_pat, children); } PatKind::Path(ref qpath) => { - visitor.visit_qpath(qpath, pattern.id, pattern.span); + visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); } PatKind::Struct(ref qpath, ref fields, _) => { - visitor.visit_qpath(qpath, pattern.id, pattern.span); + visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); for field in fields { visitor.visit_id(field.node.id); visitor.visit_ident(field.node.ident); @@ -985,7 +984,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_anon_const(count) } ExprKind::Struct(ref qpath, ref fields, ref optional_base) => { - visitor.visit_qpath(qpath, expression.id, expression.span); + visitor.visit_qpath(qpath, expression.hir_id, expression.span); for field in fields { visitor.visit_id(field.id); visitor.visit_ident(field.ident); @@ -1062,36 +1061,31 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(index_expression) } ExprKind::Path(ref qpath) => { - visitor.visit_qpath(qpath, expression.id, expression.span); + visitor.visit_qpath(qpath, expression.hir_id, expression.span); } ExprKind::Break(ref destination, ref opt_expr) => { if let Some(ref label) = destination.label { visitor.visit_label(label); - match destination.target_id { - Ok(node_id) => visitor.visit_def_mention(Def::Label(node_id)), - Err(_) => {}, - }; + if let Ok(node_id) = destination.target_id { + visitor.visit_def_mention(Def::Label(node_id)) + } } walk_list!(visitor, visit_expr, opt_expr); } ExprKind::Continue(ref destination) => { if let Some(ref label) = destination.label { visitor.visit_label(label); - match destination.target_id { - Ok(node_id) => visitor.visit_def_mention(Def::Label(node_id)), - Err(_) => {}, - }; + if let Ok(node_id) = destination.target_id { + visitor.visit_def_mention(Def::Label(node_id)) + } } } ExprKind::Ret(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } ExprKind::InlineAsm(_, ref outputs, ref inputs) => { - for output in outputs { - visitor.visit_expr(output) - } - for input in inputs { - visitor.visit_expr(input) + for expr in outputs.iter().chain(inputs.iter()) { + visitor.visit_expr(expr) } } ExprKind::Yield(ref subexpression) => { @@ -1102,15 +1096,19 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { walk_list!(visitor, visit_pat, &arm.pats); - walk_list!(visitor, visit_expr, &arm.guard); + if let Some(ref g) = arm.guard { + match g { + Guard::If(ref e) => visitor.visit_expr(e), + } + } visitor.visit_expr(&arm.body); walk_list!(visitor, visit_attribute, &arm.attrs); } pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) { - if let VisibilityKind::Restricted { ref path, id } = vis.node { + if let VisibilityKind::Restricted { ref path, id, hir_id } = vis.node { visitor.visit_id(id); - visitor.visit_path(path, id) + visitor.visit_path(path, hir_id) } } @@ -1152,7 +1150,6 @@ impl IdRange { self.min = cmp::min(self.min, id); self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1)); } - } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 63755bcea5..bd8770abb1 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,12 +50,15 @@ use hir::GenericArg; use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, ELIDED_LIFETIMES_IN_PATHS}; use middle::cstore::CrateStore; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::small_vec::OneVector; +use rustc_data_structures::thin_vec::ThinVec; use session::Session; use util::common::FN_OUTPUT_NAME; use util::nodemap::{DefIdMap, NodeMap}; -use std::collections::{BTreeMap, HashSet}; +use std::collections::BTreeMap; use std::fmt::Debug; use std::iter; use std::mem; @@ -64,14 +67,14 @@ use syntax::ast; use syntax::ast::*; use syntax::errors; use syntax::ext::hygiene::{Mark, SyntaxContext}; +use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::print::pprust; use syntax::ptr::P; -use syntax::codemap::{self, respan, CompilerDesugaringKind, Spanned}; +use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned}; use syntax::std_inject; use syntax::symbol::{keywords, Symbol}; use syntax::tokenstream::{Delimited, TokenStream, TokenTree}; use syntax::parse::token::Token; -use syntax::util::small_vector::SmallVector; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, MultiSpan}; @@ -123,8 +126,8 @@ pub struct LoweringContext<'a> { // Whether or not in-band lifetimes are being collected. This is used to // indicate whether or not we're in a place where new lifetimes will result // in in-band lifetime definitions, such a function or an impl header. - // This will always be false unless the `in_band_lifetimes` feature is - // enabled. + // This will always be false unless the `in_band_lifetimes` or + // `impl_header_lifetime_elision` feature is enabled. is_collecting_in_band_lifetimes: bool, // Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB. @@ -594,7 +597,7 @@ impl<'a> LoweringContext<'a> { }) } - fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator { + fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator { self.resolver.get_import(id).present_items().map(|pr| { if pr.unresolved_segments() != 0 { bug!("path not fully resolved: {:?}", pr); @@ -613,14 +616,14 @@ impl<'a> LoweringContext<'a> { fn allow_internal_unstable(&self, reason: CompilerDesugaringKind, span: Span) -> Span { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(codemap::ExpnInfo { + mark.set_expn_info(source_map::ExpnInfo { call_site: span, def_site: Some(span), - format: codemap::CompilerDesugaring(reason), + format: source_map::CompilerDesugaring(reason), allow_internal_unstable: true, allow_internal_unsafe: false, local_inner_macros: false, - edition: codemap::hygiene::default_edition(), + edition: source_map::hygiene::default_edition(), }); span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } @@ -658,9 +661,11 @@ impl<'a> LoweringContext<'a> { assert!(self.lifetimes_to_define.is_empty()); let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; - self.is_collecting_in_band_lifetimes = self.sess.features_untracked().in_band_lifetimes; - if self.is_collecting_in_band_lifetimes { + if self.sess.features_untracked().impl_header_lifetime_elision { self.anonymous_lifetime_mode = anonymous_lifetime_mode; + self.is_collecting_in_band_lifetimes = true; + } else if self.sess.features_untracked().in_band_lifetimes { + self.is_collecting_in_band_lifetimes = true; } let (in_band_ty_params, res) = f(self); @@ -718,6 +723,10 @@ impl<'a> LoweringContext<'a> { return; } + if !self.sess.features_untracked().in_band_lifetimes { + return; + } + if self.in_scope_lifetimes.contains(&ident.modern()) { return; } @@ -981,7 +990,7 @@ impl<'a> LoweringContext<'a> { None => { self.loop_scopes .last() - .map(|innermost_loop_id| *innermost_loop_id) + .cloned() .map(|id| Ok(self.lower_node_id(id).node_id)) .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)) .into() @@ -1046,7 +1055,10 @@ impl<'a> LoweringContext<'a> { hir::Arm { attrs: self.lower_attrs(&arm.attrs), pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(), - guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))), + guard: match arm.guard { + Some(Guard::If(ref x)) => Some(hir::Guard::If(P(self.lower_expr(x)))), + _ => None, + }, body: P(self.lower_expr(&arm.body)), } } @@ -1176,7 +1188,7 @@ impl<'a> LoweringContext<'a> { } ImplTraitContext::Universal(in_band_ty_params) => { self.lower_node_id(def_node_id); - // Add a definition for the in-band TyParam + // Add a definition for the in-band Param let def_index = self .resolver .definitions() @@ -1335,7 +1347,7 @@ impl<'a> LoweringContext<'a> { exist_ty_id: NodeId, collect_elided_lifetimes: bool, currently_bound_lifetimes: Vec, - already_defined_lifetimes: HashSet, + already_defined_lifetimes: FxHashSet, output_lifetimes: Vec, output_lifetime_params: Vec, } @@ -1469,7 +1481,7 @@ impl<'a> LoweringContext<'a> { exist_ty_id, collect_elided_lifetimes: true, currently_bound_lifetimes: Vec::new(), - already_defined_lifetimes: HashSet::new(), + already_defined_lifetimes: FxHashSet::default(), output_lifetimes: Vec::new(), output_lifetime_params: Vec::new(), }; @@ -2149,12 +2161,14 @@ impl<'a> LoweringContext<'a> { let future_path = this.std_path(span, &["future", "Future"], Some(future_params), false); + let LoweredNodeId { node_id, hir_id } = this.next_id(); let mut bounds = vec![ hir::GenericBound::Trait( hir::PolyTraitRef { trait_ref: hir::TraitRef { path: future_path, - ref_id: this.next_id().node_id, + ref_id: node_id, + hir_ref_id: hir_id, }, bound_generic_params: hir_vec![], span, @@ -2325,7 +2339,7 @@ impl<'a> LoweringContext<'a> { // FIXME: This could probably be done with less rightward drift. Also looks like two control // paths where report_error is called are also the only paths that advance to after // the match statement, so the error reporting could probably just be moved there. - let mut add_bounds = NodeMap(); + let mut add_bounds: NodeMap> = NodeMap(); for pred in &generics.where_clause.predicates { if let WherePredicate::BoundPredicate(ref bound_pred) = *pred { 'next_bound: for bound in &bound_pred.bounds { @@ -2355,7 +2369,7 @@ impl<'a> LoweringContext<'a> { GenericParamKind::Type { .. } => { if node_id == param.id { add_bounds.entry(param.id) - .or_insert(Vec::new()) + .or_default() .push(bound.clone()); continue 'next_bound; } @@ -2476,9 +2490,11 @@ impl<'a> LoweringContext<'a> { hir::QPath::Resolved(None, path) => path.and_then(|path| path), qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath), }; + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(p.ref_id); hir::TraitRef { path, - ref_id: self.lower_node_id(p.ref_id).node_id, + ref_id: node_id, + hir_ref_id: hir_id, } } @@ -2719,7 +2735,7 @@ impl<'a> LoweringContext<'a> { if let Some(ref trait_ref) = trait_ref { if let Def::Trait(def_id) = trait_ref.path.def { - this.trait_impls.entry(def_id).or_insert(vec![]).push(id); + this.trait_impls.entry(def_id).or_default().push(id); } } @@ -2837,11 +2853,13 @@ impl<'a> LoweringContext<'a> { hir::VisibilityKind::Public => hir::VisibilityKind::Public, hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, - hir::VisibilityKind::Restricted { ref path, id: _ } => { + hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => { + let id = this.next_id(); hir::VisibilityKind::Restricted { path: path.clone(), // We are allocating a new NodeId here - id: this.next_id().node_id, + id: id.node_id, + hir_id: id.hir_id, } } }; @@ -2910,11 +2928,13 @@ impl<'a> LoweringContext<'a> { hir::VisibilityKind::Public => hir::VisibilityKind::Public, hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, - hir::VisibilityKind::Restricted { ref path, id: _ } => { + hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => { + let id = this.next_id(); hir::VisibilityKind::Restricted { path: path.clone(), // We are allocating a new NodeId here - id: this.next_id().node_id, + id: id.node_id, + hir_id: id.hir_id, } } }; @@ -3122,12 +3142,12 @@ impl<'a> LoweringContext<'a> { &mut self, decl: &FnDecl, header: &FnHeader, - ids: &mut SmallVector, + ids: &mut OneVector, ) { if let Some(id) = header.asyncness.opt_return_id() { ids.push(hir::ItemId { id }); } - struct IdVisitor<'a> { ids: &'a mut SmallVector } + struct IdVisitor<'a> { ids: &'a mut OneVector } impl<'a, 'b> Visitor<'a> for IdVisitor<'b> { fn visit_ty(&mut self, ty: &'a Ty) { match ty.node { @@ -3160,21 +3180,21 @@ impl<'a> LoweringContext<'a> { } } - fn lower_item_id(&mut self, i: &Item) -> SmallVector { + fn lower_item_id(&mut self, i: &Item) -> OneVector { match i.node { ItemKind::Use(ref use_tree) => { - let mut vec = SmallVector::one(hir::ItemId { id: i.id }); + let mut vec = smallvec![hir::ItemId { id: i.id }]; self.lower_item_id_use_tree(use_tree, i.id, &mut vec); vec } - ItemKind::MacroDef(..) => SmallVector::new(), + ItemKind::MacroDef(..) => OneVector::new(), ItemKind::Fn(ref decl, ref header, ..) => { - let mut ids = SmallVector::one(hir::ItemId { id: i.id }); + let mut ids = smallvec![hir::ItemId { id: i.id }]; self.lower_impl_trait_ids(decl, header, &mut ids); ids }, ItemKind::Impl(.., None, _, ref items) => { - let mut ids = SmallVector::one(hir::ItemId { id: i.id }); + let mut ids = smallvec![hir::ItemId { id: i.id }]; for item in items { if let ImplItemKind::Method(ref sig, _) = item.node { self.lower_impl_trait_ids(&sig.decl, &sig.header, &mut ids); @@ -3182,14 +3202,14 @@ impl<'a> LoweringContext<'a> { } ids }, - _ => SmallVector::one(hir::ItemId { id: i.id }), + _ => smallvec![hir::ItemId { id: i.id }], } } fn lower_item_id_use_tree(&mut self, tree: &UseTree, base_id: NodeId, - vec: &mut SmallVector) + vec: &mut OneVector) { match tree.kind { UseTreeKind::Nested(ref nested_vec) => for &(ref nested, id) in nested_vec { @@ -3410,19 +3430,24 @@ impl<'a> LoweringContext<'a> { ParamMode::Optional, ImplTraitContext::Disallowed, ); + self.check_self_struct_ctor_feature(&qpath); hir::PatKind::TupleStruct( qpath, pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos, ) } - PatKind::Path(ref qself, ref path) => hir::PatKind::Path(self.lower_qpath( - p.id, - qself, - path, - ParamMode::Optional, - ImplTraitContext::Disallowed, - )), + PatKind::Path(ref qself, ref path) => { + let qpath = self.lower_qpath( + p.id, + qself, + path, + ParamMode::Optional, + ImplTraitContext::Disallowed, + ); + self.check_self_struct_ctor_feature(&qpath); + hir::PatKind::Path(qpath) + } PatKind::Struct(ref path, ref fields, etc) => { let qpath = self.lower_qpath( p.id, @@ -3598,15 +3623,15 @@ impl<'a> LoweringContext<'a> { hir::LoopSource::Loop, ) }), - ExprKind::Catch(ref body) => { + ExprKind::TryBlock(ref body) => { self.with_catch_scope(body.id, |this| { let unstable_span = - this.allow_internal_unstable(CompilerDesugaringKind::Catch, body.span); + this.allow_internal_unstable(CompilerDesugaringKind::TryBlock, body.span); let mut block = this.lower_block(body, true).into_inner(); let tail = block.expr.take().map_or_else( || { let LoweredNodeId { node_id, hir_id } = this.next_id(); - let span = this.sess.codemap().end_point(unstable_span); + let span = this.sess.source_map().end_point(unstable_span); hir::Expr { id: node_id, span, @@ -3753,16 +3778,14 @@ impl<'a> LoweringContext<'a> { } // Desugar `..=` to `std::ops::RangeInclusive::new(, )` ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => { - // FIXME: Use e.span directly after RangeInclusive::new() is stabilized in stage0. - let span = self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span); let id = self.next_id(); let e1 = self.lower_expr(e1); let e2 = self.lower_expr(e2); - let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], None, false)); - let ty = P(self.ty_path(id, span, hir::QPath::Resolved(None, ty_path))); + let ty_path = P(self.std_path(e.span, &["ops", "RangeInclusive"], None, false)); + let ty = P(self.ty_path(id, e.span, hir::QPath::Resolved(None, ty_path))); let new_seg = P(hir::PathSegment::from_ident(Ident::from_str("new"))); let new_path = hir::QPath::TypeRelative(ty, new_seg); - let new = P(self.expr(span, hir::ExprKind::Path(new_path), ThinVec::new())); + let new = P(self.expr(e.span, hir::ExprKind::Path(new_path), ThinVec::new())); hir::ExprKind::Call(new, hir_vec![e1, e2]) } ExprKind::Range(ref e1, ref e2, lims) => { @@ -3785,20 +3808,16 @@ impl<'a> LoweringContext<'a> { .chain(e2.iter().map(|e| ("end", e))) .map(|(s, e)| { let expr = P(self.lower_expr(&e)); - let unstable_span = - self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span); - let ident = Ident::new(Symbol::intern(s), unstable_span); - self.field(ident, expr, unstable_span) + let ident = Ident::new(Symbol::intern(s), e.span); + self.field(ident, expr, e.span) }) .collect::>(); let is_unit = fields.is_empty(); - let unstable_span = - self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span); let struct_path = iter::once("ops") .chain(iter::once(path)) .collect::>(); - let struct_path = self.std_path(unstable_span, &struct_path, None, is_unit); + let struct_path = self.std_path(e.span, &struct_path, None, is_unit); let struct_path = hir::QPath::Resolved(None, P(struct_path)); let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id); @@ -3811,17 +3830,21 @@ impl<'a> LoweringContext<'a> { } else { hir::ExprKind::Struct(struct_path, fields, None) }, - span: unstable_span, + span: e.span, attrs: e.attrs.clone(), }; } - ExprKind::Path(ref qself, ref path) => hir::ExprKind::Path(self.lower_qpath( - e.id, - qself, - path, - ParamMode::Optional, - ImplTraitContext::Disallowed, - )), + ExprKind::Path(ref qself, ref path) => { + let qpath = self.lower_qpath( + e.id, + qself, + path, + ParamMode::Optional, + ImplTraitContext::Disallowed, + ); + self.check_self_struct_ctor_feature(&qpath); + hir::ExprKind::Path(qpath) + } ExprKind::Break(opt_label, ref opt_expr) => { let destination = if self.is_in_loop_condition && opt_label.is_none() { hir::Destination { @@ -4287,8 +4310,8 @@ impl<'a> LoweringContext<'a> { } } - fn lower_stmt(&mut self, s: &Stmt) -> SmallVector { - SmallVector::one(match s.node { + fn lower_stmt(&mut self, s: &Stmt) -> OneVector { + smallvec![match s.node { StmtKind::Local(ref l) => Spanned { node: hir::StmtKind::Decl( P(Spanned { @@ -4327,7 +4350,7 @@ impl<'a> LoweringContext<'a> { span: s.span, }, StmtKind::Mac(..) => panic!("Shouldn't exist here"), - }) + }] } fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause { @@ -4350,13 +4373,17 @@ impl<'a> LoweringContext<'a> { let node = match v.node { VisibilityKind::Public => hir::VisibilityKind::Public, VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), - VisibilityKind::Restricted { ref path, id } => hir::VisibilityKind::Restricted { - path: P(self.lower_path(id, path, ParamMode::Explicit)), - id: if let Some(owner) = explicit_owner { - self.lower_node_id_with_owner(id, owner).node_id + VisibilityKind::Restricted { ref path, id } => { + let lowered_id = if let Some(owner) = explicit_owner { + self.lower_node_id_with_owner(id, owner) } else { - self.lower_node_id(id).node_id - }, + self.lower_node_id(id) + }; + hir::VisibilityKind::Restricted { + path: P(self.lower_path(id, path, ParamMode::Explicit)), + id: lowered_id.node_id, + hir_id: lowered_id.hir_id, + } }, VisibilityKind::Inherited => hir::VisibilityKind::Inherited, }; @@ -4675,6 +4702,7 @@ impl<'a> LoweringContext<'a> { trait_ref: hir::TraitRef { path: path.and_then(|path| path), ref_id: id.node_id, + hir_ref_id: id.hir_id, }, span, }; @@ -4797,6 +4825,18 @@ impl<'a> LoweringContext<'a> { ThinVec::new())); P(self.expr_call(e.span, from_err, hir_vec![e])) } + + fn check_self_struct_ctor_feature(&self, qp: &hir::QPath) { + if let hir::QPath::Resolved(_, ref p) = qp { + if p.segments.len() == 1 && + p.segments[0].ident.name == keywords::SelfType.name() && + !self.sess.features_untracked().self_struct_ctor { + emit_feature_err(&self.sess.parse_sess, "self_struct_ctor", + p.span, GateIssue::Language, + "`Self` struct constructors are unstable"); + } + } + } } fn body_ids(bodies: &BTreeMap) -> Vec { diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index f2f7f95426..c7824d411a 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -22,8 +22,8 @@ //! for the `Code` associated with a particular NodeId. use hir as ast; -use hir::map::{self, Node}; -use hir::{Expr, FnDecl}; +use hir::map; +use hir::{Expr, FnDecl, Node}; use hir::intravisit::FnKind; use syntax::ast::{Attribute, Ident, Name, NodeId}; use syntax_pos::Span; @@ -39,7 +39,7 @@ use syntax_pos::Span; /// /// To construct one, use the `Code::from_node` function. #[derive(Copy, Clone, Debug)] -pub struct FnLikeNode<'a> { node: map::Node<'a> } +pub struct FnLikeNode<'a> { node: Node<'a> } /// MaybeFnLike wraps a method that indicates if an object /// corresponds to some FnLikeNode. @@ -95,11 +95,11 @@ impl<'a> Code<'a> { /// Attempts to construct a Code from presumed FnLike or Expr node input. pub fn from_node(map: &map::Map<'a>, id: NodeId) -> Option> { match map.get(id) { - map::NodeBlock(_) => { + map::Node::Block(_) => { // Use the parent, hopefully an expression node. Code::from_node(map, map.get_parent_node(id)) } - map::NodeExpr(expr) => Some(Code::Expr(expr)), + map::Node::Expr(expr) => Some(Code::Expr(expr)), node => FnLikeNode::from_node(node).map(Code::FnLike) } } @@ -145,10 +145,10 @@ impl<'a> FnLikeNode<'a> { /// Attempts to construct a FnLikeNode from presumed FnLike node input. pub fn from_node(node: Node) -> Option { let fn_like = match node { - map::NodeItem(item) => item.is_fn_like(), - map::NodeTraitItem(tm) => tm.is_fn_like(), - map::NodeImplItem(it) => it.is_fn_like(), - map::NodeExpr(e) => e.is_fn_like(), + map::Node::Item(item) => item.is_fn_like(), + 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 }; if fn_like { @@ -161,27 +161,27 @@ impl<'a> FnLikeNode<'a> { } pub fn body(self) -> ast::BodyId { - self.handle(|i: ItemFnParts<'a>| i.body, - |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _| body, + self.handle(|i: ItemFnParts<'a>| i.body, + |_, _, _: &'a ast::MethodSig, _, 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, + self.handle(|i: ItemFnParts<'a>| &*i.decl, + |_, _, sig: &'a ast::MethodSig, _, _, _, _| &sig.decl, |c: ClosureParts<'a>| c.decl) } pub fn span(self) -> Span { - self.handle(|i: ItemFnParts| i.span, + self.handle(|i: ItemFnParts| i.span, |_, _, _: &'a ast::MethodSig, _, _, span, _| span, - |c: ClosureParts| c.span) + |c: ClosureParts| c.span) } pub fn id(self) -> NodeId { - self.handle(|i: ItemFnParts| i.id, + self.handle(|i: ItemFnParts| i.id, |id, _, _: &'a ast::MethodSig, _, _, _, _| id, - |c: ClosureParts| c.id) + |c: ClosureParts| c.id) } pub fn constness(self) -> ast::Constness { @@ -234,7 +234,7 @@ impl<'a> FnLikeNode<'a> { C: FnOnce(ClosureParts<'a>) -> A, { match self.node { - map::NodeItem(i) => match i.node { + map::Node::Item(i) => match i.node { ast::ItemKind::Fn(ref decl, header, ref generics, block) => item_fn(ItemFnParts { id: i.id, @@ -249,23 +249,21 @@ impl<'a> FnLikeNode<'a> { }), _ => bug!("item FnLikeNode that is not fn-like"), }, - map::NodeTraitItem(ti) => match ti.node { + map::Node::TraitItem(ti) => match ti.node { ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => { method(ti.id, ti.ident, sig, None, body, ti.span, &ti.attrs) } _ => bug!("trait method FnLikeNode that is not fn-like"), }, - map::NodeImplItem(ii) => { + map::Node::ImplItem(ii) => { match ii.node { ast::ImplItemKind::Method(ref sig, body) => { method(ii.id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) } - _ => { - bug!("impl method FnLikeNode that is not fn-like") - } + _ => bug!("impl method FnLikeNode that is not fn-like") } }, - map::NodeExpr(e) => match e.node { + map::Node::Expr(e) => match e.node { ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => closure(ClosureParts::new(&decl, block, e.id, e.span, &e.attrs)), _ => bug!("expr FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 0150ba659c..bd12a5e0cb 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -12,13 +12,13 @@ use super::*; use dep_graph::{DepGraph, DepKind, DepNodeIndex}; use hir::def_id::{LOCAL_CRATE, CrateNum}; use hir::intravisit::{Visitor, NestedVisitorMap}; -use hir::svh::Svh; +use rustc_data_structures::svh::Svh; use ich::Fingerprint; use middle::cstore::CrateStore; use session::CrateDisambiguator; use std::iter::repeat; use syntax::ast::{NodeId, CRATE_NODE_ID}; -use syntax::codemap::CodeMap; +use syntax::source_map::SourceMap; use syntax_pos::Span; use ich::StableHashingContext; @@ -29,7 +29,7 @@ pub(super) struct NodeCollector<'a, 'hir> { /// The crate krate: &'hir Crate, /// The node map - map: Vec>, + map: Vec>>, /// The parent of this node parent_node: NodeId, @@ -67,7 +67,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { // them explicitly here. ref attrs, span, - // These fields are handled separately: exported_macros: _, items: _, @@ -114,7 +113,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { hcx, hir_body_nodes, }; - collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_sig_dep_index)); + collector.insert_entry(CRATE_NODE_ID, Entry { + parent: CRATE_NODE_ID, + dep_node: root_mod_sig_dep_index, + node: Node::Crate, + }); collector } @@ -122,17 +125,16 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn finalize_and_compute_crate_hash(mut self, crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, - codemap: &CodeMap, + source_map: &SourceMap, commandline_args_hash: u64) - -> (Vec>, Svh) { - self - .hir_body_nodes - .sort_unstable_by(|&(ref d1, _), &(ref d2, _)| d1.cmp(d2)); + -> (Vec>>, Svh) + { + self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); let node_hashes = self .hir_body_nodes .iter() - .fold(Fingerprint::ZERO, |fingerprint , &(def_path_hash, dep_node_index)| { + .fold(Fingerprint::ZERO, |fingerprint, &(def_path_hash, dep_node_index)| { fingerprint.combine( def_path_hash.0.combine(self.dep_graph.fingerprint_of(dep_node_index)) ) @@ -140,26 +142,23 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { let name = cstore.crate_name_untracked(cnum).as_str(); - let disambiguator = cstore.crate_disambiguator_untracked(cnum) - .to_fingerprint(); + 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(|&(name1, dis1, _), &(name2, dis2, _)| { - (name1, dis1).cmp(&(name2, dis2)) - }); + upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name, dis)); // We hash the final, remapped names of all local source files so we // don't have to include the path prefix remapping commandline args. // If we included the full mapping in the SVH, we could only have // reproducible builds by compiling from the same directory. So we just // hash the result of the mapping instead of the mapping itself. - let mut source_file_names: Vec<_> = codemap + let mut source_file_names: Vec<_> = source_map .files() .iter() - .filter(|filemap| CrateNum::from_u32(filemap.crate_of_origin) == LOCAL_CRATE) - .map(|filemap| filemap.name_hash) + .filter(|source_file| CrateNum::from_u32(source_file.crate_of_origin) == LOCAL_CRATE) + .map(|source_file| source_file.name_hash) .collect(); source_file_names.sort_unstable(); @@ -178,44 +177,24 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { (self.map, svh) } - fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) { + fn insert_entry(&mut self, id: NodeId, entry: Entry<'hir>) { debug!("hir_map: {:?} => {:?}", id, entry); let len = self.map.len(); if id.as_usize() >= len { - self.map.extend(repeat(NotPresent).take(id.as_usize() - len + 1)); + self.map.extend(repeat(None).take(id.as_usize() - len + 1)); } - self.map[id.as_usize()] = entry; + self.map[id.as_usize()] = Some(entry); } fn insert(&mut self, id: NodeId, node: Node<'hir>) { - let parent = self.parent_node; - let dep_node_index = if self.currently_in_body { - self.current_full_dep_index - } else { - self.current_signature_dep_index - }; - - let entry = match node { - NodeItem(n) => EntryItem(parent, dep_node_index, n), - NodeForeignItem(n) => EntryForeignItem(parent, dep_node_index, n), - NodeTraitItem(n) => EntryTraitItem(parent, dep_node_index, n), - NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n), - NodeVariant(n) => EntryVariant(parent, dep_node_index, n), - NodeField(n) => EntryField(parent, dep_node_index, n), - NodeAnonConst(n) => EntryAnonConst(parent, dep_node_index, n), - NodeExpr(n) => EntryExpr(parent, dep_node_index, n), - NodeStmt(n) => EntryStmt(parent, dep_node_index, n), - NodeTy(n) => EntryTy(parent, dep_node_index, n), - NodeTraitRef(n) => EntryTraitRef(parent, dep_node_index, n), - NodeBinding(n) => EntryBinding(parent, dep_node_index, n), - NodePat(n) => EntryPat(parent, dep_node_index, n), - NodeBlock(n) => EntryBlock(parent, dep_node_index, n), - NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n), - NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n), - NodeGenericParam(n) => EntryGenericParam(parent, dep_node_index, n), - NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n), - NodeLocal(n) => EntryLocal(parent, dep_node_index, n), - NodeMacroDef(n) => EntryMacroDef(dep_node_index, n), + let entry = Entry { + parent: self.parent_node, + dep_node: if self.currently_in_body { + self.current_full_dep_index + } else { + self.current_signature_dep_index + }, + node, }; // Make sure that the DepNode of some node coincides with the HirId @@ -246,7 +225,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } self.insert_entry(id, entry); - } fn with_parent(&mut self, parent_id: NodeId, f: F) { @@ -326,16 +304,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { debug_assert_eq!(i.hir_id.owner, self.definitions.opt_def_index(i.id).unwrap()); self.with_dep_node_owner(i.hir_id.owner, i, |this| { - this.insert(i.id, NodeItem(i)); + this.insert(i.id, Node::Item(i)); this.with_parent(i.id, |this| { - match i.node { - ItemKind::Struct(ref struct_def, _) => { - // If this is a tuple-like struct, register the constructor. - if !struct_def.is_struct() { - this.insert(struct_def.id(), NodeStructCtor(struct_def)); - } + if let ItemKind::Struct(ref struct_def, _) = i.node { + // If this is a tuple-like struct, register the constructor. + if !struct_def.is_struct() { + this.insert(struct_def.id(), Node::StructCtor(struct_def)); } - _ => {} } intravisit::walk_item(this, i); }); @@ -343,7 +318,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem) { - self.insert(foreign_item.id, NodeForeignItem(foreign_item)); + self.insert(foreign_item.id, Node::ForeignItem(foreign_item)); self.with_parent(foreign_item.id, |this| { intravisit::walk_foreign_item(this, foreign_item); @@ -351,7 +326,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_generic_param(&mut self, param: &'hir GenericParam) { - self.insert(param.id, NodeGenericParam(param)); + self.insert(param.id, Node::GenericParam(param)); intravisit::walk_generic_param(self, param); } @@ -359,7 +334,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { debug_assert_eq!(ti.hir_id.owner, self.definitions.opt_def_index(ti.id).unwrap()); self.with_dep_node_owner(ti.hir_id.owner, ti, |this| { - this.insert(ti.id, NodeTraitItem(ti)); + this.insert(ti.id, Node::TraitItem(ti)); this.with_parent(ti.id, |this| { intravisit::walk_trait_item(this, ti); @@ -371,7 +346,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { debug_assert_eq!(ii.hir_id.owner, self.definitions.opt_def_index(ii.id).unwrap()); self.with_dep_node_owner(ii.hir_id.owner, ii, |this| { - this.insert(ii.id, NodeImplItem(ii)); + this.insert(ii.id, Node::ImplItem(ii)); this.with_parent(ii.id, |this| { intravisit::walk_impl_item(this, ii); @@ -381,9 +356,9 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_pat(&mut self, pat: &'hir Pat) { let node = if let PatKind::Binding(..) = pat.node { - NodeBinding(pat) + Node::Binding(pat) } else { - NodePat(pat) + Node::Pat(pat) }; self.insert(pat.id, node); @@ -393,7 +368,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_anon_const(&mut self, constant: &'hir AnonConst) { - self.insert(constant.id, NodeAnonConst(constant)); + self.insert(constant.id, Node::AnonConst(constant)); self.with_parent(constant.id, |this| { intravisit::walk_anon_const(this, constant); @@ -401,7 +376,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_expr(&mut self, expr: &'hir Expr) { - self.insert(expr.id, NodeExpr(expr)); + self.insert(expr.id, Node::Expr(expr)); self.with_parent(expr.id, |this| { intravisit::walk_expr(this, expr); @@ -410,7 +385,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_stmt(&mut self, stmt: &'hir Stmt) { let id = stmt.node.id(); - self.insert(id, NodeStmt(stmt)); + self.insert(id, Node::Stmt(stmt)); self.with_parent(id, |this| { intravisit::walk_stmt(this, stmt); @@ -418,7 +393,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_ty(&mut self, ty: &'hir Ty) { - self.insert(ty.id, NodeTy(ty)); + self.insert(ty.id, Node::Ty(ty)); self.with_parent(ty.id, |this| { intravisit::walk_ty(this, ty); @@ -426,7 +401,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_trait_ref(&mut self, tr: &'hir TraitRef) { - self.insert(tr.ref_id, NodeTraitRef(tr)); + self.insert(tr.ref_id, Node::TraitRef(tr)); self.with_parent(tr.ref_id, |this| { intravisit::walk_trait_ref(this, tr); @@ -440,21 +415,21 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_block(&mut self, block: &'hir Block) { - self.insert(block.id, NodeBlock(block)); + self.insert(block.id, Node::Block(block)); self.with_parent(block.id, |this| { intravisit::walk_block(this, block); }); } fn visit_local(&mut self, l: &'hir Local) { - self.insert(l.id, NodeLocal(l)); + self.insert(l.id, Node::Local(l)); self.with_parent(l.id, |this| { intravisit::walk_local(this, l) }) } fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) { - self.insert(lifetime.id, NodeLifetime(lifetime)); + self.insert(lifetime.id, Node::Lifetime(lifetime)); } fn visit_vis(&mut self, visibility: &'hir Visibility) { @@ -463,7 +438,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { VisibilityKind::Crate(_) | VisibilityKind::Inherited => {} VisibilityKind::Restricted { id, .. } => { - self.insert(id, NodeVisibility(visibility)); + self.insert(id, Node::Visibility(visibility)); self.with_parent(id, |this| { intravisit::walk_vis(this, visibility); }); @@ -475,20 +450,20 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { let def_index = self.definitions.opt_def_index(macro_def.id).unwrap(); self.with_dep_node_owner(def_index, macro_def, |this| { - this.insert(macro_def.id, NodeMacroDef(macro_def)); + this.insert(macro_def.id, Node::MacroDef(macro_def)); }); } fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: NodeId) { let id = v.node.data.id(); - self.insert(id, NodeVariant(v)); + self.insert(id, Node::Variant(v)); self.with_parent(id, |this| { intravisit::walk_variant(this, v, g, item_id); }); } fn visit_struct_field(&mut self, field: &'hir StructField) { - self.insert(field.id, NodeField(field)); + self.insert(field.id, Node::Field(field)); self.with_parent(field.id, |this| { intravisit::walk_struct_field(this, field); }); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index cab620aeec..57b3b43a33 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -76,23 +76,38 @@ impl<'a> DefCollector<'a> { fn visit_async_fn( &mut self, id: NodeId, - async_node_id: NodeId, - return_impl_trait_id: NodeId, name: Name, span: Span, - visit_fn: impl FnOnce(&mut DefCollector<'a>) + header: &FnHeader, + generics: &'a Generics, + decl: &'a FnDecl, + body: &'a Block, ) { + let (closure_id, return_impl_trait_id) = match header.asyncness { + IsAsync::Async { + closure_id, + return_impl_trait_id, + } => (closure_id, return_impl_trait_id), + _ => unreachable!(), + }; + // For async functions, we need to create their inner defs inside of a // closure to match their desugared representation. let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span); return self.with_parent(fn_def, |this| { this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span); - let closure_def = this.create_def(async_node_id, + + visit::walk_generics(this, generics); + visit::walk_fn_decl(this, decl); + + let closure_def = this.create_def(closure_id, DefPathData::ClosureExpr, REGULAR_SPACE, span); - this.with_parent(closure_def, visit_fn) + this.with_parent(closure_def, |this| { + visit::walk_block(this, body); + }) }) } @@ -122,17 +137,20 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { return visit::walk_item(self, i); } - ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async { - closure_id, - return_impl_trait_id, - }, .. }, ..) => { + ItemKind::Fn( + ref decl, + ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, + ref generics, + ref body, + ) => { return self.visit_async_fn( i.id, - closure_id, - return_impl_trait_id, i.ident.name, i.span, - |this| visit::walk_item(this, i) + header, + generics, + decl, + body, ) } ItemKind::Mod(..) => DefPathData::Module(i.ident.as_interned_str()), @@ -233,18 +251,17 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(MethodSig { - header: FnHeader { asyncness: IsAsync::Async { - closure_id, - return_impl_trait_id, - }, .. }, .. - }, ..) => { + header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, + ref decl, + }, ref body) => { return self.visit_async_fn( ii.id, - closure_id, - return_impl_trait_id, ii.ident.name, ii.span, - |this| visit::walk_impl_item(this, ii) + header, + &ii.generics, + decl, + body, ) } ImplItemKind::Method(..) | ImplItemKind::Const(..) => @@ -331,13 +348,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_token(&mut self, t: Token) { if let Token::Interpolated(nt) = t { - match nt.0 { - token::NtExpr(ref expr) => { - if let ExprKind::Mac(..) = expr.node { - self.visit_macro_invoc(expr.id); - } + if let token::NtExpr(ref expr) = nt.0 { + if let ExprKind::Mac(..) = expr.node { + self.visit_macro_invoc(expr.id); } - _ => {} } } } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index c4b28fe2c4..c85cee7366 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -317,10 +317,8 @@ pub enum DefPathData { // 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, @@ -342,7 +340,6 @@ pub enum DefPathData { MacroDef(InternedString), /// A closure expression ClosureExpr, - // Subportions of items /// A type parameter (generic parameter) TypeParam(InternedString), @@ -358,7 +355,6 @@ pub enum DefPathData { AnonConst, /// An `impl Trait` type node ImplTrait, - /// GlobalMetaData 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. @@ -380,6 +376,17 @@ impl Borrow for DefPathHash { impl Definitions { /// Create new empty definition map. + /// + /// The DefIndex returned from a new Definitions are as follows: + /// 1. At DefIndexAddressSpace::Low, + /// CRATE_ROOT has index 0:0, and then new indexes are allocated in + /// ascending order. + /// 2. At DefIndexAddressSpace::High, + /// the first FIRST_FREE_HIGH_DEF_INDEX indexes are reserved for + /// internal use, then 1:FIRST_FREE_HIGH_DEF_INDEX are allocated in + /// ascending order. + /// + /// FIXME: there is probably a better place to put this comment. pub fn new() -> Definitions { Definitions { table: DefPathTable { @@ -645,10 +652,8 @@ impl DefPathData { GlobalMetaData(name) => { return name } - // note that this does not show up in user printouts CrateRoot => "{{root}}", - Impl => "{{impl}}", Misc => "{{?}}", ClosureExpr => "{{closure}}", @@ -665,6 +670,11 @@ impl DefPathData { } } +macro_rules! count { + () => (0usize); + ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); +} + // 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 DefIndices in the DefTable. @@ -678,6 +688,7 @@ macro_rules! define_global_metadata_kind { } const GLOBAL_MD_ADDRESS_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High; + pub const FIRST_FREE_HIGH_DEF_INDEX: usize = count!($($variant)*); impl GlobalMetaDataKind { fn allocate_def_indices(definitions: &mut Definitions) { @@ -739,7 +750,7 @@ define_global_metadata_kind!(pub enum GlobalMetaDataKind { LangItems, LangItemsMissing, NativeLibraries, - CodeMap, + SourceMap, Impls, ExportedSymbols }); diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index a17c160c4d..d61b531344 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -100,8 +100,8 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { if max != self.hir_ids_seen.len() - 1 { // Collect the missing ItemLocalIds - let missing: Vec<_> = (0 .. max + 1) - .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId(i as u32))) + let missing: Vec<_> = (0 .. max as u32 + 1) + .filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId(i))) .collect(); // Try to map those to something more useful diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 49231e58cf..31fba3ad97 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::Node::*; -use self::MapEntry::*; use self::collector::NodeCollector; pub use self::def_collector::{DefCollector, MacroInvocationData}; pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, @@ -22,14 +20,14 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace}; use middle::cstore::CrateStore; use rustc_target::spec::abi::Abi; +use rustc_data_structures::svh::Svh; use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID}; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use syntax::ext::base::MacroKind; use syntax_pos::{Span, DUMMY_SP}; use hir::*; use hir::print::Nested; -use hir::svh::Svh; use util::nodemap::FxHashMap; use std::io; @@ -42,172 +40,62 @@ mod def_collector; pub mod definitions; mod hir_id_validator; - pub const ITEM_LIKE_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::Low; pub const REGULAR_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High; +/// Represents an entry and its parent NodeId. #[derive(Copy, Clone, Debug)] -pub enum Node<'hir> { - NodeItem(&'hir Item), - NodeForeignItem(&'hir ForeignItem), - NodeTraitItem(&'hir TraitItem), - NodeImplItem(&'hir ImplItem), - NodeVariant(&'hir Variant), - NodeField(&'hir StructField), - NodeAnonConst(&'hir AnonConst), - NodeExpr(&'hir Expr), - NodeStmt(&'hir Stmt), - NodeTy(&'hir Ty), - NodeTraitRef(&'hir TraitRef), - NodeBinding(&'hir Pat), - NodePat(&'hir Pat), - NodeBlock(&'hir Block), - NodeLocal(&'hir Local), - NodeMacroDef(&'hir MacroDef), - - /// NodeStructCtor represents a tuple struct. - NodeStructCtor(&'hir VariantData), - - NodeLifetime(&'hir Lifetime), - NodeGenericParam(&'hir GenericParam), - NodeVisibility(&'hir Visibility), -} - -/// Represents an entry and its parent NodeID. -/// The odd layout is to bring down the total size. -#[derive(Copy, Debug)] -enum MapEntry<'hir> { - /// Placeholder for holes in the map. - NotPresent, - - /// All the node types, with a parent ID. - EntryItem(NodeId, DepNodeIndex, &'hir Item), - EntryForeignItem(NodeId, DepNodeIndex, &'hir ForeignItem), - EntryTraitItem(NodeId, DepNodeIndex, &'hir TraitItem), - EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem), - EntryVariant(NodeId, DepNodeIndex, &'hir Variant), - EntryField(NodeId, DepNodeIndex, &'hir StructField), - EntryAnonConst(NodeId, DepNodeIndex, &'hir AnonConst), - EntryExpr(NodeId, DepNodeIndex, &'hir Expr), - EntryStmt(NodeId, DepNodeIndex, &'hir Stmt), - EntryTy(NodeId, DepNodeIndex, &'hir Ty), - EntryTraitRef(NodeId, DepNodeIndex, &'hir TraitRef), - EntryBinding(NodeId, DepNodeIndex, &'hir Pat), - EntryPat(NodeId, DepNodeIndex, &'hir Pat), - EntryBlock(NodeId, DepNodeIndex, &'hir Block), - EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData), - EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime), - EntryGenericParam(NodeId, DepNodeIndex, &'hir GenericParam), - EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility), - EntryLocal(NodeId, DepNodeIndex, &'hir Local), - - EntryMacroDef(DepNodeIndex, &'hir MacroDef), - - /// Roots for node trees. The DepNodeIndex is the dependency node of the - /// crate's root module. - RootCrate(DepNodeIndex), -} - -impl<'hir> Clone for MapEntry<'hir> { - fn clone(&self) -> MapEntry<'hir> { - *self - } +pub struct Entry<'hir> { + parent: NodeId, + dep_node: DepNodeIndex, + node: Node<'hir>, } -impl<'hir> MapEntry<'hir> { +impl<'hir> Entry<'hir> { fn parent_node(self) -> Option { - Some(match self { - EntryItem(id, _, _) => id, - EntryForeignItem(id, _, _) => id, - EntryTraitItem(id, _, _) => id, - EntryImplItem(id, _, _) => id, - EntryVariant(id, _, _) => id, - EntryField(id, _, _) => id, - EntryAnonConst(id, _, _) => id, - EntryExpr(id, _, _) => id, - EntryStmt(id, _, _) => id, - EntryTy(id, _, _) => id, - EntryTraitRef(id, _, _) => id, - EntryBinding(id, _, _) => id, - EntryPat(id, _, _) => id, - EntryBlock(id, _, _) => id, - EntryStructCtor(id, _, _) => id, - EntryLifetime(id, _, _) => id, - EntryGenericParam(id, _, _) => id, - EntryVisibility(id, _, _) => id, - EntryLocal(id, _, _) => id, - - NotPresent | - EntryMacroDef(..) | - RootCrate(_) => return None, - }) - } - - fn to_node(self) -> Option> { - Some(match self { - EntryItem(_, _, n) => NodeItem(n), - EntryForeignItem(_, _, n) => NodeForeignItem(n), - EntryTraitItem(_, _, n) => NodeTraitItem(n), - EntryImplItem(_, _, n) => NodeImplItem(n), - EntryVariant(_, _, n) => NodeVariant(n), - EntryField(_, _, n) => NodeField(n), - EntryAnonConst(_, _, n) => NodeAnonConst(n), - EntryExpr(_, _, n) => NodeExpr(n), - EntryStmt(_, _, n) => NodeStmt(n), - EntryTy(_, _, n) => NodeTy(n), - EntryTraitRef(_, _, n) => NodeTraitRef(n), - EntryBinding(_, _, n) => NodeBinding(n), - EntryPat(_, _, n) => NodePat(n), - EntryBlock(_, _, n) => NodeBlock(n), - EntryStructCtor(_, _, n) => NodeStructCtor(n), - EntryLifetime(_, _, n) => NodeLifetime(n), - EntryGenericParam(_, _, n) => NodeGenericParam(n), - EntryVisibility(_, _, n) => NodeVisibility(n), - EntryLocal(_, _, n) => NodeLocal(n), - EntryMacroDef(_, n) => NodeMacroDef(n), - - NotPresent | - RootCrate(_) => return None - }) + match self.node { + Node::Crate | Node::MacroDef(_) => None, + _ => Some(self.parent), + } } fn fn_decl(&self) -> Option<&FnDecl> { - match self { - EntryItem(_, _, ref item) => { + match self.node { + Node::Item(ref item) => { match item.node { ItemKind::Fn(ref fn_decl, _, _, _) => Some(&fn_decl), _ => None, } } - EntryTraitItem(_, _, ref item) => { + Node::TraitItem(ref item) => { match item.node { TraitItemKind::Method(ref method_sig, _) => Some(&method_sig.decl), _ => None } } - EntryImplItem(_, _, ref item) => { + Node::ImplItem(ref item) => { match item.node { ImplItemKind::Method(ref method_sig, _) => Some(&method_sig.decl), _ => None, } } - EntryExpr(_, _, ref expr) => { + Node::Expr(ref expr) => { match expr.node { ExprKind::Closure(_, ref fn_decl, ..) => Some(&fn_decl), _ => None, } } - _ => None + _ => None, } } fn associated_body(self) -> Option { - match self { - EntryItem(_, _, item) => { + match self.node { + Node::Item(item) => { match item.node { ItemKind::Const(_, body) | ItemKind::Static(.., body) | @@ -216,7 +104,7 @@ impl<'hir> MapEntry<'hir> { } } - EntryTraitItem(_, _, item) => { + Node::TraitItem(item) => { match item.node { TraitItemKind::Const(_, Some(body)) | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), @@ -224,7 +112,7 @@ impl<'hir> MapEntry<'hir> { } } - EntryImplItem(_, _, item) => { + Node::ImplItem(item) => { match item.node { ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), @@ -232,9 +120,9 @@ impl<'hir> MapEntry<'hir> { } } - EntryAnonConst(_, _, constant) => Some(constant.body), + Node::AnonConst(constant) => Some(constant.body), - EntryExpr(_, _, expr) => { + Node::Expr(expr) => { match expr.node { ExprKind::Closure(.., body, _, _) => Some(body), _ => None, @@ -287,16 +175,16 @@ pub struct Map<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, - /// NodeIds are sequential integers from 0, so we can be + /// `NodeId`s are sequential integers from 0, so we can be /// super-compact by storing them in a vector. Not everything with - /// a NodeId is in the map, but empirically the occupancy is about + /// a `NodeId` is in the map, but empirically the occupancy is about /// 75-80%, so there's not too much overhead (certainly less than /// a hashmap, since they (at the time of writing) have a maximum /// of 75% occupancy). /// /// Also, indexing is pretty quick when you've got a vector and /// plain old integers. - map: Vec>, + map: Vec>>, definitions: &'hir Definitions, @@ -313,34 +201,10 @@ impl<'hir> Map<'hir> { /// read recorded). If the function just returns a DefId or /// NodeId, no actual content was returned, so no read is needed. pub fn read(&self, id: NodeId) { - let entry = self.map[id.as_usize()]; - match entry { - EntryItem(_, dep_node_index, _) | - EntryTraitItem(_, dep_node_index, _) | - EntryImplItem(_, dep_node_index, _) | - EntryVariant(_, dep_node_index, _) | - EntryForeignItem(_, dep_node_index, _) | - EntryField(_, dep_node_index, _) | - EntryStmt(_, dep_node_index, _) | - EntryTy(_, dep_node_index, _) | - EntryTraitRef(_, dep_node_index, _) | - EntryBinding(_, dep_node_index, _) | - EntryPat(_, dep_node_index, _) | - EntryBlock(_, dep_node_index, _) | - EntryStructCtor(_, dep_node_index, _) | - EntryLifetime(_, dep_node_index, _) | - EntryGenericParam(_, dep_node_index, _) | - EntryVisibility(_, dep_node_index, _) | - EntryAnonConst(_, dep_node_index, _) | - EntryExpr(_, dep_node_index, _) | - EntryLocal(_, dep_node_index, _) | - EntryMacroDef(dep_node_index, _) | - RootCrate(dep_node_index) => { - self.dep_graph.read_index(dep_node_index); - } - NotPresent => { - bug!("called HirMap::read() with invalid NodeId") - } + if let Some(entry) = self.map[id.as_usize()] { + self.dep_graph.read_index(entry.dep_node); + } else { + bug!("called `HirMap::read()` with invalid `NodeId`") } } @@ -421,18 +285,16 @@ impl<'hir> Map<'hir> { }; match node { - NodeItem(item) => { + Node::Item(item) => { let def_id = || { self.local_def_id(item.id) }; match item.node { - ItemKind::Static(_, m, _) => Some(Def::Static(def_id(), - m == MutMutable)), + ItemKind::Static(_, m, _) => Some(Def::Static(def_id(), m == MutMutable)), ItemKind::Const(..) => Some(Def::Const(def_id())), ItemKind::Fn(..) => Some(Def::Fn(def_id())), ItemKind::Mod(..) => Some(Def::Mod(def_id())), - ItemKind::GlobalAsm(..) => Some(Def::GlobalAsm(def_id())), ItemKind::Existential(..) => Some(Def::Existential(def_id())), ItemKind::Ty(..) => Some(Def::TyAlias(def_id())), ItemKind::Enum(..) => Some(Def::Enum(def_id())), @@ -445,18 +307,19 @@ impl<'hir> Map<'hir> { ItemKind::ExternCrate(_) | ItemKind::Use(..) | ItemKind::ForeignMod(..) | + ItemKind::GlobalAsm(..) | ItemKind::Impl(..) => None, } } - NodeForeignItem(item) => { + Node::ForeignItem(item) => { let def_id = self.local_def_id(item.id); match item.node { ForeignItemKind::Fn(..) => Some(Def::Fn(def_id)), ForeignItemKind::Static(_, m) => Some(Def::Static(def_id, m)), - ForeignItemKind::Type => Some(Def::TyForeign(def_id)), + ForeignItemKind::Type => Some(Def::ForeignTy(def_id)), } } - NodeTraitItem(item) => { + Node::TraitItem(item) => { let def_id = self.local_def_id(item.id); match item.node { TraitItemKind::Const(..) => Some(Def::AssociatedConst(def_id)), @@ -464,7 +327,7 @@ impl<'hir> Map<'hir> { TraitItemKind::Type(..) => Some(Def::AssociatedTy(def_id)), } } - NodeImplItem(item) => { + Node::ImplItem(item) => { let def_id = self.local_def_id(item.id); match item.node { ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)), @@ -473,30 +336,31 @@ impl<'hir> Map<'hir> { ImplItemKind::Existential(..) => Some(Def::AssociatedExistential(def_id)), } } - NodeVariant(variant) => { + Node::Variant(variant) => { let def_id = self.local_def_id(variant.node.data.id()); Some(Def::Variant(def_id)) } - NodeField(_) | - NodeAnonConst(_) | - NodeExpr(_) | - NodeStmt(_) | - NodeTy(_) | - NodeTraitRef(_) | - NodePat(_) | - NodeBinding(_) | - NodeStructCtor(_) | - NodeLifetime(_) | - NodeVisibility(_) | - NodeBlock(_) => None, - NodeLocal(local) => { + Node::Field(_) | + Node::AnonConst(_) | + Node::Expr(_) | + Node::Stmt(_) | + Node::Ty(_) | + Node::TraitRef(_) | + Node::Pat(_) | + Node::Binding(_) | + Node::StructCtor(_) | + Node::Lifetime(_) | + Node::Visibility(_) | + Node::Block(_) | + Node::Crate => None, + Node::Local(local) => { Some(Def::Local(local.id)) } - NodeMacroDef(macro_def) => { + Node::MacroDef(macro_def) => { Some(Def::Macro(self.local_def_id(macro_def.id), MacroKind::Bang)) } - NodeGenericParam(param) => { + Node::GenericParam(param) => { Some(match param.kind { GenericParamKind::Lifetime { .. } => Def::Local(param.id), GenericParamKind::Type { .. } => Def::TyParam(self.local_def_id(param.id)), @@ -509,8 +373,8 @@ impl<'hir> Map<'hir> { self.map.len() } - fn find_entry(&self, id: NodeId) -> Option> { - self.map.get(id.as_usize()).cloned() + fn find_entry(&self, id: NodeId) -> Option> { + self.map.get(id.as_usize()).cloned().unwrap_or(None) } pub fn krate(&self) -> &'hir Crate { @@ -543,7 +407,7 @@ impl<'hir> Map<'hir> { pub fn fn_decl(&self, node_id: ast::NodeId) -> Option { if let Some(entry) = self.find_entry(node_id) { - entry.fn_decl().map(|fd| fd.clone()) + entry.fn_decl().cloned() } else { bug!("no entry for node_id `{}`", node_id) } @@ -554,7 +418,7 @@ impl<'hir> Map<'hir> { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId { let parent = self.get_parent_node(node_id); - assert!(self.map[parent.as_usize()].is_body_owner(node_id)); + assert!(self.map[parent.as_usize()].map_or(false, |e| e.is_body_owner(node_id))); parent } @@ -588,13 +452,13 @@ impl<'hir> Map<'hir> { pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind { match self.get(id) { - NodeItem(&Item { node: ItemKind::Const(..), .. }) | - NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) | - NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) | - NodeAnonConst(_) => { + Node::Item(&Item { node: ItemKind::Const(..), .. }) | + Node::TraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) | + Node::ImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) | + Node::AnonConst(_) => { BodyOwnerKind::Const } - NodeItem(&Item { node: ItemKind::Static(_, m, _), .. }) => { + Node::Item(&Item { node: ItemKind::Static(_, m, _), .. }) => { BodyOwnerKind::Static(m) } // Default to function if it's not a constant or static. @@ -604,21 +468,16 @@ impl<'hir> Map<'hir> { pub fn ty_param_owner(&self, id: NodeId) -> NodeId { match self.get(id) { - NodeItem(&Item { node: ItemKind::Trait(..), .. }) => id, - NodeGenericParam(_) => self.get_parent_node(id), - _ => { - bug!("ty_param_owner: {} not a type parameter", - self.node_to_string(id)) - } + Node::Item(&Item { node: ItemKind::Trait(..), .. }) => id, + Node::GenericParam(_) => self.get_parent_node(id), + _ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id)) } } pub fn ty_param_name(&self, id: NodeId) -> Name { match self.get(id) { - NodeItem(&Item { node: ItemKind::Trait(..), .. }) => { - keywords::SelfType.name() - } - NodeGenericParam(param) => param.name.ident().name, + Node::Item(&Item { node: ItemKind::Trait(..), .. }) => keywords::SelfType.name(), + Node::GenericParam(param) => param.name.ident().name, _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)), } } @@ -656,10 +515,8 @@ impl<'hir> Map<'hir> { /// Retrieve the Node corresponding to `id`, panicking if it cannot /// be found. pub fn get(&self, id: NodeId) -> Node<'hir> { - match self.find(id) { - Some(node) => node, // read recorded by `find` - None => bug!("couldn't find node id {} in the AST map", id) - } + // read recorded by `find` + self.find(id).unwrap_or_else(|| bug!("couldn't find node id {} in the AST map", id)) } pub fn get_if_local(&self, id: DefId) -> Option> { @@ -669,9 +526,9 @@ impl<'hir> Map<'hir> { pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics> { self.get_if_local(id).and_then(|node| { match node { - NodeImplItem(ref impl_item) => Some(&impl_item.generics), - NodeTraitItem(ref trait_item) => Some(&trait_item.generics), - NodeItem(ref item) => { + Node::ImplItem(ref impl_item) => Some(&impl_item.generics), + Node::TraitItem(ref trait_item) => Some(&trait_item.generics), + Node::Item(ref item) => { match item.node { ItemKind::Fn(_, _, ref generics, _) | ItemKind::Ty(_, ref generics) | @@ -696,7 +553,13 @@ impl<'hir> Map<'hir> { /// Retrieve the Node corresponding to `id`, returning None if /// cannot be found. pub fn find(&self, id: NodeId) -> Option> { - let result = self.find_entry(id).and_then(|x| x.to_node()); + let result = self.find_entry(id).and_then(|entry| { + if let Node::Crate = entry.node { + None + } else { + Some(entry.node) + } + }); if result.is_some() { self.read(id); } @@ -727,14 +590,14 @@ impl<'hir> Map<'hir> { /// immediate parent is an item or a closure. pub fn is_argument(&self, id: NodeId) -> bool { match self.find(id) { - Some(NodeBinding(_)) => (), + Some(Node::Binding(_)) => (), _ => return false, } match self.find(self.get_parent_node(id)) { - Some(NodeItem(_)) | - Some(NodeTraitItem(_)) | - Some(NodeImplItem(_)) => true, - Some(NodeExpr(e)) => { + Some(Node::Item(_)) | + Some(Node::TraitItem(_)) | + Some(Node::ImplItem(_)) => true, + Some(Node::Expr(e)) => { match e.node { ExprKind::Closure(..) => true, _ => false, @@ -766,24 +629,19 @@ impl<'hir> Map<'hir> { return Err(id); } - let node = self.find_entry(parent_node); - if node.is_none() { - return Err(id); - } - let node = node.unwrap().to_node(); - match node { - Some(ref node) => { - if found(node) { - return Ok(parent_node); - } else if bail_early(node) { - return Err(parent_node); - } + if let Some(entry) = self.find_entry(parent_node) { + if let Node::Crate = entry.node { + return Err(id); } - None => { + if found(&entry.node) { + return Ok(parent_node); + } else if bail_early(&entry.node) { return Err(parent_node); } + id = parent_node; + } else { + return Err(id); } - id = parent_node; } } @@ -812,16 +670,16 @@ impl<'hir> Map<'hir> { pub fn get_return_block(&self, id: NodeId) -> Option { let match_fn = |node: &Node| { match *node { - NodeItem(_) | - NodeForeignItem(_) | - NodeTraitItem(_) | - NodeImplItem(_) => true, + Node::Item(_) | + Node::ForeignItem(_) | + Node::TraitItem(_) | + Node::ImplItem(_) => true, _ => false, } }; let match_non_returning_block = |node: &Node| { match *node { - NodeExpr(ref expr) => { + Node::Expr(ref expr) => { match expr.node { ExprKind::While(..) | ExprKind::Loop(..) => true, _ => false, @@ -831,10 +689,7 @@ impl<'hir> Map<'hir> { } }; - match self.walk_parent_nodes(id, match_fn, match_non_returning_block) { - Ok(id) => Some(id), - Err(_) => None, - } + self.walk_parent_nodes(id, match_fn, match_non_returning_block).ok() } /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no @@ -843,10 +698,10 @@ impl<'hir> Map<'hir> { /// in a module, trait, or impl. pub fn get_parent(&self, id: NodeId) -> NodeId { match self.walk_parent_nodes(id, |node| match *node { - NodeItem(_) | - NodeForeignItem(_) | - NodeTraitItem(_) | - NodeImplItem(_) => true, + Node::Item(_) | + Node::ForeignItem(_) | + Node::TraitItem(_) | + Node::ImplItem(_) => true, _ => false, }, |_| false) { Ok(id) => id, @@ -858,7 +713,7 @@ impl<'hir> Map<'hir> { /// module parent is in this map. pub fn get_module_parent(&self, id: NodeId) -> DefId { let id = match self.walk_parent_nodes(id, |node| match *node { - NodeItem(&Item { node: ItemKind::Mod(_), .. }) => true, + Node::Item(&Item { node: ItemKind::Mod(_), .. }) => true, _ => false, }, |_| false) { Ok(id) => id, @@ -872,17 +727,14 @@ impl<'hir> Map<'hir> { /// and associated types probably shouldn't, for example. Behavior in this /// regard should be expected to be highly unstable. pub fn get_enclosing_scope(&self, id: NodeId) -> Option { - match self.walk_parent_nodes(id, |node| match *node { - NodeItem(_) | - NodeForeignItem(_) | - NodeTraitItem(_) | - NodeImplItem(_) | - NodeBlock(_) => true, + self.walk_parent_nodes(id, |node| match *node { + Node::Item(_) | + Node::ForeignItem(_) | + Node::TraitItem(_) | + Node::ImplItem(_) | + Node::Block(_) => true, _ => false, - }, |_| false) { - Ok(id) => Some(id), - Err(_) => None, - } + }, |_| false).ok() } pub fn get_parent_did(&self, id: NodeId) -> DefId { @@ -891,84 +743,70 @@ impl<'hir> Map<'hir> { pub fn get_foreign_abi(&self, id: NodeId) -> Abi { let parent = self.get_parent(id); - let abi = match self.find_entry(parent) { - Some(EntryItem(_, _, i)) => { - match i.node { - ItemKind::ForeignMod(ref nm) => Some(nm.abi), - _ => None - } - } - _ => None - }; - match abi { - Some(abi) => { + if let Some(entry) = self.find_entry(parent) { + if let Entry { + node: Node::Item(Item { node: ItemKind::ForeignMod(ref nm), .. }), .. } = entry + { self.read(id); // reveals some of the content of a node - abi + return nm.abi; } - None => bug!("expected foreign mod or inlined parent, found {}", - self.node_to_string(parent)) } + bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent)) } pub fn expect_item(&self, id: NodeId) -> &'hir Item { match self.find(id) { // read recorded by `find` - Some(NodeItem(item)) => item, + Some(Node::Item(item)) => item, _ => bug!("expected item, found {}", self.node_to_string(id)) } } pub fn expect_impl_item(&self, id: NodeId) -> &'hir ImplItem { match self.find(id) { - Some(NodeImplItem(item)) => item, + Some(Node::ImplItem(item)) => item, _ => bug!("expected impl item, found {}", self.node_to_string(id)) } } pub fn expect_trait_item(&self, id: NodeId) -> &'hir TraitItem { match self.find(id) { - Some(NodeTraitItem(item)) => item, + Some(Node::TraitItem(item)) => item, _ => bug!("expected trait item, found {}", self.node_to_string(id)) } } pub fn expect_variant_data(&self, id: NodeId) -> &'hir VariantData { match self.find(id) { - Some(NodeItem(i)) => { + Some(Node::Item(i)) => { match i.node { ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => struct_def, - _ => { - bug!("struct ID bound to non-struct {}", - self.node_to_string(id)); - } + _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id)) } } - Some(NodeStructCtor(data)) => data, - Some(NodeVariant(variant)) => &variant.node.data, - _ => { - bug!("expected struct or variant, found {}", - self.node_to_string(id)); - } + Some(Node::StructCtor(data)) => data, + Some(Node::Variant(variant)) => &variant.node.data, + _ => bug!("expected struct or variant, found {}", self.node_to_string(id)) } } pub fn expect_variant(&self, id: NodeId) -> &'hir Variant { match self.find(id) { - Some(NodeVariant(variant)) => variant, + Some(Node::Variant(variant)) => variant, _ => bug!("expected variant, found {}", self.node_to_string(id)), } } pub fn expect_foreign_item(&self, id: NodeId) -> &'hir ForeignItem { match self.find(id) { - Some(NodeForeignItem(item)) => item, + Some(Node::ForeignItem(item)) => item, _ => bug!("expected foreign item, found {}", self.node_to_string(id)) } } pub fn expect_expr(&self, id: NodeId) -> &'hir Expr { match self.find(id) { // read recorded by find - Some(NodeExpr(expr)) => expr, + Some(Node::Expr(expr)) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)) } } @@ -976,16 +814,16 @@ impl<'hir> Map<'hir> { /// Returns the name associated with the given NodeId's AST. pub fn name(&self, id: NodeId) -> Name { match self.get(id) { - NodeItem(i) => i.name, - NodeForeignItem(i) => i.name, - NodeImplItem(ii) => ii.ident.name, - NodeTraitItem(ti) => ti.ident.name, - NodeVariant(v) => v.node.name, - NodeField(f) => f.ident.name, - NodeLifetime(lt) => lt.name.ident().name, - NodeGenericParam(param) => param.name.ident().name, - NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.name, - NodeStructCtor(_) => self.name(self.get_parent(id)), + Node::Item(i) => i.name, + Node::ForeignItem(i) => i.name, + Node::ImplItem(ii) => ii.ident.name, + Node::TraitItem(ti) => ti.ident.name, + Node::Variant(v) => v.node.name, + Node::Field(f) => f.ident.name, + Node::Lifetime(lt) => lt.name.ident().name, + Node::GenericParam(param) => param.name.ident().name, + Node::Binding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.name, + Node::StructCtor(_) => self.name(self.get_parent(id)), _ => bug!("no name for {}", self.node_to_string(id)) } } @@ -995,20 +833,18 @@ impl<'hir> Map<'hir> { pub fn attrs(&self, id: NodeId) -> &'hir [ast::Attribute] { self.read(id); // reveals attributes on the node let attrs = match self.find(id) { - Some(NodeItem(i)) => Some(&i.attrs[..]), - Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]), - Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]), - Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]), - Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]), - Some(NodeField(ref f)) => Some(&f.attrs[..]), - Some(NodeExpr(ref e)) => Some(&*e.attrs), - Some(NodeStmt(ref s)) => Some(s.node.attrs()), - Some(NodeGenericParam(param)) => Some(¶m.attrs[..]), + Some(Node::Item(i)) => Some(&i.attrs[..]), + Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]), + Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]), + Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]), + Some(Node::Variant(ref v)) => Some(&v.node.attrs[..]), + Some(Node::Field(ref f)) => Some(&f.attrs[..]), + Some(Node::Expr(ref e)) => Some(&*e.attrs), + Some(Node::Stmt(ref s)) => Some(s.node.attrs()), + Some(Node::GenericParam(param)) => Some(¶m.attrs[..]), // unit/tuple structs take the attributes straight from // the struct definition. - Some(NodeStructCtor(_)) => { - return self.attrs(self.get_parent(id)); - } + Some(Node::StructCtor(_)) => return self.attrs(self.get_parent(id)), _ => None }; attrs.unwrap_or(&[]) @@ -1033,35 +869,32 @@ impl<'hir> Map<'hir> { pub fn span(&self, id: NodeId) -> Span { self.read(id); // reveals span from node - match self.find_entry(id) { - Some(EntryItem(_, _, item)) => item.span, - Some(EntryForeignItem(_, _, foreign_item)) => foreign_item.span, - Some(EntryTraitItem(_, _, trait_method)) => trait_method.span, - Some(EntryImplItem(_, _, impl_item)) => impl_item.span, - Some(EntryVariant(_, _, variant)) => variant.span, - Some(EntryField(_, _, field)) => field.span, - Some(EntryAnonConst(_, _, constant)) => self.body(constant.body).value.span, - Some(EntryExpr(_, _, expr)) => expr.span, - Some(EntryStmt(_, _, stmt)) => stmt.span, - Some(EntryTy(_, _, ty)) => ty.span, - Some(EntryTraitRef(_, _, tr)) => tr.path.span, - Some(EntryBinding(_, _, pat)) => pat.span, - Some(EntryPat(_, _, pat)) => pat.span, - Some(EntryBlock(_, _, block)) => block.span, - Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span, - Some(EntryLifetime(_, _, lifetime)) => lifetime.span, - Some(EntryGenericParam(_, _, param)) => param.span, - Some(EntryVisibility(_, _, &Spanned { + match self.find_entry(id).map(|entry| entry.node) { + Some(Node::Item(item)) => item.span, + Some(Node::ForeignItem(foreign_item)) => foreign_item.span, + Some(Node::TraitItem(trait_method)) => trait_method.span, + Some(Node::ImplItem(impl_item)) => impl_item.span, + Some(Node::Variant(variant)) => variant.span, + Some(Node::Field(field)) => field.span, + Some(Node::AnonConst(constant)) => self.body(constant.body).value.span, + Some(Node::Expr(expr)) => expr.span, + Some(Node::Stmt(stmt)) => stmt.span, + Some(Node::Ty(ty)) => ty.span, + Some(Node::TraitRef(tr)) => tr.path.span, + Some(Node::Binding(pat)) => pat.span, + Some(Node::Pat(pat)) => pat.span, + Some(Node::Block(block)) => block.span, + Some(Node::StructCtor(_)) => self.expect_item(self.get_parent(id)).span, + Some(Node::Lifetime(lifetime)) => lifetime.span, + Some(Node::GenericParam(param)) => param.span, + Some(Node::Visibility(&Spanned { node: VisibilityKind::Restricted { ref path, .. }, .. })) => path.span, - Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v), - Some(EntryLocal(_, _, local)) => local.span, - Some(EntryMacroDef(_, macro_def)) => macro_def.span, - - Some(RootCrate(_)) => self.forest.krate.span, - Some(NotPresent) | None => { - bug!("hir::map::Map::span: id not in map: {:?}", id) - } + Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v), + Some(Node::Local(local)) => local.span, + Some(Node::MacroDef(macro_def)) => macro_def.span, + Some(Node::Crate) => self.forest.krate.span, + None => bug!("hir::map::Map::span: id not in map: {:?}", id), } } @@ -1118,10 +951,10 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { // chain, then returns `None`. fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId) -> Option<(NodeId, Name)> { loop { - match map.find(id)? { - NodeItem(item) if item_is_mod(&item) => - return Some((id, item.name)), - _ => {} + if let Node::Item(item) = map.find(id)? { + if item_is_mod(&item) { + return Some((id, item.name)) + } } let parent = map.get_parent(id); if parent == id { return None } @@ -1154,13 +987,13 @@ impl<'a, 'hir> Iterator for NodesMatchingSuffix<'a, 'hir> { return None; } self.idx = NodeId::from_u32(self.idx.as_u32() + 1); - let name = match self.map.find_entry(idx) { - Some(EntryItem(_, _, n)) => n.name(), - Some(EntryForeignItem(_, _, n))=> n.name(), - Some(EntryTraitItem(_, _, n)) => n.name(), - Some(EntryImplItem(_, _, n)) => n.name(), - Some(EntryVariant(_, _, n)) => n.name(), - Some(EntryField(_, _, n)) => n.name(), + let name = match self.map.find_entry(idx).map(|entry| entry.node) { + Some(Node::Item(n)) => n.name(), + Some(Node::ForeignItem(n)) => n.name(), + Some(Node::TraitItem(n)) => n.name(), + Some(Node::ImplItem(n)) => n.name(), + Some(Node::Variant(n)) => n.name(), + Some(Node::Field(n)) => n.name(), _ => continue, }; if self.matches_names(self.map.get_parent(idx), name) { @@ -1183,7 +1016,6 @@ 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: &::session::Session, cstore: &dyn CrateStore, forest: &'hir mut Forest, @@ -1202,19 +1034,15 @@ pub fn map_crate<'hir>(sess: &::session::Session, let cmdline_args = sess.opts.dep_tracking_hash(); collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, - sess.codemap(), + sess.source_map(), cmdline_args) }; if log_enabled!(::log::Level::Debug) { // This only makes sense for ordered stores; note the // enumerate to count the number of entries. - let (entries_less_1, _) = map.iter().filter(|&x| { - match *x { - NotPresent => false, - _ => true - } - }).enumerate().last().expect("AST map was empty after folding?"); + let (entries_less_1, _) = map.iter().filter_map(|x| *x).enumerate().last() + .expect("AST map was empty after folding?"); let entries = entries_less_1 + 1; let vector_length = map.len(); @@ -1257,19 +1085,19 @@ impl<'hir> print::PpAnn for Map<'hir> { impl<'a> print::State<'a> { pub fn print_node(&mut self, node: Node) -> io::Result<()> { match node { - NodeItem(a) => self.print_item(&a), - NodeForeignItem(a) => self.print_foreign_item(&a), - NodeTraitItem(a) => self.print_trait_item(a), - NodeImplItem(a) => self.print_impl_item(a), - NodeVariant(a) => self.print_variant(&a), - NodeAnonConst(a) => self.print_anon_const(&a), - NodeExpr(a) => self.print_expr(&a), - NodeStmt(a) => self.print_stmt(&a), - NodeTy(a) => self.print_type(&a), - NodeTraitRef(a) => self.print_trait_ref(&a), - NodeBinding(a) | - NodePat(a) => self.print_pat(&a), - NodeBlock(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::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::Block(a) => { use syntax::print::pprust::PrintState; // containing cbox, will be closed by print-block at } @@ -1278,16 +1106,17 @@ impl<'a> print::State<'a> { self.ibox(0)?; self.print_block(&a) } - NodeLifetime(a) => self.print_lifetime(&a), - NodeVisibility(a) => self.print_visibility(&a), - NodeGenericParam(_) => bug!("cannot print NodeGenericParam"), - NodeField(_) => bug!("cannot print StructField"), + 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"), // these cases do not carry enough information in the // hir_map to reconstruct their full structure for pretty // printing. - NodeStructCtor(_) => bug!("cannot print isolated StructCtor"), - NodeLocal(a) => self.print_local_decl(&a), - NodeMacroDef(_) => bug!("cannot print MacroDef"), + Node::StructCtor(_) => bug!("cannot print isolated StructCtor"), + Node::Local(a) => self.print_local_decl(&a), + Node::MacroDef(_) => bug!("cannot print MacroDef"), + Node::Crate => bug!("cannot print Crate"), } } } @@ -1313,7 +1142,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { }; match map.find(id) { - Some(NodeItem(item)) => { + Some(Node::Item(item)) => { let item_str = match item.node { ItemKind::ExternCrate(..) => "extern crate", ItemKind::Use(..) => "use", @@ -1334,10 +1163,10 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { }; format!("{} {}{}", item_str, path_str(), id_str) } - Some(NodeForeignItem(_)) => { + Some(Node::ForeignItem(_)) => { format!("foreign item {}{}", path_str(), id_str) } - Some(NodeImplItem(ii)) => { + Some(Node::ImplItem(ii)) => { match ii.node { ImplItemKind::Const(..) => { format!("assoc const {} in {}{}", ii.ident, path_str(), id_str) @@ -1353,7 +1182,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { } } } - Some(NodeTraitItem(ti)) => { + Some(Node::TraitItem(ti)) => { let kind = match ti.node { TraitItemKind::Const(..) => "assoc constant", TraitItemKind::Method(..) => "trait method", @@ -1362,61 +1191,60 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { format!("{} {} in {}{}", kind, ti.ident, path_str(), id_str) } - Some(NodeVariant(ref variant)) => { + Some(Node::Variant(ref variant)) => { format!("variant {} in {}{}", variant.node.name, path_str(), id_str) } - Some(NodeField(ref field)) => { + Some(Node::Field(ref field)) => { format!("field {} in {}{}", field.ident, path_str(), id_str) } - Some(NodeAnonConst(_)) => { + Some(Node::AnonConst(_)) => { format!("const {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeExpr(_)) => { + Some(Node::Expr(_)) => { format!("expr {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeStmt(_)) => { + Some(Node::Stmt(_)) => { format!("stmt {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeTy(_)) => { + Some(Node::Ty(_)) => { format!("type {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeTraitRef(_)) => { + Some(Node::TraitRef(_)) => { format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeBinding(_)) => { + Some(Node::Binding(_)) => { format!("local {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodePat(_)) => { + Some(Node::Pat(_)) => { format!("pat {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeBlock(_)) => { + Some(Node::Block(_)) => { format!("block {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeLocal(_)) => { + Some(Node::Local(_)) => { format!("local {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeStructCtor(_)) => { + Some(Node::StructCtor(_)) => { format!("struct_ctor {}{}", path_str(), id_str) } - Some(NodeLifetime(_)) => { + Some(Node::Lifetime(_)) => { format!("lifetime {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeGenericParam(ref param)) => { + Some(Node::GenericParam(ref param)) => { format!("generic_param {:?}{}", param, id_str) } - Some(NodeVisibility(ref vis)) => { + Some(Node::Visibility(ref vis)) => { format!("visibility {:?}{}", vis, id_str) } - Some(NodeMacroDef(_)) => { + Some(Node::MacroDef(_)) => { format!("macro {}{}", path_str(), id_str) } - None => { - format!("unknown node{}", id_str) - } + Some(Node::Crate) => format!("root_crate"), + None => format!("unknown node{}", id_str), } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 610add90b8..de9808ffe7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -24,7 +24,7 @@ use util::nodemap::{NodeMap, FxHashSet}; use mir::mono::Linkage; use syntax_pos::{Span, DUMMY_SP, symbol::InternedString}; -use syntax::codemap::{self, Spanned}; +use syntax::source_map::{self, Spanned}; use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; @@ -33,13 +33,13 @@ use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; use syntax::tokenstream::TokenStream; -use syntax::util::ThinVec; use syntax::util::parser::ExprPrecedence; use ty::AdtKind; use ty::query::Providers; use rustc_data_structures::indexed_vec; use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope}; +use rustc_data_structures::thin_vec::ThinVec; use serialize::{self, Encoder, Encodable, Decoder, Decodable}; use std::collections::BTreeMap; @@ -70,7 +70,6 @@ pub mod lowering; pub mod map; pub mod pat_util; pub mod print; -pub mod svh; /// A HirId uniquely identifies a node in the HIR of the current crate. It is /// composed of the `owner`, which is the DefIndex of the directly enclosing @@ -402,6 +401,13 @@ impl GenericArg { GenericArg::Type(t) => t.span, } } + + pub fn id(&self) -> NodeId { + match self { + GenericArg::Lifetime(l) => l.id, + GenericArg::Type(t) => t.id, + } + } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -446,6 +452,22 @@ impl GenericArgs { } bug!("GenericArgs::inputs: not a `Fn(T) -> U`"); } + + pub fn own_counts(&self) -> GenericParamCount { + // We could cache this as a property of `GenericParamCount`, but + // the aim is to refactor this away entirely eventually and the + // presence of this method will be a constant reminder. + let mut own_counts: GenericParamCount = Default::default(); + + for arg in &self.args { + match arg { + GenericArg::Lifetime(_) => own_counts.lifetimes += 1, + GenericArg::Type(_) => own_counts.types += 1, + }; + } + + own_counts + } } /// A modifier on a bound, currently this is only used for `?Sized`, where the @@ -504,6 +526,7 @@ pub struct GenericParam { pub kind: GenericParamKind, } +#[derive(Default)] pub struct GenericParamCount { pub lifetimes: usize, pub types: usize, @@ -534,10 +557,7 @@ impl Generics { // We could cache this as a property of `GenericParamCount`, but // the aim is to refactor this away entirely eventually and the // presence of this method will be a constant reminder. - let mut own_counts = GenericParamCount { - lifetimes: 0, - types: 0, - }; + let mut own_counts: GenericParamCount = Default::default(); for param in &self.params { match param.kind { @@ -811,9 +831,10 @@ impl Pat { s.walk_(it) } PatKind::Slice(ref before, ref slice, ref after) => { - before.iter().all(|p| p.walk_(it)) && - slice.iter().all(|p| p.walk_(it)) && - after.iter().all(|p| p.walk_(it)) + before.iter() + .chain(slice.iter()) + .chain(after.iter()) + .all(|p| p.walk_(it)) } PatKind::Wild | PatKind::Lit(_) | @@ -852,23 +873,23 @@ pub struct FieldPat { /// inference. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum BindingAnnotation { - /// No binding annotation given: this means that the final binding mode - /// will depend on whether we have skipped through a `&` reference - /// when matching. For example, the `x` in `Some(x)` will have binding - /// mode `None`; if you do `let Some(x) = &Some(22)`, it will - /// ultimately be inferred to be by-reference. - /// - /// Note that implicit reference skipping is not implemented yet (#42640). - Unannotated, + /// No binding annotation given: this means that the final binding mode + /// will depend on whether we have skipped through a `&` reference + /// when matching. For example, the `x` in `Some(x)` will have binding + /// mode `None`; if you do `let Some(x) = &Some(22)`, it will + /// ultimately be inferred to be by-reference. + /// + /// Note that implicit reference skipping is not implemented yet (#42640). + Unannotated, - /// Annotated with `mut x` -- could be either ref or not, similar to `None`. - Mutable, + /// Annotated with `mut x` -- could be either ref or not, similar to `None`. + Mutable, - /// Annotated as `ref`, like `ref x` - Ref, + /// Annotated as `ref`, like `ref x` + Ref, - /// Annotated as `ref mut x`. - RefMut, + /// Annotated as `ref mut x`. + RefMut, } #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] @@ -1101,7 +1122,7 @@ pub type Stmt = Spanned; impl fmt::Debug for StmtKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Sadness. - let spanned = codemap::dummy_spanned(self.clone()); + let spanned = source_map::dummy_spanned(self.clone()); write!(f, "stmt({}: {})", spanned.node.id(), @@ -1184,10 +1205,15 @@ impl DeclKind { pub struct Arm { pub attrs: HirVec, pub pats: HirVec>, - pub guard: Option>, + pub guard: Option, pub body: P, } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum Guard { + If(P), +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Field { pub id: NodeId, @@ -1633,7 +1659,6 @@ pub struct TypeBinding { pub span: Span, } - #[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Ty { pub id: NodeId, @@ -1652,12 +1677,12 @@ impl fmt::Debug for Ty { /// Not represented directly in the AST, referred to by name through a ty_path. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum PrimTy { - TyInt(IntTy), - TyUint(UintTy), - TyFloat(FloatTy), - TyStr, - TyBool, - TyChar, + Int(IntTy), + Uint(UintTy), + Float(FloatTy), + Str, + Bool, + Char, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -1912,6 +1937,7 @@ pub enum UseKind { pub struct TraitRef { pub path: Path, pub ref_id: NodeId, + pub hir_ref_id: HirId, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -1931,7 +1957,7 @@ pub type Visibility = Spanned; pub enum VisibilityKind { Public, Crate(CrateSugar), - Restricted { path: P, id: NodeId }, + Restricted { path: P, id: NodeId, hir_id: HirId }, Inherited, } @@ -2258,7 +2284,6 @@ pub type TraitMap = NodeMap>; // imported. pub type GlobMap = NodeMap>; - pub fn provide(providers: &mut Providers) { providers.describe_def = map::describe_def; } @@ -2266,25 +2291,59 @@ pub fn provide(providers: &mut Providers) { #[derive(Clone, RustcEncodable, RustcDecodable)] pub struct CodegenFnAttrs { pub flags: CodegenFnAttrFlags, + /// Parsed representation of the `#[inline]` attribute pub inline: InlineAttr, + /// The `#[export_name = "..."]` attribute, indicating a custom symbol a + /// function should be exported under pub export_name: Option, + /// The `#[link_name = "..."]` attribute, indicating a custom symbol an + /// imported function should be imported as. Note that `export_name` + /// probably isn't set when this is set, this is for foreign items while + /// `#[export_name]` is for Rust-defined functions. + pub link_name: Option, + /// The `#[target_feature(enable = "...")]` attribute and the enabled + /// features (only enabled features are supported right now). pub target_features: Vec, + /// The `#[linkage = "..."]` attribute and the value we found. pub linkage: Option, + /// The `#[link_section = "..."]` attribute, or what executable section this + /// should be placed in. pub link_section: Option, } bitflags! { #[derive(RustcEncodable, RustcDecodable)] pub struct CodegenFnAttrFlags: u32 { + /// #[cold], a hint to LLVM that this function, when called, is never on + /// the hot path const COLD = 1 << 0; + /// #[allocator], a hint to LLVM that the pointer returned from this + /// function is never null const ALLOCATOR = 1 << 1; + /// #[unwind], an indicator that this function may unwind despite what + /// its ABI signature may otherwise imply const UNWIND = 1 << 2; + /// #[rust_allocator_nounwind], an indicator that an imported FFI + /// function will never unwind. Probably obsolete by recent changes with + /// #[unwind], but hasn't been removed/migrated yet const RUSTC_ALLOCATOR_NOUNWIND = 1 << 3; + /// #[naked], indicates to LLVM that no function prologue/epilogue + /// should be generated const NAKED = 1 << 4; + /// #[no_mangle], the function's name should be the same as its symbol const NO_MANGLE = 1 << 5; + /// #[rustc_std_internal_symbol], and indicator that this symbol is a + /// "weird symbol" for the standard library in that it has slightly + /// different linkage, visibility, and reachability rules. const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6; + /// #[no_debug], indicates that no debugging information should be + /// generated for this function by LLVM const NO_DEBUG = 1 << 7; + /// #[thread_local], indicates a static is actually a thread local + /// piece of memory const THREAD_LOCAL = 1 << 8; + /// #[used], indicates that LLVM can't eliminate this function (but the + /// linker can!) const USED = 1 << 9; } } @@ -2295,6 +2354,7 @@ impl CodegenFnAttrs { flags: CodegenFnAttrFlags::empty(), inline: InlineAttr::None, export_name: None, + link_name: None, target_features: vec![], linkage: None, link_section: None, @@ -2314,3 +2374,32 @@ impl CodegenFnAttrs { self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) || self.export_name.is_some() } } + +#[derive(Copy, Clone, Debug)] +pub enum Node<'hir> { + Item(&'hir Item), + ForeignItem(&'hir ForeignItem), + TraitItem(&'hir TraitItem), + ImplItem(&'hir ImplItem), + Variant(&'hir Variant), + Field(&'hir StructField), + AnonConst(&'hir AnonConst), + Expr(&'hir Expr), + Stmt(&'hir Stmt), + Ty(&'hir Ty), + TraitRef(&'hir TraitRef), + Binding(&'hir Pat), + Pat(&'hir Pat), + Block(&'hir Block), + Local(&'hir Local), + MacroDef(&'hir MacroDef), + + /// StructCtor represents a tuple struct. + StructCtor(&'hir VariantData), + + Lifetime(&'hir Lifetime), + GenericParam(&'hir GenericParam), + Visibility(&'hir Visibility), + + Crate, +} diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 4499a378be..7638a2cc14 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::AnnNode::*; - use rustc_target::spec::abi::Abi; use syntax::ast; -use syntax::codemap::{CodeMap, Spanned}; +use syntax::source_map::{SourceMap, Spanned}; use syntax::parse::ParseSess; use syntax::parse::lexer::comments; use syntax::print::pp::{self, Breaks}; @@ -33,12 +31,12 @@ use std::iter::Peekable; use std::vec; pub enum AnnNode<'a> { - NodeName(&'a ast::Name), - NodeBlock(&'a hir::Block), - NodeItem(&'a hir::Item), - NodeSubItem(ast::NodeId), - NodeExpr(&'a hir::Expr), - NodePat(&'a hir::Pat), + Name(&'a ast::Name), + Block(&'a hir::Block), + Item(&'a hir::Item), + SubItem(ast::NodeId), + Expr(&'a hir::Expr), + Pat(&'a hir::Pat), } pub enum Nested { @@ -85,7 +83,7 @@ impl PpAnn for hir::Crate { pub struct State<'a> { pub s: pp::Printer<'a>, - cm: Option<&'a CodeMap>, + cm: Option<&'a SourceMap>, comments: Option>, literals: Peekable>, cur_cmnt: usize, @@ -129,7 +127,7 @@ pub const default_columns: usize = 78; /// Requires you to pass an input filename and reader so that /// it can scan the input text for comments and literals to /// copy forward. -pub fn print_crate<'a>(cm: &'a CodeMap, +pub fn print_crate<'a>(cm: &'a SourceMap, sess: &ParseSess, krate: &hir::Crate, filename: FileName, @@ -149,7 +147,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, } impl<'a> State<'a> { - pub fn new_from_input(cm: &'a CodeMap, + pub fn new_from_input(cm: &'a SourceMap, sess: &ParseSess, filename: FileName, input: &mut dyn Read, @@ -173,7 +171,7 @@ impl<'a> State<'a> { }) } - pub fn new(cm: &'a CodeMap, + pub fn new(cm: &'a SourceMap, out: Box, ann: &'a dyn PpAnn, comments: Option>, @@ -253,6 +251,7 @@ impl<'a> State<'a> { pub fn bclose_(&mut self, span: syntax_pos::Span, indented: usize) -> io::Result<()> { self.bclose_maybe_open(span, indented, true) } + pub fn bclose_maybe_open(&mut self, span: syntax_pos::Span, indented: usize, @@ -266,6 +265,7 @@ impl<'a> State<'a> { } Ok(()) } + pub fn bclose(&mut self, span: syntax_pos::Span) -> io::Result<()> { self.bclose_(span, indent_unit) } @@ -276,12 +276,14 @@ impl<'a> State<'a> { None => false, } } + pub fn space_if_not_bol(&mut self) -> io::Result<()> { if !self.is_bol() { self.s.space()?; } Ok(()) } + pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> { if !self.is_bol() { self.s.break_offset(n, off) @@ -306,7 +308,6 @@ impl<'a> State<'a> { self.s.word("*/") } - pub fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], @@ -529,7 +530,7 @@ impl<'a> State<'a> { self.hardbreak_if_not_bol()?; self.maybe_print_comment(item.span.lo())?; self.print_outer_attributes(&item.attrs)?; - self.ann.pre(self, NodeItem(item))?; + self.ann.pre(self, AnnNode::Item(item))?; match item.node { hir::ItemKind::ExternCrate(orig_name) => { self.head(&visibility_qualified(&item.vis, "extern crate"))?; @@ -691,20 +692,14 @@ impl<'a> State<'a> { self.s.space()?; } - match polarity { - hir::ImplPolarity::Negative => { - self.s.word("!")?; - } - _ => {} + if let hir::ImplPolarity::Negative = polarity { + self.s.word("!")?; } - match opt_trait { - &Some(ref t) => { - self.print_trait_ref(t)?; - self.s.space()?; - self.word_space("for")?; - } - &None => {} + if let Some(ref t) = opt_trait { + self.print_trait_ref(t)?; + self.s.space()?; + self.word_space("for")?; } self.print_type(&ty)?; @@ -768,7 +763,7 @@ impl<'a> State<'a> { self.s.word(";")?; } } - self.ann.post(self, NodeItem(item)) + self.ann.post(self, AnnNode::Item(item)) } pub fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> { @@ -933,7 +928,7 @@ impl<'a> State<'a> { } pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> { - self.ann.pre(self, NodeSubItem(ti.id))?; + self.ann.pre(self, AnnNode::SubItem(ti.id))?; self.hardbreak_if_not_bol()?; self.maybe_print_comment(ti.span.lo())?; self.print_outer_attributes(&ti.attrs)?; @@ -965,11 +960,11 @@ impl<'a> State<'a> { default.as_ref().map(|ty| &**ty))?; } } - self.ann.post(self, NodeSubItem(ti.id)) + self.ann.post(self, AnnNode::SubItem(ti.id)) } pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> { - self.ann.pre(self, NodeSubItem(ii.id))?; + self.ann.pre(self, AnnNode::SubItem(ii.id))?; self.hardbreak_if_not_bol()?; self.maybe_print_comment(ii.span.lo())?; self.print_outer_attributes(&ii.attrs)?; @@ -995,7 +990,7 @@ impl<'a> State<'a> { self.print_associated_type(ii.ident, Some(bounds), None)?; } } - self.ann.post(self, NodeSubItem(ii.id)) + self.ann.post(self, AnnNode::SubItem(ii.id)) } pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> { @@ -1055,7 +1050,7 @@ impl<'a> State<'a> { hir::DefaultBlock => (), } self.maybe_print_comment(blk.span.lo())?; - self.ann.pre(self, NodeBlock(blk))?; + self.ann.pre(self, AnnNode::Block(blk))?; self.bopen()?; self.print_inner_attributes(attrs)?; @@ -1063,16 +1058,13 @@ impl<'a> State<'a> { for st in &blk.stmts { self.print_stmt(st)?; } - match blk.expr { - Some(ref expr) => { - self.space_if_not_bol()?; - self.print_expr(&expr)?; - self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()))?; - } - _ => (), + if let Some(ref expr) = blk.expr { + self.space_if_not_bol()?; + self.print_expr(&expr)?; + self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()))?; } self.bclose_maybe_open(blk.span, indented, close_box)?; - self.ann.post(self, NodeBlock(blk)) + self.ann.post(self, AnnNode::Block(blk)) } fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> { @@ -1321,7 +1313,7 @@ impl<'a> State<'a> { self.maybe_print_comment(expr.span.lo())?; self.print_outer_attributes(&expr.attrs)?; self.ibox(indent_unit)?; - self.ann.pre(self, NodeExpr(expr))?; + self.ann.pre(self, AnnNode::Expr(expr))?; match expr.node { hir::ExprKind::Box(ref expr) => { self.word_space("box")?; @@ -1481,12 +1473,9 @@ impl<'a> State<'a> { } hir::ExprKind::Ret(ref result) => { self.s.word("return")?; - match *result { - Some(ref expr) => { - self.s.word(" ")?; - self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?; - } - _ => (), + if let Some(ref expr) = *result { + self.s.word(" ")?; + self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?; } } hir::ExprKind::InlineAsm(ref a, ref outputs, ref inputs) => { @@ -1559,7 +1548,7 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?; } } - self.ann.post(self, NodeExpr(expr))?; + self.ann.post(self, AnnNode::Expr(expr))?; self.end() } @@ -1606,7 +1595,7 @@ impl<'a> State<'a> { } else { self.s.word(&ident.as_str())?; } - self.ann.post(self, NodeName(&ident.name)) + self.ann.post(self, AnnNode::Name(&ident.name)) } pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { @@ -1774,7 +1763,7 @@ impl<'a> State<'a> { pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> { self.maybe_print_comment(pat.span.lo())?; - self.ann.pre(self, NodePat(pat))?; + self.ann.pre(self, AnnNode::Pat(pat))?; // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.node { @@ -1928,7 +1917,7 @@ impl<'a> State<'a> { self.s.word("]")?; } } - self.ann.post(self, NodePat(pat)) + self.ann.post(self, AnnNode::Pat(pat)) } fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> { @@ -1951,10 +1940,14 @@ impl<'a> State<'a> { self.print_pat(&p)?; } self.s.space()?; - if let Some(ref e) = arm.guard { - self.word_space("if")?; - self.print_expr(&e)?; - self.s.space()?; + if let Some(ref g) = arm.guard { + match g { + hir::Guard::If(e) => { + self.word_space("if")?; + self.print_expr(&e)?; + self.s.space()?; + } + } } self.word_space("=>")?; diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs index e5bf384d25..9711477904 100644 --- a/src/librustc/ich/caching_codemap_view.rs +++ b/src/librustc/ich/caching_codemap_view.rs @@ -9,8 +9,8 @@ // except according to those terms. use rustc_data_structures::sync::Lrc; -use syntax::codemap::CodeMap; -use syntax_pos::{BytePos, FileMap}; +use syntax::source_map::SourceMap; +use syntax_pos::{BytePos, SourceFile}; #[derive(Clone)] struct CacheEntry { @@ -18,20 +18,20 @@ struct CacheEntry { line_number: usize, line_start: BytePos, line_end: BytePos, - file: Lrc, + file: Lrc, file_index: usize, } #[derive(Clone)] -pub struct CachingCodemapView<'cm> { - codemap: &'cm CodeMap, +pub struct CachingSourceMapView<'cm> { + source_map: &'cm SourceMap, line_cache: [CacheEntry; 3], time_stamp: usize, } -impl<'cm> CachingCodemapView<'cm> { - pub fn new(codemap: &'cm CodeMap) -> CachingCodemapView<'cm> { - let files = codemap.files(); +impl<'cm> CachingSourceMapView<'cm> { + pub fn new(source_map: &'cm SourceMap) -> CachingSourceMapView<'cm> { + let files = source_map.files(); let first_file = files[0].clone(); let entry = CacheEntry { time_stamp: 0, @@ -42,8 +42,8 @@ impl<'cm> CachingCodemapView<'cm> { file_index: 0, }; - CachingCodemapView { - codemap, + CachingSourceMapView { + source_map, line_cache: [entry.clone(), entry.clone(), entry.clone()], time_stamp: 0, } @@ -51,7 +51,7 @@ impl<'cm> CachingCodemapView<'cm> { pub fn byte_pos_to_line_and_col(&mut self, pos: BytePos) - -> Option<(Lrc, usize, BytePos)> { + -> Option<(Lrc, usize, BytePos)> { self.time_stamp += 1; // Check if the position is in one of the cached lines @@ -78,9 +78,9 @@ impl<'cm> CachingCodemapView<'cm> { // If the entry doesn't point to the correct file, fix it up if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos { let file_valid; - if self.codemap.files().len() > 0 { - let file_index = self.codemap.lookup_filemap_idx(pos); - let file = self.codemap.files()[file_index].clone(); + if self.source_map.files().len() > 0 { + let file_index = self.source_map.lookup_source_file_idx(pos); + let file = self.source_map.files()[file_index].clone(); if pos >= file.start_pos && pos < file.end_pos { cache_entry.file = file; diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 05361b6564..0694c0f05b 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -12,10 +12,9 @@ use hir; use hir::def_id::{DefId, DefIndex}; use hir::map::DefPathHash; use hir::map::definitions::Definitions; -use ich::{self, CachingCodemapView, Fingerprint}; +use ich::{self, CachingSourceMapView, Fingerprint}; use middle::cstore::CrateStore; use ty::{TyCtxt, fast_reject}; -use mir::interpret::AllocId; use session::Session; use std::cmp::Ord; @@ -25,19 +24,20 @@ use std::cell::RefCell; use syntax::ast; -use syntax::codemap::CodeMap; +use syntax::source_map::SourceMap; use syntax::ext::hygiene::SyntaxContext; use syntax::symbol::Symbol; +use syntax::tokenstream::DelimSpan; use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::hygiene; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult, ToStableHashKey}; -use rustc_data_structures::accumulate_vec::AccumulateVec; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use smallvec::SmallVec; -pub fn compute_ignored_attr_names() -> FxHashSet { +fn compute_ignored_attr_names() -> FxHashSet { debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0); ich::IGNORED_ATTRIBUTES.iter().map(|&s| Symbol::intern(s)).collect() } @@ -57,11 +57,9 @@ pub struct StableHashingContext<'a> { node_id_hashing_mode: NodeIdHashingMode, // Very often, we are hashing something that does not need the - // CachingCodemapView, so we initialize it lazily. - raw_codemap: &'a CodeMap, - caching_codemap: Option>, - - pub(super) alloc_id_recursion_tracker: FxHashSet, + // CachingSourceMapView, so we initialize it lazily. + raw_source_map: &'a SourceMap, + caching_source_map: Option>, } #[derive(PartialEq, Eq, Clone, Copy)] @@ -100,12 +98,11 @@ impl<'a> StableHashingContext<'a> { body_resolver: BodyResolver(krate), definitions, cstore, - caching_codemap: None, - raw_codemap: sess.codemap(), + caching_source_map: None, + raw_source_map: sess.source_map(), hash_spans: hash_spans_initial, hash_bodies: true, node_id_hashing_mode: NodeIdHashingMode::HashDefPath, - alloc_id_recursion_tracker: Default::default(), } } @@ -169,13 +166,13 @@ impl<'a> StableHashingContext<'a> { } #[inline] - pub fn codemap(&mut self) -> &mut CachingCodemapView<'a> { - match self.caching_codemap { + pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { + match self.caching_source_map { Some(ref mut cm) => { cm } ref mut none => { - *none = Some(CachingCodemapView::new(self.raw_codemap)); + *none = Some(CachingSourceMapView::new(self.raw_source_map)); none.as_mut().unwrap() } } @@ -183,7 +180,10 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn is_ignored_attr(&self, name: Symbol) -> bool { - self.sess.ignored_attr_names.contains(&name) + thread_local! { + static IGNORED_ATTRIBUTES: FxHashSet = compute_ignored_attr_names(); + } + IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) } pub fn hash_hir_item_like(&mut self, f: F) { @@ -305,9 +305,9 @@ impl<'a> HashStable> for Span { // Hash a span in a stable way. We can't directly hash the span's BytePos // fields (that would be similar to hashing pointers, since those are just - // offsets into the CodeMap). Instead, we hash the (file name, line, column) - // triple, which stays the same even if the containing FileMap has moved - // within the CodeMap. + // offsets into the SourceMap). Instead, we hash the (file name, line, column) + // triple, which stays the same even if the containing SourceFile has moved + // within the SourceMap. // Also note that we are hashing byte offsets for the column, not unicode // codepoint offsets. For the purpose of the hash that's sufficient. // Also, hashing filenames is expensive so we avoid doing it twice when the @@ -337,7 +337,7 @@ impl<'a> HashStable> for Span { return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher); } - let (file_lo, line_lo, col_lo) = match hcx.codemap() + let (file_lo, line_lo, col_lo) = match hcx.source_map() .byte_pos_to_line_and_col(span.lo) { Some(pos) => pos, None => { @@ -393,6 +393,17 @@ impl<'a> HashStable> for Span { } } +impl<'a> HashStable> for DelimSpan { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { + self.open.hash_stable(hcx, hasher); + self.close.hash_stable(hcx, hasher); + } +} + pub fn hash_stable_trait_impls<'a, 'gcx, W, R>( hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher, @@ -402,7 +413,7 @@ pub fn hash_stable_trait_impls<'a, 'gcx, W, R>( R: std_hash::BuildHasher, { { - let mut blanket_impls: AccumulateVec<[_; 8]> = blanket_impls + let mut blanket_impls: SmallVec<[_; 8]> = blanket_impls .iter() .map(|&def_id| hcx.def_path_hash(def_id)) .collect(); @@ -415,7 +426,7 @@ pub fn hash_stable_trait_impls<'a, 'gcx, W, R>( } { - let mut keys: AccumulateVec<[_; 8]> = + let mut keys: SmallVec<[_; 8]> = non_blanket_impls.keys() .map(|k| (k, k.map_def(|d| hcx.def_path_hash(d)))) .collect(); @@ -423,7 +434,7 @@ pub fn hash_stable_trait_impls<'a, 'gcx, W, R>( keys.len().hash_stable(hcx, hasher); for (key, ref stable_key) in keys { stable_key.hash_stable(hcx, hasher); - let mut impls : AccumulateVec<[_; 8]> = non_blanket_impls[key] + let mut impls : SmallVec<[_; 8]> = non_blanket_impls[key] .iter() .map(|&impl_id| hcx.def_path_hash(impl_id)) .collect(); diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 410d578d40..bc2eb5f442 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -308,12 +308,12 @@ impl<'a> HashStable> for hir::Ty { } impl_stable_hash_for!(enum hir::PrimTy { - TyInt(int_ty), - TyUint(uint_ty), - TyFloat(float_ty), - TyStr, - TyBool, - TyChar + Int(int_ty), + Uint(uint_ty), + Float(float_ty), + Str, + Bool, + Char }); impl_stable_hash_for!(struct hir::BareFnTy { @@ -360,6 +360,7 @@ impl_stable_hash_for!(enum hir::FunctionRetTy { impl_stable_hash_for!(struct hir::TraitRef { // Don't hash the ref_id. It is tracked via the thing it is used to access ref_id -> _, + hir_ref_id -> _, path, }); @@ -492,6 +493,10 @@ impl_stable_hash_for!(struct hir::Arm { body }); +impl_stable_hash_for!(enum hir::Guard { + If(expr), +}); + impl_stable_hash_for!(struct hir::Field { id -> _, ident, @@ -723,9 +728,10 @@ impl<'a> HashStable> for hir::VisibilityKind { hir::VisibilityKind::Crate(sugar) => { sugar.hash_stable(hcx, hasher); } - hir::VisibilityKind::Restricted { ref path, id } => { + hir::VisibilityKind::Restricted { ref path, id, hir_id } => { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { id.hash_stable(hcx, hasher); + hir_id.hash_stable(hcx, hasher); }); path.hash_stable(hcx, hasher); } @@ -988,6 +994,13 @@ impl_stable_hash_for!(enum hir::def::CtorKind { Fictive }); +impl_stable_hash_for!(enum hir::def::NonMacroAttrKind { + Builtin, + Tool, + DeriveHelper, + Custom, +}); + impl_stable_hash_for!(enum hir::def::Def { Mod(def_id), Struct(def_id), @@ -1003,11 +1016,12 @@ impl_stable_hash_for!(enum hir::def::Def { PrimTy(prim_ty), TyParam(def_id), SelfTy(trait_def_id, impl_def_id), - TyForeign(def_id), + ForeignTy(def_id), Fn(def_id), Const(def_id), Static(def_id, is_mutbl), StructCtor(def_id, ctor_kind), + SelfCtor(impl_def_id), VariantCtor(def_id, ctor_kind), Method(def_id), AssociatedConst(def_id), @@ -1015,7 +1029,8 @@ impl_stable_hash_for!(enum hir::def::Def { Upvar(def_id, index, expr_id), Label(node_id), Macro(def_id, macro_kind), - GlobalAsm(def_id), + ToolMod, + NonMacroAttr(attr_kind), Err }); @@ -1070,6 +1085,11 @@ impl_stable_hash_for!(struct hir::def::Export { span }); +impl_stable_hash_for!(struct ::middle::lib_features::LibFeatures { + stable, + unstable +}); + impl<'a> HashStable> for ::middle::lang_items::LangItem { fn hash_stable(&self, _: &mut StableHashingContext<'a>, @@ -1121,6 +1141,7 @@ impl_stable_hash_for!(struct hir::CodegenFnAttrs { flags, inline, export_name, + link_name, target_features, linkage, link_section, diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 38ea536b4e..5f35c9fea0 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -24,6 +24,7 @@ impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer }); impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, + user_ty, name, source_info, visibility_scope, @@ -65,6 +66,7 @@ for mir::UnsafetyViolationKind { match *self { mir::UnsafetyViolationKind::General => {} + mir::UnsafetyViolationKind::MinConstFn => {} mir::UnsafetyViolationKind::ExternStatic(lint_node_id) | mir::UnsafetyViolationKind::BorrowPacked(lint_node_id) => { lint_node_id.hash_stable(hcx, hasher); @@ -101,7 +103,6 @@ impl<'a> HashStable> for mir::Local { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } @@ -111,7 +112,6 @@ impl<'a> HashStable> for mir::BasicBlock { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } @@ -121,7 +121,6 @@ impl<'a> HashStable> for mir::Field { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } @@ -132,7 +131,6 @@ for mir::SourceScope { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } @@ -142,7 +140,6 @@ impl<'a> HashStable> for mir::Promoted { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } @@ -259,9 +256,10 @@ for mir::StatementKind<'gcx> { op.hash_stable(hcx, hasher); places.hash_stable(hcx, hasher); } - mir::StatementKind::UserAssertTy(ref c_ty, ref local) => { + mir::StatementKind::AscribeUserType(ref place, ref variance, ref c_ty) => { + place.hash_stable(hcx, hasher); + variance.hash_stable(hcx, hasher); c_ty.hash_stable(hcx, hasher); - local.hash_stable(hcx, hasher); } mir::StatementKind::Nop => {} mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { @@ -479,10 +477,11 @@ for mir::AggregateKind<'gcx> { mir::AggregateKind::Array(t) => { t.hash_stable(hcx, hasher); } - mir::AggregateKind::Adt(adt_def, idx, substs, active_field) => { + mir::AggregateKind::Adt(adt_def, idx, substs, user_substs, active_field) => { adt_def.hash_stable(hcx, hasher); idx.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); + user_substs.hash_stable(hcx, hasher); active_field.hash_stable(hcx, hasher); } mir::AggregateKind::Closure(def_id, ref substs) => { @@ -528,7 +527,7 @@ impl_stable_hash_for!(enum mir::NullOp { SizeOf }); -impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal }); +impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, user_ty, literal }); impl_stable_hash_for!(struct mir::Location { block, statement_index }); diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index c106966fb7..a15411c7d8 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -21,13 +21,13 @@ use syntax::feature_gate; use syntax::parse::token; use syntax::symbol::{InternedString, LocalInternedString}; use syntax::tokenstream; -use syntax_pos::FileMap; +use syntax_pos::SourceFile; use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX}; +use smallvec::SmallVec; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; -use rustc_data_structures::accumulate_vec::AccumulateVec; impl<'a> HashStable> for InternedString { #[inline] @@ -130,7 +130,7 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr, - rustc_const_unstable + const_stability }); impl<'a> HashStable> @@ -161,7 +161,6 @@ for ::syntax::attr::StabilityLevel { } impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason }); -impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature }); impl_stable_hash_for!(enum ::syntax::attr::IntType { @@ -207,7 +206,7 @@ impl<'a> HashStable> for [ast::Attribute] { } // Some attributes are always ignored during hashing. - let filtered: AccumulateVec<[&ast::Attribute; 8]> = self + let filtered: SmallVec<[&ast::Attribute; 8]> = self .iter() .filter(|attr| { !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name()) @@ -409,11 +408,10 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat { impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind { Async, - DotFill, QuestionMark, ExistentialReturnType, ForLoop, - Catch + TryBlock }); impl_stable_hash_for!(enum ::syntax_pos::FileName { @@ -428,11 +426,11 @@ impl_stable_hash_for!(enum ::syntax_pos::FileName { Custom(s) }); -impl<'a> HashStable> for FileMap { +impl<'a> HashStable> for SourceFile { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let FileMap { + let SourceFile { name: _, // We hash the smaller name_hash instead of this name_hash, name_was_remapped, @@ -459,13 +457,13 @@ impl<'a> HashStable> for FileMap { src_hash.hash_stable(hcx, hasher); - // We only hash the relative position within this filemap + // We only hash the relative position within this source_file lines.len().hash_stable(hcx, hasher); for &line in lines.iter() { stable_byte_pos(line, start_pos).hash_stable(hcx, hasher); } - // We only hash the relative position within this filemap + // We only hash the relative position within this source_file multibyte_chars.len().hash_stable(hcx, hasher); for &char_pos in multibyte_chars.iter() { stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher); @@ -479,29 +477,29 @@ impl<'a> HashStable> for FileMap { } fn stable_byte_pos(pos: ::syntax_pos::BytePos, - filemap_start: ::syntax_pos::BytePos) + source_file_start: ::syntax_pos::BytePos) -> u32 { - pos.0 - filemap_start.0 + pos.0 - source_file_start.0 } fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar, - filemap_start: ::syntax_pos::BytePos) + source_file_start: ::syntax_pos::BytePos) -> (u32, u32) { let ::syntax_pos::MultiByteChar { pos, bytes, } = mbc; - (pos.0 - filemap_start.0, bytes as u32) + (pos.0 - source_file_start.0, bytes as u32) } fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar, - filemap_start: ::syntax_pos::BytePos) + source_file_start: ::syntax_pos::BytePos) -> (u32, u32) { let pos = swc.pos(); let width = swc.width(); - (pos.0 - filemap_start.0, width as u32) + (pos.0 - source_file_start.0, width as u32) } @@ -512,7 +510,7 @@ impl<'gcx> HashStable> for feature_gate::Features { hasher: &mut StableHasher) { // Unfortunately we cannot exhaustively list fields here, since the // struct is macro generated. - self.declared_stable_lang_features.hash_stable(hcx, hasher); + self.declared_lang_features.hash_stable(hcx, hasher); self.declared_lib_features.hash_stable(hcx, hasher); self.walk_feature_fields(|feature_name, value| { diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index cb685f83ab..2bf1c79c8a 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -25,7 +25,7 @@ use ty; use mir; impl<'a, 'gcx, T> HashStable> -for &'gcx ty::Slice +for &'gcx ty::List where T: HashStable> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, @@ -53,7 +53,7 @@ for &'gcx ty::Slice } } -impl<'a, 'gcx, T> ToStableHashKey> for &'gcx ty::Slice +impl<'a, 'gcx, T> ToStableHashKey> for &'gcx ty::List where T: HashStable> { type KeyType = Fingerprint; @@ -143,7 +143,6 @@ impl<'a> HashStable> for ty::RegionVid { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } @@ -153,7 +152,6 @@ impl<'gcx> HashStable> for ty::CanonicalVar { fn hash_stable(&self, hcx: &mut StableHashingContext<'gcx>, hasher: &mut StableHasher) { - use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } @@ -344,13 +342,13 @@ impl<'a> HashStable> for ty::AdtFlags { } } -impl_stable_hash_for!(struct ty::VariantDef { - did, - name, - discr, - fields, - ctor_kind -}); +impl<'a> HashStable> for ty::VariantFlags { + fn hash_stable(&self, + _: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + std_hash::Hash::hash(self, hasher); + } +} impl_stable_hash_for!(enum ty::VariantDiscr { Explicit(def_id), @@ -384,7 +382,8 @@ for ::mir::interpret::ConstValue<'gcx> { a.hash_stable(hcx, hasher); b.hash_stable(hcx, hasher); } - ByRef(alloc, offset) => { + ByRef(id, alloc, offset) => { + id.hash_stable(hcx, hasher); alloc.hash_stable(hcx, hasher); offset.hash_stable(hcx, hasher); } @@ -392,10 +391,9 @@ for ::mir::interpret::ConstValue<'gcx> { } } -impl_stable_hash_for!(enum mir::interpret::Value { +impl_stable_hash_for!(enum mir::interpret::ScalarMaybeUndef { Scalar(v), - ScalarPair(a, b), - ByRef(ptr, align) + Undef }); impl_stable_hash_for!(struct mir::interpret::Pointer { @@ -412,7 +410,7 @@ impl<'a> HashStable> for mir::interpret::AllocId { ty::tls::with_opt(|tcx| { trace!("hashing {:?}", *self); let tcx = tcx.expect("can't hash AllocIds during hir lowering"); - let alloc_kind = tcx.alloc_map.lock().get(*self).expect("no value for AllocId"); + let alloc_kind = tcx.alloc_map.lock().get(*self); alloc_kind.hash_stable(hcx, hasher); }); } @@ -447,7 +445,7 @@ impl<'a> HashStable> for mir::interpret::Allocation { } self.undef_mask.hash_stable(hcx, hasher); self.align.hash_stable(hcx, hasher); - self.runtime_mutability.hash_stable(hcx, hasher); + self.mutability.hash_stable(hcx, hasher); } } @@ -466,9 +464,9 @@ for ::mir::interpret::Scalar { mem::discriminant(self).hash_stable(hcx, hasher); match *self { - Bits { bits, defined } => { + Bits { bits, size } => { bits.hash_stable(hcx, hasher); - defined.hash_stable(hcx, hasher); + size.hash_stable(hcx, hasher); }, Ptr(ptr) => ptr.hash_stable(hcx, hasher), } @@ -512,18 +510,17 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> { mem::discriminant(&self).hash_stable(hcx, hasher); match *self { + FunctionArgCountMismatch | DanglingPointerDeref | DoubleFree | InvalidMemoryAccess | InvalidFunctionPointer | InvalidBool | - InvalidDiscriminant | InvalidNullPointerUsage | ReadPointerAsBytes | ReadBytesAsPointer | ReadForeignStatic | InvalidPointerMath | - ReadUndefBytes | DeadLocal | StackFrameLimitReached | OutOfTls | @@ -537,7 +534,6 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> { DeallocateNonBasePtr | HeapAllocZeroBytes | Unreachable | - Panic | ReadFromReturnPointer | UnimplementedTraitSelection | TypeckError | @@ -551,9 +547,21 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> { GeneratorResumedAfterReturn | GeneratorResumedAfterPanic | InfiniteLoop => {} + ReadUndefBytes(offset) => offset.hash_stable(hcx, hasher), + InvalidDiscriminant(val) => val.hash_stable(hcx, hasher), + Panic { ref msg, ref file, line, col } => { + msg.hash_stable(hcx, hasher); + file.hash_stable(hcx, hasher); + line.hash_stable(hcx, hasher); + col.hash_stable(hcx, hasher); + }, ReferencedConstant(ref err) => err.hash_stable(hcx, hasher), MachineError(ref err) => err.hash_stable(hcx, hasher), - FunctionPointerTyMismatch(a, b) => { + FunctionAbiMismatch(a, b) => { + a.hash_stable(hcx, hasher); + b.hash_stable(hcx, hasher) + }, + FunctionArgMismatch(a, b) => { a.hash_stable(hcx, hasher); b.hash_stable(hcx, hasher) }, @@ -764,8 +772,15 @@ impl_stable_hash_for!(enum ty::cast::CastKind { FnPtrAddrCast }); -impl_stable_hash_for!(tuple_struct ::middle::region::FirstStatementIndex { idx }); -impl_stable_hash_for!(struct ::middle::region::Scope { id, code }); +impl_stable_hash_for!(struct ::middle::region::Scope { id, data }); + +impl_stable_hash_for!(enum ::middle::region::ScopeData { + Node, + CallSite, + Arguments, + Destruction, + Remainder(first_statement_index) +}); impl<'a> ToStableHashKey> for region::Scope { type KeyType = region::Scope; @@ -776,11 +791,6 @@ impl<'a> ToStableHashKey> for region::Scope { } } -impl_stable_hash_for!(struct ::middle::region::BlockRemainder { - block, - first_statement_index -}); - impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo { custom_kind }); @@ -798,90 +808,90 @@ impl_stable_hash_for!(enum ty::BoundRegion { }); impl<'a, 'gcx> HashStable> -for ty::TypeVariants<'gcx> +for ty::TyKind<'gcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use ty::TypeVariants::*; + use ty::TyKind::*; mem::discriminant(self).hash_stable(hcx, hasher); match *self { - TyBool | - TyChar | - TyStr | - TyError | - TyNever => { + Bool | + Char | + Str | + Error | + Never => { // Nothing more to hash. } - TyInt(int_ty) => { + Int(int_ty) => { int_ty.hash_stable(hcx, hasher); } - TyUint(uint_ty) => { + Uint(uint_ty) => { uint_ty.hash_stable(hcx, hasher); } - TyFloat(float_ty) => { + Float(float_ty) => { float_ty.hash_stable(hcx, hasher); } - TyAdt(adt_def, substs) => { + Adt(adt_def, substs) => { adt_def.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); } - TyArray(inner_ty, len) => { + Array(inner_ty, len) => { inner_ty.hash_stable(hcx, hasher); len.hash_stable(hcx, hasher); } - TySlice(inner_ty) => { + Slice(inner_ty) => { inner_ty.hash_stable(hcx, hasher); } - TyRawPtr(pointee_ty) => { + RawPtr(pointee_ty) => { pointee_ty.hash_stable(hcx, hasher); } - TyRef(region, pointee_ty, mutbl) => { + Ref(region, pointee_ty, mutbl) => { region.hash_stable(hcx, hasher); pointee_ty.hash_stable(hcx, hasher); mutbl.hash_stable(hcx, hasher); } - TyFnDef(def_id, substs) => { + FnDef(def_id, substs) => { def_id.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); } - TyFnPtr(ref sig) => { + FnPtr(ref sig) => { sig.hash_stable(hcx, hasher); } - TyDynamic(ref existential_predicates, region) => { + Dynamic(ref existential_predicates, region) => { existential_predicates.hash_stable(hcx, hasher); region.hash_stable(hcx, hasher); } - TyClosure(def_id, closure_substs) => { + Closure(def_id, closure_substs) => { def_id.hash_stable(hcx, hasher); closure_substs.hash_stable(hcx, hasher); } - TyGenerator(def_id, generator_substs, movability) => { + Generator(def_id, generator_substs, movability) => { def_id.hash_stable(hcx, hasher); generator_substs.hash_stable(hcx, hasher); movability.hash_stable(hcx, hasher); } - TyGeneratorWitness(types) => { + GeneratorWitness(types) => { types.hash_stable(hcx, hasher) } - TyTuple(inner_tys) => { + Tuple(inner_tys) => { inner_tys.hash_stable(hcx, hasher); } - TyProjection(ref projection_ty) => { + Projection(ref projection_ty) => { projection_ty.hash_stable(hcx, hasher); } - TyAnon(def_id, substs) => { + Opaque(def_id, substs) => { def_id.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); } - TyParam(param_ty) => { + Param(param_ty) => { param_ty.hash_stable(hcx, hasher); } - TyForeign(def_id) => { + Foreign(def_id) => { def_id.hash_stable(hcx, hasher); } - TyInfer(infer_ty) => { + Infer(infer_ty) => { infer_ty.hash_stable(hcx, hasher); } } @@ -906,7 +916,7 @@ for ty::TyVid _hasher: &mut StableHasher) { // TyVid values are confined to an inference context and hence // should not be hashed. - bug!("ty::TypeVariants::hash_stable() - can't hash a TyVid {:?}.", *self) + bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self) } } @@ -918,7 +928,7 @@ for ty::IntVid _hasher: &mut StableHasher) { // IntVid values are confined to an inference context and hence // should not be hashed. - bug!("ty::TypeVariants::hash_stable() - can't hash an IntVid {:?}.", *self) + bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self) } } @@ -930,7 +940,7 @@ for ty::FloatVid _hasher: &mut StableHasher) { // FloatVid values are confined to an inference context and hence // should not be hashed. - bug!("ty::TypeVariants::hash_stable() - can't hash a FloatVid {:?}.", *self) + bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self) } } @@ -1087,6 +1097,7 @@ impl_stable_hash_for!(enum traits::Reveal { }); impl_stable_hash_for!(enum ::middle::privacy::AccessLevel { + ReachableFromImplTrait, Reachable, Exported, Public diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index d58eb64c36..6e5134c3c0 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -10,11 +10,10 @@ //! ICH - Incremental Compilation Hash -pub use self::fingerprint::Fingerprint; -pub use self::caching_codemap_view::CachingCodemapView; +crate use rustc_data_structures::fingerprint::Fingerprint; +pub use self::caching_codemap_view::CachingSourceMapView; pub use self::hcx::{StableHashingContextProvider, StableHashingContext, NodeIdHashingMode, - hash_stable_trait_impls, compute_ignored_attr_names}; -mod fingerprint; + hash_stable_trait_impls}; mod caching_codemap_view; mod hcx; diff --git a/src/librustc/infer/anon_types/mod.rs b/src/librustc/infer/anon_types/mod.rs deleted file mode 100644 index 205f8c5ad0..0000000000 --- a/src/librustc/infer/anon_types/mod.rs +++ /dev/null @@ -1,861 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use hir::def_id::DefId; -use hir; -use infer::{self, InferCtxt, InferOk, TypeVariableOrigin}; -use infer::outlives::free_region_map::FreeRegionRelations; -use rustc_data_structures::fx::FxHashMap; -use syntax::ast; -use traits::{self, PredicateObligation}; -use ty::{self, Ty, TyCtxt, GenericParamDefKind}; -use ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; -use ty::outlives::Component; -use ty::subst::{Kind, Substs, UnpackedKind}; -use util::nodemap::DefIdMap; - -pub type AnonTypeMap<'tcx> = DefIdMap>; - -/// Information about the anonymous, abstract types whose values we -/// are inferring in this function (these are the `impl Trait` that -/// appear in the return type). -#[derive(Copy, Clone, Debug)] -pub struct AnonTypeDecl<'tcx> { - /// The substitutions that we apply to the abstract that that this - /// `impl Trait` desugars to. e.g., if: - /// - /// fn foo<'a, 'b, T>() -> impl Trait<'a> - /// - /// winds up desugared to: - /// - /// abstract type Foo<'x, T>: Trait<'x> - /// fn foo<'a, 'b, T>() -> Foo<'a, T> - /// - /// then `substs` would be `['a, T]`. - pub substs: &'tcx Substs<'tcx>, - - /// The type variable that represents the value of the abstract type - /// that we require. In other words, after we compile this function, - /// we will be created a constraint like: - /// - /// Foo<'a, T> = ?C - /// - /// where `?C` is the value of this type variable. =) It may - /// naturally refer to the type and lifetime parameters in scope - /// in this function, though ultimately it should only reference - /// those that are arguments to `Foo` in the constraint above. (In - /// other words, `?C` should not include `'b`, even though it's a - /// lifetime parameter on `foo`.) - pub concrete_ty: Ty<'tcx>, - - /// True if the `impl Trait` bounds include region bounds. - /// For example, this would be true for: - /// - /// fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b - /// - /// but false for: - /// - /// fn foo<'c>() -> impl Trait<'c> - /// - /// unless `Trait` was declared like: - /// - /// trait Trait<'c>: 'c - /// - /// in which case it would be true. - /// - /// This is used during regionck to decide whether we need to - /// impose any additional constraints to ensure that region - /// variables in `concrete_ty` wind up being constrained to - /// something from `substs` (or, at minimum, things that outlive - /// the fn body). (Ultimately, writeback is responsible for this - /// check.) - pub has_required_region_bounds: bool, -} - -impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - /// Replace all anonymized types in `value` with fresh inference variables - /// and creates appropriate obligations. For example, given the input: - /// - /// impl Iterator - /// - /// this method would create two type variables, `?0` and `?1`. It would - /// return the type `?0` but also the obligations: - /// - /// ?0: Iterator - /// ?1: Debug - /// - /// Moreover, it returns a `AnonTypeMap` that would map `?0` to - /// info about the `impl Iterator<..>` type and `?1` to info about - /// the `impl Debug` type. - /// - /// # Parameters - /// - /// - `parent_def_id` -- we will only instantiate anonymous types - /// with this parent. This is typically the def-id of the function - /// in whose return type anon types are being instantiated. - /// - `body_id` -- the body-id with which the resulting obligations should - /// be associated - /// - `param_env` -- the in-scope parameter environment to be used for - /// obligations - /// - `value` -- the value within which we are instantiating anon types - pub fn instantiate_anon_types>( - &self, - parent_def_id: DefId, - body_id: ast::NodeId, - param_env: ty::ParamEnv<'tcx>, - value: &T, - ) -> InferOk<'tcx, (T, AnonTypeMap<'tcx>)> { - debug!( - "instantiate_anon_types(value={:?}, parent_def_id={:?}, body_id={:?}, param_env={:?})", - value, parent_def_id, body_id, param_env, - ); - let mut instantiator = Instantiator { - infcx: self, - parent_def_id, - body_id, - param_env, - anon_types: DefIdMap(), - obligations: vec![], - }; - let value = instantiator.instantiate_anon_types_in_map(value); - InferOk { - value: (value, instantiator.anon_types), - obligations: instantiator.obligations, - } - } - - /// Given the map `anon_types` containing the existential `impl - /// Trait` types whose underlying, hidden types are being - /// inferred, this method adds constraints to the regions - /// appearing in those underlying hidden types to ensure that they - /// at least do not refer to random scopes within the current - /// function. These constraints are not (quite) sufficient to - /// guarantee that the regions are actually legal values; that - /// final condition is imposed after region inference is done. - /// - /// # The Problem - /// - /// Let's work through an example to explain how it works. Assume - /// the current function is as follows: - /// - /// ```text - /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>) - /// ``` - /// - /// Here, we have two `impl Trait` types whose values are being - /// inferred (the `impl Bar<'a>` and the `impl - /// Bar<'b>`). Conceptually, this is sugar for a setup where we - /// define underlying abstract types (`Foo1`, `Foo2`) and then, in - /// the return type of `foo`, we *reference* those definitions: - /// - /// ```text - /// abstract type Foo1<'x>: Bar<'x>; - /// abstract type Foo2<'x>: Bar<'x>; - /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } - /// // ^^^^ ^^ - /// // | | - /// // | substs - /// // def_id - /// ``` - /// - /// As indicating in the comments above, each of those references - /// is (in the compiler) basically a substitution (`substs`) - /// applied to the type of a suitable `def_id` (which identifies - /// `Foo1` or `Foo2`). - /// - /// Now, at this point in compilation, what we have done is to - /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with - /// fresh inference variables C1 and C2. We wish to use the values - /// of these variables to infer the underlying types of `Foo1` and - /// `Foo2`. That is, this gives rise to higher-order (pattern) unification - /// constraints like: - /// - /// ```text - /// for<'a> (Foo1<'a> = C1) - /// for<'b> (Foo1<'b> = C2) - /// ``` - /// - /// For these equation to be satisfiable, the types `C1` and `C2` - /// can only refer to a limited set of regions. For example, `C1` - /// can only refer to `'static` and `'a`, and `C2` can only refer - /// to `'static` and `'b`. The job of this function is to impose that - /// constraint. - /// - /// Up to this point, C1 and C2 are basically just random type - /// inference variables, and hence they may contain arbitrary - /// regions. In fact, it is fairly likely that they do! Consider - /// this possible definition of `foo`: - /// - /// ```text - /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) { - /// (&*x, &*y) - /// } - /// ``` - /// - /// Here, the values for the concrete types of the two impl - /// traits will include inference variables: - /// - /// ```text - /// &'0 i32 - /// &'1 i32 - /// ``` - /// - /// Ordinarily, the subtyping rules would ensure that these are - /// sufficiently large. But since `impl Bar<'a>` isn't a specific - /// type per se, we don't get such constraints by default. This - /// is where this function comes into play. It adds extra - /// constraints to ensure that all the regions which appear in the - /// inferred type are regions that could validly appear. - /// - /// This is actually a bit of a tricky constraint in general. We - /// want to say that each variable (e.g., `'0`) can only take on - /// values that were supplied as arguments to the abstract type - /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in - /// scope. We don't have a constraint quite of this kind in the current - /// region checker. - /// - /// # The Solution - /// - /// We make use of the constraint that we *do* have in the `<=` - /// relation. To do that, we find the "minimum" of all the - /// arguments that appear in the substs: that is, some region - /// which is less than all the others. In the case of `Foo1<'a>`, - /// that would be `'a` (it's the only choice, after all). Then we - /// apply that as a least bound to the variables (e.g., `'a <= - /// '0`). - /// - /// In some cases, there is no minimum. Consider this example: - /// - /// ```text - /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... } - /// ``` - /// - /// Here we would report an error, because `'a` and `'b` have no - /// relation to one another. - /// - /// # The `free_region_relations` parameter - /// - /// The `free_region_relations` argument is used to find the - /// "minimum" of the regions supplied to a given abstract type. - /// It must be a relation that can answer whether `'a <= 'b`, - /// where `'a` and `'b` are regions that appear in the "substs" - /// for the abstract type references (the `<'a>` in `Foo1<'a>`). - /// - /// Note that we do not impose the constraints based on the - /// generic regions from the `Foo1` definition (e.g., `'x`). This - /// is because the constraints we are imposing here is basically - /// the concern of the one generating the constraining type C1, - /// which is the current function. It also means that we can - /// take "implied bounds" into account in some cases: - /// - /// ```text - /// trait SomeTrait<'a, 'b> { } - /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. } - /// ``` - /// - /// Here, the fact that `'b: 'a` is known only because of the - /// implied bounds from the `&'a &'b u32` parameter, and is not - /// "inherent" to the abstract type definition. - /// - /// # Parameters - /// - /// - `anon_types` -- the map produced by `instantiate_anon_types` - /// - `free_region_relations` -- something that can be used to relate - /// the free regions (`'a`) that appear in the impl trait. - pub fn constrain_anon_types>( - &self, - anon_types: &AnonTypeMap<'tcx>, - free_region_relations: &FRR, - ) { - debug!("constrain_anon_types()"); - - for (&def_id, anon_defn) in anon_types { - self.constrain_anon_type(def_id, anon_defn, free_region_relations); - } - } - - fn constrain_anon_type>( - &self, - def_id: DefId, - anon_defn: &AnonTypeDecl<'tcx>, - free_region_relations: &FRR, - ) { - debug!("constrain_anon_type()"); - debug!("constrain_anon_type: def_id={:?}", def_id); - debug!("constrain_anon_type: anon_defn={:#?}", anon_defn); - - let concrete_ty = self.resolve_type_vars_if_possible(&anon_defn.concrete_ty); - - debug!("constrain_anon_type: concrete_ty={:?}", concrete_ty); - - let abstract_type_generics = self.tcx.generics_of(def_id); - - let span = self.tcx.def_span(def_id); - - // If there are required region bounds, we can just skip - // ahead. There will already be a registered region - // obligation related `concrete_ty` to those regions. - if anon_defn.has_required_region_bounds { - return; - } - - // There were no `required_region_bounds`, - // so we have to search for a `least_region`. - // Go through all the regions used as arguments to the - // abstract type. These are the parameters to the abstract - // type; so in our example above, `substs` would contain - // `['a]` for the first impl trait and `'b` for the - // second. - let mut least_region = None; - for param in &abstract_type_generics.params { - match param.kind { - GenericParamDefKind::Lifetime => {} - _ => continue - } - // Get the value supplied for this region from the substs. - let subst_arg = anon_defn.substs.region_at(param.index as usize); - - // Compute the least upper bound of it with the other regions. - debug!("constrain_anon_types: least_region={:?}", least_region); - debug!("constrain_anon_types: subst_arg={:?}", subst_arg); - match least_region { - None => least_region = Some(subst_arg), - Some(lr) => { - if free_region_relations.sub_free_regions(lr, subst_arg) { - // keep the current least region - } else if free_region_relations.sub_free_regions(subst_arg, lr) { - // switch to `subst_arg` - least_region = Some(subst_arg); - } else { - // There are two regions (`lr` and - // `subst_arg`) which are not relatable. We can't - // find a best choice. - self.tcx - .sess - .struct_span_err(span, "ambiguous lifetime bound in `impl Trait`") - .span_label( - span, - format!("neither `{}` nor `{}` outlives the other", lr, subst_arg), - ) - .emit(); - - least_region = Some(self.tcx.mk_region(ty::ReEmpty)); - break; - } - } - } - } - - let least_region = least_region.unwrap_or(self.tcx.types.re_static); - debug!("constrain_anon_types: least_region={:?}", least_region); - - // Require that the type `concrete_ty` outlives - // `least_region`, modulo any type parameters that appear - // in the type, which we ignore. This is because impl - // trait values are assumed to capture all the in-scope - // type parameters. This little loop here just invokes - // `outlives` repeatedly, draining all the nested - // obligations that result. - let mut types = vec![concrete_ty]; - let bound_region = |r| self.sub_regions(infer::CallReturn(span), least_region, r); - while let Some(ty) = types.pop() { - let mut components = self.tcx.outlives_components(ty); - while let Some(component) = components.pop() { - match component { - Component::Region(r) => { - bound_region(r); - } - - Component::Param(_) => { - // ignore type parameters like `T`, they are captured - // implicitly by the `impl Trait` - } - - Component::UnresolvedInferenceVariable(_) => { - // we should get an error that more type - // annotations are needed in this case - self.tcx - .sess - .delay_span_bug(span, "unresolved inf var in anon"); - } - - Component::Projection(ty::ProjectionTy { - substs, - item_def_id: _, - }) => { - for r in substs.regions() { - bound_region(r); - } - types.extend(substs.types()); - } - - Component::EscapingProjection(more_components) => { - components.extend(more_components); - } - } - } - } - } - - /// Given the fully resolved, instantiated type for an anonymous - /// type, i.e., the value of an inference variable like C1 or C2 - /// (*), computes the "definition type" for an abstract type - /// definition -- that is, the inferred value of `Foo1<'x>` or - /// `Foo2<'x>` that we would conceptually use in its definition: - /// - /// abstract type Foo1<'x>: Bar<'x> = AAA; <-- this type AAA - /// abstract type Foo2<'x>: Bar<'x> = BBB; <-- or this type BBB - /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } - /// - /// Note that these values are defined in terms of a distinct set of - /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main - /// purpose of this function is to do that translation. - /// - /// (*) C1 and C2 were introduced in the comments on - /// `constrain_anon_types`. Read that comment for more context. - /// - /// # Parameters - /// - /// - `def_id`, the `impl Trait` type - /// - `anon_defn`, the anonymous definition created in `instantiate_anon_types` - /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of - /// `anon_defn.concrete_ty` - pub fn infer_anon_definition_from_instantiation( - &self, - def_id: DefId, - anon_defn: &AnonTypeDecl<'tcx>, - instantiated_ty: Ty<'gcx>, - ) -> Ty<'gcx> { - debug!( - "infer_anon_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})", - def_id, instantiated_ty - ); - - let gcx = self.tcx.global_tcx(); - - // Use substs to build up a reverse map from regions to their - // identity mappings. This is necessary because of `impl - // Trait` lifetimes are computed by replacing existing - // lifetimes with 'static and remapping only those used in the - // `impl Trait` return type, resulting in the parameters - // shifting. - let id_substs = Substs::identity_for_item(gcx, def_id); - let map: FxHashMap, Kind<'gcx>> = anon_defn - .substs - .iter() - .enumerate() - .map(|(index, subst)| (*subst, id_substs[index])) - .collect(); - - // Convert the type from the function into a type valid outside - // the function, by replacing invalid regions with 'static, - // after producing an error for each of them. - let definition_ty = - instantiated_ty.fold_with(&mut ReverseMapper::new( - self.tcx, - self.is_tainted_by_errors(), - def_id, - map, - instantiated_ty, - )); - debug!( - "infer_anon_definition_from_instantiation: definition_ty={:?}", - definition_ty - ); - - // We can unwrap here because our reverse mapper always - // produces things with 'gcx lifetime, though the type folder - // obscures that. - let definition_ty = gcx.lift(&definition_ty).unwrap(); - - definition_ty - } -} - -struct ReverseMapper<'cx, 'gcx: 'tcx, 'tcx: 'cx> { - tcx: TyCtxt<'cx, 'gcx, 'tcx>, - - /// If errors have already been reported in this fn, we suppress - /// our own errors because they are sometimes derivative. - tainted_by_errors: bool, - - anon_type_def_id: DefId, - map: FxHashMap, Kind<'gcx>>, - map_missing_regions_to_empty: bool, - - /// initially `Some`, set to `None` once error has been reported - hidden_ty: Option>, -} - -impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> { - fn new( - tcx: TyCtxt<'cx, 'gcx, 'tcx>, - tainted_by_errors: bool, - anon_type_def_id: DefId, - map: FxHashMap, Kind<'gcx>>, - hidden_ty: Ty<'tcx>, - ) -> Self { - Self { - tcx, - tainted_by_errors, - anon_type_def_id, - map, - map_missing_regions_to_empty: false, - hidden_ty: Some(hidden_ty), - } - } - - fn fold_kind_mapping_missing_regions_to_empty(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> { - assert!(!self.map_missing_regions_to_empty); - self.map_missing_regions_to_empty = true; - let kind = kind.fold_with(self); - self.map_missing_regions_to_empty = false; - kind - } - - fn fold_kind_normally(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> { - assert!(!self.map_missing_regions_to_empty); - kind.fold_with(self) - } -} - -impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> { - fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { - self.tcx - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match r { - // ignore bound regions that appear in the type (e.g., this - // would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | - - // ignore `'static`, as that can appear anywhere - ty::ReStatic | - - // ignore `ReScope`, as that can appear anywhere - // See `src/test/run-pass/issue-49556.rs` for example. - ty::ReScope(..) => return r, - - _ => { } - } - - match self.map.get(&r.into()).map(|k| k.unpack()) { - Some(UnpackedKind::Lifetime(r1)) => r1, - Some(u) => panic!("region mapped to unexpected kind: {:?}", u), - None => { - if !self.map_missing_regions_to_empty && !self.tainted_by_errors { - if let Some(hidden_ty) = self.hidden_ty.take() { - let span = self.tcx.def_span(self.anon_type_def_id); - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0700, - "hidden type for `impl Trait` captures lifetime that \ - does not appear in bounds", - ); - - // Assuming regionck succeeded, then we must - // be capturing *some* region from the fn - // header, and hence it must be free, so it's - // ok to invoke this fn (which doesn't accept - // all regions, and would ICE if an - // inappropriate region is given). We check - // `is_tainted_by_errors` by errors above, so - // we don't get in here unless regionck - // succeeded. (Note also that if regionck - // failed, then the regions we are attempting - // to map here may well be giving errors - // *because* the constraints were not - // satisfiable.) - self.tcx.note_and_explain_free_region( - &mut err, - &format!("hidden type `{}` captures ", hidden_ty), - r, - "" - ); - - err.emit(); - } - } - self.tcx.types.re_empty - }, - } - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { - ty::TyClosure(def_id, substs) => { - // I am a horrible monster and I pray for death. When - // we encounter a closure here, it is always a closure - // from within the function that we are currently - // type-checking -- one that is now being encapsulated - // in an existential abstract type. Ideally, we would - // go through the types/lifetimes that it references - // and treat them just like we would any other type, - // which means we would error out if we find any - // reference to a type/region that is not in the - // "reverse map". - // - // **However,** in the case of closures, there is a - // somewhat subtle (read: hacky) consideration. The - // problem is that our closure types currently include - // all the lifetime parameters declared on the - // enclosing function, even if they are unused by the - // closure itself. We can't readily filter them out, - // so here we replace those values with `'empty`. This - // can't really make a difference to the rest of the - // compiler; those regions are ignored for the - // outlives relation, and hence don't affect trait - // selection or auto traits, and they are erased - // during codegen. - - let generics = self.tcx.generics_of(def_id); - let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map( - |(index, &kind)| { - if index < generics.parent_count { - // Accommodate missing regions in the parent kinds... - self.fold_kind_mapping_missing_regions_to_empty(kind) - } else { - // ...but not elsewhere. - self.fold_kind_normally(kind) - } - }, - )); - - self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs }) - } - - _ => ty.super_fold_with(self), - } - } -} - -struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> { - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - parent_def_id: DefId, - body_id: ast::NodeId, - param_env: ty::ParamEnv<'tcx>, - anon_types: AnonTypeMap<'tcx>, - obligations: Vec>, -} - -impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { - fn instantiate_anon_types_in_map>(&mut self, value: &T) -> T { - debug!("instantiate_anon_types_in_map(value={:?})", value); - let tcx = self.infcx.tcx; - value.fold_with(&mut BottomUpFolder { - tcx, - reg_op: |reg| reg, - fldop: |ty| { - if let ty::TyAnon(def_id, substs) = ty.sty { - // Check that this is `impl Trait` type is - // declared by `parent_def_id` -- i.e., one whose - // value we are inferring. At present, this is - // always true during the first phase of - // type-check, but not always true later on during - // NLL. Once we support named abstract types more fully, - // this same scenario will be able to arise during all phases. - // - // Here is an example using `abstract type` that indicates - // the distinction we are checking for: - // - // ```rust - // mod a { - // pub abstract type Foo: Iterator; - // pub fn make_foo() -> Foo { .. } - // } - // - // mod b { - // fn foo() -> a::Foo { a::make_foo() } - // } - // ``` - // - // Here, the return type of `foo` references a - // `TyAnon` indeed, but not one whose value is - // presently being inferred. You can get into a - // similar situation with closure return types - // today: - // - // ```rust - // fn foo() -> impl Iterator { .. } - // fn bar() { - // let x = || foo(); // returns the Anon assoc with `foo` - // } - // ``` - if let Some(anon_node_id) = tcx.hir.as_local_node_id(def_id) { - let parent_def_id = self.parent_def_id; - let def_scope_default = || { - let anon_parent_node_id = tcx.hir.get_parent(anon_node_id); - parent_def_id == tcx.hir.local_def_id(anon_parent_node_id) - }; - let in_definition_scope = match tcx.hir.find(anon_node_id) { - Some(hir::map::NodeItem(item)) => match item.node { - // impl trait - hir::ItemKind::Existential(hir::ExistTy { - impl_trait_fn: Some(parent), - .. - }) => parent == self.parent_def_id, - // named existential types - hir::ItemKind::Existential(hir::ExistTy { - impl_trait_fn: None, - .. - }) => may_define_existential_type( - tcx, - self.parent_def_id, - anon_node_id, - ), - _ => def_scope_default(), - }, - Some(hir::map::NodeImplItem(item)) => match item.node { - hir::ImplItemKind::Existential(_) => may_define_existential_type( - tcx, - self.parent_def_id, - anon_node_id, - ), - _ => def_scope_default(), - }, - _ => bug!( - "expected (impl) item, found {}", - tcx.hir.node_to_string(anon_node_id), - ), - }; - if in_definition_scope { - return self.fold_anon_ty(ty, def_id, substs); - } - - debug!( - "instantiate_anon_types_in_map: \ - encountered anon outside it's definition scope \ - def_id={:?}", - def_id, - ); - } - } - - ty - }, - }) - } - - fn fold_anon_ty( - &mut self, - ty: Ty<'tcx>, - def_id: DefId, - substs: &'tcx Substs<'tcx>, - ) -> Ty<'tcx> { - let infcx = self.infcx; - let tcx = infcx.tcx; - - debug!( - "instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})", - def_id, substs - ); - - // Use the same type variable if the exact same TyAnon appears more - // than once in the return type (e.g. if it's passed to a type alias). - if let Some(anon_defn) = self.anon_types.get(&def_id) { - return anon_defn.concrete_ty; - } - let span = tcx.def_span(def_id); - let ty_var = infcx.next_ty_var(TypeVariableOrigin::TypeInference(span)); - - let predicates_of = tcx.predicates_of(def_id); - debug!( - "instantiate_anon_types: predicates: {:#?}", - predicates_of, - ); - let bounds = predicates_of.instantiate(tcx, substs); - debug!("instantiate_anon_types: bounds={:?}", bounds); - - let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone()); - debug!( - "instantiate_anon_types: required_region_bounds={:?}", - required_region_bounds - ); - - // make sure that we are in fact defining the *entire* type - // e.g. `existential type Foo: Bar;` needs to be - // defined by a function like `fn foo() -> Foo`. - debug!( - "instantiate_anon_types: param_env: {:#?}", - self.param_env, - ); - debug!( - "instantiate_anon_types: generics: {:#?}", - tcx.generics_of(def_id), - ); - - self.anon_types.insert( - def_id, - AnonTypeDecl { - substs, - concrete_ty: ty_var, - has_required_region_bounds: !required_region_bounds.is_empty(), - }, - ); - debug!("instantiate_anon_types: ty_var={:?}", ty_var); - - for predicate in bounds.predicates { - // Change the predicate to refer to the type variable, - // which will be the concrete type, instead of the TyAnon. - // This also instantiates nested `impl Trait`. - let predicate = self.instantiate_anon_types_in_map(&predicate); - - let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType); - - // Require that the predicate holds for the concrete type. - debug!("instantiate_anon_types: predicate={:?}", predicate); - self.obligations - .push(traits::Obligation::new(cause, self.param_env, predicate)); - } - - ty_var - } -} - -/// Whether `anon_node_id` is a sibling or a child of a sibling of `def_id` -/// -/// ```rust -/// pub mod foo { -/// pub mod bar { -/// pub existential type Baz; -/// -/// fn f1() -> Baz { .. } -/// } -/// -/// fn f2() -> bar::Baz { .. } -/// } -/// ``` -/// -/// Here, `def_id` will be the `DefId` of the existential type `Baz`. -/// `anon_node_id` is the `NodeId` of the reference to Baz -- so either the return type of f1 or f2. -/// We will return true if the reference is within the same module as the existential type -/// So true for f1, false for f2. -pub fn may_define_existential_type( - tcx: TyCtxt, - def_id: DefId, - anon_node_id: ast::NodeId, -) -> bool { - let mut node_id = tcx - .hir - .as_local_node_id(def_id) - .unwrap(); - // named existential types can be defined by any siblings or - // children of siblings - let mod_id = tcx.hir.get_parent(anon_node_id); - // so we walk up the node tree until we hit the root or the parent - // of the anon type - while node_id != mod_id && node_id != ast::CRATE_NODE_ID { - node_id = tcx.hir.get_parent(node_id); - } - // syntactically we are allowed to define the concrete type - node_id == mod_id -} diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index c4de95c60b..b30ccb5976 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -23,11 +23,11 @@ use infer::InferCtxt; use std::sync::atomic::Ordering; use ty::fold::{TypeFoldable, TypeFolder}; use ty::subst::Kind; -use ty::{self, CanonicalVar, Lift, Slice, Ty, TyCtxt, TypeFlags}; +use ty::{self, CanonicalVar, Lift, List, Ty, TyCtxt, TypeFlags}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// Canonicalizes a query value `V`. When we canonicalize a query, @@ -246,46 +246,46 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { - ty::TyInfer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t), + ty::Infer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t), - ty::TyInfer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t), + ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t), - ty::TyInfer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t), + ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t), - ty::TyInfer(ty::FreshTy(_)) - | ty::TyInfer(ty::FreshIntTy(_)) - | ty::TyInfer(ty::FreshFloatTy(_)) => { + ty::Infer(ty::FreshTy(_)) + | ty::Infer(ty::FreshIntTy(_)) + | ty::Infer(ty::FreshFloatTy(_)) => { bug!("encountered a fresh type during canonicalization") } - ty::TyInfer(ty::CanonicalTy(_)) => { + ty::Infer(ty::CanonicalTy(_)) => { bug!("encountered a canonical type during canonicalization") } - ty::TyClosure(..) - | ty::TyGenerator(..) - | ty::TyGeneratorWitness(..) - | ty::TyBool - | ty::TyChar - | ty::TyInt(..) - | ty::TyUint(..) - | ty::TyFloat(..) - | ty::TyAdt(..) - | ty::TyStr - | ty::TyError - | ty::TyArray(..) - | ty::TySlice(..) - | ty::TyRawPtr(..) - | ty::TyRef(..) - | ty::TyFnDef(..) - | ty::TyFnPtr(_) - | ty::TyDynamic(..) - | ty::TyNever - | ty::TyTuple(..) - | ty::TyProjection(..) - | ty::TyForeign(..) - | ty::TyParam(..) - | ty::TyAnon(..) => { + ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Adt(..) + | ty::Str + | ty::Error + | ty::Array(..) + | ty::Slice(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Dynamic(..) + | ty::Never + | ty::Tuple(..) + | ty::Projection(..) + | ty::Foreign(..) + | ty::Param(..) + | ty::Opaque(..) => { if t.flags.intersects(self.needs_canonical_flags) { t.super_fold_with(self) } else { @@ -327,7 +327,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { if !value.has_type_flags(needs_canonical_flags) { let out_value = gcx.lift(value).unwrap(); let canon_value = Canonical { - variables: Slice::empty(), + variables: List::empty(), value: out_value, }; return canon_value; @@ -380,7 +380,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { // avoid allocations in those cases. We also don't use `indices` to // determine if a kind has been seen before until the limit of 8 has // been exceeded, to also avoid allocations for `indices`. - if var_values.is_array() { + if !var_values.spilled() { // `var_values` is stack-allocated. `indices` isn't used yet. Do a // direct linear search of `var_values`. if let Some(idx) = var_values.iter().position(|&k| k == kind) { @@ -395,7 +395,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { // If `var_values` has become big enough to be heap-allocated, // fill up `indices` to facilitate subsequent lookups. - if !var_values.is_array() { + if var_values.spilled() { assert!(indices.is_empty()); *indices = var_values.iter() diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 958b339106..85aa4f62f2 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -33,14 +33,14 @@ use infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin}; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; use rustc_data_structures::sync::Lrc; use serialize::UseSpecializedDecodable; use std::ops::Index; -use syntax::codemap::Span; +use syntax::source_map::Span; use ty::fold::TypeFoldable; use ty::subst::Kind; -use ty::{self, CanonicalVar, Lift, Region, Slice, TyCtxt}; +use ty::{self, CanonicalVar, Lift, Region, List, TyCtxt}; mod canonicalizer; @@ -49,7 +49,7 @@ pub mod query_result; mod substitute; /// A "canonicalized" type `V` is one where all free inference -/// variables have been rewriten to "canonical vars". These are +/// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] pub struct Canonical<'gcx, V> { @@ -57,7 +57,7 @@ pub struct Canonical<'gcx, V> { pub value: V, } -pub type CanonicalVarInfos<'gcx> = &'gcx Slice; +pub type CanonicalVarInfos<'gcx> = &'gcx List; impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {} @@ -188,6 +188,36 @@ impl<'tcx, R> Canonical<'tcx, QueryResult<'tcx, R>> { } } +impl<'gcx, V> Canonical<'gcx, V> { + /// Allows you to map the `value` of a canonical while keeping the + /// same set of bound variables. + /// + /// **WARNING:** This function is very easy to mis-use, hence the + /// name! In particular, the new value `W` must use all **the + /// same type/region variables** in **precisely the same order** + /// as the original! (The ordering is defined by the + /// `TypeFoldable` implementation of the type in question.) + /// + /// An example of a **correct** use of this: + /// + /// ```rust,ignore (not real code) + /// let a: Canonical<'_, T> = ...; + /// let b: Canonical<'_, (T,)> = a.unchecked_map(|v| (v, )); + /// ``` + /// + /// An example of an **incorrect** use of this: + /// + /// ```rust,ignore (not real code) + /// let a: Canonical<'tcx, T> = ...; + /// let ty: Ty<'tcx> = ...; + /// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty)); + /// ``` + pub fn unchecked_map(self, map_op: impl FnOnce(V) -> W) -> Canonical<'gcx, W> { + let Canonical { variables, value } = self; + Canonical { variables, value: map_op(value) } + } +} + pub type QueryRegionConstraint<'tcx> = ty::Binder, Region<'tcx>>>; impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { @@ -221,7 +251,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { fn fresh_inference_vars_for_canonical_vars( &self, span: Span, - variables: &Slice, + variables: &List, ) -> CanonicalVarValues<'tcx> { let var_values: IndexVec> = variables .iter() diff --git a/src/librustc/infer/canonical/query_result.rs b/src/librustc/infer/canonical/query_result.rs index f0b6d25e9d..65d42c0888 100644 --- a/src/librustc/infer/canonical/query_result.rs +++ b/src/librustc/infer/canonical/query_result.rs @@ -24,19 +24,18 @@ use infer::canonical::{ }; use infer::region_constraints::{Constraint, RegionConstraintData}; use infer::InferCtxtBuilder; -use infer::{InferCtxt, InferOk, InferResult, RegionObligation}; +use infer::{InferCtxt, InferOk, InferResult}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::Lrc; use std::fmt::Debug; -use syntax::ast; use syntax_pos::DUMMY_SP; use traits::query::{Fallible, NoSolution}; use traits::{FulfillmentContext, TraitEngine}; use traits::{Obligation, ObligationCause, PredicateObligation}; use ty::fold::TypeFoldable; use ty::subst::{Kind, UnpackedKind}; -use ty::{self, CanonicalVar, Lift, TyCtxt}; +use ty::{self, CanonicalVar, Lift, Ty, TyCtxt}; impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> { /// The "main method" for a canonicalized trait query. Given the @@ -157,7 +156,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { let region_obligations = self.take_registered_region_obligations(); let region_constraints = self.with_region_constraints(|region_constraints| { - make_query_outlives(tcx, region_obligations, region_constraints) + make_query_outlives( + tcx, + region_obligations + .iter() + .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)), + region_constraints) }); let certainty = if ambig_errors.is_empty() { @@ -421,7 +425,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { match result_value.unpack() { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... - if let ty::TyInfer(ty::InferTy::CanonicalTy(index)) = result_value.sty { + if let ty::Infer(ty::InferTy::CanonicalTy(index)) = result_value.sty { // in which case we would set `canonical_vars[0]` to `Some(?U)`. opt_values[index] = Some(*original_value); } @@ -567,7 +571,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// creates query region constraints. pub fn make_query_outlives<'tcx>( tcx: TyCtxt<'_, '_, 'tcx>, - region_obligations: Vec<(ast::NodeId, RegionObligation<'tcx>)>, + outlives_obligations: impl Iterator, ty::Region<'tcx>)>, region_constraints: &RegionConstraintData<'tcx>, ) -> Vec> { let RegionConstraintData { @@ -600,9 +604,8 @@ pub fn make_query_outlives<'tcx>( .collect(); outlives.extend( - region_obligations - .into_iter() - .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region)) + outlives_obligations + .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r)) .map(ty::Binder::dummy), // no bound regions in the code above ); diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 679829f43c..f3fe01d5fd 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -85,7 +85,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { - ty::TyInfer(ty::InferTy::CanonicalTy(c)) => { + ty::Infer(ty::InferTy::CanonicalTy(c)) => { match self.var_values.var_values[c].unpack() { UnpackedKind::Type(ty) => ty, r => bug!("{:?} is a type but value is {:?}", c, r), diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index ccba5a09cf..4738a03cbd 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -76,44 +76,44 @@ impl<'infcx, 'gcx, 'tcx> InferCtxt<'infcx, 'gcx, 'tcx> { match (&a.sty, &b.sty) { // Relate integral variables to other types - (&ty::TyInfer(ty::IntVar(a_id)), &ty::TyInfer(ty::IntVar(b_id))) => { + (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => { self.int_unification_table .borrow_mut() .unify_var_var(a_id, b_id) .map_err(|e| int_unification_error(a_is_expected, e))?; Ok(a) } - (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyInt(v)) => { + (&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => { self.unify_integral_variable(a_is_expected, v_id, IntType(v)) } - (&ty::TyInt(v), &ty::TyInfer(ty::IntVar(v_id))) => { + (&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => { self.unify_integral_variable(!a_is_expected, v_id, IntType(v)) } - (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyUint(v)) => { + (&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => { self.unify_integral_variable(a_is_expected, v_id, UintType(v)) } - (&ty::TyUint(v), &ty::TyInfer(ty::IntVar(v_id))) => { + (&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => { self.unify_integral_variable(!a_is_expected, v_id, UintType(v)) } // Relate floating-point variables to other types - (&ty::TyInfer(ty::FloatVar(a_id)), &ty::TyInfer(ty::FloatVar(b_id))) => { + (&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => { self.float_unification_table .borrow_mut() .unify_var_var(a_id, b_id) .map_err(|e| float_unification_error(relation.a_is_expected(), e))?; Ok(a) } - (&ty::TyInfer(ty::FloatVar(v_id)), &ty::TyFloat(v)) => { + (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => { self.unify_float_variable(a_is_expected, v_id, v) } - (&ty::TyFloat(v), &ty::TyInfer(ty::FloatVar(v_id))) => { + (&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => { self.unify_float_variable(!a_is_expected, v_id, v) } // All other cases of inference are errors - (&ty::TyInfer(_), _) | - (_, &ty::TyInfer(_)) => { + (&ty::Infer(_), _) | + (_, &ty::Infer(_)) => { Err(TypeError::Sorts(ty::relate::expected_found(relation, &a, &b))) } @@ -393,7 +393,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' // subtyping. This is basically our "occurs check", preventing // us from creating infinitely sized types. match t.sty { - ty::TyInfer(ty::TyVar(vid)) => { + ty::Infer(ty::TyVar(vid)) => { let mut variables = self.infcx.type_variables.borrow_mut(); let vid = variables.root_var(vid); let sub_vid = variables.sub_root_var(vid); @@ -433,8 +433,8 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } } } - ty::TyInfer(ty::IntVar(_)) | - ty::TyInfer(ty::FloatVar(_)) => { + ty::Infer(ty::IntVar(_)) | + ty::Infer(ty::FloatVar(_)) => { // No matter what mode we are in, // integer/floating-point types must be equal to be // relatable. diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 2ae8f8ae93..26eb2ffbf6 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -75,17 +75,17 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> let a = infcx.type_variables.borrow_mut().replace_if_possible(a); let b = infcx.type_variables.borrow_mut().replace_if_possible(b); match (&a.sty, &b.sty) { - (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => { + (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().equate(a_id, b_id); Ok(a) } - (&ty::TyInfer(TyVar(a_id)), _) => { + (&ty::Infer(TyVar(a_id)), _) => { self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?; Ok(a) } - (_, &ty::TyInfer(TyVar(b_id))) => { + (_, &ty::Infer(TyVar(b_id))) => { self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?; Ok(a) } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 212821cac2..cf76c3b7e0 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -62,18 +62,17 @@ use super::lexical_region_resolve::RegionResolutionError; use std::{cmp, fmt}; use hir; -use hir::map as hir_map; +use hir::Node; use hir::def_id::DefId; use middle::region; use traits::{ObligationCause, ObligationCauseCode}; -use ty::{self, subst::Subst, Region, Ty, TyCtxt, TypeFoldable, TypeVariants}; +use ty::{self, subst::Subst, Region, Ty, TyCtxt, TypeFoldable, TyKind}; use ty::error::TypeError; +use session::config::BorrowckMode; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; -use rustc_data_structures::indexed_vec::Idx; - mod note; mod need_type_info; @@ -100,8 +99,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; let span = scope.span(self, region_scope_tree); let tag = match self.hir.find(scope.node_id(self, region_scope_tree)) { - Some(hir_map::NodeBlock(_)) => "block", - Some(hir_map::NodeExpr(expr)) => match expr.node { + Some(Node::Block(_)) => "block", + Some(Node::Expr(expr)) => match expr.node { hir::ExprKind::Call(..) => "call", hir::ExprKind::MethodCall(..) => "method call", hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let", @@ -110,27 +109,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { hir::ExprKind::Match(..) => "match", _ => "expression", }, - Some(hir_map::NodeStmt(_)) => "statement", - Some(hir_map::NodeItem(it)) => Self::item_scope_tag(&it), - Some(hir_map::NodeTraitItem(it)) => Self::trait_item_scope_tag(&it), - Some(hir_map::NodeImplItem(it)) => Self::impl_item_scope_tag(&it), + Some(Node::Stmt(_)) => "statement", + Some(Node::Item(it)) => Self::item_scope_tag(&it), + Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it), + Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it), Some(_) | None => { err.span_note(span, &unknown_scope()); return; } }; - let scope_decorated_tag = match scope.data() { - region::ScopeData::Node(_) => tag, - region::ScopeData::CallSite(_) => "scope of call-site for function", - region::ScopeData::Arguments(_) => "scope of function body", - region::ScopeData::Destruction(_) => { + let scope_decorated_tag = match scope.data { + region::ScopeData::Node => tag, + region::ScopeData::CallSite => "scope of call-site for function", + region::ScopeData::Arguments => "scope of function body", + region::ScopeData::Destruction => { new_string = format!("destruction scope surrounding {}", tag); &new_string[..] } - region::ScopeData::Remainder(r) => { + region::ScopeData::Remainder(first_statement_index) => { new_string = format!( "block suffix following statement {}", - r.first_statement_index.index() + first_statement_index.index() ); &new_string[..] } @@ -189,15 +188,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self, region: ty::Region<'tcx>, ) -> (String, Option) { - let cm = self.sess.codemap(); + let cm = self.sess.source_map(); let scope = region.free_region_binding_scope(self); let node = self.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); let tag = match self.hir.find(node) { - Some(hir_map::NodeBlock(_)) | Some(hir_map::NodeExpr(_)) => "body", - Some(hir_map::NodeItem(it)) => Self::item_scope_tag(&it), - Some(hir_map::NodeTraitItem(it)) => Self::trait_item_scope_tag(&it), - Some(hir_map::NodeImplItem(it)) => Self::impl_item_scope_tag(&it), + Some(Node::Block(_)) | Some(Node::Expr(_)) => "body", + Some(Node::Item(it)) => Self::item_scope_tag(&it), + Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it), + Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it), _ => unreachable!() }; let (prefix, span) = match *region { @@ -286,7 +285,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } fn explain_span(self, heading: &str, span: Span) -> (String, Option) { - let lo = self.sess.codemap().lookup_char_pos_adj(span.lo()); + let lo = self.sess.source_map().lookup_char_pos_adj(span.lo()); ( format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span), @@ -303,40 +302,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) { debug!("report_region_errors(): {} errors to start", errors.len()); - if will_later_be_reported_by_nll && - // FIXME: `use_mir_borrowck` seems wrong here... - self.tcx.use_mir_borrowck() && - // ... this is a band-aid; may be better to explicitly - // match on every borrowck_mode variant to guide decision - // here. - !self.tcx.migrate_borrowck() { - - // With `#![feature(nll)]`, we want to present a nice user - // experience, so don't even mention the errors from the - // AST checker. - if self.tcx.features().nll { - return; - } - - // But with nll, it's nice to have some note for later. - for error in errors { - match *error { - RegionResolutionError::ConcreteFailure(ref origin, ..) - | RegionResolutionError::GenericBoundFailure(ref origin, ..) => { - self.tcx - .sess - .span_warn(origin.span(), "not reporting region error due to nll"); - } - - RegionResolutionError::SubSupConflict(ref rvo, ..) => { - self.tcx - .sess - .span_warn(rvo.span(), "not reporting region error due to nll"); - } - } + // If the errors will later be reported by NLL, choose wether to display them or not based + // on the borrowck mode + if will_later_be_reported_by_nll { + match self.tcx.borrowck_mode() { + // If we're on AST or Migrate mode, report AST region errors + BorrowckMode::Ast | BorrowckMode::Migrate => {}, + // If we're on MIR or Compare mode, don't report AST region errors as they should + // be reported by NLL + BorrowckMode::Compare | BorrowckMode::Mir => return, } - - return; } // try to pre-process the errors, which will group some of them @@ -484,7 +459,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // if they are both "path types", there's a chance of ambiguity // due to different versions of the same crate match (&exp_found.expected.sty, &exp_found.found.sty) { - (&ty::TyAdt(exp_adt, _), &ty::TyAdt(found_adt, _)) => { + (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) => { report_path_match(err, exp_adt.did, found_adt.did); } _ => (), @@ -502,14 +477,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source { hir::MatchSource::IfLetDesugar { .. } => { let msg = "`if let` arm with an incompatible type"; - if self.tcx.sess.codemap().is_multiline(arm_span) { + if self.tcx.sess.source_map().is_multiline(arm_span) { err.span_note(arm_span, msg); } else { err.span_label(arm_span, msg); } }, hir::MatchSource::TryDesugar => { // Issue #51632 - if let Ok(try_snippet) = self.tcx.sess.codemap().span_to_snippet(arm_span) { + if let Ok(try_snippet) = self.tcx.sess.source_map().span_to_snippet(arm_span) { err.span_suggestion_with_applicability( arm_span, "try wrapping with a success variant", @@ -520,7 +495,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }, _ => { let msg = "match arm with an incompatible type"; - if self.tcx.sess.codemap().is_multiline(arm_span) { + if self.tcx.sess.source_map().is_multiline(arm_span) { err.span_note(arm_span, msg); } else { err.span_label(arm_span, msg); @@ -561,7 +536,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { value.push_highlighted("<"); } - // Output the lifetimes fot the first type + // Output the lifetimes for the first type let lifetimes = sub.regions() .map(|lifetime| { let s = lifetime.to_string(); @@ -636,7 +611,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty); return Some(()); } - if let &ty::TyAdt(def, _) = &ta.sty { + if let &ty::Adt(def, _) = &ta.sty { let path_ = self.tcx.item_path_str(def.did.clone()); if path_ == other_path { self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty); @@ -704,14 +679,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn equals<'tcx>(a: &Ty<'tcx>, b: &Ty<'tcx>) -> bool { match (&a.sty, &b.sty) { (a, b) if *a == *b => true, - (&ty::TyInt(_), &ty::TyInfer(ty::InferTy::IntVar(_))) - | (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInt(_)) - | (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInfer(ty::InferTy::IntVar(_))) - | (&ty::TyFloat(_), &ty::TyInfer(ty::InferTy::FloatVar(_))) - | (&ty::TyInfer(ty::InferTy::FloatVar(_)), &ty::TyFloat(_)) + (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_))) + | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Int(_)) + | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Infer(ty::InferTy::IntVar(_))) + | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_))) + | (&ty::Infer(ty::InferTy::FloatVar(_)), &ty::Float(_)) | ( - &ty::TyInfer(ty::InferTy::FloatVar(_)), - &ty::TyInfer(ty::InferTy::FloatVar(_)), + &ty::Infer(ty::InferTy::FloatVar(_)), + &ty::Infer(ty::InferTy::FloatVar(_)), ) => true, _ => false, } @@ -738,7 +713,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } match (&t1.sty, &t2.sty) { - (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => { + (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => { let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1); let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2); let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); @@ -877,13 +852,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } // When finding T != &T, highlight only the borrow - (&ty::TyRef(r1, ref_ty1, mutbl1), _) if equals(&ref_ty1, &t2) => { + (&ty::Ref(r1, ref_ty1, mutbl1), _) if equals(&ref_ty1, &t2) => { let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0); values.1.push_normal(t2.to_string()); values } - (_, &ty::TyRef(r2, ref_ty2, mutbl2)) if equals(&t1, &ref_ty2) => { + (_, &ty::Ref(r2, ref_ty2, mutbl2)) if equals(&t1, &ref_ty2) => { let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); values.0.push_normal(t1.to_string()); push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1); @@ -891,8 +866,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } // When encountering &T != &mut T, highlight only the borrow - (&ty::TyRef(r1, ref_ty1, mutbl1), - &ty::TyRef(r2, ref_ty2, mutbl2)) if equals(&ref_ty1, &ref_ty2) => { + (&ty::Ref(r1, ref_ty1, mutbl1), + &ty::Ref(r2, ref_ty2, mutbl2)) if equals(&ref_ty1, &ref_ty2) => { let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0); push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1); @@ -979,14 +954,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { (_, false, _) => { if let Some(exp_found) = exp_found { let (def_id, ret_ty) = match exp_found.found.sty { - TypeVariants::TyFnDef(def, _) => { + TyKind::FnDef(def, _) => { (Some(def), Some(self.tcx.fn_sig(def).output())) } _ => (None, None), }; let exp_is_struct = match exp_found.expected.sty { - TypeVariants::TyAdt(def, _) => def.is_struct(), + TyKind::Adt(def, _) => def.is_struct(), _ => false, }; @@ -1123,11 +1098,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let type_param = generics.type_param(param, self.tcx); let hir = &self.tcx.hir; hir.as_local_node_id(type_param.def_id).map(|id| { - // Get the `hir::TyParam` to verify whether it already has any bounds. + // Get the `hir::Param` to verify whether it already has any bounds. // We do this to avoid suggesting code that ends up as `T: 'a'b`, // instead we suggest `T: 'a + 'b` in that case. let mut has_bounds = false; - if let hir_map::NodeGenericParam(ref param) = hir.get(id) { + if let Node::GenericParam(ref param) = hir.get(id) { has_bounds = !param.bounds.is_empty(); } let sp = hir.span(id); @@ -1136,8 +1111,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let sp = if has_bounds { sp.to(self.tcx .sess - .codemap() - .next_point(self.tcx.sess.codemap().next_point(sp))) + .source_map() + .next_point(self.tcx.sess.source_map().next_point(sp))) } else { sp }; @@ -1330,7 +1305,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { s }; let var_description = match var_origin { - infer::MiscVariable(_) => "".to_string(), + infer::MiscVariable(_) => String::new(), infer::PatternRegion(_) => " for pattern".to_string(), infer::AddrOfRegion(_) => " for borrow expression".to_string(), infer::Autoref(_) => " for autoref".to_string(), diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index b71c886a89..505b1bc032 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -12,8 +12,8 @@ use hir::{self, Local, Pat, Body, HirId}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use infer::InferCtxt; use infer::type_variable::TypeVariableOrigin; -use ty::{self, Ty, TyInfer, TyVar}; -use syntax::codemap::CompilerDesugaringKind; +use ty::{self, Ty, Infer, TyVar}; +use syntax::source_map::CompilerDesugaringKind; use syntax_pos::Span; use errors::DiagnosticBuilder; @@ -35,7 +35,7 @@ impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { let ty = self.infcx.resolve_type_vars_if_possible(&ty); ty.walk().any(|inner_ty| { inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { - (&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => { + (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => { self.infcx .type_variables .borrow_mut() @@ -75,7 +75,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { - if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty { + if let ty::Infer(ty::TyVar(ty_vid)) = (*ty).sty { let ty_vars = self.type_variables.borrow(); if let TypeVariableOrigin::TypeParameterDefinition(_, name) = *ty_vars.var_origin(ty_vid) { diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs index 21be09b0ba..e3faf75567 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -10,7 +10,7 @@ use hir; use ty::{self, Region, TyCtxt}; -use hir::map as hir_map; +use hir::Node; use middle::resolve_lifetime as rl; use hir::intravisit::{self, NestedVisitorMap, Visitor}; use infer::error_reporting::nice_region_error::NiceRegionError; @@ -40,15 +40,15 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { let def_id = anon_reg.def_id; if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { let fndecl = match self.tcx.hir.get(node_id) { - hir_map::NodeItem(&hir::Item { + Node::Item(&hir::Item { node: hir::ItemKind::Fn(ref fndecl, ..), .. }) => &fndecl, - hir_map::NodeTraitItem(&hir::TraitItem { + Node::TraitItem(&hir::TraitItem { node: hir::TraitItemKind::Method(ref m, ..), .. }) - | hir_map::NodeImplItem(&hir::ImplItem { + | Node::ImplItem(&hir::ImplItem { node: hir::ImplItemKind::Method(ref m, ..), .. }) => &m.decl, diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs index f50c23b0aa..0ff5630f63 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs @@ -11,7 +11,7 @@ use infer::InferCtxt; use infer::lexical_region_resolve::RegionResolutionError; use infer::lexical_region_resolve::RegionResolutionError::*; -use syntax::codemap::Span; +use syntax::source_map::Span; use ty::{self, TyCtxt}; use util::common::ErrorReported; @@ -64,6 +64,12 @@ impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> { Self { tcx, error: None, regions: Some((span, sub, sup)), tables } } + pub fn try_report_from_nll(&self) -> Option { + // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of + // the nice region errors are required when running under the MIR borrow checker. + self.try_report_named_anon_conflict() + } + pub fn try_report(&self) -> Option { self.try_report_named_anon_conflict() .or_else(|| self.try_report_anon_anon_conflict()) diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 51abfa2505..4e26a4178b 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -65,9 +65,10 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { region_info ); - let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = ( + let (arg, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = ( anon_arg_info.arg, anon_arg_info.arg_ty, + anon_arg_info.arg_ty_span, anon_arg_info.bound_region, anon_arg_info.is_first, region_info.def_id, @@ -110,9 +111,10 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { E0621, "explicit lifetime required in {}", error_var - ).span_label( - arg.pat.span, - format!("consider changing {} to `{}`", span_label_var, new_ty), + ).span_suggestion( + new_ty_span, + &format!("add explicit lifetime `{}` to {}", named, span_label_var), + new_ty.to_string() ) .span_label(span, format!("lifetime `{}` required", named)) .emit(); @@ -127,7 +129,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { ty::BrNamed(..) => true, _ => false, }, - ty::ReEarlyBound(_) => true, + ty::ReEarlyBound(ebr) => ebr.has_name(), _ => false, } } diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs index f4ef197e5b..5c27cdb6fb 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs @@ -15,7 +15,7 @@ use infer::error_reporting::nice_region_error::NiceRegionError; use infer::SubregionOrigin; use ty::RegionKind; use hir::{Expr, ExprKind::Closure}; -use hir::map::NodeExpr; +use hir::Node; use util::common::ErrorReported; use infer::lexical_region_resolve::RegionResolutionError::SubSupConflict; @@ -59,7 +59,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { let hir = &self.tcx.hir; if let Some(node_id) = hir.as_local_node_id(free_region.scope) { match hir.get(node_id) { - NodeExpr(Expr { + Node::Expr(Expr { node: Closure(_, _, _, closure_span, None), .. }) => { diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index 193f86a382..d25dcd5b04 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -60,7 +60,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { }) => name.to_string(), _ => "'_".to_owned(), }; - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(return_sp) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) { err.span_suggestion( return_sp, &format!( diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index 1cc2b9d50b..30406f1fec 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -10,11 +10,12 @@ //! Helper functions corresponding to lifetime errors due to //! anonymous regions. + use hir; use infer::error_reporting::nice_region_error::NiceRegionError; use ty::{self, Region, Ty}; use hir::def_id::DefId; -use hir::map as hir_map; +use hir::Node; use syntax_pos::Span; // The struct contains the information about the anonymous region @@ -27,6 +28,8 @@ pub(super) struct AnonymousArgInfo<'tcx> { pub arg_ty: Ty<'tcx>, // the ty::BoundRegion corresponding to the anonymous region pub bound_region: ty::BoundRegion, + // arg_ty_span contains span of argument type + pub arg_ty_span : Span, // corresponds to id the argument is the first parameter // in the declaration pub is_first: bool, @@ -74,12 +77,16 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { if let Some(node_id) = hir.as_local_node_id(id) { if let Some(body_id) = hir.maybe_body_owned_by(node_id) { let body = hir.body(body_id); + let owner_id = hir.body_owner(body_id); + let fn_decl = hir.fn_decl(owner_id).unwrap(); if let Some(tables) = self.tables { body.arguments .iter() .enumerate() .filter_map(|(index, arg)| { // May return None; sometimes the tables are not yet populated. + let ty_hir_id = fn_decl.inputs[index].hir_id; + let arg_ty_span = hir.span(hir.hir_to_node_id(ty_hir_id)); let ty = tables.node_id_to_type_opt(arg.hir_id)?; let mut found_anon_region = false; let new_arg_ty = self.tcx.fold_regions(&ty, &mut false, |r, _| { @@ -95,6 +102,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { Some(AnonymousArgInfo { arg: arg, arg_ty: new_arg_ty, + arg_ty_span : arg_ty_span, bound_region: bound_region, is_first: is_first, }) @@ -130,8 +138,8 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { .as_local_node_id(suitable_region_binding_scope) .unwrap(); let is_impl_item = match self.tcx.hir.find(node_id) { - Some(hir_map::NodeItem(..)) | Some(hir_map::NodeTraitItem(..)) => false, - Some(hir_map::NodeImplItem(..)) => { + Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false, + Some(Node::ImplItem(..)) => { self.is_bound_region_in_impl_item(suitable_region_binding_scope) } _ => return None, @@ -155,7 +163,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { ) -> Option { let ret_ty = self.tcx.type_of(scope_def_id); match ret_ty.sty { - ty::TyFnDef(_, _) => { + ty::FnDef(_, _) => { let sig = ret_ty.fn_sig(self.tcx); let late_bound_regions = self.tcx .collect_referenced_late_bound_regions(&sig.output()); @@ -174,7 +182,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { ) -> bool { let ret_ty = self.tcx.type_of(scope_def_id); match ret_ty.sty { - ty::TyFnDef(_, _) => { + ty::FnDef(_, _) => { let sig = ret_ty.fn_sig(self.tcx); let output = self.tcx.erase_late_bound_regions(&sig.output()); return output.is_impl_trait(); diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 6074bfd083..1cb813c39e 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -133,7 +133,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { let tcx = self.infcx.tcx; match t.sty { - ty::TyInfer(ty::TyVar(v)) => { + ty::Infer(ty::TyVar(v)) => { let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known(); self.freshen( opt_ty, @@ -141,7 +141,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::FreshTy) } - ty::TyInfer(ty::IntVar(v)) => { + ty::Infer(ty::IntVar(v)) => { self.freshen( self.infcx.int_unification_table.borrow_mut() .probe_value(v) @@ -150,7 +150,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::FreshIntTy) } - ty::TyInfer(ty::FloatVar(v)) => { + ty::Infer(ty::FloatVar(v)) => { self.freshen( self.infcx.float_unification_table.borrow_mut() .probe_value(v) @@ -159,9 +159,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::FreshFloatTy) } - ty::TyInfer(ty::FreshTy(c)) | - ty::TyInfer(ty::FreshIntTy(c)) | - ty::TyInfer(ty::FreshFloatTy(c)) => { + ty::Infer(ty::FreshTy(c)) | + ty::Infer(ty::FreshIntTy(c)) | + ty::Infer(ty::FreshFloatTy(c)) => { if c >= self.freshen_count { bug!("Encountered a freshend type with id {} \ but our counter is only at {}", @@ -171,33 +171,33 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { t } - ty::TyInfer(ty::CanonicalTy(..)) => + ty::Infer(ty::CanonicalTy(..)) => bug!("encountered canonical ty during freshening"), - ty::TyGenerator(..) | - ty::TyBool | - ty::TyChar | - ty::TyInt(..) | - ty::TyUint(..) | - ty::TyFloat(..) | - ty::TyAdt(..) | - ty::TyStr | - ty::TyError | - ty::TyArray(..) | - ty::TySlice(..) | - ty::TyRawPtr(..) | - ty::TyRef(..) | - ty::TyFnDef(..) | - ty::TyFnPtr(_) | - ty::TyDynamic(..) | - ty::TyNever | - ty::TyTuple(..) | - ty::TyProjection(..) | - ty::TyForeign(..) | - ty::TyParam(..) | - ty::TyClosure(..) | - ty::TyGeneratorWitness(..) | - ty::TyAnon(..) => { + ty::Generator(..) | + ty::Bool | + ty::Char | + ty::Int(..) | + ty::Uint(..) | + ty::Float(..) | + ty::Adt(..) | + ty::Str | + ty::Error | + ty::Array(..) | + ty::Slice(..) | + ty::RawPtr(..) | + ty::Ref(..) | + ty::FnDef(..) | + ty::FnPtr(_) | + ty::Dynamic(..) | + ty::Never | + ty::Tuple(..) | + ty::Projection(..) | + ty::Foreign(..) | + ty::Param(..) | + ty::Closure(..) | + ty::GeneratorWitness(..) | + ty::Opaque(..) => { t.super_fold_with(self) } } diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 961dd70a46..39dc24b86e 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -123,7 +123,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { - ty::TyInfer(ty::InferTy::TyVar(vid)) => { + ty::Infer(ty::InferTy::TyVar(vid)) => { match self.type_variables.get(&vid) { None => { // This variable was created before the diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index cb4e1ab65e..bb1c944813 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -527,7 +527,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { * we're not careful, it will succeed. * * The reason is that when we walk through the subtyping - * algorith, we begin by replacing `'a` with a skolemized + * algorithm, we begin by replacing `'a` with a skolemized * variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This * can be made true by unifying `_#0t` with `&'1 int`. In the * process, we create a fresh variable for the skolemized diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs index 28aba51ab3..6848c625b5 100644 --- a/src/librustc/infer/lattice.rs +++ b/src/librustc/infer/lattice.rs @@ -88,12 +88,12 @@ pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L, // is (e.g.) `Box`. A more obvious solution might be to // iterate on the subtype obligations that are returned, but I // think this suffices. -nmatsakis - (&ty::TyInfer(TyVar(..)), _) => { + (&ty::Infer(TyVar(..)), _) => { let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span)); this.relate_bound(v, b, a)?; Ok(v) } - (_, &ty::TyInfer(TyVar(..))) => { + (_, &ty::Infer(TyVar(..))) => { let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span)); this.relate_bound(v, a, b)?; Ok(v) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 0b84c6a0aa..e628a3458f 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -10,60 +10,60 @@ //! See the Book for more information. +pub use self::freshen::TypeFreshener; pub use self::LateBoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; pub use ty::IntVarValue; -pub use self::freshen::TypeFreshener; +use arena::SyncDroplessArena; +use errors::DiagnosticBuilder; use hir::def_id::DefId; use middle::free_region::RegionRelations; -use middle::region; use middle::lang_items; -use ty::subst::{Kind, Substs}; -use ty::{TyVid, IntVid, FloatVid}; -use ty::{self, Ty, TyCtxt, GenericParamDefKind}; -use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; -use ty::fold::TypeFoldable; -use ty::relate::RelateResult; -use traits::{self, ObligationCause, PredicateObligations, TraitEngine}; +use middle::region; use rustc_data_structures::unify as ut; -use std::cell::{Cell, RefCell, Ref, RefMut}; +use std::cell::{Cell, Ref, RefCell, RefMut}; use std::collections::BTreeMap; use std::fmt; use syntax::ast; -use errors::DiagnosticBuilder; -use syntax_pos::{self, Span}; use syntax_pos::symbol::InternedString; +use syntax_pos::{self, Span}; +use traits::{self, ObligationCause, PredicateObligations, TraitEngine}; +use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; +use ty::fold::TypeFoldable; +use ty::relate::RelateResult; +use ty::subst::{Kind, Substs}; +use ty::{self, GenericParamDefKind, Ty, TyCtxt}; +use ty::{FloatVid, IntVid, TyVid}; use util::nodemap::FxHashMap; -use arena::SyncDroplessArena; use self::combine::CombineFields; use self::higher_ranked::HrMatchResult; -use self::region_constraints::{RegionConstraintCollector, RegionSnapshot}; -use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarInfos}; use self::lexical_region_resolve::LexicalRegionResolutions; use self::outlives::env::OutlivesEnvironment; +use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound}; +use self::region_constraints::{RegionConstraintCollector, RegionSnapshot}; use self::type_variable::TypeVariableOrigin; use self::unify_key::ToType; -pub mod anon_types; +pub mod opaque_types; pub mod at; pub mod canonical; mod combine; mod equate; pub mod error_reporting; +mod freshen; mod fudge; mod glb; mod higher_ranked; pub mod lattice; -mod lub; -pub mod region_constraints; mod lexical_region_resolve; +mod lub; pub mod outlives; +pub mod region_constraints; pub mod resolve; -mod freshen; mod sub; pub mod type_variable; pub mod unify_key; @@ -80,7 +80,7 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" -pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, /// During type-checking/inference of a body, `in_progress_tables` @@ -314,10 +314,10 @@ pub enum SubregionOrigin<'tcx> { /// Places that type/region parameters can appear. #[derive(Clone, Copy, Debug)] pub enum ParameterOrigin { - Path, // foo::bar - MethodCall, // foo.bar() <-- parameters on impl providing bar() + Path, // foo::bar + MethodCall, // foo.bar() <-- parameters on impl providing bar() OverloadedOperator, // a + b when overloaded - OverloadedDeref, // *a when overloaded + OverloadedDeref, // *a when overloaded } /// Times when we replace late-bound regions with variables: @@ -400,7 +400,7 @@ impl NLLRegionVariableOrigin { pub enum FixupError { UnresolvedIntTy(IntVid), UnresolvedFloatTy(FloatVid), - UnresolvedTy(TyVid) + UnresolvedTy(TyVid), } /// See the `region_obligations` field for more information. @@ -416,15 +416,17 @@ impl fmt::Display for FixupError { use self::FixupError::*; match *self { - UnresolvedIntTy(_) => { - write!(f, "cannot determine the type of this integer; \ - add a suffix to specify the type explicitly") - } - UnresolvedFloatTy(_) => { - write!(f, "cannot determine the type of this number; \ - add a suffix to specify the type explicitly") - } - UnresolvedTy(_) => write!(f, "unconstrained type") + UnresolvedIntTy(_) => write!( + f, + "cannot determine the type of this integer; \ + add a suffix to specify the type explicitly" + ), + UnresolvedFloatTy(_) => write!( + f, + "cannot determine the type of this number; \ + add a suffix to specify the type explicitly" + ), + UnresolvedTy(_) => write!(f, "unconstrained type"), } } } @@ -432,7 +434,7 @@ impl fmt::Display for FixupError { /// Helper type of a temporary returned by tcx.infer_ctxt(). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>). -pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { global_tcx: TyCtxt<'a, 'gcx, 'gcx>, arena: SyncDroplessArena, fresh_tables: Option>>, @@ -444,7 +446,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { global_tcx: self, arena: SyncDroplessArena::new(), fresh_tables: None, - } } } @@ -458,7 +459,8 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { } pub fn enter(&'tcx mut self, f: F) -> R - where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R + where + F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R, { let InferCtxtBuilder { global_tcx, @@ -466,40 +468,51 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { ref fresh_tables, } = *self; let in_progress_tables = fresh_tables.as_ref(); - global_tcx.enter_local(arena, |tcx| f(InferCtxt { - tcx, - in_progress_tables, - projection_cache: RefCell::new(traits::ProjectionCache::new()), - type_variables: RefCell::new(type_variable::TypeVariableTable::new()), - int_unification_table: RefCell::new(ut::UnificationTable::new()), - float_unification_table: RefCell::new(ut::UnificationTable::new()), - region_constraints: RefCell::new(Some(RegionConstraintCollector::new())), - lexical_region_resolutions: RefCell::new(None), - selection_cache: traits::SelectionCache::new(), - evaluation_cache: traits::EvaluationCache::new(), - reported_trait_errors: RefCell::new(FxHashMap()), - tainted_by_errors_flag: Cell::new(false), - err_count_on_creation: tcx.sess.err_count(), - in_snapshot: Cell::new(false), - region_obligations: RefCell::new(vec![]), - universe: Cell::new(ty::UniverseIndex::ROOT), - })) + global_tcx.enter_local(arena, |tcx| { + f(InferCtxt { + tcx, + in_progress_tables, + projection_cache: RefCell::new(traits::ProjectionCache::new()), + type_variables: RefCell::new(type_variable::TypeVariableTable::new()), + int_unification_table: RefCell::new(ut::UnificationTable::new()), + float_unification_table: RefCell::new(ut::UnificationTable::new()), + region_constraints: RefCell::new(Some(RegionConstraintCollector::new())), + lexical_region_resolutions: RefCell::new(None), + selection_cache: traits::SelectionCache::new(), + evaluation_cache: traits::EvaluationCache::new(), + reported_trait_errors: RefCell::new(FxHashMap()), + tainted_by_errors_flag: Cell::new(false), + err_count_on_creation: tcx.sess.err_count(), + in_snapshot: Cell::new(false), + region_obligations: RefCell::new(vec![]), + universe: Cell::new(ty::UniverseIndex::ROOT), + }) + }) } } impl ExpectedFound { pub fn new(a_is_expected: bool, a: T, b: T) -> Self { if a_is_expected { - ExpectedFound {expected: a, found: b} + ExpectedFound { + expected: a, + found: b, + } } else { - ExpectedFound {expected: b, found: a} + ExpectedFound { + expected: b, + found: a, + } } } } impl<'tcx, T> InferOk<'tcx, T> { pub fn unit(self) -> InferOk<'tcx, ()> { - InferOk { value: (), obligations: self.obligations } + InferOk { + value: (), + obligations: self.obligations, + } } /// Extract `value`, registering any obligations into `fulfill_cx` @@ -523,7 +536,7 @@ impl<'tcx> InferOk<'tcx, ()> { } #[must_use = "once you start a snapshot, you should always consume it"] -pub struct CombinedSnapshot<'a, 'tcx:'a> { +pub struct CombinedSnapshot<'a, 'tcx: 'a> { projection_cache_snapshot: traits::ProjectionCacheSnapshot, type_snapshot: type_variable::Snapshot<'tcx>, int_snapshot: ut::Snapshot>, @@ -540,14 +553,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.in_snapshot.get() } - pub fn freshen>(&self, t: T) -> T { + pub fn freshen>(&self, t: T) -> T { t.fold_with(&mut self.freshener()) } pub fn type_var_diverges(&'a self, ty: Ty) -> bool { match ty.sty { - ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid), - _ => false + ty::Infer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid), + _ => false, } } @@ -557,22 +570,30 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric { use ty::error::UnconstrainedNumeric::Neither; - use ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; + use ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt}; match ty.sty { - ty::TyInfer(ty::IntVar(vid)) => { - if self.int_unification_table.borrow_mut().probe_value(vid).is_some() { + ty::Infer(ty::IntVar(vid)) => { + if self.int_unification_table + .borrow_mut() + .probe_value(vid) + .is_some() + { Neither } else { UnconstrainedInt } - }, - ty::TyInfer(ty::FloatVar(vid)) => { - if self.float_unification_table.borrow_mut().probe_value(vid).is_some() { + } + ty::Infer(ty::FloatVar(vid)) => { + if self.float_unification_table + .borrow_mut() + .probe_value(vid) + .is_some() + { Neither } else { UnconstrainedFloat } - }, + } _ => Neither, } } @@ -590,17 +611,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { (0..int_unification_table.len()) .map(|i| ty::IntVid { index: i as u32 }) .filter(|&vid| int_unification_table.probe_value(vid).is_none()) - .map(|v| self.tcx.mk_int_var(v)) - ).chain( + .map(|v| self.tcx.mk_int_var(v)), + ) + .chain( (0..float_unification_table.len()) .map(|i| ty::FloatVid { index: i as u32 }) .filter(|&vid| float_unification_table.probe_value(vid).is_none()) - .map(|v| self.tcx.mk_float_var(v)) - ).collect() + .map(|v| self.tcx.mk_float_var(v)), + ) + .collect() } - fn combine_fields(&'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>) - -> CombineFields<'a, 'gcx, 'tcx> { + fn combine_fields( + &'a self, + trace: TypeTrace<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> CombineFields<'a, 'gcx, 'tcx> { CombineFields { infcx: self, trace, @@ -627,7 +653,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // escaping obligations in the main cx. In those cases, you can // use this function. pub fn save_and_restore_in_snapshot_flag(&self, func: F) -> R - where F: FnOnce(&Self) -> R + where + F: FnOnce(&Self) -> R, { let flag = self.in_snapshot.get(); self.in_snapshot.set(false); @@ -653,23 +680,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { was_in_snapshot: in_snapshot, // Borrow tables "in progress" (i.e. during typeck) // to ban writes from within a snapshot to them. - _in_progress_tables: self.in_progress_tables.map(|tables| { - tables.borrow() - }) + _in_progress_tables: self.in_progress_tables.map(|tables| tables.borrow()), } } fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) { debug!("rollback_to(cause={})", cause); - let CombinedSnapshot { projection_cache_snapshot, - type_snapshot, - int_snapshot, - float_snapshot, - region_constraints_snapshot, - region_obligations_snapshot, - universe, - was_in_snapshot, - _in_progress_tables } = snapshot; + let CombinedSnapshot { + projection_cache_snapshot, + type_snapshot, + int_snapshot, + float_snapshot, + region_constraints_snapshot, + region_obligations_snapshot, + universe, + was_in_snapshot, + _in_progress_tables, + } = snapshot; self.in_snapshot.set(was_in_snapshot); self.universe.set(universe); @@ -677,9 +704,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.projection_cache .borrow_mut() .rollback_to(projection_cache_snapshot); - self.type_variables - .borrow_mut() - .rollback_to(type_snapshot); + self.type_variables.borrow_mut().rollback_to(type_snapshot); self.int_unification_table .borrow_mut() .rollback_to(int_snapshot); @@ -695,27 +720,25 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) { debug!("commit_from()"); - let CombinedSnapshot { projection_cache_snapshot, - type_snapshot, - int_snapshot, - float_snapshot, - region_constraints_snapshot, - region_obligations_snapshot: _, - universe: _, - was_in_snapshot, - _in_progress_tables } = snapshot; + let CombinedSnapshot { + projection_cache_snapshot, + type_snapshot, + int_snapshot, + float_snapshot, + region_constraints_snapshot, + region_obligations_snapshot: _, + universe: _, + was_in_snapshot, + _in_progress_tables, + } = snapshot; self.in_snapshot.set(was_in_snapshot); self.projection_cache .borrow_mut() - .commit(projection_cache_snapshot); - self.type_variables - .borrow_mut() - .commit(type_snapshot); - self.int_unification_table - .borrow_mut() - .commit(int_snapshot); + .commit(&projection_cache_snapshot); + self.type_variables.borrow_mut().commit(type_snapshot); + self.int_unification_table.borrow_mut().commit(int_snapshot); self.float_unification_table .borrow_mut() .commit(float_snapshot); @@ -724,7 +747,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Execute `f` and commit the bindings - pub fn commit_unconditionally(&self, f: F) -> R where + pub fn commit_unconditionally(&self, f: F) -> R + where F: FnOnce() -> R, { debug!("commit()"); @@ -735,23 +759,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)` - pub fn commit_if_ok(&self, f: F) -> Result where - F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result + pub fn commit_if_ok(&self, f: F) -> Result + where + F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result, { debug!("commit_if_ok()"); let snapshot = self.start_snapshot(); let r = f(&snapshot); debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); match r { - Ok(_) => { self.commit_from(snapshot); } - Err(_) => { self.rollback_to("commit_if_ok -- error", snapshot); } + Ok(_) => { + self.commit_from(snapshot); + } + Err(_) => { + self.rollback_to("commit_if_ok -- error", snapshot); + } } r } // Execute `f` in a snapshot, and commit the bindings it creates - pub fn in_snapshot(&self, f: F) -> T where - F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T + pub fn in_snapshot(&self, f: F) -> T + where + F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T, { debug!("in_snapshot()"); let snapshot = self.start_snapshot(); @@ -761,7 +791,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Execute `f` then unroll any bindings it creates - pub fn probe(&self, f: F) -> R where + pub fn probe(&self, f: F) -> R + where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R, { debug!("probe()"); @@ -771,59 +802,57 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { r } - pub fn add_given(&self, - sub: ty::Region<'tcx>, - sup: ty::RegionVid) - { + pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) { self.borrow_region_constraints().add_given(sub, sup); } - pub fn can_sub(&self, - param_env: ty::ParamEnv<'tcx>, - a: T, - b: T) - -> UnitResult<'tcx> - where T: at::ToTrace<'tcx> + pub fn can_sub(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx> + where + T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); self.probe(|_| { - self.at(origin, param_env).sub(a, b).map(|InferOk { obligations: _, .. }| { - // Ignore obligations, since we are unrolling - // everything anyway. - }) + self.at(origin, param_env) + .sub(a, b) + .map(|InferOk { obligations: _, .. }| { + // Ignore obligations, since we are unrolling + // everything anyway. + }) }) } - pub fn can_eq(&self, - param_env: ty::ParamEnv<'tcx>, - a: T, - b: T) - -> UnitResult<'tcx> - where T: at::ToTrace<'tcx> + pub fn can_eq(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx> + where + T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); self.probe(|_| { - self.at(origin, param_env).eq(a, b).map(|InferOk { obligations: _, .. }| { - // Ignore obligations, since we are unrolling - // everything anyway. - }) + self.at(origin, param_env) + .eq(a, b) + .map(|InferOk { obligations: _, .. }| { + // Ignore obligations, since we are unrolling + // everything anyway. + }) }) } - pub fn sub_regions(&self, - origin: SubregionOrigin<'tcx>, - a: ty::Region<'tcx>, - b: ty::Region<'tcx>) { + pub fn sub_regions( + &self, + origin: SubregionOrigin<'tcx>, + a: ty::Region<'tcx>, + b: ty::Region<'tcx>, + ) { debug!("sub_regions({:?} <: {:?})", a, b); - self.borrow_region_constraints().make_subregion(origin, a, b); + self.borrow_region_constraints() + .make_subregion(origin, a, b); } - pub fn subtype_predicate(&self, - cause: &ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - predicate: &ty::PolySubtypePredicate<'tcx>) - -> Option> - { + pub fn subtype_predicate( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + predicate: &ty::PolySubtypePredicate<'tcx>, + ) -> Option> { // Subtle: it's ok to skip the binder here and resolve because // `shallow_resolve` just ignores anything that is not a type // variable, and because type variable's can't (at present, at @@ -845,8 +874,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } Some(self.commit_if_ok(|snapshot| { - let (ty::SubtypePredicate { a_is_expected, a, b}, skol_map) = - self.skolemize_late_bound_regions(predicate); + let ( + ty::SubtypePredicate { + a_is_expected, + a, + b, + }, + skol_map, + ) = self.skolemize_late_bound_regions(predicate); let cause_span = cause.span; let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; @@ -856,17 +891,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { })) } - pub fn region_outlives_predicate(&self, - cause: &traits::ObligationCause<'tcx>, - predicate: &ty::PolyRegionOutlivesPredicate<'tcx>) - -> UnitResult<'tcx> - { + pub fn region_outlives_predicate( + &self, + cause: &traits::ObligationCause<'tcx>, + predicate: &ty::PolyRegionOutlivesPredicate<'tcx>, + ) -> UnitResult<'tcx> { self.commit_if_ok(|snapshot| { let (ty::OutlivesPredicate(r_a, r_b), skol_map) = self.skolemize_late_bound_regions(predicate); - let origin = - SubregionOrigin::from_obligation_cause(cause, - || RelateRegionParamBound(cause.span)); + let origin = SubregionOrigin::from_obligation_cause(cause, || { + RelateRegionParamBound(cause.span) + }); self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` self.leak_check(false, cause.span, &skol_map, snapshot)?; Ok(self.pop_skolemized(skol_map, snapshot)) @@ -888,27 +923,30 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub fn next_int_var_id(&self) -> IntVid { - self.int_unification_table - .borrow_mut() - .new_key(None) + self.int_unification_table.borrow_mut().new_key(None) } pub fn next_float_var_id(&self) -> FloatVid { - self.float_unification_table - .borrow_mut() - .new_key(None) + self.float_unification_table.borrow_mut().new_key(None) } /// Create a fresh region variable with the next available index. - /// - /// # Parameters - /// - /// - `origin`: information about why we created this variable, for use - /// during diagnostics / error-reporting. - pub fn next_region_var(&self, origin: RegionVariableOrigin) - -> ty::Region<'tcx> { + /// The variable will be created in the maximum universe created + /// thus far, allowing it to name any region created thus far. + pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> { + self.next_region_var_in_universe(origin, self.universe()) + } + + /// Create a fresh region variable with the next available index + /// in the given universe; typically, you can use + /// `next_region_var` and just use the maximal universe. + pub fn next_region_var_in_universe( + &self, + origin: RegionVariableOrigin, + universe: ty::UniverseIndex, + ) -> ty::Region<'tcx> { let region_var = self.borrow_region_constraints() - .new_region_var(self.universe(), origin); + .new_region_var(universe, origin); self.tcx.mk_region(ty::ReVar(region_var)) } @@ -918,22 +956,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Just a convenient wrapper of `next_region_var` for using during NLL. - pub fn next_nll_region_var(&self, origin: NLLRegionVariableOrigin) - -> ty::Region<'tcx> { + pub fn next_nll_region_var(&self, origin: NLLRegionVariableOrigin) -> ty::Region<'tcx> { self.next_region_var(RegionVariableOrigin::NLL(origin)) } - pub fn var_for_def(&self, - span: Span, - param: &ty::GenericParamDef) - -> Kind<'tcx> { + /// Just a convenient wrapper of `next_region_var` for using during NLL. + pub fn next_nll_region_var_in_universe( + &self, + origin: NLLRegionVariableOrigin, + universe: ty::UniverseIndex, + ) -> ty::Region<'tcx> { + self.next_region_var_in_universe(RegionVariableOrigin::NLL(origin), universe) + } + + pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> Kind<'tcx> { match param.kind { GenericParamDefKind::Lifetime => { // Create a region inference variable for the given // region parameter definition. - self.next_region_var(EarlyBoundRegion(span, param.name)).into() + self.next_region_var(EarlyBoundRegion(span, param.name)) + .into() } - GenericParamDefKind::Type {..} => { + GenericParamDefKind::Type { .. } => { // Create a type inference variable for the given // type parameter definition. The substitutions are // for actual parameters that may be referred to by @@ -942,12 +986,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // used in a path such as `Foo::::new()` will // use an inference variable for `C` with `[T, U]` // as the substitutions for the default, `(T, U)`. - let ty_var_id = - self.type_variables - .borrow_mut() - .new_var(self.universe(), - false, - TypeVariableOrigin::TypeParameterDefinition(span, param.name)); + let ty_var_id = self.type_variables.borrow_mut().new_var( + self.universe(), + false, + TypeVariableOrigin::TypeParameterDefinition(span, param.name), + ); self.tcx.mk_var(ty_var_id).into() } @@ -956,13 +999,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Given a set of generics defined on a type or impl, returns a substitution mapping each /// type/region parameter to a fresh inference variable. - pub fn fresh_substs_for_item(&self, - span: Span, - def_id: DefId) - -> &'tcx Substs<'tcx> { - Substs::for_item(self.tcx, def_id, |param, _| { - self.var_for_def(span, param) - }) + pub fn fresh_substs_for_item(&self, span: Span, def_id: DefId) -> &'tcx Substs<'tcx> { + Substs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param)) } /// True if errors have been reported since this infcx was @@ -971,11 +1009,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// errors, but where it's hard to be 100% sure (e.g., unresolved /// inference variables, regionck errors). pub fn is_tainted_by_errors(&self) -> bool { - debug!("is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ - tainted_by_errors_flag={})", - self.tcx.sess.err_count(), - self.err_count_on_creation, - self.tainted_by_errors_flag.get()); + debug!( + "is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ + tainted_by_errors_flag={})", + self.tcx.sess.err_count(), + self.err_count_on_creation, + self.tainted_by_errors_flag.get() + ); if self.tcx.sess.err_count() > self.err_count_on_creation { return true; // errors reported since this infcx was made @@ -1018,12 +1058,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_map: ®ion::ScopeTree, outlives_env: &OutlivesEnvironment<'tcx>, ) { - self.resolve_regions_and_report_errors_inner( - region_context, - region_map, - outlives_env, - true, - ) + self.resolve_regions_and_report_errors_inner(region_context, region_map, outlives_env, true) } fn resolve_regions_and_report_errors_inner( @@ -1033,22 +1068,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { outlives_env: &OutlivesEnvironment<'tcx>, will_later_be_reported_by_nll: bool, ) { - assert!(self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(), - "region_obligations not empty: {:#?}", - self.region_obligations.borrow()); - - let region_rels = &RegionRelations::new(self.tcx, - region_context, - region_map, - outlives_env.free_region_map()); - let (var_infos, data) = self.region_constraints.borrow_mut() - .take() - .expect("regions already resolved") - .into_infos_and_data(); + assert!( + self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(), + "region_obligations not empty: {:#?}", + self.region_obligations.borrow() + ); + + let region_rels = &RegionRelations::new( + self.tcx, + region_context, + region_map, + outlives_env.free_region_map(), + ); + let (var_infos, data) = self.region_constraints + .borrow_mut() + .take() + .expect("regions already resolved") + .into_infos_and_data(); let (lexical_region_resolutions, errors) = lexical_region_resolve::resolve(region_rels, var_infos, data); - let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); + let old_value = self.lexical_region_resolutions + .replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); if !self.is_tainted_by_errors() { @@ -1072,9 +1113,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// translate them into the form that the NLL solver /// understands. See the NLL module for mode details. pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> { - assert!(self.region_obligations.borrow().is_empty(), - "region_obligations not empty: {:#?}", - self.region_obligations.borrow()); + assert!( + self.region_obligations.borrow().is_empty(), + "region_obligations not empty: {:#?}", + self.region_obligations.borrow() + ); self.borrow_region_constraints().take_and_reset_data() } @@ -1095,10 +1138,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// called. This is used only during NLL processing to "hand off" ownership /// of the set of region vairables into the NLL region context. pub fn take_region_var_origins(&self) -> VarInfos { - let (var_infos, data) = self.region_constraints.borrow_mut() - .take() - .expect("regions already resolved") - .into_infos_and_data(); + let (var_infos, data) = self.region_constraints + .borrow_mut() + .take() + .expect("regions already resolved") + .into_infos_and_data(); assert!(data.is_empty()); var_infos } @@ -1116,9 +1160,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.resolve_type_vars_if_possible(t).to_string() } - pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> { + // We have this force-inlined variant of shallow_resolve() for the one + // callsite that is extremely hot. All other callsites use the normal + // variant. + #[inline(always)] + pub fn inlined_shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> { match typ.sty { - ty::TyInfer(ty::TyVar(v)) => { + ty::Infer(ty::TyVar(v)) => { // Not entirely obvious: if `typ` is a type variable, // it can be resolved to an int/float variable, which // can then be recursively resolved, hence the @@ -1128,37 +1176,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // structurally), and we prevent cycles in any case, // so this recursion should always be of very limited // depth. - self.type_variables.borrow_mut() - .probe(v) - .known() - .map(|t| self.shallow_resolve(t)) - .unwrap_or(typ) - } - - ty::TyInfer(ty::IntVar(v)) => { - self.int_unification_table + self.type_variables .borrow_mut() - .probe_value(v) - .map(|v| v.to_type(self.tcx)) + .probe(v) + .known() + .map(|t| self.shallow_resolve(t)) .unwrap_or(typ) } - ty::TyInfer(ty::FloatVar(v)) => { - self.float_unification_table - .borrow_mut() - .probe_value(v) - .map(|v| v.to_type(self.tcx)) - .unwrap_or(typ) - } + ty::Infer(ty::IntVar(v)) => self.int_unification_table + .borrow_mut() + .probe_value(v) + .map(|v| v.to_type(self.tcx)) + .unwrap_or(typ), - _ => { - typ - } + ty::Infer(ty::FloatVar(v)) => self.float_unification_table + .borrow_mut() + .probe_value(v) + .map(|v| v.to_type(self.tcx)) + .unwrap_or(typ), + + _ => typ, } } + pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> { + self.inlined_shallow_resolve(typ) + } + pub fn resolve_type_vars_if_possible(&self, value: &T) -> T - where T: TypeFoldable<'tcx> + where + T: TypeFoldable<'tcx>, { /*! * Where possible, replaces type/int/float variables in @@ -1182,20 +1230,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// resolved type, so it's more efficient than /// `resolve_type_vars_if_possible()`. pub fn any_unresolved_type_vars(&self, value: &T) -> bool - where T: TypeFoldable<'tcx> + where + T: TypeFoldable<'tcx>, { let mut r = resolve::UnresolvedTypeFinder::new(self); value.visit_with(&mut r) } pub fn resolve_type_and_region_vars_if_possible(&self, value: &T) -> T - where T: TypeFoldable<'tcx> + where + T: TypeFoldable<'tcx>, { let mut r = resolve::OpportunisticTypeAndRegionResolver::new(self); value.fold_with(&mut r) } - pub fn fully_resolve>(&self, value: &T) -> FixupResult { + pub fn fully_resolve>(&self, value: &T) -> FixupResult { /*! * Attempts to resolve all type/region variables in * `value`. Region inference must have been run already (e.g., @@ -1210,27 +1260,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } // [Note-Type-error-reporting] - // An invariant is that anytime the expected or actual type is TyError (the special + // An invariant is that anytime the expected or actual type is Error (the special // error type, meaning that an error occurred when typechecking this expression), // this is a derived error. The error cascaded from another error (that was already // reported), so it's not useful to display it to the user. // The following methods implement this logic. - // They check if either the actual or expected type is TyError, and don't print the error + // They check if either the actual or expected type is Error, and don't print the error // in this case. The typechecker should only ever report type errors involving mismatched // types using one of these methods, and should not call span_err directly for such // errors. - pub fn type_error_struct_with_diag(&self, - sp: Span, - mk_diag: M, - actual_ty: Ty<'tcx>) - -> DiagnosticBuilder<'tcx> - where M: FnOnce(String) -> DiagnosticBuilder<'tcx>, + pub fn type_error_struct_with_diag( + &self, + sp: Span, + mk_diag: M, + actual_ty: Ty<'tcx>, + ) -> DiagnosticBuilder<'tcx> + where + M: FnOnce(String) -> DiagnosticBuilder<'tcx>, { let actual_ty = self.resolve_type_vars_if_possible(&actual_ty); debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); - // Don't report an error if actual type is TyError. + // Don't report an error if actual type is Error. if actual_ty.references_error() { return self.tcx.sess.diagnostic().struct_dummy(); } @@ -1238,12 +1290,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { mk_diag(self.ty_to_string(actual_ty)) } - pub fn report_mismatched_types(&self, - cause: &ObligationCause<'tcx>, - expected: Ty<'tcx>, - actual: Ty<'tcx>, - err: TypeError<'tcx>) - -> DiagnosticBuilder<'tcx> { + pub fn report_mismatched_types( + &self, + cause: &ObligationCause<'tcx>, + expected: Ty<'tcx>, + actual: Ty<'tcx>, + err: TypeError<'tcx>, + ) -> DiagnosticBuilder<'tcx> { let trace = TypeTrace::types(cause, true, expected, actual); self.report_and_explain_type_error(trace, &err) } @@ -1252,13 +1305,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { &self, span: Span, lbrct: LateBoundRegionConversionTime, - value: &ty::Binder) - -> (T, BTreeMap>) - where T : TypeFoldable<'tcx> + value: &ty::Binder, + ) -> (T, BTreeMap>) + where + T: TypeFoldable<'tcx>, { - self.tcx.replace_late_bound_regions( - value, - |br| self.next_region_var(LateBoundRegion(span, br, lbrct))) + self.tcx.replace_late_bound_regions(value, |br| { + self.next_region_var(LateBoundRegion(span, br, lbrct)) + }) } /// Given a higher-ranked projection predicate like: @@ -1276,43 +1330,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// /// See `higher_ranked_match` in `higher_ranked/mod.rs` for more /// details. - pub fn match_poly_projection_predicate(&self, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - match_a: ty::PolyProjectionPredicate<'tcx>, - match_b: ty::TraitRef<'tcx>) - -> InferResult<'tcx, HrMatchResult>> - { + pub fn match_poly_projection_predicate( + &self, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + match_a: ty::PolyProjectionPredicate<'tcx>, + match_b: ty::TraitRef<'tcx>, + ) -> InferResult<'tcx, HrMatchResult>> { let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty)); let trace = TypeTrace { cause, - values: TraitRefs(ExpectedFound::new(true, match_pair.skip_binder().0, match_b)) + values: TraitRefs(ExpectedFound::new( + true, + match_pair.skip_binder().0, + match_b, + )), }; let mut combine = self.combine_fields(trace, param_env); let result = combine.higher_ranked_match(&match_pair, &match_b, true)?; - Ok(InferOk { value: result, obligations: combine.obligations }) + Ok(InferOk { + value: result, + obligations: combine.obligations, + }) } /// See `verify_generic_bound` method in `region_constraints` - pub fn verify_generic_bound(&self, - origin: SubregionOrigin<'tcx>, - kind: GenericKind<'tcx>, - a: ty::Region<'tcx>, - bound: VerifyBound<'tcx>) { - debug!("verify_generic_bound({:?}, {:?} <: {:?})", - kind, - a, - bound); - - self.borrow_region_constraints().verify_generic_bound(origin, kind, a, bound); - } - - pub fn type_moves_by_default(&self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span) - -> bool { + pub fn verify_generic_bound( + &self, + origin: SubregionOrigin<'tcx>, + kind: GenericKind<'tcx>, + a: ty::Region<'tcx>, + bound: VerifyBound<'tcx>, + ) { + debug!("verify_generic_bound({:?}, {:?} <: {:?})", kind, a, bound); + + self.borrow_region_constraints() + .verify_generic_bound(origin, kind, a, bound); + } + + pub fn type_moves_by_default( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + ) -> bool { let ty = self.resolve_type_vars_if_possible(&ty); // Even if the type may have no inference variables, during // type-checking closure types are in local tables only. @@ -1334,11 +1396,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Obtains the latest type of the given closure; this may be a /// closure in the current function, in which case its /// `ClosureKind` may not yet be known. - pub fn closure_kind(&self, - closure_def_id: DefId, - closure_substs: ty::ClosureSubsts<'tcx>) - -> Option - { + pub fn closure_kind( + &self, + closure_def_id: DefId, + closure_substs: ty::ClosureSubsts<'tcx>, + ) -> Option { let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx); let closure_kind_ty = self.shallow_resolve(&closure_kind_ty); closure_kind_ty.to_opt_closure_kind() @@ -1351,7 +1413,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn closure_sig( &self, def_id: DefId, - substs: ty::ClosureSubsts<'tcx> + substs: ty::ClosureSubsts<'tcx>, ) -> ty::PolyFnSig<'tcx> { let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx); let closure_sig_ty = self.shallow_resolve(&closure_sig_ty); @@ -1360,29 +1422,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Normalizes associated types in `value`, potentially returning /// new obligations that must further be processed. - pub fn partially_normalize_associated_types_in(&self, - span: Span, - body_id: ast::NodeId, - param_env: ty::ParamEnv<'tcx>, - value: &T) - -> InferOk<'tcx, T> - where T : TypeFoldable<'tcx> + pub fn partially_normalize_associated_types_in( + &self, + span: Span, + body_id: ast::NodeId, + param_env: ty::ParamEnv<'tcx>, + value: &T, + ) -> InferOk<'tcx, T> + where + T: TypeFoldable<'tcx>, { debug!("partially_normalize_associated_types_in(value={:?})", value); let mut selcx = traits::SelectionContext::new(self); let cause = ObligationCause::misc(span, body_id); let traits::Normalized { value, obligations } = traits::normalize(&mut selcx, param_env, cause, value); - debug!("partially_normalize_associated_types_in: result={:?} predicates={:?}", - value, - obligations); + debug!( + "partially_normalize_associated_types_in: result={:?} predicates={:?}", + value, obligations + ); InferOk { value, obligations } } pub fn borrow_region_constraints(&self) -> RefMut<'_, RegionConstraintCollector<'tcx>> { - RefMut::map( - self.region_constraints.borrow_mut(), - |c| c.as_mut().expect("region constraints already solved")) + RefMut::map(self.region_constraints.borrow_mut(), |c| { + c.as_mut().expect("region constraints already solved") + }) } /// Clears the selection, evaluation, and projection cachesThis is useful when @@ -1415,14 +1480,15 @@ impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> { self.cause.span } - pub fn types(cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Ty<'tcx>, - b: Ty<'tcx>) - -> TypeTrace<'tcx> { + pub fn types( + cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: Ty<'tcx>, + b: Ty<'tcx>, + ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: Types(ExpectedFound::new(a_is_expected, a, b)) + values: Types(ExpectedFound::new(a_is_expected, a, b)), } } @@ -1432,7 +1498,7 @@ impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> { values: Types(ExpectedFound { expected: tcx.types.err, found: tcx.types.err, - }) + }), } } } @@ -1474,24 +1540,25 @@ impl<'tcx> SubregionOrigin<'tcx> { } } - pub fn from_obligation_cause(cause: &traits::ObligationCause<'tcx>, - default: F) - -> Self - where F: FnOnce() -> Self + pub fn from_obligation_cause(cause: &traits::ObligationCause<'tcx>, default: F) -> Self + where + F: FnOnce() -> Self, { match cause.code { - traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => - SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span), - - traits::ObligationCauseCode::CompareImplMethodObligation { item_name, - impl_item_def_id, - trait_item_def_id, } => - SubregionOrigin::CompareImplMethodObligation { - span: cause.span, - item_name, - impl_item_def_id, - trait_item_def_id, - }, + traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => { + SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span) + } + + traits::ObligationCauseCode::CompareImplMethodObligation { + item_name, + impl_item_def_id, + trait_item_def_id, + } => SubregionOrigin::CompareImplMethodObligation { + span: cause.span, + item_name, + impl_item_def_id, + trait_item_def_id, + }, _ => default(), } @@ -1526,8 +1593,10 @@ EnumTypeFoldableImpl! { impl<'tcx> fmt::Debug for RegionObligation<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "RegionObligation(sub_region={:?}, sup_type={:?})", - self.sub_region, - self.sup_type) + write!( + f, + "RegionObligation(sub_region={:?}, sup_type={:?})", + self.sub_region, self.sup_type + ) } } diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs new file mode 100644 index 0000000000..9d65c39506 --- /dev/null +++ b/src/librustc/infer/opaque_types/mod.rs @@ -0,0 +1,865 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use hir::def_id::DefId; +use hir; +use hir::Node; +use infer::{self, InferCtxt, InferOk, TypeVariableOrigin}; +use infer::outlives::free_region_map::FreeRegionRelations; +use rustc_data_structures::fx::FxHashMap; +use syntax::ast; +use traits::{self, PredicateObligation}; +use ty::{self, Ty, TyCtxt, GenericParamDefKind}; +use ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; +use ty::outlives::Component; +use ty::subst::{Kind, Substs, UnpackedKind}; +use util::nodemap::DefIdMap; + +pub type OpaqueTypeMap<'tcx> = DefIdMap>; + +/// Information about the opaque, abstract types whose values we +/// are inferring in this function (these are the `impl Trait` that +/// appear in the return type). +#[derive(Copy, Clone, Debug)] +pub struct OpaqueTypeDecl<'tcx> { + /// The substitutions that we apply to the abstract that that this + /// `impl Trait` desugars to. e.g., if: + /// + /// fn foo<'a, 'b, T>() -> impl Trait<'a> + /// + /// winds up desugared to: + /// + /// abstract type Foo<'x, T>: Trait<'x> + /// fn foo<'a, 'b, T>() -> Foo<'a, T> + /// + /// then `substs` would be `['a, T]`. + pub substs: &'tcx Substs<'tcx>, + + /// The type variable that represents the value of the abstract type + /// that we require. In other words, after we compile this function, + /// we will be created a constraint like: + /// + /// Foo<'a, T> = ?C + /// + /// where `?C` is the value of this type variable. =) It may + /// naturally refer to the type and lifetime parameters in scope + /// in this function, though ultimately it should only reference + /// those that are arguments to `Foo` in the constraint above. (In + /// other words, `?C` should not include `'b`, even though it's a + /// lifetime parameter on `foo`.) + pub concrete_ty: Ty<'tcx>, + + /// True if the `impl Trait` bounds include region bounds. + /// For example, this would be true for: + /// + /// fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b + /// + /// but false for: + /// + /// fn foo<'c>() -> impl Trait<'c> + /// + /// unless `Trait` was declared like: + /// + /// trait Trait<'c>: 'c + /// + /// in which case it would be true. + /// + /// This is used during regionck to decide whether we need to + /// impose any additional constraints to ensure that region + /// variables in `concrete_ty` wind up being constrained to + /// something from `substs` (or, at minimum, things that outlive + /// the fn body). (Ultimately, writeback is responsible for this + /// check.) + pub has_required_region_bounds: bool, +} + +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + /// Replace all opaque types in `value` with fresh inference variables + /// and creates appropriate obligations. For example, given the input: + /// + /// impl Iterator + /// + /// this method would create two type variables, `?0` and `?1`. It would + /// return the type `?0` but also the obligations: + /// + /// ?0: Iterator + /// ?1: Debug + /// + /// Moreover, it returns a `OpaqueTypeMap` that would map `?0` to + /// info about the `impl Iterator<..>` type and `?1` to info about + /// the `impl Debug` type. + /// + /// # Parameters + /// + /// - `parent_def_id` -- we will only instantiate opaque types + /// with this parent. This is typically the def-id of the function + /// in whose return type opaque types are being instantiated. + /// - `body_id` -- the body-id with which the resulting obligations should + /// be associated + /// - `param_env` -- the in-scope parameter environment to be used for + /// obligations + /// - `value` -- the value within which we are instantiating opaque types + pub fn instantiate_opaque_types>( + &self, + parent_def_id: DefId, + body_id: ast::NodeId, + param_env: ty::ParamEnv<'tcx>, + value: &T, + ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> { + debug!( + "instantiate_opaque_types(value={:?}, + parent_def_id={:?}, body_id={:?}, + param_env={:?})", + value, parent_def_id, body_id, param_env, + ); + let mut instantiator = Instantiator { + infcx: self, + parent_def_id, + body_id, + param_env, + opaque_types: DefIdMap(), + obligations: vec![], + }; + let value = instantiator.instantiate_opaque_types_in_map(value); + InferOk { + value: (value, instantiator.opaque_types), + obligations: instantiator.obligations, + } + } + + /// Given the map `opaque_types` containing the existential `impl + /// Trait` types whose underlying, hidden types are being + /// inferred, this method adds constraints to the regions + /// appearing in those underlying hidden types to ensure that they + /// at least do not refer to random scopes within the current + /// function. These constraints are not (quite) sufficient to + /// guarantee that the regions are actually legal values; that + /// final condition is imposed after region inference is done. + /// + /// # The Problem + /// + /// Let's work through an example to explain how it works. Assume + /// the current function is as follows: + /// + /// ```text + /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>) + /// ``` + /// + /// Here, we have two `impl Trait` types whose values are being + /// inferred (the `impl Bar<'a>` and the `impl + /// Bar<'b>`). Conceptually, this is sugar for a setup where we + /// define underlying abstract types (`Foo1`, `Foo2`) and then, in + /// the return type of `foo`, we *reference* those definitions: + /// + /// ```text + /// abstract type Foo1<'x>: Bar<'x>; + /// abstract type Foo2<'x>: Bar<'x>; + /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } + /// // ^^^^ ^^ + /// // | | + /// // | substs + /// // def_id + /// ``` + /// + /// As indicating in the comments above, each of those references + /// is (in the compiler) basically a substitution (`substs`) + /// applied to the type of a suitable `def_id` (which identifies + /// `Foo1` or `Foo2`). + /// + /// Now, at this point in compilation, what we have done is to + /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with + /// fresh inference variables C1 and C2. We wish to use the values + /// of these variables to infer the underlying types of `Foo1` and + /// `Foo2`. That is, this gives rise to higher-order (pattern) unification + /// constraints like: + /// + /// ```text + /// for<'a> (Foo1<'a> = C1) + /// for<'b> (Foo1<'b> = C2) + /// ``` + /// + /// For these equation to be satisfiable, the types `C1` and `C2` + /// can only refer to a limited set of regions. For example, `C1` + /// can only refer to `'static` and `'a`, and `C2` can only refer + /// to `'static` and `'b`. The job of this function is to impose that + /// constraint. + /// + /// Up to this point, C1 and C2 are basically just random type + /// inference variables, and hence they may contain arbitrary + /// regions. In fact, it is fairly likely that they do! Consider + /// this possible definition of `foo`: + /// + /// ```text + /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) { + /// (&*x, &*y) + /// } + /// ``` + /// + /// Here, the values for the concrete types of the two impl + /// traits will include inference variables: + /// + /// ```text + /// &'0 i32 + /// &'1 i32 + /// ``` + /// + /// Ordinarily, the subtyping rules would ensure that these are + /// sufficiently large. But since `impl Bar<'a>` isn't a specific + /// type per se, we don't get such constraints by default. This + /// is where this function comes into play. It adds extra + /// constraints to ensure that all the regions which appear in the + /// inferred type are regions that could validly appear. + /// + /// This is actually a bit of a tricky constraint in general. We + /// want to say that each variable (e.g., `'0`) can only take on + /// values that were supplied as arguments to the abstract type + /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in + /// scope. We don't have a constraint quite of this kind in the current + /// region checker. + /// + /// # The Solution + /// + /// We make use of the constraint that we *do* have in the `<=` + /// relation. To do that, we find the "minimum" of all the + /// arguments that appear in the substs: that is, some region + /// which is less than all the others. In the case of `Foo1<'a>`, + /// that would be `'a` (it's the only choice, after all). Then we + /// apply that as a least bound to the variables (e.g., `'a <= + /// '0`). + /// + /// In some cases, there is no minimum. Consider this example: + /// + /// ```text + /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... } + /// ``` + /// + /// Here we would report an error, because `'a` and `'b` have no + /// relation to one another. + /// + /// # The `free_region_relations` parameter + /// + /// The `free_region_relations` argument is used to find the + /// "minimum" of the regions supplied to a given abstract type. + /// It must be a relation that can answer whether `'a <= 'b`, + /// where `'a` and `'b` are regions that appear in the "substs" + /// for the abstract type references (the `<'a>` in `Foo1<'a>`). + /// + /// Note that we do not impose the constraints based on the + /// generic regions from the `Foo1` definition (e.g., `'x`). This + /// is because the constraints we are imposing here is basically + /// the concern of the one generating the constraining type C1, + /// which is the current function. It also means that we can + /// take "implied bounds" into account in some cases: + /// + /// ```text + /// trait SomeTrait<'a, 'b> { } + /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. } + /// ``` + /// + /// Here, the fact that `'b: 'a` is known only because of the + /// implied bounds from the `&'a &'b u32` parameter, and is not + /// "inherent" to the abstract type definition. + /// + /// # Parameters + /// + /// - `opaque_types` -- the map produced by `instantiate_opaque_types` + /// - `free_region_relations` -- something that can be used to relate + /// the free regions (`'a`) that appear in the impl trait. + pub fn constrain_opaque_types>( + &self, + opaque_types: &OpaqueTypeMap<'tcx>, + free_region_relations: &FRR, + ) { + debug!("constrain_opaque_types()"); + + for (&def_id, opaque_defn) in opaque_types { + self.constrain_opaque_type(def_id, opaque_defn, free_region_relations); + } + } + + fn constrain_opaque_type>( + &self, + def_id: DefId, + opaque_defn: &OpaqueTypeDecl<'tcx>, + free_region_relations: &FRR, + ) { + debug!("constrain_opaque_type()"); + debug!("constrain_opaque_type: def_id={:?}", def_id); + debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn); + + let concrete_ty = self.resolve_type_vars_if_possible(&opaque_defn.concrete_ty); + + debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty); + + let abstract_type_generics = self.tcx.generics_of(def_id); + + let span = self.tcx.def_span(def_id); + + // If there are required region bounds, we can just skip + // ahead. There will already be a registered region + // obligation related `concrete_ty` to those regions. + if opaque_defn.has_required_region_bounds { + return; + } + + // There were no `required_region_bounds`, + // so we have to search for a `least_region`. + // Go through all the regions used as arguments to the + // abstract type. These are the parameters to the abstract + // type; so in our example above, `substs` would contain + // `['a]` for the first impl trait and `'b` for the + // second. + let mut least_region = None; + for param in &abstract_type_generics.params { + match param.kind { + GenericParamDefKind::Lifetime => {} + _ => continue + } + // Get the value supplied for this region from the substs. + let subst_arg = opaque_defn.substs.region_at(param.index as usize); + + // Compute the least upper bound of it with the other regions. + debug!("constrain_opaque_types: least_region={:?}", least_region); + debug!("constrain_opaque_types: subst_arg={:?}", subst_arg); + match least_region { + None => least_region = Some(subst_arg), + Some(lr) => { + if free_region_relations.sub_free_regions(lr, subst_arg) { + // keep the current least region + } else if free_region_relations.sub_free_regions(subst_arg, lr) { + // switch to `subst_arg` + least_region = Some(subst_arg); + } else { + // There are two regions (`lr` and + // `subst_arg`) which are not relatable. We can't + // find a best choice. + self.tcx + .sess + .struct_span_err(span, "ambiguous lifetime bound in `impl Trait`") + .span_label( + span, + format!("neither `{}` nor `{}` outlives the other", lr, subst_arg), + ) + .emit(); + + least_region = Some(self.tcx.mk_region(ty::ReEmpty)); + break; + } + } + } + } + + let least_region = least_region.unwrap_or(self.tcx.types.re_static); + debug!("constrain_opaque_types: least_region={:?}", least_region); + + // Require that the type `concrete_ty` outlives + // `least_region`, modulo any type parameters that appear + // in the type, which we ignore. This is because impl + // trait values are assumed to capture all the in-scope + // type parameters. This little loop here just invokes + // `outlives` repeatedly, draining all the nested + // obligations that result. + let mut types = vec![concrete_ty]; + let bound_region = |r| self.sub_regions(infer::CallReturn(span), least_region, r); + while let Some(ty) = types.pop() { + let mut components = self.tcx.outlives_components(ty); + while let Some(component) = components.pop() { + match component { + Component::Region(r) => { + bound_region(r); + } + + Component::Param(_) => { + // ignore type parameters like `T`, they are captured + // implicitly by the `impl Trait` + } + + Component::UnresolvedInferenceVariable(_) => { + // we should get an error that more type + // annotations are needed in this case + self.tcx + .sess + .delay_span_bug(span, "unresolved inf var in opaque"); + } + + Component::Projection(ty::ProjectionTy { + substs, + item_def_id: _, + }) => { + for r in substs.regions() { + bound_region(r); + } + types.extend(substs.types()); + } + + Component::EscapingProjection(more_components) => { + components.extend(more_components); + } + } + } + } + } + + /// Given the fully resolved, instantiated type for an opaque + /// type, i.e., the value of an inference variable like C1 or C2 + /// (*), computes the "definition type" for an abstract type + /// definition -- that is, the inferred value of `Foo1<'x>` or + /// `Foo2<'x>` that we would conceptually use in its definition: + /// + /// abstract type Foo1<'x>: Bar<'x> = AAA; <-- this type AAA + /// abstract type Foo2<'x>: Bar<'x> = BBB; <-- or this type BBB + /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } + /// + /// Note that these values are defined in terms of a distinct set of + /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main + /// purpose of this function is to do that translation. + /// + /// (*) C1 and C2 were introduced in the comments on + /// `constrain_opaque_types`. Read that comment for more context. + /// + /// # Parameters + /// + /// - `def_id`, the `impl Trait` type + /// - `opaque_defn`, the opaque definition created in `instantiate_opaque_types` + /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of + /// `opaque_defn.concrete_ty` + pub fn infer_opaque_definition_from_instantiation( + &self, + def_id: DefId, + opaque_defn: &OpaqueTypeDecl<'tcx>, + instantiated_ty: Ty<'gcx>, + ) -> Ty<'gcx> { + debug!( + "infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})", + def_id, instantiated_ty + ); + + let gcx = self.tcx.global_tcx(); + + // Use substs to build up a reverse map from regions to their + // identity mappings. This is necessary because of `impl + // Trait` lifetimes are computed by replacing existing + // lifetimes with 'static and remapping only those used in the + // `impl Trait` return type, resulting in the parameters + // shifting. + let id_substs = Substs::identity_for_item(gcx, def_id); + let map: FxHashMap, Kind<'gcx>> = opaque_defn + .substs + .iter() + .enumerate() + .map(|(index, subst)| (*subst, id_substs[index])) + .collect(); + + // Convert the type from the function into a type valid outside + // the function, by replacing invalid regions with 'static, + // after producing an error for each of them. + let definition_ty = + instantiated_ty.fold_with(&mut ReverseMapper::new( + self.tcx, + self.is_tainted_by_errors(), + def_id, + map, + instantiated_ty, + )); + debug!( + "infer_opaque_definition_from_instantiation: definition_ty={:?}", + definition_ty + ); + + // We can unwrap here because our reverse mapper always + // produces things with 'gcx lifetime, though the type folder + // obscures that. + let definition_ty = gcx.lift(&definition_ty).unwrap(); + + definition_ty + } +} + +struct ReverseMapper<'cx, 'gcx: 'tcx, 'tcx: 'cx> { + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + + /// If errors have already been reported in this fn, we suppress + /// our own errors because they are sometimes derivative. + tainted_by_errors: bool, + + opaque_type_def_id: DefId, + map: FxHashMap, Kind<'gcx>>, + map_missing_regions_to_empty: bool, + + /// initially `Some`, set to `None` once error has been reported + hidden_ty: Option>, +} + +impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> { + fn new( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + tainted_by_errors: bool, + opaque_type_def_id: DefId, + map: FxHashMap, Kind<'gcx>>, + hidden_ty: Ty<'tcx>, + ) -> Self { + Self { + tcx, + tainted_by_errors, + opaque_type_def_id, + map, + map_missing_regions_to_empty: false, + hidden_ty: Some(hidden_ty), + } + } + + fn fold_kind_mapping_missing_regions_to_empty(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> { + assert!(!self.map_missing_regions_to_empty); + self.map_missing_regions_to_empty = true; + let kind = kind.fold_with(self); + self.map_missing_regions_to_empty = false; + kind + } + + fn fold_kind_normally(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> { + assert!(!self.map_missing_regions_to_empty); + kind.fold_with(self) + } +} + +impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { + self.tcx + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match r { + // ignore bound regions that appear in the type (e.g., this + // would ignore `'r` in a type like `for<'r> fn(&'r u32)`. + ty::ReLateBound(..) | + + // ignore `'static`, as that can appear anywhere + ty::ReStatic | + + // ignore `ReScope`, as that can appear anywhere + // See `src/test/run-pass/issue-49556.rs` for example. + ty::ReScope(..) => return r, + + _ => { } + } + + match self.map.get(&r.into()).map(|k| k.unpack()) { + Some(UnpackedKind::Lifetime(r1)) => r1, + Some(u) => panic!("region mapped to unexpected kind: {:?}", u), + None => { + if !self.map_missing_regions_to_empty && !self.tainted_by_errors { + if let Some(hidden_ty) = self.hidden_ty.take() { + let span = self.tcx.def_span(self.opaque_type_def_id); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0700, + "hidden type for `impl Trait` captures lifetime that \ + does not appear in bounds", + ); + + // Assuming regionck succeeded, then we must + // be capturing *some* region from the fn + // header, and hence it must be free, so it's + // ok to invoke this fn (which doesn't accept + // all regions, and would ICE if an + // inappropriate region is given). We check + // `is_tainted_by_errors` by errors above, so + // we don't get in here unless regionck + // succeeded. (Note also that if regionck + // failed, then the regions we are attempting + // to map here may well be giving errors + // *because* the constraints were not + // satisfiable.) + self.tcx.note_and_explain_free_region( + &mut err, + &format!("hidden type `{}` captures ", hidden_ty), + r, + "" + ); + + err.emit(); + } + } + self.tcx.types.re_empty + }, + } + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.sty { + ty::Closure(def_id, substs) => { + // I am a horrible monster and I pray for death. When + // we encounter a closure here, it is always a closure + // from within the function that we are currently + // type-checking -- one that is now being encapsulated + // in an existential abstract type. Ideally, we would + // go through the types/lifetimes that it references + // and treat them just like we would any other type, + // which means we would error out if we find any + // reference to a type/region that is not in the + // "reverse map". + // + // **However,** in the case of closures, there is a + // somewhat subtle (read: hacky) consideration. The + // problem is that our closure types currently include + // all the lifetime parameters declared on the + // enclosing function, even if they are unused by the + // closure itself. We can't readily filter them out, + // so here we replace those values with `'empty`. This + // can't really make a difference to the rest of the + // compiler; those regions are ignored for the + // outlives relation, and hence don't affect trait + // selection or auto traits, and they are erased + // during codegen. + + let generics = self.tcx.generics_of(def_id); + let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map( + |(index, &kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + }, + )); + + self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs }) + } + + _ => ty.super_fold_with(self), + } + } +} + +struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> { + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + parent_def_id: DefId, + body_id: ast::NodeId, + param_env: ty::ParamEnv<'tcx>, + opaque_types: OpaqueTypeMap<'tcx>, + obligations: Vec>, +} + +impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { + fn instantiate_opaque_types_in_map>(&mut self, value: &T) -> T { + debug!("instantiate_opaque_types_in_map(value={:?})", value); + let tcx = self.infcx.tcx; + value.fold_with(&mut BottomUpFolder { + tcx, + reg_op: |reg| reg, + fldop: |ty| { + if let ty::Opaque(def_id, substs) = ty.sty { + // Check that this is `impl Trait` type is + // declared by `parent_def_id` -- i.e., one whose + // value we are inferring. At present, this is + // always true during the first phase of + // type-check, but not always true later on during + // NLL. Once we support named abstract types more fully, + // this same scenario will be able to arise during all phases. + // + // Here is an example using `abstract type` that indicates + // the distinction we are checking for: + // + // ```rust + // mod a { + // pub abstract type Foo: Iterator; + // pub fn make_foo() -> Foo { .. } + // } + // + // mod b { + // fn foo() -> a::Foo { a::make_foo() } + // } + // ``` + // + // Here, the return type of `foo` references a + // `Opaque` indeed, but not one whose value is + // presently being inferred. You can get into a + // similar situation with closure return types + // today: + // + // ```rust + // fn foo() -> impl Iterator { .. } + // fn bar() { + // let x = || foo(); // returns the Opaque assoc with `foo` + // } + // ``` + if let Some(opaque_node_id) = tcx.hir.as_local_node_id(def_id) { + let parent_def_id = self.parent_def_id; + let def_scope_default = || { + let opaque_parent_node_id = tcx.hir.get_parent(opaque_node_id); + parent_def_id == tcx.hir.local_def_id(opaque_parent_node_id) + }; + let in_definition_scope = match tcx.hir.find(opaque_node_id) { + Some(Node::Item(item)) => match item.node { + // impl trait + hir::ItemKind::Existential(hir::ExistTy { + impl_trait_fn: Some(parent), + .. + }) => parent == self.parent_def_id, + // named existential types + hir::ItemKind::Existential(hir::ExistTy { + impl_trait_fn: None, + .. + }) => may_define_existential_type( + tcx, + self.parent_def_id, + opaque_node_id, + ), + _ => def_scope_default(), + }, + Some(Node::ImplItem(item)) => match item.node { + hir::ImplItemKind::Existential(_) => may_define_existential_type( + tcx, + self.parent_def_id, + opaque_node_id, + ), + _ => def_scope_default(), + }, + _ => bug!( + "expected (impl) item, found {}", + tcx.hir.node_to_string(opaque_node_id), + ), + }; + if in_definition_scope { + return self.fold_opaque_ty(ty, def_id, substs); + } + + debug!( + "instantiate_opaque_types_in_map: \ + encountered opaque outside it's definition scope \ + def_id={:?}", + def_id, + ); + } + } + + ty + }, + }) + } + + fn fold_opaque_ty( + &mut self, + ty: Ty<'tcx>, + def_id: DefId, + substs: &'tcx Substs<'tcx>, + ) -> Ty<'tcx> { + let infcx = self.infcx; + let tcx = infcx.tcx; + + debug!( + "instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", + def_id, substs + ); + + // Use the same type variable if the exact same Opaque appears more + // than once in the return type (e.g. if it's passed to a type alias). + if let Some(opaque_defn) = self.opaque_types.get(&def_id) { + return opaque_defn.concrete_ty; + } + let span = tcx.def_span(def_id); + let ty_var = infcx.next_ty_var(TypeVariableOrigin::TypeInference(span)); + + let predicates_of = tcx.predicates_of(def_id); + debug!( + "instantiate_opaque_types: predicates: {:#?}", + predicates_of, + ); + let bounds = predicates_of.instantiate(tcx, substs); + debug!("instantiate_opaque_types: bounds={:?}", bounds); + + let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone()); + debug!( + "instantiate_opaque_types: required_region_bounds={:?}", + required_region_bounds + ); + + // make sure that we are in fact defining the *entire* type + // e.g. `existential type Foo: Bar;` needs to be + // defined by a function like `fn foo() -> Foo`. + debug!( + "instantiate_opaque_types: param_env: {:#?}", + self.param_env, + ); + debug!( + "instantiate_opaque_types: generics: {:#?}", + tcx.generics_of(def_id), + ); + + self.opaque_types.insert( + def_id, + OpaqueTypeDecl { + substs, + concrete_ty: ty_var, + has_required_region_bounds: !required_region_bounds.is_empty(), + }, + ); + debug!("instantiate_opaque_types: ty_var={:?}", ty_var); + + for predicate in bounds.predicates { + // Change the predicate to refer to the type variable, + // which will be the concrete type, instead of the Opaque. + // This also instantiates nested `impl Trait`. + let predicate = self.instantiate_opaque_types_in_map(&predicate); + + let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType); + + // Require that the predicate holds for the concrete type. + debug!("instantiate_opaque_types: predicate={:?}", predicate); + self.obligations + .push(traits::Obligation::new(cause, self.param_env, predicate)); + } + + ty_var + } +} + +/// Whether `opaque_node_id` is a sibling or a child of a sibling of `def_id` +/// +/// ```rust +/// pub mod foo { +/// pub mod bar { +/// pub existential type Baz; +/// +/// fn f1() -> Baz { .. } +/// } +/// +/// fn f2() -> bar::Baz { .. } +/// } +/// ``` +/// +/// Here, `def_id` will be the `DefId` of the existential type `Baz`. +/// `opaque_node_id` is the `NodeId` of the reference to Baz -- +/// so either the return type of f1 or f2. +/// We will return true if the reference is within the same module as the existential type +/// So true for f1, false for f2. +pub fn may_define_existential_type( + tcx: TyCtxt, + def_id: DefId, + opaque_node_id: ast::NodeId, +) -> bool { + let mut node_id = tcx + .hir + .as_local_node_id(def_id) + .unwrap(); + // named existential types can be defined by any siblings or + // children of siblings + let mod_id = tcx.hir.get_parent(opaque_node_id); + // so we walk up the node tree until we hit the root or the parent + // of the opaque type + while node_id != mod_id && node_id != ast::CRATE_NODE_ID { + node_id = tcx.hir.get_parent(node_id); + } + // syntactically we are allowed to define the concrete type + node_id == mod_id +} diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index c74783f5e4..817280b97e 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -151,12 +151,14 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { debug!("process_registered_region_obligations()"); // pull out the region obligations with the given `body_id` (leaving the rest) - let my_region_obligations = { + let mut my_region_obligations = Vec::with_capacity(self.region_obligations.borrow().len()); + { let mut r_o = self.region_obligations.borrow_mut(); - let my_r_o = r_o.drain_filter(|(ro_body_id, _)| *ro_body_id == body_id) - .map(|(_, obligation)| obligation).collect::>(); - my_r_o - }; + my_region_obligations.extend( + r_o.drain_filter(|(ro_body_id, _)| *ro_body_id == body_id) + .map(|(_, obligation)| obligation) + ); + } let outlives = &mut TypeOutlives::new( self, @@ -448,8 +450,8 @@ where fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> { match ty.sty { - ty::TyParam(p) => self.param_bound(p), - ty::TyProjection(data) => { + ty::Param(p) => self.param_bound(p), + ty::Projection(data) => { let declared_bounds = self.projection_declared_bounds(data); self.projection_bound(declared_bounds, data) } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 296808cea2..d8f3b9a05b 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -16,7 +16,7 @@ use self::CombineMapType::*; use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin}; use super::unify_key; -use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unify as ut; use ty::{self, Ty, TyCtxt}; diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index 77b722c569..be13fb9a2a 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -104,7 +104,7 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx> fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { let t = self.infcx.shallow_resolve(t); if t.has_infer_types() { - if let ty::TyInfer(_) = t.sty { + if let ty::Infer(_) = t.sty { // Since we called `shallow_resolve` above, this must // be an (as yet...) unresolved inference variable. true @@ -158,19 +158,19 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> } else { let t = self.infcx.shallow_resolve(t); match t.sty { - ty::TyInfer(ty::TyVar(vid)) => { + ty::Infer(ty::TyVar(vid)) => { self.err = Some(FixupError::UnresolvedTy(vid)); self.tcx().types.err } - ty::TyInfer(ty::IntVar(vid)) => { + ty::Infer(ty::IntVar(vid)) => { self.err = Some(FixupError::UnresolvedIntTy(vid)); self.tcx().types.err } - ty::TyInfer(ty::FloatVar(vid)) => { + ty::Infer(ty::FloatVar(vid)) => { self.err = Some(FixupError::UnresolvedFloatTy(vid)); self.tcx().types.err } - ty::TyInfer(_) => { + ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); } _ => { diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 58eae5e6a5..048810c042 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -80,7 +80,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> let a = infcx.type_variables.borrow_mut().replace_if_possible(a); let b = infcx.type_variables.borrow_mut().replace_if_possible(b); match (&a.sty, &b.sty) { - (&ty::TyInfer(TyVar(a_vid)), &ty::TyInfer(TyVar(b_vid))) => { + (&ty::Infer(TyVar(a_vid)), &ty::Infer(TyVar(b_vid))) => { // Shouldn't have any LBR here, so we can safely put // this under a binder below without fear of accidental // capture. @@ -106,17 +106,17 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> Ok(a) } - (&ty::TyInfer(TyVar(a_id)), _) => { + (&ty::Infer(TyVar(a_id)), _) => { self.fields .instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?; Ok(a) } - (_, &ty::TyInfer(TyVar(b_id))) => { + (_, &ty::Infer(TyVar(b_id))) => { self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?; Ok(a) } - (&ty::TyError, _) | (_, &ty::TyError) => { + (&ty::Error, _) | (_, &ty::Error) => { infcx.set_tainted_by_errors(); Ok(self.tcx().types.err) } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index d40e1b3760..b1e4fc7c7f 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -245,7 +245,7 @@ impl<'tcx> TypeVariableTable<'tcx> { /// instantiated. Otherwise, returns `t`. pub fn replace_if_possible(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { - ty::TyInfer(ty::TyVar(v)) => { + ty::Infer(ty::TyVar(v)) => { match self.probe(v) { TypeVariableValue::Unknown { .. } => t, TypeVariableValue::Known { value } => value, diff --git a/src/librustc/infer/unify_key.rs b/src/librustc/infer/unify_key.rs index a1145572b7..cdc92877a5 100644 --- a/src/librustc/infer/unify_key.rs +++ b/src/librustc/infer/unify_key.rs @@ -49,8 +49,8 @@ impl UnifyValue for RegionVidKey { impl UnifyKey for ty::RegionVid { type Value = RegionVidKey; - fn index(&self) -> u32 { self.0 } - fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid(i) } + fn index(&self) -> u32 { u32::from(*self) } + fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid::from(i) } fn tag() -> &'static str { "RegionVid" } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 8e71df3c34..2eaf1eebb3 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -42,23 +42,24 @@ #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![feature(core_intrinsics)] #![feature(drain_filter)] -#![feature(from_ref)] -#![feature(fs_read_write)] -#![feature(iterator_find_map)] #![cfg_attr(windows, feature(libc))] -#![feature(macro_vis_matcher)] +#![cfg_attr(stage0, feature(macro_vis_matcher))] #![feature(never_type)] #![feature(exhaustive_patterns)] #![feature(extern_types)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(non_exhaustive)] #![feature(proc_macro_internals)] #![feature(quote)] #![feature(optin_builtin_traits)] #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] +#![feature(rustc_attrs)] +#![cfg_attr(stage0, feature(attr_literals))] #![feature(slice_patterns)] #![feature(slice_sort_by_cached_key)] #![feature(specialization)] @@ -66,14 +67,14 @@ #![feature(trace_macros)] #![feature(trusted_len)] #![feature(vec_remove_item)] -#![feature(catch_expr)] #![feature(step_trait)] #![feature(integer_atomics)] #![feature(test)] +#![cfg_attr(not(stage0), feature(impl_header_lifetime_elision))] #![feature(in_band_lifetimes)] #![feature(macro_at_most_once_rep)] -#![feature(inclusive_range_methods)] -#![feature(crate_in_paths)] +#![cfg_attr(stage0, feature(crate_in_paths))] +#![feature(crate_visibility_modifier)] #![recursion_limit="512"] @@ -101,6 +102,7 @@ extern crate syntax_pos; extern crate jobserver; extern crate proc_macro; extern crate chalk_engine; +extern crate rustc_fs_util; extern crate serialize as rustc_serialize; // used by deriving @@ -108,6 +110,9 @@ extern crate rustc_apfloat; extern crate byteorder; extern crate backtrace; +#[macro_use] +extern crate smallvec; + // Note that librustc doesn't actually depend on these crates, see the note in // `Cargo.toml` for this crate about why these are here. #[allow(unused_extern_crates)] @@ -134,13 +139,13 @@ pub mod middle { pub mod borrowck; pub mod expr_use_visitor; pub mod cstore; - pub mod dataflow; pub mod dead; pub mod dependency_format; pub mod entry; pub mod exported_symbols; pub mod free_region; pub mod intrinsicck; + pub mod lib_features; pub mod lang_items; pub mod liveness; pub mod mem_categorization; @@ -163,8 +168,9 @@ pub mod util { pub mod common; pub mod ppaux; pub mod nodemap; - pub mod fs; pub mod time_graph; + pub mod profiling; + pub mod bug; } // A private module so that macro-expanded idents like diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 47f7c759d9..e6452ad092 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -18,7 +18,7 @@ use errors::{Applicability, DiagnosticBuilder}; use lint::{LintPass, LateLintPass, LintArray}; use session::Session; use syntax::ast; -use syntax::codemap::Span; +use syntax::source_map::Span; declare_lint! { pub EXCEEDING_BITSHIFTS, @@ -102,7 +102,7 @@ declare_lint! { declare_lint! { pub UNUSED_FEATURES, Warn, - "unused or unknown features found in crate-level #[feature] directives" + "unused features found in crate-level #[feature] directives" } declare_lint! { @@ -331,6 +331,13 @@ declare_lint! { via the module system" } +declare_lint! { + pub MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, + Deny, + "macro-expanded `macro_export` macros from the current crate \ + cannot be referred to by absolute paths" +} + /// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`. pub mod parser { declare_lint! { @@ -398,6 +405,7 @@ impl LintPass for HardwiredLints { WHERE_CLAUSES_OBJECT_SAFETY, PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, MACRO_USE_EXTERN_CRATE, + MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, parser::QUESTION_MARK_MACRO_SEP, ) } @@ -412,7 +420,9 @@ pub enum BuiltinLintDiagnostics { AbsPathWithModule(Span), DuplicatedMacroExports(ast::Ident, Span, Span), ProcMacroDeriveResolutionFallback(Span), + MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span, String), + UnknownCrateTypes(Span, String, String), } impl BuiltinLintDiagnostics { @@ -420,7 +430,7 @@ impl BuiltinLintDiagnostics { match self { BuiltinLintDiagnostics::Normal => (), BuiltinLintDiagnostics::BareTraitObject(span, is_global) => { - let (sugg, app) = match sess.codemap().span_to_snippet(span) { + let (sugg, app) = match sess.source_map().span_to_snippet(span) { Ok(ref s) if is_global => (format!("dyn ({})", s), Applicability::MachineApplicable), Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable), @@ -429,7 +439,7 @@ impl BuiltinLintDiagnostics { db.span_suggestion_with_applicability(span, "use `dyn`", sugg, app); } BuiltinLintDiagnostics::AbsPathWithModule(span) => { - let (sugg, app) = match sess.codemap().span_to_snippet(span) { + let (sugg, app) = match sess.source_map().span_to_snippet(span) { Ok(ref s) => { // FIXME(Manishearth) ideally the emitting code // can tell us whether or not this is global @@ -453,6 +463,9 @@ impl BuiltinLintDiagnostics { db.span_label(span, "names from parent modules are not \ accessible without an explicit import"); } + BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => { + db.span_note(span_def, "the macro is defined here"); + } BuiltinLintDiagnostics::ElidedLifetimesInPaths( n, path_span, incl_angl_brckt, insertion_span, anon_lts ) => { @@ -462,7 +475,7 @@ impl BuiltinLintDiagnostics { // When possible, prefer a suggestion that replaces the whole // `Path` expression with `Path<'_, T>`, rather than inserting `'_, ` // at a point (which makes for an ugly/confusing label) - if let Ok(snippet) = sess.codemap().span_to_snippet(path_span) { + if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) { // But our spans can get out of whack due to macros; if the place we think // we want to insert `'_` isn't even within the path expression's span, we // should bail out of making any suggestion rather than panicking on a @@ -488,6 +501,14 @@ impl BuiltinLintDiagnostics { Applicability::MachineApplicable ); } + BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { + db.span_suggestion_with_applicability( + span, + ¬e, + sugg, + Applicability::MaybeIncorrect + ); + } } } } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 14cfaa8153..e22792305a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -42,7 +42,7 @@ use util::nodemap::FxHashMap; use std::default::Default as StdDefault; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span}; +use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString}; use errors::DiagnosticBuilder; use hir; use hir::def_id::LOCAL_CRATE; @@ -67,9 +67,10 @@ pub struct LintStore { /// Lints indexed by name. by_name: FxHashMap, - /// Map of registered lint groups to what lints they expand to. The bool - /// is true if the lint group was added by a plugin. - lint_groups: FxHashMap<&'static str, (Vec, bool)>, + /// Map of registered lint groups to what lints they expand to. The first + /// bool is true if the lint group was added by a plugin. The optional string + /// is used to store the new names of deprecated lint group names. + lint_groups: FxHashMap<&'static str, (Vec, bool, Option<&'static str>)>, /// Extra info for future incompatibility lints, describing the /// issue or RFC that caused the incompatibility. @@ -133,6 +134,12 @@ pub enum CheckLintNameResult<'a> { /// The lint is either renamed or removed. This is the warning /// message, and an optional new name (`None` if removed). Warning(String, Option), + /// The lint is from a tool. If the Option is None, then either + /// the lint does not exist in the tool or the code was not + /// compiled with the tool and therefore the lint was never + /// added to the `LintStore`. Otherwise the `LintId` will be + /// returned as if it where a rustc lint. + Tool(Result<&'a [LintId], (Option<&'a [LintId]>, String)>), } impl LintStore { @@ -215,7 +222,7 @@ impl LintStore { let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id) .collect::>(); if !lints.is_empty() { - self.register_group(sess, false, edition.lint_name(), lints) + self.register_group(sess, false, edition.lint_name(), None, lints) } } @@ -225,19 +232,35 @@ impl LintStore { self.future_incompatible.insert(lint.id, lint); } - self.register_group(sess, false, "future_incompatible", future_incompatible); - - + self.register_group( + sess, + false, + "future_incompatible", + None, + future_incompatible, + ); } pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> { self.future_incompatible.get(&id) } - pub fn register_group(&mut self, sess: Option<&Session>, - from_plugin: bool, name: &'static str, - to: Vec) { - let new = self.lint_groups.insert(name, (to, from_plugin)).is_none(); + pub fn register_group( + &mut self, + sess: Option<&Session>, + from_plugin: bool, + name: &'static str, + deprecated_name: Option<&'static str>, + to: Vec, + ) { + let new = self + .lint_groups + .insert(name, (to, from_plugin, None)) + .is_none(); + if let Some(deprecated) = deprecated_name { + self.lint_groups + .insert(deprecated, (vec![], from_plugin, Some(name))); + } if !new { let msg = format!("duplicate specification of lint group {}", name); @@ -288,7 +311,7 @@ impl LintStore { sess: &Session, lint_name: &str, level: Level) { - let db = match self.check_lint_name(lint_name) { + let db = match self.check_lint_name(lint_name, None) { CheckLintNameResult::Ok(_) => None, CheckLintNameResult::Warning(ref msg, _) => { Some(sess.struct_warn(msg)) @@ -296,6 +319,15 @@ impl LintStore { CheckLintNameResult::NoLint => { Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) } + CheckLintNameResult::Tool(result) => match result { + Err((Some(_), new_name)) => Some(sess.struct_warn(&format!( + "lint name `{}` is deprecated \ + and does not have an effect anymore. \ + Use: {}", + lint_name, new_name + ))), + _ => None, + }, }; if let Some(mut db) = db { @@ -319,27 +351,87 @@ impl LintStore { /// it emits non-fatal warnings and there are *two* lint passes that /// inspect attributes, this is only run from the late pass to avoid /// printing duplicate warnings. - pub fn check_lint_name(&self, lint_name: &str) -> CheckLintNameResult { - match self.by_name.get(lint_name) { - Some(&Renamed(ref new_name, _)) => { - CheckLintNameResult::Warning( - format!("lint `{}` has been renamed to `{}`", lint_name, new_name), - Some(new_name.to_owned()) - ) - }, - Some(&Removed(ref reason)) => { - CheckLintNameResult::Warning( - format!("lint `{}` has been removed: `{}`", lint_name, reason), - None - ) + pub fn check_lint_name( + &self, + lint_name: &str, + tool_name: Option, + ) -> CheckLintNameResult { + let complete_name = if let Some(tool_name) = tool_name { + format!("{}::{}", tool_name, lint_name) + } else { + lint_name.to_string() + }; + // If the lint was scoped with `tool::` check if the tool lint exists + if let Some(_) = tool_name { + match self.by_name.get(&complete_name) { + None => match self.lint_groups.get(&*complete_name) { + None => return CheckLintNameResult::Tool(Err((None, String::new()))), + Some(ids) => return CheckLintNameResult::Tool(Ok(&ids.0)), + }, + Some(&Id(ref id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))), + // If the lint was registered as removed or renamed by the lint tool, we don't need + // to treat tool_lints and rustc lints different and can use the code below. + _ => {} + } + } + match self.by_name.get(&complete_name) { + Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning( + format!( + "lint `{}` has been renamed to `{}`", + complete_name, new_name + ), + Some(new_name.to_owned()), + ), + Some(&Removed(ref reason)) => CheckLintNameResult::Warning( + format!("lint `{}` has been removed: `{}`", complete_name, reason), + None, + ), + None => match self.lint_groups.get(&*complete_name) { + // If neither the lint, nor the lint group exists check if there is a `clippy::` + // variant of this lint + None => self.check_tool_name_for_backwards_compat(&complete_name, "clippy"), + Some(ids) => { + // Check if the lint group name is deprecated + if let Some(new_name) = ids.2 { + let lint_ids = self.lint_groups.get(new_name).unwrap(); + return CheckLintNameResult::Tool(Err(( + Some(&lint_ids.0), + new_name.to_string(), + ))); + } + CheckLintNameResult::Ok(&ids.0) + } }, - None => { - match self.lint_groups.get(lint_name) { - None => CheckLintNameResult::NoLint, - Some(ids) => CheckLintNameResult::Ok(&ids.0), + Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)), + } + } + + fn check_tool_name_for_backwards_compat( + &self, + lint_name: &str, + tool_name: &str, + ) -> CheckLintNameResult { + let complete_name = format!("{}::{}", tool_name, lint_name); + match self.by_name.get(&complete_name) { + None => match self.lint_groups.get(&*complete_name) { + // Now we are sure, that this lint exists nowhere + None => CheckLintNameResult::NoLint, + Some(ids) => { + // Reaching this would be weird, but lets cover this case anyway + if let Some(new_name) = ids.2 { + let lint_ids = self.lint_groups.get(new_name).unwrap(); + return CheckLintNameResult::Tool(Err(( + Some(&lint_ids.0), + new_name.to_string(), + ))); + } + CheckLintNameResult::Tool(Err((Some(&ids.0), complete_name))) } + }, + Some(&Id(ref id)) => { + CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name))) } - Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)), + _ => CheckLintNameResult::NoLint, } } } @@ -847,7 +939,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::walk_lifetime(self, lt); } - fn visit_path(&mut self, p: &'tcx hir::Path, id: ast::NodeId) { + fn visit_path(&mut self, p: &'tcx hir::Path, id: hir::HirId) { run_lints!(self, check_path, p, id); hir_visit::walk_path(self, p); } @@ -1024,7 +1116,14 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { self.check_id(id); } - fn visit_mac(&mut self, mac: &'ast ast::Mac) { + fn visit_mac(&mut self, mac: &'a ast::Mac) { + // FIXME(#54110): So, this setup isn't really right. I think + // that (a) the libsyntax visitor ought to be doing this as + // part of `walk_mac`, and (b) we should be calling + // `visit_path`, *but* that would require a `NodeId`, and I + // want to get #53686 fixed quickly. -nmatsakis + ast_visit::walk_path(self, &mac.node.path); + run_lints!(self, check_mac, mac); } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index b7b6aba970..336ebe79d3 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -21,7 +21,7 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, use session::Session; use syntax::ast; use syntax::attr; -use syntax::codemap::MultiSpan; +use syntax::source_map::MultiSpan; use syntax::feature_gate; use syntax::symbol::Symbol; use util::nodemap::FxHashMap; @@ -227,17 +227,19 @@ impl<'a> LintLevelsBuilder<'a> { continue } }; - if let Some(lint_tool) = word.is_scoped() { - if !self.sess.features_untracked().tool_lints { - feature_gate::emit_feature_err(&sess.parse_sess, - "tool_lints", - word.span, - feature_gate::GateIssue::Language, - &format!("scoped lint `{}` is experimental", - word.ident)); + let tool_name = if let Some(lint_tool) = word.is_scoped() { + let gate_feature = !self.sess.features_untracked().tool_lints; + let known_tool = attr::is_known_lint_tool(lint_tool); + if gate_feature { + feature_gate::emit_feature_err( + &sess.parse_sess, + "tool_lints", + word.span, + feature_gate::GateIssue::Language, + &format!("scoped lint `{}` is experimental", word.ident), + ); } - - if !attr::is_known_lint_tool(lint_tool) { + if !known_tool { span_err!( sess, lint_tool.span, @@ -247,10 +249,16 @@ impl<'a> LintLevelsBuilder<'a> { ); } - continue - } + if gate_feature || !known_tool { + continue; + } + + Some(lint_tool.as_str()) + } else { + None + }; let name = word.name(); - match store.check_lint_name(&name.as_str()) { + match store.check_lint_name(&name.as_str(), tool_name) { CheckLintNameResult::Ok(ids) => { let src = LintSource::Node(name, li.span); for id in ids { @@ -258,6 +266,55 @@ impl<'a> LintLevelsBuilder<'a> { } } + CheckLintNameResult::Tool(result) => { + match result { + Ok(ids) => { + let complete_name = &format!("{}::{}", tool_name.unwrap(), name); + let src = LintSource::Node(Symbol::intern(complete_name), li.span); + for id in ids { + specs.insert(*id, (level, src)); + } + } + Err((Some(ids), new_lint_name)) => { + let lint = builtin::RENAMED_AND_REMOVED_LINTS; + let (lvl, src) = + self.sets + .get_lint_level(lint, self.cur, Some(&specs), &sess); + let msg = format!( + "lint name `{}` is deprecated \ + and may not have an effect in the future. \ + Also `cfg_attr(cargo-clippy)` won't be necessary anymore", + name + ); + let mut err = lint::struct_lint_level( + self.sess, + lint, + lvl, + src, + Some(li.span.into()), + &msg, + ); + err.span_suggestion_with_applicability( + li.span, + "change it to", + new_lint_name.to_string(), + Applicability::MachineApplicable, + ).emit(); + + let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span); + for id in ids { + specs.insert(*id, (level, src)); + } + } + Err((None, _)) => { + // If Tool(Err(None, _)) is returned, then either the lint does not + // exist in the tool or the code was not compiled with the tool and + // therefore the lint was never added to the `LintStore`. To detect + // this is the responsibility of the lint tool. + } + } + } + _ if !self.warn_about_weird_lints => {} CheckLintNameResult::Warning(msg, renamed) => { @@ -298,7 +355,7 @@ impl<'a> LintLevelsBuilder<'a> { if name.as_str().chars().any(|c| c.is_uppercase()) { let name_lower = name.as_str().to_lowercase().to_string(); if let CheckLintNameResult::NoLint = - store.check_lint_name(&name_lower) { + store.check_lint_name(&name_lower, tool_name) { db.emit(); } else { db.span_suggestion_with_applicability( diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c1b205620..8d2851d1b7 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -42,7 +42,7 @@ use lint::builtin::parser::QUESTION_MARK_MACRO_SEP; use session::{Session, DiagnosticMessageId}; use std::{hash, ptr}; use syntax::ast; -use syntax::codemap::{MultiSpan, ExpnFormat}; +use syntax::source_map::{MultiSpan, ExpnFormat}; use syntax::early_buffered_lints::BufferedEarlyLintId; use syntax::edition::Edition; use syntax::symbol::Symbol; @@ -53,7 +53,7 @@ use ty::query::Providers; use util::nodemap::NodeMap; pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, - check_crate, check_ast_crate, + check_crate, check_ast_crate, CheckLintNameResult, FutureIncompatibleInfo, BufferedEarlyLint}; /// Specification of a single lint. @@ -139,6 +139,26 @@ macro_rules! declare_lint { ); } +#[macro_export] +macro_rules! declare_tool_lint { + ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => ( + declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false} + ); + ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, + report_in_external_macro: $rep: expr) => ( + declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep} + ); + ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => ( + $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint { + name: &concat!(stringify!($tool), "::", stringify!($NAME)), + default_level: $crate::lint::$Level, + desc: $desc, + edition_lint_opts: None, + report_in_external_macro: $external, + }; + ); +} + /// Declare a static `LintArray` and return it as an expression. #[macro_export] macro_rules! lint_array { @@ -222,7 +242,7 @@ macro_rules! late_lint_methods { fn check_variant(a: &$hir hir::Variant, b: &$hir hir::Generics); fn check_variant_post(a: &$hir hir::Variant, b: &$hir hir::Generics); fn check_lifetime(a: &$hir hir::Lifetime); - fn check_path(a: &$hir hir::Path, b: ast::NodeId); + fn check_path(a: &$hir hir::Path, b: hir::HirId); fn check_attribute(a: &$hir ast::Attribute); /// Called when entering a syntax node that can have lint attributes such @@ -246,7 +266,7 @@ macro_rules! late_lint_methods { macro_rules! expand_lint_pass_methods { ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(#[inline(always)] fn $name(&mut self, $context, $(_: $arg),*) {})* + $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})* ) } @@ -492,7 +512,7 @@ impl LintBuffer { msg: msg.to_string(), diagnostic }; - let arr = self.map.entry(id).or_insert(Vec::new()); + let arr = self.map.entry(id).or_default(); if !arr.contains(&early_lint) { arr.push(early_lint); } @@ -575,7 +595,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session, // Check for future incompatibility lints and issue a stronger warning. let lints = sess.lint_store.borrow(); let lint_id = LintId::of(lint); - if let Some(future_incompatible) = lints.future_incompatible(lint_id) { + let future_incompatible = lints.future_incompatible(lint_id); + if let Some(future_incompatible) = future_incompatible { const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ it will become a hard error"; @@ -593,20 +614,21 @@ pub fn struct_lint_level<'a>(sess: &'a Session, future_incompatible.reference); err.warn(&explanation); err.note(&citation); + } - // If this lint is *not* a future incompatibility warning then we want to be - // sure to not be too noisy in some situations. If this code originates in a - // foreign macro, aka something that this crate did not itself author, then - // it's likely that there's nothing this crate can do about it. We probably - // want to skip the lint entirely. - // - // For some lints though (like unreachable code) there's clear actionable - // items to take care of (delete the macro invocation). As a result we have - // a few lints we whitelist here for allowing a lint even though it's in a - // foreign macro invocation. - } else if !lint.report_in_external_macro { - if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { - err.cancel(); + // If this code originates in a foreign macro, aka something that this crate + // did not itself author, then it's likely that there's nothing this crate + // can do about it. We probably want to skip the lint entirely. + if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { + // Any suggestions made here are likely to be incorrect, so anything we + // emit shouldn't be automatically fixed by rustfix. + err.allow_suggestions(false); + + // If this is a future incompatible lint it'll become a hard error, so + // we have to emit *something*. Also allow lints to whitelist themselves + // on a case-by-case basis for emission in a foreign macro. + if future_incompatible.is_none() && !lint.report_in_external_macro { + err.cancel() } } @@ -732,7 +754,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { None => return true, }; - match sess.codemap().span_to_snippet(def_site) { + match sess.source_map().span_to_snippet(def_site) { Ok(code) => !code.starts_with("macro_rules"), // no snippet = external macro or compiler-builtin expansion Err(_) => true, diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index 0bf1f4decc..759ac1a795 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -51,14 +51,14 @@ macro_rules! enum_from_u32 { macro_rules! bug { () => ( bug!("impossible case reached") ); ($($message:tt)*) => ({ - $crate::session::bug_fmt(file!(), line!(), format_args!($($message)*)) + $crate::util::bug::bug_fmt(file!(), line!(), format_args!($($message)*)) }) } #[macro_export] macro_rules! span_bug { ($span:expr, $($message:tt)*) => ({ - $crate::session::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*)) + $crate::util::bug::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*)) }) } @@ -147,7 +147,7 @@ macro_rules! impl_stable_hash_for { macro_rules! impl_stable_hash_for_spanned { ($T:path) => ( - impl<'a, 'tcx> HashStable> for ::syntax::codemap::Spanned<$T> + impl<'a, 'tcx> HashStable> for ::syntax::source_map::Spanned<$T> { #[inline] fn hash_stable(&self, diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 54169acac4..f4b4404338 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -22,11 +22,10 @@ //! are *mostly* used as a part of that interface, but these should //! probably get a better home if someone can find one. -use hir::def; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as hir_map; -use hir::map::definitions::{Definitions, DefKey, DefPathTable}; -use hir::svh::Svh; +use hir::map::definitions::{DefKey, DefPathTable}; +use rustc_data_structures::svh::Svh; use ty::{self, TyCtxt}; use session::{Session, CrateDisambiguator}; use session::search_paths::PathKind; @@ -34,8 +33,6 @@ use session::search_paths::PathKind; use std::any::Any; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::edition::Edition; -use syntax::ext::base::SyntaxExtension; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_target::spec::Target; @@ -45,11 +42,6 @@ pub use self::NativeLibraryKind::*; // lonely orphan structs and enums looking for a better home -#[derive(Clone, Debug, Copy)] -pub struct LinkMeta { - pub crate_hash: Svh, -} - /// Where a crate came from on the local filesystem. One of these three options /// must be non-None. #[derive(PartialEq, Clone, Debug)] @@ -140,11 +132,6 @@ pub struct ForeignModule { pub def_id: DefId, } -pub enum LoadedMacro { - MacroDef(ast::Item), - ProcMacro(Lrc), -} - #[derive(Copy, Clone, Debug)] pub struct ExternCrate { pub src: ExternCrateSource, @@ -221,9 +208,6 @@ pub trait MetadataLoader { pub trait CrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc; - // access to the metadata loader - fn metadata_loader(&self) -> &dyn MetadataLoader; - // resolve fn def_key(&self, def: DefId) -> DefKey; fn def_path(&self, def: DefId) -> hir_map::DefPath; @@ -231,19 +215,11 @@ pub trait CrateStore { fn def_path_table(&self, cnum: CrateNum) -> Lrc; // "queries" used in resolve that aren't tracked for incremental compilation - fn visibility_untracked(&self, def: DefId) -> ty::Visibility; - fn export_macros_untracked(&self, cnum: CrateNum); - fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind; fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator; fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; - fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition; - fn struct_field_names_untracked(&self, def: DefId) -> Vec; - fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec; - fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro; fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option; fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics; - fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem; fn postorder_cnums_untracked(&self) -> Vec; // This is basically a 1-based range of ints, which is a little @@ -252,124 +228,13 @@ pub trait CrateStore { // utility functions fn encode_metadata<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta) + tcx: TyCtxt<'a, 'tcx, 'tcx>) -> EncodedMetadata; fn metadata_encoding_version(&self) -> &[u8]; } pub type CrateStoreDyn = dyn CrateStore + sync::Sync; -// FIXME: find a better place for this? -pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { - let mut err_count = 0; - { - let mut say = |s: &str| { - match (sp, sess) { - (_, None) => bug!("{}", s), - (Some(sp), Some(sess)) => sess.span_err(sp, s), - (None, Some(sess)) => sess.err(s), - } - err_count += 1; - }; - if s.is_empty() { - say("crate name must not be empty"); - } - for c in s.chars() { - if c.is_alphanumeric() { continue } - if c == '_' { continue } - say(&format!("invalid character `{}` in crate name: `{}`", c, s)); - } - } - - if err_count > 0 { - sess.unwrap().abort_if_errors(); - } -} - -/// A dummy crate store that does not support any non-local crates, -/// for test purposes. -pub struct DummyCrateStore; - -#[allow(unused_variables)] -impl CrateStore for DummyCrateStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc - { bug!("crate_data_as_rc_any") } - // item info - fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") } - fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics - { bug!("item_generics_cloned") } - - // trait/impl-item info - fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem - { bug!("associated_item_cloned") } - - // crate metadata - fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") } - fn export_macros_untracked(&self, cnum: CrateNum) { bug!("export_macros") } - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") } - fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator { - bug!("crate_disambiguator") - } - fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") } - fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { bug!("crate_edition_untracked") } - - // resolve - fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") } - fn def_path(&self, def: DefId) -> hir_map::DefPath { - bug!("relative_def_path") - } - fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash { - bug!("def_path_hash") - } - fn def_path_table(&self, cnum: CrateNum) -> Lrc { - bug!("def_path_table") - } - fn struct_field_names_untracked(&self, def: DefId) -> Vec { - bug!("struct_field_names") - } - fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec { - bug!("item_children") - } - fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } - - fn crates_untracked(&self) -> Vec { vec![] } - - // utility functions - fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option { None } - fn encode_metadata<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta) - -> EncodedMetadata { - bug!("encode_metadata") - } - fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } - fn postorder_cnums_untracked(&self) -> Vec { bug!("postorder_cnums_untracked") } - - // access to the metadata loader - fn metadata_loader(&self) -> &dyn MetadataLoader { bug!("metadata_loader") } -} - -pub trait CrateLoader { - fn process_extern_crate(&mut self, item: &ast::Item, defs: &Definitions) -> CrateNum; - - fn process_path_extern( - &mut self, - name: Symbol, - span: Span, - ) -> CrateNum; - - fn process_use_extern( - &mut self, - name: Symbol, - span: Span, - id: ast::NodeId, - defs: &Definitions, - ) -> CrateNum; - - fn postprocess(&mut self, krate: &ast::Crate); -} - // This method is used when generating the command line to pass through to // system linker. The linker expects undefined symbols on the left of the // command line to be defined in libraries on the right, not the other way diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index e4fc1b09fc..d320173f9f 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -12,7 +12,7 @@ // closely. The idea is that all reachable symbols are live, codes called // from live codes are live, and everything else is dead. -use hir::map as hir_map; +use hir::Node; use hir::{self, PatKind}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::itemlikevisit::ItemLikeVisitor; @@ -24,21 +24,21 @@ use middle::privacy; use ty::{self, TyCtxt}; use util::nodemap::FxHashSet; -use syntax::{ast, codemap}; +use syntax::{ast, source_map}; use syntax::attr; use syntax_pos; // Any local node that may call something in its body block should be -// explored. For example, if it's a live NodeItem that is a +// explored. For example, if it's a live Node::Item that is a // function, then we should explore its block to check for codes that // may need to be marked as live. fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) -> bool { match tcx.hir.find(node_id) { - Some(hir_map::NodeItem(..)) | - Some(hir_map::NodeImplItem(..)) | - Some(hir_map::NodeForeignItem(..)) | - Some(hir_map::NodeTraitItem(..)) => + Some(Node::Item(..)) | + Some(Node::ImplItem(..)) | + Some(Node::ForeignItem(..)) | + Some(Node::TraitItem(..)) => true, _ => false @@ -105,19 +105,19 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_access(&mut self, lhs: &hir::Expr, node_id: ast::NodeId) { match self.tables.expr_ty_adjusted(lhs).sty { - ty::TyAdt(def, _) => { + ty::Adt(def, _) => { let index = self.tcx.field_index(node_id, self.tables); self.insert_def_id(def.non_enum_variant().fields[index].did); } - ty::TyTuple(..) => {} + ty::Tuple(..) => {} _ => span_bug!(lhs.span, "named field access on non-ADT"), } } fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def, - pats: &[codemap::Spanned]) { + pats: &[source_map::Spanned]) { let variant = match self.tables.node_id_to_type(lhs.hir_id).sty { - ty::TyAdt(adt, _) => adt.variant_of_def(def), + ty::Adt(adt, _) => adt.variant_of_def(def), _ => span_bug!(lhs.span, "non-ADT in struct pattern") }; for pat in pats { @@ -145,13 +145,13 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } } - fn visit_node(&mut self, node: &hir_map::Node<'tcx>) { + fn visit_node(&mut self, node: &Node<'tcx>) { let had_repr_c = self.repr_has_repr_c; self.repr_has_repr_c = false; let had_inherited_pub_visibility = self.inherited_pub_visibility; self.inherited_pub_visibility = false; match *node { - hir_map::NodeItem(item) => { + Node::Item(item) => { match item.node { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { let def_id = self.tcx.hir.local_def_id(item.id); @@ -173,13 +173,13 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { _ => () } } - hir_map::NodeTraitItem(trait_item) => { + Node::TraitItem(trait_item) => { intravisit::walk_trait_item(self, trait_item); } - hir_map::NodeImplItem(impl_item) => { + Node::ImplItem(impl_item) => { intravisit::walk_impl_item(self, impl_item); } - hir_map::NodeForeignItem(foreign_item) => { + Node::ForeignItem(foreign_item) => { intravisit::walk_foreign_item(self, &foreign_item); } _ => () @@ -236,7 +236,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_field_access(&lhs, expr.id); } hir::ExprKind::Struct(_, ref fields, _) => { - if let ty::TypeVariants::TyAdt(ref adt, _) = self.tables.expr_ty(expr).sty { + if let ty::Adt(ref adt, _) = self.tables.expr_ty(expr).sty { self.mark_as_used_if_union(adt, fields); } } @@ -279,7 +279,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.in_pat = false; } - fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) { + fn visit_path(&mut self, path: &'tcx hir::Path, _: hir::HirId) { self.handle_definition(path.def); intravisit::walk_path(self, path); } @@ -293,7 +293,9 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt, } // (To be) stable attribute for #[lang = "panic_impl"] - if attr::contains_name(attrs, "panic_implementation") { + if attr::contains_name(attrs, "panic_implementation") || + attr::contains_name(attrs, "panic_handler") + { return true; } @@ -551,15 +553,19 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Trait(..) | - hir::ItemKind::Impl(..) => self.tcx.sess.codemap().def_span(item.span), + hir::ItemKind::Impl(..) => self.tcx.sess.source_map().def_span(item.span), _ => item.span, }; + let participle = match item.node { + hir::ItemKind::Struct(..) => "constructed", // Issue #52325 + _ => "used" + }; self.warn_dead_code( item.id, span, item.name, item.node.descriptive_variant(), - "used", + participle, ); } else { // Only continue if we didn't warn @@ -608,7 +614,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { } hir::ImplItemKind::Method(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { - let span = self.tcx.sess.codemap().def_span(impl_item.span); + let span = self.tcx.sess.source_map().def_span(impl_item.span); self.warn_dead_code(impl_item.id, span, impl_item.ident.name, "method", "used"); } self.visit_nested_body(body_id) diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 4c99b46ddf..a9c118d606 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -115,30 +115,30 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let preferred_linkage = match ty { // cdylibs must have all static dependencies. - config::CrateTypeCdylib => Linkage::Static, + config::CrateType::Cdylib => Linkage::Static, // Generating a dylib without `-C prefer-dynamic` means that we're going // to try to eagerly statically link all dependencies. This is normally // done for end-product dylibs, not intermediate products. - config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => Linkage::Static, - config::CrateTypeDylib => Linkage::Dynamic, + config::CrateType::Dylib if !sess.opts.cg.prefer_dynamic => Linkage::Static, + config::CrateType::Dylib => Linkage::Dynamic, // If the global prefer_dynamic switch is turned off, or the final // executable will be statically linked, prefer static crate linkage. - config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic || + config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static() => Linkage::Static, - config::CrateTypeExecutable => Linkage::Dynamic, + config::CrateType::Executable => Linkage::Dynamic, // proc-macro crates are required to be dylibs, and they're currently // required to link to libsyntax as well. - config::CrateTypeProcMacro => Linkage::Dynamic, + config::CrateType::ProcMacro => Linkage::Dynamic, // No linkage happens with rlibs, we just needed the metadata (which we // got long ago), so don't bother with anything. - config::CrateTypeRlib => Linkage::NotLinked, + config::CrateType::Rlib => Linkage::NotLinked, // staticlibs must have all static dependencies. - config::CrateTypeStaticlib => Linkage::Static, + config::CrateType::Staticlib => Linkage::Static, }; if preferred_linkage == Linkage::NotLinked { @@ -155,8 +155,8 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Staticlibs, cdylibs, and static executables must have all static // dependencies. If any are not found, generate some nice pretty errors. - if ty == config::CrateTypeCdylib || ty == config::CrateTypeStaticlib || - (ty == config::CrateTypeExecutable && sess.crt_static() && + if ty == config::CrateType::Cdylib || ty == config::CrateType::Staticlib || + (ty == config::CrateType::Executable && sess.crt_static() && !sess.target.target.options.crt_static_allows_dylibs) { for &cnum in tcx.crates().iter() { if tcx.dep_kind(cnum).macros_only() { continue } diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index feeb508d67..b0acc6f20e 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -12,6 +12,7 @@ use hir::map as hir_map; use hir::def_id::{CRATE_DEF_INDEX}; use session::{config, Session}; +use session::config::EntryFnType; use syntax::ast::NodeId; use syntax::attr; use syntax::entry::EntryPointType; @@ -59,7 +60,7 @@ pub fn find_entry_point(session: &Session, hir_map: &hir_map::Map, crate_name: &str) { let any_exe = session.crate_types.borrow().iter().any(|ty| { - *ty == config::CrateTypeExecutable + *ty == config::CrateType::Executable }); if !any_exe { // No need to find a main function @@ -155,11 +156,11 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) { fn configure_main(this: &mut EntryContext, crate_name: &str) { if let Some((node_id, span)) = this.start_fn { - this.session.entry_fn.set(Some((node_id, span, config::EntryStart))); + this.session.entry_fn.set(Some((node_id, span, EntryFnType::Start))); } else if let Some((node_id, span)) = this.attr_main_fn { - this.session.entry_fn.set(Some((node_id, span, config::EntryMain))); + this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main))); } else if let Some((node_id, span)) = this.main_fn { - this.session.entry_fn.set(Some((node_id, span, config::EntryMain))); + this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main))); } else { // No main function this.session.entry_fn.set(None); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 5beafe2b60..469ae04c0f 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -317,7 +317,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("consume_body: arg_ty = {:?}", arg_ty); let fn_body_scope_r = - self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id))); + self.tcx().mk_region(ty::ReScope( + region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Node + })); let arg_cmt = Rc::new(self.mc.cat_rvalue( arg.hir_id, arg.pat.span, @@ -457,7 +461,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: let expr_ty = return_if_err!(self.mc.expr_ty(expr)); - if let ty::TyRef(r, _, _) = expr_ty.sty { + if let ty::Ref(r, _, _) = expr_ty.sty { let bk = ty::BorrowKind::from_mutbl(m); self.borrow_expr(&base, r, bk, AddrOf); } @@ -551,14 +555,17 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("walk_callee: callee={:?} callee_ty={:?}", callee, callee_ty); match callee_ty.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { self.consume_expr(callee); } - ty::TyError => { } + ty::Error => { } _ => { if let Some(def) = self.mc.tables.type_dependent_defs().get(call.hir_id) { let def_id = def.def_id(); - let call_scope = region::Scope::Node(call.hir_id.local_id); + let call_scope = region::Scope { + id: call.hir_id.local_id, + data: region::ScopeData::Node + }; match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope)); @@ -659,7 +666,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // Select just those fields of the `with` // expression that will actually be used match with_cmt.ty.sty { - ty::TyAdt(adt, substs) if adt.is_struct() => { + ty::Adt(adt, substs) if adt.is_struct() => { // Consume those fields of the with expression that are needed. for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() { let is_mentioned = fields.iter().any(|f| { @@ -766,7 +773,10 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // treated as borrowing it for the enclosing temporary // scope. let r = self.tcx().mk_region(ty::ReScope( - region::Scope::Node(expr.hir_id.local_id))); + region::Scope { + id: expr.hir_id.local_id, + data: region::ScopeData::Node + })); self.delegate.borrow(expr.id, expr.span, @@ -792,7 +802,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } if let Some(ref guard) = arm.guard { - self.consume_expr(&guard); + match guard { + hir::Guard::If(ref e) => self.consume_expr(e), + } } self.consume_expr(&arm.body); @@ -867,7 +879,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // It is also a borrow or copy/move of the value being matched. match bm { ty::BindByReference(m) => { - if let ty::TyRef(r, _, _) = pat_ty.sty { + if let ty::Ref(r, _, _) = pat_ty.sty { let bk = ty::BorrowKind::from_mutbl(m); delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding); } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 8e4fb547d4..8058f3dde6 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -41,7 +41,7 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { let (def, substs) = match ty.sty { - ty::TyAdt(def, substs) => (def, substs), + ty::Adt(def, substs) => (def, substs), _ => return ty }; @@ -83,7 +83,7 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { // Special-case transmutting from `typeof(function)` and // `Option` to present a clearer error. let from = unpack_option_like(self.tcx.global_tcx(), from); - if let (&ty::TyFnDef(..), SizeSkeleton::Known(size_to)) = (&from.sty, sk_to) { + if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (&from.sty, sk_to) { if size_to == Pointer.size(self.tcx) { struct_span_err!(self.tcx.sess, span, E0591, "can't transmute zero-sized type") diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index cf94a0fb4b..bfde4e4a3a 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -185,7 +185,9 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { if let Some(value) = attribute.value_str() { return Some((value, attribute.span)); } - } else if attribute.check_name("panic_implementation") { + } else if attribute.check_name("panic_implementation") || + attribute.check_name("panic_handler") + { return Some((Symbol::intern("panic_impl"), attribute.span)) } else if attribute.check_name("alloc_error_handler") { return Some((Symbol::intern("oom"), attribute.span)) @@ -305,6 +307,8 @@ language_item_table! { PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn; PanicInfoLangItem, "panic_info", panic_info; PanicImplLangItem, "panic_impl", panic_impl; + // Libstd panic entry point. Necessary for const eval to be able to catch it + BeginPanicFnLangItem, "begin_panic", begin_panic_fn; ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; BoxFreeFnLangItem, "box_free", box_free_fn; @@ -322,8 +326,6 @@ language_item_table! { PhantomDataItem, "phantom_data", phantom_data; - NonZeroItem, "non_zero", non_zero; - ManuallyDropItem, "manually_drop", manually_drop; DebugTraitLangItem, "debug_trait", debug_trait; diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs new file mode 100644 index 0000000000..ec618de677 --- /dev/null +++ b/src/librustc/middle/lib_features.rs @@ -0,0 +1,157 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Detecting lib features (i.e. features that are not lang features). +// +// These are declared using stability attributes (e.g. `#[stable (..)]` +// and `#[unstable (..)]`), but are not declared in one single location +// (unlike lang features), which means we need to collect them instead. + +use ty::TyCtxt; +use syntax::symbol::Symbol; +use syntax::ast::{Attribute, MetaItem, MetaItemKind}; +use syntax_pos::Span; +use hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use errors::DiagnosticId; + +pub struct LibFeatures { + // A map from feature to stabilisation version. + pub stable: FxHashMap, + pub unstable: FxHashSet, +} + +impl LibFeatures { + fn new() -> LibFeatures { + LibFeatures { + stable: FxHashMap(), + unstable: FxHashSet(), + } + } + + pub fn to_vec(&self) -> Vec<(Symbol, Option)> { + let mut all_features: Vec<_> = self.stable.iter().map(|(f, s)| (*f, Some(*s))) + .chain(self.unstable.iter().map(|f| (*f, None))) + .collect(); + all_features.sort_unstable_by_key(|f| f.0.as_str()); + all_features + } +} + +pub struct LibFeatureCollector<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + lib_features: LibFeatures, +} + +impl<'a, 'tcx> LibFeatureCollector<'a, 'tcx> { + fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LibFeatureCollector<'a, 'tcx> { + LibFeatureCollector { + tcx, + lib_features: LibFeatures::new(), + } + } + + fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option, Span)> { + let stab_attrs = vec!["stable", "unstable", "rustc_const_unstable"]; + + // Find a stability attribute (i.e. `#[stable (..)]`, `#[unstable (..)]`, + // `#[rustc_const_unstable (..)]`). + if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| { + attr.check_name(stab_attr) + }) { + let meta_item = attr.meta(); + if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta_item { + let mut feature = None; + let mut since = None; + for meta in metas { + if let Some(mi) = meta.meta_item() { + // Find the `feature = ".."` meta-item. + match (&*mi.name().as_str(), mi.value_str()) { + ("feature", val) => feature = val, + ("since", val) => since = val, + _ => {} + } + } + } + if let Some(feature) = feature { + // This additional check for stability is to make sure we + // don't emit additional, irrelevant errors for malformed + // attributes. + if *stab_attr != "stable" || since.is_some() { + return Some((feature, since, attr.span)); + } + } + // We need to iterate over the other attributes, because + // `rustc_const_unstable` is not mutually exclusive with + // the other stability attributes, so we can't just `break` + // here. + } + } + + None + } + + fn collect_feature(&mut self, feature: Symbol, since: Option, span: Span) { + let already_in_stable = self.lib_features.stable.contains_key(&feature); + let already_in_unstable = self.lib_features.unstable.contains(&feature); + + match (since, already_in_stable, already_in_unstable) { + (Some(since), _, false) => { + if let Some(prev_since) = self.lib_features.stable.get(&feature) { + if *prev_since != since { + let msg = format!( + "feature `{}` is declared stable since {}, \ + but was previously declared stable since {}", + feature, + since, + prev_since, + ); + self.tcx.sess.struct_span_err_with_code(span, &msg, + DiagnosticId::Error("E0711".into())).emit(); + return; + } + } + + self.lib_features.stable.insert(feature, since); + } + (None, false, _) => { + self.lib_features.unstable.insert(feature); + } + (Some(_), _, true) | (None, true, _) => { + let msg = format!( + "feature `{}` is declared {}, but was previously declared {}", + feature, + if since.is_some() { "stable"} else { "unstable" }, + if since.is_none() { "stable"} else { "unstable" }, + ); + self.tcx.sess.struct_span_err_with_code(span, &msg, + DiagnosticId::Error("E0711".into())).emit(); + } + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for LibFeatureCollector<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::All(&self.tcx.hir) + } + + fn visit_attribute(&mut self, attr: &'tcx Attribute) { + if let Some((feature, stable, span)) = self.extract(attr) { + self.collect_feature(feature, stable, span); + } + } +} + +pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LibFeatures { + let mut collector = LibFeatureCollector::new(tcx); + intravisit::walk_crate(&mut collector, tcx.hir.krate()); + collector.lib_features +} diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b828b1bd30..c34a0a654e 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -102,11 +102,13 @@ //! only dead if the end of the function's block can never be reached. //! It is the responsibility of typeck to ensure that there are no //! `return` expressions in a function declared as diverging. + use self::LoopKind::*; use self::LiveNodeKind::*; use self::VarKind::*; use hir::def::*; +use hir::Node; use ty::{self, TyCtxt}; use lint; use errors::Applicability; @@ -157,7 +159,7 @@ enum LiveNodeKind { } fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt) -> String { - let cm = tcx.sess.codemap(); + let cm = tcx.sess.source_map(); match lnk { FreeVarNode(s) => { format!("Free var node [{}]", cm.span_to_string(s)) @@ -362,7 +364,7 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // Don't run unused pass for #[derive()] if let FnKind::Method(..) = fk { let parent = ir.tcx.hir.get_parent(id); - if let Some(hir::map::Node::NodeItem(i)) = ir.tcx.hir.find(parent) { + if let Some(Node::Item(i)) = ir.tcx.hir.find(parent) { if i.attrs.iter().any(|a| a.check_name("automatically_derived")) { return; } @@ -1028,7 +1030,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let body_succ = self.propagate_through_expr(&arm.body, succ); let guard_succ = - self.propagate_through_opt_expr(arm.guard.as_ref().map(|e| &**e), body_succ); + self.propagate_through_opt_expr( + arm.guard.as_ref().map(|g| + match g { + hir::Guard::If(e) => &**e, + }), + body_succ); // only consider the first pattern; any later patterns must have // the same bindings, and we also consider the first pattern to be // the "authoritative" set of ids diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 8feefdf5a1..1725114747 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -70,7 +70,7 @@ use self::Aliasability::*; use middle::region; use hir::def_id::{DefId, LocalDefId}; -use hir::map as hir_map; +use hir::Node; use infer::InferCtxt; use hir::def::{Def, CtorKind}; use ty::adjustment; @@ -214,8 +214,8 @@ impl<'tcx> cmt_<'tcx> { fn resolve_field(&self, field_index: usize) -> Option<(&'tcx ty::AdtDef, &'tcx ty::FieldDef)> { let adt_def = match self.ty.sty { - ty::TyAdt(def, _) => def, - ty::TyTuple(..) => return None, + ty::Adt(def, _) => def, + ty::Tuple(..) => return None, // closures get `Categorization::Upvar` rather than `Categorization::Interior` _ => bug!("interior cmt {:?} is not an ADT", self) }; @@ -343,7 +343,7 @@ impl MutabilityCategory { fn from_local(tcx: TyCtxt, tables: &ty::TypeckTables, id: ast::NodeId) -> MutabilityCategory { let ret = match tcx.hir.get(id) { - hir_map::NodeBinding(p) => match p.node { + Node::Binding(p) => match p.node { PatKind::Binding(..) => { let bm = *tables.pat_binding_modes() .get(p.hir_id) @@ -708,7 +708,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { match def { Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | - Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => { + Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => { Ok(self.cat_rvalue_node(hir_id, span, expr_ty)) } @@ -783,8 +783,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // FnOnce | copied | upvar -> &'up bk let kind = match self.node_ty(fn_hir_id)?.sty { - ty::TyGenerator(..) => ty::ClosureKind::FnOnce, - ty::TyClosure(closure_def_id, closure_substs) => { + ty::Generator(..) => ty::ClosureKind::FnOnce, + ty::Closure(closure_def_id, closure_substs) => { match self.infcx { // During upvar inference we may not know the // closure kind, just use the LATTICE_BOTTOM value. @@ -893,7 +893,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // that the above is actually immutable and // has a ref type. However, nothing should // actually look at the type, so we can get - // away with stuffing a `TyError` in there + // away with stuffing a `Error` in there // instead of bothering to construct a proper // one. let cmt_result = cmt_ { @@ -956,7 +956,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // Always promote `[T; 0]` (even when e.g. borrowed mutably). let promotable = match expr_ty.sty { - ty::TyArray(_, len) if len.assert_usize(self.tcx) == Some(0) => true, + ty::Array(_, len) if len.assert_usize(self.tcx) == Some(0) => true, _ => promotable, }; @@ -1035,7 +1035,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let base_ty = self.expr_ty_adjusted(base)?; let (region, mutbl) = match base_ty.sty { - ty::TyRef(region, _, mutbl) => (region, mutbl), + ty::Ref(region, _, mutbl) => (region, mutbl), _ => { span_bug!(expr.span, "cat_overloaded_place: base is not a reference") } @@ -1068,9 +1068,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { }; let ptr = match base_cmt.ty.sty { - ty::TyAdt(def, ..) if def.is_box() => Unique, - ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl), - ty::TyRef(r, _, mutbl) => { + ty::Adt(def, ..) if def.is_box() => Unique, + ty::RawPtr(ref mt) => UnsafePtr(mt.mutbl), + ty::Ref(r, _, mutbl) => { let bk = ty::BorrowKind::from_mutbl(mutbl); BorrowedPtr(bk, r) } @@ -1288,9 +1288,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { (self.cat_downcast_if_needed(pat, cmt, def_id), self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()) } - Def::StructCtor(_, CtorKind::Fn) => { + Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => { match self.pat_ty_unadjusted(&pat)?.sty { - ty::TyAdt(adt_def, _) => { + ty::Adt(adt_def, _) => { (cmt, adt_def.non_enum_variant().fields.len()) } ref ty => { @@ -1343,7 +1343,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { PatKind::Tuple(ref subpats, ddpos) => { // (p1, ..., pN) let expected_len = match self.pat_ty_unadjusted(&pat)?.sty { - ty::TyTuple(ref tys) => tys.len(), + ty::Tuple(ref tys) => tys.len(), ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), }; for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index e2de0b6bd0..70fed9af92 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -21,6 +21,8 @@ use syntax::ast::NodeId; // Accessibility levels, sorted in ascending order #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum AccessLevel { + // Superset of Reachable used to mark impl Trait items. + ReachableFromImplTrait, // Exported items + items participating in various kinds of public interfaces, // but not directly nameable. For example, if function `fn f() -> T {...}` is // public, then type `T` is reachable. Its values can be obtained by other crates @@ -40,7 +42,7 @@ pub struct AccessLevels { impl AccessLevels { pub fn is_reachable(&self, id: Id) -> bool { - self.map.contains_key(&id) + self.map.get(&id) >= Some(&AccessLevel::Reachable) } pub fn is_exported(&self, id: Id) -> bool { self.map.get(&id) >= Some(&AccessLevel::Exported) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 19c82d7d27..55ee8987e8 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -15,12 +15,12 @@ // makes all other generics or inline functions that it references // reachable as well. -use hir::CodegenFnAttrs; -use hir::map as hir_map; +use hir::{CodegenFnAttrs, CodegenFnAttrFlags}; +use hir::Node; use hir::def::Def; use hir::def_id::{DefId, CrateNum}; use rustc_data_structures::sync::Lrc; -use ty::{self, TyCtxt, GenericParamDefKind}; +use ty::{self, TyCtxt}; use ty::query::Providers; use middle::privacy; use session::config; @@ -28,25 +28,12 @@ use util::nodemap::{NodeSet, FxHashSet}; use rustc_target::spec::abi::Abi; use syntax::ast; -use syntax::attr; use hir; use hir::def_id::LOCAL_CRATE; use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::itemlikevisit::ItemLikeVisitor; use hir::intravisit; -// Returns true if the given set of generics implies that the item it's -// associated with must be inlined. -fn generics_require_inlining(generics: &ty::Generics) -> bool { - for param in &generics.params { - match param.kind { - GenericParamDefKind::Lifetime { .. } => {} - GenericParamDefKind::Type { .. } => return true, - } - } - false -} - // Returns true if the given item must be inlined because it may be // monomorphized or it was marked with `#[inline]`. This will only return // true for functions. @@ -61,7 +48,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir::ItemKind::Impl(..) | hir::ItemKind::Fn(..) => { let generics = tcx.generics_of(tcx.hir.local_def_id(item.id)); - generics_require_inlining(generics) + generics.requires_monomorphization(tcx) } _ => false, } @@ -72,12 +59,12 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_src: DefId) -> bool { let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id()); let generics = tcx.generics_of(tcx.hir.local_def_id(impl_item.id)); - if codegen_fn_attrs.requests_inline() || generics_require_inlining(generics) { + if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true } if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) { match tcx.hir.find(impl_node_id) { - Some(hir_map::NodeItem(item)) => + Some(Node::Item(item)) => item_might_be_inlined(tcx, &item, codegen_fn_attrs), Some(..) | None => span_bug!(impl_item.span, "impl did is not an item") @@ -169,14 +156,14 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { }; match self.tcx.hir.find(node_id) { - Some(hir_map::NodeItem(item)) => { + Some(Node::Item(item)) => { match item.node { hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)), _ => false, } } - Some(hir_map::NodeTraitItem(trait_method)) => { + Some(Node::TraitItem(trait_method)) => { match trait_method.node { hir::TraitItemKind::Const(_, ref default) => default.is_some(), hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true, @@ -184,14 +171,13 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::TraitItemKind::Type(..) => false, } } - Some(hir_map::NodeImplItem(impl_item)) => { + Some(Node::ImplItem(impl_item)) => { match impl_item.node { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Method(..) => { let attrs = self.tcx.codegen_fn_attrs(def_id); let generics = self.tcx.generics_of(def_id); - if generics_require_inlining(&generics) || - attrs.requests_inline() { + if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() { true } else { let impl_did = self.tcx @@ -204,7 +190,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { match self.tcx.hir.expect_item(impl_node_id).node { hir::ItemKind::Impl(..) => { let generics = self.tcx.generics_of(impl_did); - generics_require_inlining(&generics) + generics.requires_monomorphization(self.tcx) } _ => false } @@ -233,20 +219,23 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } } - fn propagate_node(&mut self, node: &hir_map::Node<'tcx>, + fn propagate_node(&mut self, node: &Node<'tcx>, search_item: ast::NodeId) { if !self.any_library { // If we are building an executable, only explicitly extern // types need to be exported. - if let hir_map::NodeItem(item) = *node { + if let Node::Item(item) = *node { let reachable = if let hir::ItemKind::Fn(_, header, ..) = item.node { header.abi != Abi::Rust } else { false }; let def_id = self.tcx.hir.local_def_id(item.id); - let is_extern = self.tcx.codegen_fn_attrs(def_id).contains_extern_indicator(); - if reachable || is_extern { + let codegen_attrs = self.tcx.codegen_fn_attrs(def_id); + let is_extern = codegen_attrs.contains_extern_indicator(); + let std_internal = codegen_attrs.flags.contains( + CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL); + if reachable || is_extern || std_internal { self.reachable_symbols.insert(search_item); } } @@ -259,7 +248,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } match *node { - hir_map::NodeItem(item) => { + Node::Item(item) => { match item.node { hir::ItemKind::Fn(.., body) => { let def_id = self.tcx.hir.local_def_id(item.id); @@ -296,7 +285,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ItemKind::GlobalAsm(..) => {} } } - hir_map::NodeTraitItem(trait_method) => { + Node::TraitItem(trait_method) => { match trait_method.node { hir::TraitItemKind::Const(_, None) | hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => { @@ -309,7 +298,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::TraitItemKind::Type(..) => {} } } - hir_map::NodeImplItem(impl_item) => { + Node::ImplItem(impl_item) => { match impl_item.node { hir::ImplItemKind::Const(_, body) => { self.visit_nested_body(body); @@ -324,16 +313,16 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ImplItemKind::Type(_) => {} } } - hir_map::NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(.., body, _, _), .. }) => { + Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(.., body, _, _), .. }) => { self.visit_nested_body(body); } // Nothing to recurse on for these - hir_map::NodeForeignItem(_) | - hir_map::NodeVariant(_) | - hir_map::NodeStructCtor(_) | - hir_map::NodeField(_) | - hir_map::NodeTy(_) | - hir_map::NodeMacroDef(_) => {} + Node::ForeignItem(_) | + Node::Variant(_) | + Node::StructCtor(_) | + Node::Field(_) | + Node::Ty(_) | + Node::MacroDef(_) => {} _ => { bug!("found unexpected thingy in worklist: {}", self.tcx.hir.node_to_string(search_item)) @@ -359,8 +348,12 @@ struct CollectPrivateImplItemsVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { // Anything which has custom linkage gets thrown on the worklist no - // matter where it is in the crate. - if attr::contains_name(&item.attrs, "linkage") { + // matter where it is in the crate, along with "special std symbols" + // which are currently akin to allocator symbols. + let def_id = self.tcx.hir.local_def_id(item.id); + let codegen_attrs = self.tcx.codegen_fn_attrs(def_id); + if codegen_attrs.linkage.is_some() || + codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { self.worklist.push(item.id); } @@ -408,8 +401,8 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { - *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || - *ty == config::CrateTypeProcMacro + *ty == config::CrateType::Rlib || *ty == config::CrateType::Dylib || + *ty == config::CrateType::ProcMacro }); let mut reachable_context = ReachableContext { tcx, @@ -444,6 +437,8 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> // Step 2: Mark all symbols that the symbols on the worklist touch. reachable_context.propagate(); + debug!("Inline reachability shows: {:?}", reachable_context.reachable_symbols); + // Return the set of reachable symbols. ReachableSet(Lrc::new(reachable_context.reachable_symbols)) } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index ebdc9c922b..788fbcef17 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -20,16 +20,17 @@ use ich::{StableHashingContext, NodeIdHashingMode}; use util::nodemap::{FxHashMap, FxHashSet}; use ty; -use std::fmt; use std::mem; +use std::fmt; use rustc_data_structures::sync::Lrc; -use syntax::codemap; +use syntax::source_map; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; use ty::TyCtxt; use ty::query::Providers; use hir; +use hir::Node; use hir::def_id::DefId; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; @@ -50,7 +51,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, /// `DestructionScope`, but those that are `terminating_scopes` do; /// see discussion with `ScopeTree`. /// -/// `Remainder(BlockRemainder { block, statement_index })` represents +/// `Remainder { block, statement_index }` represents /// the scope of user code running immediately after the initializer /// expression for the indexed statement, until the end of the block. /// @@ -99,39 +100,46 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, /// placate the same deriving in `ty::FreeRegion`, but we may want to /// actually attach a more meaningful ordering to scopes than the one /// generated via deriving here. -/// -/// Scope is a bit-packed to save space - if `code` is SCOPE_DATA_REMAINDER_MAX -/// or less, it is a `ScopeData::Remainder`, otherwise it is a type specified -/// by the bitpacking. #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)] pub struct Scope { - pub(crate) id: hir::ItemLocalId, - pub(crate) code: u32 + pub id: hir::ItemLocalId, + pub data: ScopeData, } -const SCOPE_DATA_NODE: u32 = !0; -const SCOPE_DATA_CALLSITE: u32 = !1; -const SCOPE_DATA_ARGUMENTS: u32 = !2; -const SCOPE_DATA_DESTRUCTION: u32 = !3; -const SCOPE_DATA_REMAINDER_MAX: u32 = !4; +impl fmt::Debug for Scope { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self.data { + ScopeData::Node => write!(fmt, "Node({:?})", self.id), + ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.id), + ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id), + ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id), + ScopeData::Remainder(fsi) => write!( + fmt, + "Remainder {{ block: {:?}, first_statement_index: {}}}", + self.id, + fsi.as_u32(), + ), + } + } +} #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] pub enum ScopeData { - Node(hir::ItemLocalId), + Node, // Scope of the call-site for a function or closure // (outlives the arguments as well as the body). - CallSite(hir::ItemLocalId), + CallSite, // Scope of arguments passed to a function or closure // (they outlive its body). - Arguments(hir::ItemLocalId), + Arguments, // Scope of destructors for temporaries of node-id. - Destruction(hir::ItemLocalId), + Destruction, // Scope following a `let id = expr;` binding in a block. - Remainder(BlockRemainder) + Remainder(FirstStatementIndex) } /// Represents a subscope of `block` for a binding that is introduced @@ -151,80 +159,18 @@ pub enum ScopeData { /// /// * the subscope with `first_statement_index == 1` is scope of `c`, /// and thus does not include EXPR_2, but covers the `...`. -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, - RustcDecodable, Debug, Copy)] -pub struct BlockRemainder { - pub block: hir::ItemLocalId, - pub first_statement_index: FirstStatementIndex, -} -newtype_index!(FirstStatementIndex - { - pub idx - MAX = SCOPE_DATA_REMAINDER_MAX - }); - -impl From for Scope { - #[inline] - fn from(scope_data: ScopeData) -> Self { - let (id, code) = match scope_data { - ScopeData::Node(id) => (id, SCOPE_DATA_NODE), - ScopeData::CallSite(id) => (id, SCOPE_DATA_CALLSITE), - ScopeData::Arguments(id) => (id, SCOPE_DATA_ARGUMENTS), - ScopeData::Destruction(id) => (id, SCOPE_DATA_DESTRUCTION), - ScopeData::Remainder(r) => (r.block, r.first_statement_index.index() as u32) - }; - Self { id, code } - } +newtype_index! { + pub struct FirstStatementIndex { .. } } -impl fmt::Debug for Scope { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.data(), formatter) - } -} +impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private }); -#[allow(non_snake_case)] -impl Scope { - #[inline] - pub fn data(self) -> ScopeData { - match self.code { - SCOPE_DATA_NODE => ScopeData::Node(self.id), - SCOPE_DATA_CALLSITE => ScopeData::CallSite(self.id), - SCOPE_DATA_ARGUMENTS => ScopeData::Arguments(self.id), - SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id), - idx => ScopeData::Remainder(BlockRemainder { - block: self.id, - first_statement_index: FirstStatementIndex::new(idx as usize) - }) - } - } - - #[inline] - pub fn Node(id: hir::ItemLocalId) -> Self { - Self::from(ScopeData::Node(id)) - } - - #[inline] - pub fn CallSite(id: hir::ItemLocalId) -> Self { - Self::from(ScopeData::CallSite(id)) - } - - #[inline] - pub fn Arguments(id: hir::ItemLocalId) -> Self { - Self::from(ScopeData::Arguments(id)) - } - - #[inline] - pub fn Destruction(id: hir::ItemLocalId) -> Self { - Self::from(ScopeData::Destruction(id)) - } - - #[inline] - pub fn Remainder(r: BlockRemainder) -> Self { - Self::from(ScopeData::Remainder(r)) - } -} +// compilation error if size of `ScopeData` is not the same as a `u32` +#[allow(dead_code)] +// only works on stage 1 when the rustc_layout_scalar_valid_range attribute actually exists +#[cfg(not(stage0))] +static ASSERT: () = [()][!(mem::size_of::() == 4) as usize]; impl Scope { /// Returns a item-local id associated with this scope. @@ -256,8 +202,8 @@ impl Scope { return DUMMY_SP; } let span = tcx.hir.span(node_id); - if let ScopeData::Remainder(r) = self.data() { - if let hir::map::NodeBlock(ref blk) = tcx.hir.get(node_id) { + if let ScopeData::Remainder(first_statement_index) = self.data { + if let Node::Block(ref blk) = tcx.hir.get(node_id) { // Want span for scope starting after the // indexed statement and ending at end of // `blk`; reuse span of `blk` and shift `lo` @@ -266,7 +212,7 @@ impl Scope { // (This is the special case aluded to in the // doc-comment for this method) - let stmt_span = blk.stmts[r.first_statement_index.index()].span; + let stmt_span = blk.stmts[first_statement_index.index()].span; // To avoid issues with macro-generated spans, the span // of the statement must be nested in that of the block. @@ -510,8 +456,8 @@ impl<'tcx> ScopeTree { } // record the destruction scopes for later so we can query them - if let ScopeData::Destruction(n) = child.data() { - self.destruction_scopes.insert(n, child); + if let ScopeData::Destruction = child.data { + self.destruction_scopes.insert(child.item_local_id(), child); } } @@ -590,11 +536,11 @@ impl<'tcx> ScopeTree { // if there's one. Static items, for instance, won't // have an enclosing scope, hence no scope will be // returned. - let mut id = Scope::Node(expr_id); + let mut id = Scope { id: expr_id, data: ScopeData::Node }; while let Some(&(p, _)) = self.parent_map.get(&id) { - match p.data() { - ScopeData::Destruction(..) => { + match p.data { + ScopeData::Destruction => { debug!("temporary_scope({:?}) = {:?} [enclosing]", expr_id, id); return Some(id); @@ -649,8 +595,8 @@ impl<'tcx> ScopeTree { /// Returns the id of the innermost containing body pub fn containing_body(&self, mut scope: Scope)-> Option { loop { - if let ScopeData::CallSite(id) = scope.data() { - return Some(id); + if let ScopeData::CallSite = scope.data { + return Some(scope.item_local_id()); } match self.opt_encl_scope(scope) { @@ -742,7 +688,7 @@ impl<'tcx> ScopeTree { self.root_body.unwrap().local_id }); - Scope::CallSite(scope) + Scope { id: scope, data: ScopeData::CallSite } } /// Assuming that the provided region was defined within this `ScopeTree`, @@ -762,7 +708,7 @@ impl<'tcx> ScopeTree { let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap(); let body_id = tcx.hir.body_owned_by(param_owner_id); - Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id) + Scope { id: tcx.hir.body(body_id).value.hir_id.local_id, data: ScopeData::CallSite } } /// Checks whether the given scope contains a `yield`. If so, @@ -866,10 +812,10 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: // except for the first such subscope, which has the // block itself as a parent. visitor.enter_scope( - Scope::Remainder(BlockRemainder { - block: blk.hir_id.local_id, - first_statement_index: FirstStatementIndex::new(i) - }) + Scope { + id: blk.hir_id.local_id, + data: ScopeData::Remainder(FirstStatementIndex::new(i)) + } ); visitor.cx.var_parent = visitor.cx.parent; } @@ -884,15 +830,17 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) { visitor.terminating_scopes.insert(arm.body.hir_id.local_id); - if let Some(ref expr) = arm.guard { - visitor.terminating_scopes.insert(expr.hir_id.local_id); + if let Some(ref g) = arm.guard { + match g { + hir::Guard::If(ref expr) => visitor.terminating_scopes.insert(expr.hir_id.local_id), + }; } intravisit::walk_arm(visitor, arm); } fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) { - visitor.record_child_scope(Scope::Node(pat.hir_id.local_id)); + visitor.record_child_scope(Scope { id: pat.hir_id.local_id, data: ScopeData::Node }); // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.node { @@ -943,11 +891,15 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: // scopes, meaning that temporaries cannot outlive them. // This ensures fixed size stacks. - hir::ExprKind::Binary(codemap::Spanned { node: hir::BinOpKind::And, .. }, _, ref r) | - hir::ExprKind::Binary(codemap::Spanned { node: hir::BinOpKind::Or, .. }, _, ref r) => { - // For shortcircuiting operators, mark the RHS as a terminating - // scope since it only executes conditionally. - terminating(r.hir_id.local_id); + hir::ExprKind::Binary( + source_map::Spanned { node: hir::BinOpKind::And, .. }, + _, ref r) | + hir::ExprKind::Binary( + source_map::Spanned { node: hir::BinOpKind::Or, .. }, + _, ref r) => { + // For shortcircuiting operators, mark the RHS as a terminating + // scope since it only executes conditionally. + terminating(r.hir_id.local_id); } hir::ExprKind::If(ref expr, ref then, Some(ref otherwise)) => { @@ -1017,7 +969,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: if let hir::ExprKind::Yield(..) = expr.node { // Mark this expr's scope and all parent scopes as containing `yield`. - let mut scope = Scope::Node(expr.hir_id.local_id); + let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node }; loop { visitor.scope_tree.yield_in_scope.insert(scope, (expr.span, visitor.expr_and_pat_count)); @@ -1025,8 +977,8 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: // Keep traversing up while we can. match visitor.scope_tree.parent_map.get(&scope) { // Don't cross from closure bodies to their parent. - Some(&(superscope, _)) => match superscope.data() { - ScopeData::CallSite(_) => break, + Some(&(superscope, _)) => match superscope.data { + ScopeData::CallSite => break, _ => scope = superscope }, None => break @@ -1289,9 +1241,9 @@ impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> { // account for the destruction scope representing the scope of // the destructors that run immediately after it completes. if self.terminating_scopes.contains(&id) { - self.enter_scope(Scope::Destruction(id)); + self.enter_scope(Scope { id, data: ScopeData::Destruction }); } - self.enter_scope(Scope::Node(id)); + self.enter_scope(Scope { id, data: ScopeData::Node }); } } @@ -1310,7 +1262,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { debug!("visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})", owner_id, - self.tcx.sess.codemap().span_to_string(body.value.span), + self.tcx.sess.source_map().span_to_string(body.value.span), body_id, self.cx.parent); @@ -1324,8 +1276,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { } self.cx.root_id = Some(body.value.hir_id.local_id); - self.enter_scope(Scope::CallSite(body.value.hir_id.local_id)); - self.enter_scope(Scope::Arguments(body.value.hir_id.local_id)); + self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite }); + self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments }); // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); @@ -1416,8 +1368,8 @@ fn region_scope_tree<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) // record its impl/trait parent, as it can also have // lifetime parameters free in this body. match tcx.hir.get(id) { - hir::map::NodeImplItem(_) | - hir::map::NodeTraitItem(_) => { + Node::ImplItem(_) | + Node::TraitItem(_) => { visitor.scope_tree.root_parent = Some(tcx.hir.get_parent(id)); } _ => {} diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ca8fe46311..db931d0a73 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -18,7 +18,7 @@ use hir::def::Def; use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use hir::map::Map; -use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName}; +use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName, Node}; use ty::{self, TyCtxt, GenericParamDefKind}; use errors::DiagnosticBuilder; @@ -391,37 +391,33 @@ fn resolve_lifetimes<'tcx>( let named_region_map = krate(tcx); - let mut defs = FxHashMap(); + let mut rl = ResolveLifetimes { + defs: FxHashMap(), + late_bound: FxHashMap(), + object_lifetime_defaults: FxHashMap(), + }; + for (k, v) in named_region_map.defs { let hir_id = tcx.hir.node_to_hir_id(k); - let map = defs.entry(hir_id.owner_local_def_id()) - .or_insert_with(|| Lrc::new(FxHashMap())); + let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default(); Lrc::get_mut(map).unwrap().insert(hir_id.local_id, v); } - let mut late_bound = FxHashMap(); for k in named_region_map.late_bound { let hir_id = tcx.hir.node_to_hir_id(k); - let map = late_bound - .entry(hir_id.owner_local_def_id()) - .or_insert_with(|| Lrc::new(FxHashSet())); + let map = rl.late_bound.entry(hir_id.owner_local_def_id()).or_default(); Lrc::get_mut(map).unwrap().insert(hir_id.local_id); } - let mut object_lifetime_defaults = FxHashMap(); for (k, v) in named_region_map.object_lifetime_defaults { let hir_id = tcx.hir.node_to_hir_id(k); - let map = object_lifetime_defaults + let map = rl.object_lifetime_defaults .entry(hir_id.owner_local_def_id()) - .or_insert_with(|| Lrc::new(FxHashMap())); + .or_default(); Lrc::get_mut(map) .unwrap() .insert(hir_id.local_id, Lrc::new(v)); } - Lrc::new(ResolveLifetimes { - defs, - late_bound, - object_lifetime_defaults, - }) + Lrc::new(rl) } fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap { @@ -903,7 +899,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.resolve_lifetime_ref(lifetime_ref); } - fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) { + fn visit_path(&mut self, path: &'tcx hir::Path, _: hir::HirId) { for (i, segment) in path.segments.iter().enumerate() { let depth = path.segments.len() - i - 1; if let Some(ref args) = segment.args { @@ -1444,10 +1440,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); debug!("node id first={:?}", node_id); if let Some((id, span, name)) = match self.tcx.hir.get(node_id) { - hir::map::NodeLifetime(hir_lifetime) => { + Node::Lifetime(hir_lifetime) => { Some((hir_lifetime.id, hir_lifetime.span, hir_lifetime.name.ident())) } - hir::map::NodeGenericParam(param) => { + Node::GenericParam(param) => { Some((param.id, param.span, param.name.ident())) } _ => None, @@ -1470,10 +1466,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { None => { let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); if let Some((id, span, name)) = match self.tcx.hir.get(node_id) { - hir::map::NodeLifetime(hir_lifetime) => { + Node::Lifetime(hir_lifetime) => { Some((hir_lifetime.id, hir_lifetime.span, hir_lifetime.name.ident())) } - hir::map::NodeGenericParam(param) => { + Node::GenericParam(param) => { Some((param.id, param.span, param.name.ident())) } _ => None, @@ -1647,15 +1643,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } else if let Some(body_id) = outermost_body { let fn_id = self.tcx.hir.body_owner(body_id); match self.tcx.hir.get(fn_id) { - hir::map::NodeItem(&hir::Item { + Node::Item(&hir::Item { node: hir::ItemKind::Fn(..), .. }) - | hir::map::NodeTraitItem(&hir::TraitItem { + | Node::TraitItem(&hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) - | hir::map::NodeImplItem(&hir::ImplItem { + | Node::ImplItem(&hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => { @@ -1872,12 +1868,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let parent = self.tcx.hir.get_parent_node(output.id); let body = match self.tcx.hir.get(parent) { // `fn` definitions and methods. - hir::map::NodeItem(&hir::Item { + Node::Item(&hir::Item { node: hir::ItemKind::Fn(.., body), .. }) => Some(body), - hir::map::NodeTraitItem(&hir::TraitItem { + Node::TraitItem(&hir::TraitItem { node: hir::TraitItemKind::Method(_, ref m), .. }) => { @@ -1900,7 +1896,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - hir::map::NodeImplItem(&hir::ImplItem { + Node::ImplItem(&hir::ImplItem { node: hir::ImplItemKind::Method(_, body), .. }) => { @@ -1922,7 +1918,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds). - hir::map::NodeForeignItem(_) | hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => None, + Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => None, // Everything else (only closures?) doesn't // actually enjoy elision in return types. _ => { @@ -2461,7 +2457,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { "insert_lifetime: {} resolved to {:?} span={:?}", self.tcx.hir.node_to_string(lifetime_ref.id), def, - self.tcx.sess.codemap().span_to_string(lifetime_ref.span) + self.tcx.sess.source_map().span_to_string(lifetime_ref.span) ); self.map.defs.insert(lifetime_ref.id, def); @@ -2571,6 +2567,13 @@ fn insert_late_bound_lifetimes( // - do not appear in the where-clauses // - are not implicitly captured by `impl Trait` for param in &generics.params { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => { /* fall through */ } + + // Types are not late-bound. + hir::GenericParamKind::Type { .. } => continue, + } + let lt_name = hir::LifetimeName::Param(param.name.modern()); // appears in the where clauses? early-bound. if appears_in_where_clause.regions.contains(<_name) { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 262a617cb6..73a55265f0 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -18,12 +18,12 @@ use hir::def::Def; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use ty::{self, TyCtxt}; use middle::privacy::AccessLevels; -use session::DiagnosticMessageId; +use session::{DiagnosticMessageId, Session}; use syntax::symbol::Symbol; use syntax_pos::{Span, MultiSpan}; use syntax::ast; use syntax::ast::{NodeId, Attribute}; -use syntax::feature_gate::{GateIssue, emit_feature_err, find_lang_feature_accepted_version}; +use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::attr::{self, Stability, Deprecation}; use util::nodemap::{FxHashSet, FxHashMap}; @@ -440,7 +440,7 @@ impl<'a, 'tcx> Index<'tcx> { }, feature: Symbol::intern("rustc_private"), rustc_depr: None, - rustc_const_unstable: None, + const_stability: None, }); annotator.parent_stab = Some(stability); } @@ -685,7 +685,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; let msp: MultiSpan = span.into(); - let cm = &self.sess.parse_sess.codemap(); + let cm = &self.sess.parse_sess.source_map(); let span_key = msp.primary_span().and_then(|sp: Span| if !sp.is_dummy() { let file = cm.lookup_char_pos(sp.lo()).file; @@ -780,9 +780,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { intravisit::walk_item(self, item); } - fn visit_path(&mut self, path: &'tcx hir::Path, id: ast::NodeId) { + fn visit_path(&mut self, path: &'tcx hir::Path, id: hir::HirId) { + let id = self.tcx.hir.hir_to_node_id(id); match path.def { - Def::Local(..) | Def::Upvar(..) | + Def::Local(..) | Def::Upvar(..) | Def::SelfCtor(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => {} _ => self.tcx.check_stability(path.def.def_id(), Some(id), path.span) } @@ -813,37 +814,90 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } - let ref declared_lib_features = tcx.features().declared_lib_features; - let mut remaining_lib_features: FxHashMap - = declared_lib_features.clone().into_iter().collect(); - remaining_lib_features.remove(&Symbol::intern("proc_macro")); - - for &(ref stable_lang_feature, span) in &tcx.features().declared_stable_lang_features { - let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str()) - .expect("unexpectedly couldn't find version feature was stabilized"); - tcx.lint_node(lint::builtin::STABLE_FEATURES, - ast::CRATE_NODE_ID, - span, - &format_stable_since_msg(version)); - } - - // FIXME(#44232) the `used_features` table no longer exists, so we don't - // lint about unknown or unused features. We should reenable - // this one day! - // - // let index = tcx.stability(); - // for (used_lib_feature, level) in &index.used_features { - // remaining_lib_features.remove(used_lib_feature); - // } - // - // for &span in remaining_lib_features.values() { - // tcx.lint_node(lint::builtin::UNUSED_FEATURES, - // ast::CRATE_NODE_ID, - // span, - // "unused or unknown feature"); - // } + let declared_lang_features = &tcx.features().declared_lang_features; + let mut lang_features = FxHashSet(); + for &(feature, span, since) in declared_lang_features { + if let Some(since) = since { + // Warn if the user has enabled an already-stable lang feature. + unnecessary_stable_feature_lint(tcx, span, feature, since); + } + if lang_features.contains(&feature) { + // Warn if the user enables a lang feature multiple times. + duplicate_feature_err(tcx.sess, span, feature); + } + lang_features.insert(feature); + } + + let declared_lib_features = &tcx.features().declared_lib_features; + let mut remaining_lib_features = FxHashMap(); + for (feature, span) in declared_lib_features { + if remaining_lib_features.contains_key(&feature) { + // Warn if the user enables a lib feature multiple times. + duplicate_feature_err(tcx.sess, *span, *feature); + } + remaining_lib_features.insert(feature, span.clone()); + } + // `stdbuild` has special handling for `libc`, so we need to + // recognise the feature when building std. + // Likewise, libtest is handled specially, so `test` isn't + // available as we'd like it to be. + // FIXME: only remove `libc` when `stdbuild` is active. + // FIXME: remove special casing for `test`. + remaining_lib_features.remove(&Symbol::intern("libc")); + remaining_lib_features.remove(&Symbol::intern("test")); + + let check_features = + |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &Vec<_>| { + for &(feature, since) in defined_features { + if let Some(since) = since { + if let Some(span) = remaining_lib_features.get(&feature) { + // Warn if the user has enabled an already-stable lib feature. + unnecessary_stable_feature_lint(tcx, *span, feature, since); + } + } + remaining_lib_features.remove(&feature); + if remaining_lib_features.is_empty() { + break; + } + } + }; + + // We always collect the lib features declared in the current crate, even if there are + // no unknown features, because the collection also does feature attribute validation. + let local_defined_features = tcx.lib_features().to_vec(); + if !remaining_lib_features.is_empty() { + check_features(&mut remaining_lib_features, &local_defined_features); + + for &cnum in &*tcx.crates() { + if remaining_lib_features.is_empty() { + break; + } + check_features(&mut remaining_lib_features, &tcx.defined_lib_features(cnum)); + } + } + + for (feature, span) in remaining_lib_features { + struct_span_err!(tcx.sess, span, E0635, "unknown feature `{}`", feature).emit(); + } + + // FIXME(#44232): the `used_features` table no longer exists, so we + // don't lint about unused features. We should reenable this one day! +} + +fn unnecessary_stable_feature_lint<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + span: Span, + feature: Symbol, + since: Symbol +) { + tcx.lint_node(lint::builtin::STABLE_FEATURES, + ast::CRATE_NODE_ID, + span, + &format!("the feature `{}` has been stable since {} and no longer requires \ + an attribute to enable", feature, since)); } -fn format_stable_since_msg(version: &str) -> String { - format!("this feature has been stable since {}. Attribute no longer needed", version) +fn duplicate_feature_err(sess: &Session, span: Span, feature: Symbol) { + struct_span_err!(sess, span, E0636, "the feature `{}` has already been declared", feature) + .emit(); } diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index d8570b43fb..cbf6722c0f 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -13,6 +13,7 @@ use session::config; use middle::lang_items; +use rustc_data_structures::fx::FxHashSet; use rustc_target::spec::PanicStrategy; use syntax::ast; use syntax::symbol::Symbol; @@ -23,8 +24,6 @@ use hir::intravisit; use hir; use ty::TyCtxt; -use std::collections::HashSet; - macro_rules! weak_lang_items { ($($name:ident, $item:ident, $sym:ident;)*) => ( @@ -89,19 +88,19 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // emitting something that's not an rlib. let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| { match *kind { - config::CrateTypeDylib | - config::CrateTypeProcMacro | - config::CrateTypeCdylib | - config::CrateTypeExecutable | - config::CrateTypeStaticlib => true, - config::CrateTypeRlib => false, + config::CrateType::Dylib | + config::CrateType::ProcMacro | + config::CrateType::Cdylib | + config::CrateType::Executable | + config::CrateType::Staticlib => true, + config::CrateType::Rlib => false, } }); if !needs_check { return } - let mut missing = HashSet::new(); + let mut missing = FxHashSet::default(); for &cnum in tcx.crates().iter() { for &item in tcx.missing_lang_items(cnum).iter() { missing.insert(item); @@ -113,7 +112,7 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, !whitelisted(tcx, lang_items::$item) && items.$name().is_none() { if lang_items::$item == lang_items::PanicImplLangItem { - tcx.sess.err(&format!("`#[panic_implementation]` function required, \ + tcx.sess.err(&format!("`#[panic_handler]` function required, \ but not found")); } else if lang_items::$item == lang_items::OomLangItem { tcx.sess.err(&format!("`#[alloc_error_handler]` function required, \ diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 41ba526b73..d1f050fcd4 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc_data_structures::indexed_vec::IndexVec; -use rustc_data_structures::sync::{RwLock, ReadGuard}; +use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use ich::StableHashingContext; @@ -55,7 +55,10 @@ impl Cache { *self.predecessors.borrow_mut() = None; } - pub fn predecessors(&self, mir: &Mir) -> ReadGuard>> { + pub fn predecessors( + &self, + mir: &Mir + ) -> MappedReadGuard>> { if self.predecessors.borrow().is_none() { *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir)); } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 1e9584bc55..cccde692bf 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -1,9 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use std::{fmt, env}; use mir; -use ty::{FnSig, Ty, layout}; +use ty::{Ty, layout}; use ty::layout::{Size, Align}; use rustc_data_structures::sync::Lrc; +use rustc_target::spec::abi::Abi; use super::{ Pointer, Lock, AccessKind @@ -17,6 +28,7 @@ use errors::DiagnosticBuilder; use syntax_pos::Span; use syntax::ast; +use syntax::symbol::Symbol; pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, Lrc>>; @@ -171,7 +183,10 @@ pub enum EvalErrorKind<'tcx, O> { /// This variant is used by machines to signal their own errors that do not /// match an existing variant MachineError(String), - FunctionPointerTyMismatch(FnSig<'tcx>, FnSig<'tcx>), + + FunctionAbiMismatch(Abi, Abi), + FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), + FunctionArgCountMismatch, NoMirFor(String), UnterminatedCString(Pointer), DanglingPointerDeref, @@ -179,7 +194,7 @@ pub enum EvalErrorKind<'tcx, O> { InvalidMemoryAccess, InvalidFunctionPointer, InvalidBool, - InvalidDiscriminant, + InvalidDiscriminant(u128), PointerOutOfBounds { ptr: Pointer, access: bool, @@ -190,7 +205,7 @@ pub enum EvalErrorKind<'tcx, O> { ReadBytesAsPointer, ReadForeignStatic, InvalidPointerMath, - ReadUndefBytes, + ReadUndefBytes(Size), DeadLocal, InvalidBoolOp(mir::BinOp), Unimplemented(String), @@ -250,7 +265,12 @@ pub enum EvalErrorKind<'tcx, O> { HeapAllocZeroBytes, HeapAllocNonPowerOfTwoAlignment(u64), Unreachable, - Panic, + Panic { + msg: Symbol, + line: u32, + col: u32, + file: Symbol, + }, ReadFromReturnPointer, PathNotFound(Vec), UnimplementedTraitSelection, @@ -274,8 +294,8 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> { use self::EvalErrorKind::*; match *self { MachineError(ref inner) => inner, - FunctionPointerTyMismatch(..) => - "tried to call a function through a function pointer of a different type", + FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionArgCountMismatch => + "tried to call a function through a function pointer of incompatible type", InvalidMemoryAccess => "tried to access memory through an invalid pointer", DanglingPointerDeref => @@ -286,7 +306,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> { "tried to use a function pointer after offsetting it", InvalidBool => "invalid boolean value read", - InvalidDiscriminant => + InvalidDiscriminant(..) => "invalid enum discriminant value read", PointerOutOfBounds { .. } => "pointer offset outside bounds of allocation", @@ -309,8 +329,9 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> { ReadForeignStatic => "tried to read from foreign (extern) static", InvalidPointerMath => - "attempted to do invalid arithmetic on pointers that would leak base addresses, e.g. comparing pointers into different allocations", - ReadUndefBytes => + "attempted to do invalid arithmetic on pointers that would leak base addresses, \ + e.g. comparing pointers into different allocations", + ReadUndefBytes(_) => "attempted to read undefined bytes", DeadLocal => "tried to access a dead local variable", @@ -363,14 +384,16 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> { Layout(_) => "rustc layout computation failed", UnterminatedCString(_) => - "attempted to get length of a null terminated string, but no null found before end of allocation", + "attempted to get length of a null terminated string, but no null found before end \ + of allocation", HeapAllocZeroBytes => "tried to re-, de- or allocate zero bytes on the heap", HeapAllocNonPowerOfTwoAlignment(_) => - "tried to re-, de-, or allocate heap memory with alignment that is not a power of two", + "tried to re-, de-, or allocate heap memory with alignment that is not a power of \ + two", Unreachable => "entered unreachable code", - Panic => + Panic { .. } => "the evaluated program panicked", ReadFromReturnPointer => "tried to read from the return pointer", @@ -429,8 +452,8 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { kind, ptr, len, lock) } InvalidMemoryLockRelease { ptr, len, frame, ref lock } => { - write!(f, "frame {} tried to release memory write lock at {:?}, size {}, but cannot release lock {:?}", - frame, ptr, len, lock) + write!(f, "frame {} tried to release memory write lock at {:?}, size {}, but \ + cannot release lock {:?}", frame, ptr, len, lock) } DeallocatedLockedMemory { ptr, ref lock } => { write!(f, "tried to deallocate memory at {:?} in conflict with lock {:?}", @@ -440,8 +463,15 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { write!(f, "type validation failed: {}", err) } NoMirFor(ref func) => write!(f, "no mir for `{}`", func), - FunctionPointerTyMismatch(sig, got) => - write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got), + FunctionAbiMismatch(caller_abi, callee_abi) => + write!(f, "tried to call a function with ABI {:?} using caller ABI {:?}", + callee_abi, caller_abi), + FunctionArgMismatch(caller_ty, callee_ty) => + write!(f, "tried to call a function with argument of type {:?} \ + passing data of type {:?}", + callee_ty, caller_ty), + FunctionArgCountMismatch => + write!(f, "tried to call a function with incorrect number of arguments"), BoundsCheck { ref len, ref index } => write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index), ReallocatedWrongMemoryKind(ref old, ref new) => @@ -464,7 +494,12 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { MachineError(ref inner) => write!(f, "{}", inner), IncorrectAllocationInformation(size, size2, align, align2) => - write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()), + write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and \ + align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()), + Panic { ref msg, line, col, ref file } => + write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col), + InvalidDiscriminant(val) => + write!(f, "encountered invalid enum discriminant {}", val), _ => write!(f, "{}", self.description()), } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 4164fe3fd9..5fa47ef42e 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -1,3 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! An interpreter for MIR used in CTFE and by miri #[macro_export] @@ -13,7 +23,7 @@ pub use self::error::{ FrameInfo, ConstEvalResult, }; -pub use self::value::{Scalar, Value, ConstValue}; +pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef}; use std::fmt; use mir; @@ -40,7 +50,8 @@ use std::num::NonZeroU32; pub enum Lock { NoLock, WriteLock(DynamicLifetime), - /// This should never be empty -- that would be a read lock held and nobody there to release it... + /// This should never be empty -- that would be a read lock held and nobody + /// there to release it... ReadLock(Vec), } @@ -74,9 +85,14 @@ pub struct GlobalId<'tcx> { pub trait PointerArithmetic: layout::HasDataLayout { // These are not supposed to be overridden. + #[inline(always)] + fn pointer_size(self) -> Size { + self.data_layout().pointer_size + } + //// Trunace the given value to the pointer size; also return whether there was an overflow fn truncate_to_ptr(self, val: u128) -> (u64, bool) { - let max_ptr_plus_1 = 1u128 << self.data_layout().pointer_size.bits(); + let max_ptr_plus_1 = 1u128 << self.pointer_size().bits(); ((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1) } @@ -117,9 +133,14 @@ pub trait PointerArithmetic: layout::HasDataLayout { impl PointerArithmetic for T {} +/// Pointer is generic over the type that represents a reference to Allocations, +/// thus making it possible for the most convenient representation to be used in +/// each context. +/// +/// Defaults to the index based and loosely coupled AllocId. #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] -pub struct Pointer { - pub alloc_id: AllocId, +pub struct Pointer { + pub alloc_id: Id, pub offset: Size, } @@ -135,7 +156,7 @@ impl<'tcx> Pointer { Pointer { alloc_id, offset } } - pub(crate) fn wrapping_signed_offset(self, i: i64, cx: C) -> Self { + pub fn wrapping_signed_offset(self, i: i64, cx: C) -> Self { Pointer::new( self.alloc_id, Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)), @@ -147,7 +168,7 @@ impl<'tcx> Pointer { (Pointer::new(self.alloc_id, Size::from_bytes(res)), over) } - pub(crate) fn signed_offset(self, i: i64, cx: C) -> EvalResult<'tcx, Self> { + pub fn signed_offset(self, i: i64, cx: C) -> EvalResult<'tcx, Self> { Ok(Pointer::new( self.alloc_id, Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?), @@ -382,7 +403,8 @@ impl fmt::Display for AllocId { pub enum AllocType<'tcx, M> { /// The alloc id is used as a function pointer Function(Instance<'tcx>), - /// The alloc id points to a static variable + /// The alloc id points to a "lazy" static variable that did not get computed (yet). + /// This is also used to break the cycle in recursive statics. Static(DefId), /// The alloc id points to memory Memory(M) @@ -479,19 +501,22 @@ pub struct Allocation { /// Note that the bytes of a pointer represent the offset of the pointer pub bytes: Vec, /// Maps from byte addresses to allocations. - /// Only the first byte of a pointer is inserted into the map. + /// Only the first byte of a pointer is inserted into the map; i.e., + /// every entry in this map applies to `pointer_size` consecutive bytes starting + /// at the given offset. pub relocations: Relocations, /// Denotes undefined memory. Reading from undefined memory is forbidden in miri pub undef_mask: UndefMask, /// The alignment of the allocation to detect unaligned reads. pub align: Align, - /// Whether the allocation (of a static) should be put into mutable memory when codegenning - /// - /// Only happens for `static mut` or `static` with interior mutability - pub runtime_mutability: Mutability, + /// Whether the allocation is mutable. + /// Also used by codegen to determine if a static should be put into mutable memory, + /// which happens for `static mut` and `static` with interior mutability. + pub mutability: Mutability, } impl Allocation { + /// Creates a read-only allocation initialized by the given bytes pub fn from_bytes(slice: &[u8], align: Align) -> Self { let mut undef_mask = UndefMask::new(Size::ZERO); undef_mask.grow(Size::from_bytes(slice.len() as u64), true); @@ -500,7 +525,7 @@ impl Allocation { relocations: Relocations::new(), undef_mask, align, - runtime_mutability: Mutability::Immutable, + mutability: Mutability::Immutable, } } @@ -515,7 +540,7 @@ impl Allocation { relocations: Relocations::new(), undef_mask: UndefMask::new(size), align, - runtime_mutability: Mutability::Immutable, + mutability: Mutability::Mutable, } } } @@ -523,16 +548,16 @@ impl Allocation { impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {} #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct Relocations(SortedMap); +pub struct Relocations(SortedMap); -impl Relocations { - pub fn new() -> Relocations { +impl Relocations { + pub fn new() -> Self { Relocations(SortedMap::new()) } // The caller must guarantee that the given relocations are already sorted // by address and contain no duplicates. - pub fn from_presorted(r: Vec<(Size, AllocId)>) -> Relocations { + pub fn from_presorted(r: Vec<(Size, Id)>) -> Self { Relocations(SortedMap::from_presorted_elements(r)) } } @@ -567,18 +592,6 @@ pub fn write_target_uint( } } -pub fn write_target_int( - endianness: layout::Endian, - mut target: &mut [u8], - data: i128, -) -> Result<(), io::Error> { - let len = target.len(); - match endianness { - layout::Endian::Little => target.write_int128::(data, len), - layout::Endian::Big => target.write_int128::(data, len), - } -} - pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result { match endianness { layout::Endian::Little => source.read_uint128::(source.len()), @@ -586,6 +599,26 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result } } +//////////////////////////////////////////////////////////////////////////////// +// Methods to faciliate working with signed integers stored in a u128 +//////////////////////////////////////////////////////////////////////////////// + +pub fn sign_extend(value: u128, size: Size) -> u128 { + let size = size.bits(); + // sign extend + let shift = 128 - size; + // shift the unsigned value to the left + // and back to the right as signed (essentially fills with FF on the left) + (((value << shift) as i128) >> shift) as u128 +} + +pub fn truncate(value: u128, size: Size) -> u128 { + let size = size.bits(); + let shift = 128 - size; + // truncate (shift left to drop out leftover values, shift right to fill with zeroes) + (value << shift) >> shift +} + //////////////////////////////////////////////////////////////////////////////// // Undefined byte tracking //////////////////////////////////////////////////////////////////////////////// @@ -612,16 +645,23 @@ impl UndefMask { } /// Check whether the range `start..end` (end-exclusive) is entirely defined. - pub fn is_range_defined(&self, start: Size, end: Size) -> bool { + /// + /// Returns `Ok(())` if it's defined. Otherwise returns the index of the byte + /// at which the first undefined access begins. + #[inline] + pub fn is_range_defined(&self, start: Size, end: Size) -> Result<(), Size> { if end > self.len { - return false; + return Err(self.len); } - for i in start.bytes()..end.bytes() { - if !self.get(Size::from_bytes(i)) { - return false; - } + + let idx = (start.bytes()..end.bytes()) + .map(|i| Size::from_bytes(i)) + .find(|&i| !self.get(i)); + + match idx { + Some(idx) => Err(idx), + None => Ok(()) } - true } pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) { diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index ffd138c9c4..be7d9b06fb 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -1,55 +1,45 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![allow(unknown_lints)] -use ty::layout::{Align, HasDataLayout, Size}; -use ty; +use ty::layout::{HasDataLayout, Size}; use ty::subst::Substs; use hir::def_id::DefId; -use super::{EvalResult, Pointer, PointerArithmetic, Allocation}; +use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate}; /// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which -/// matches Value's optimizations for easy conversions between these two types +/// matches the LocalValue optimizations for easy conversions between Value and ConstValue. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)] pub enum ConstValue<'tcx> { /// Never returned from the `const_eval` query, but the HIR contains these frequently in order /// to allow HIR creation to happen for everything before needing to be able to run constant /// evaluation Unevaluated(DefId, &'tcx Substs<'tcx>), - /// Used only for types with layout::abi::Scalar ABI and ZSTs which use Scalar::undef() + /// Used only for types with layout::abi::Scalar ABI and ZSTs + /// + /// Not using the enum `Value` to encode that this must not be `Undef` Scalar(Scalar), /// Used only for types with layout::abi::ScalarPair - ScalarPair(Scalar, Scalar), - /// Used only for the remaining cases. An allocation + offset into the allocation - ByRef(&'tcx Allocation, Size), + /// + /// The second field may be undef in case of `Option::None` + ScalarPair(Scalar, ScalarMaybeUndef), + /// Used only for the remaining cases. An allocation + offset into the allocation. + /// Invariant: The AllocId matches the allocation. + ByRef(AllocId, &'tcx Allocation, Size), } impl<'tcx> ConstValue<'tcx> { #[inline] - pub fn from_byval_value(val: Value) -> Self { - match val { - Value::ByRef(..) => bug!(), - Value::ScalarPair(a, b) => ConstValue::ScalarPair(a, b), - Value::Scalar(val) => ConstValue::Scalar(val), - } - } - - #[inline] - pub fn to_byval_value(&self) -> Option { - match *self { - ConstValue::Unevaluated(..) | - ConstValue::ByRef(..) => None, - ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a, b)), - ConstValue::Scalar(val) => Some(Value::Scalar(val)), - } - } - - #[inline] - pub fn from_scalar(val: Scalar) -> Self { - ConstValue::Scalar(val) - } - - #[inline] - pub fn to_scalar(&self) -> Option { + pub fn try_to_scalar(&self) -> Option { match *self { ConstValue::Unevaluated(..) | ConstValue::ByRef(..) | @@ -59,187 +49,171 @@ impl<'tcx> ConstValue<'tcx> { } #[inline] - pub fn to_bits(&self, size: Size) -> Option { - self.to_scalar()?.to_bits(size).ok() + pub fn try_to_bits(&self, size: Size) -> Option { + self.try_to_scalar()?.to_bits(size).ok() } #[inline] - pub fn to_ptr(&self) -> Option { - self.to_scalar()?.to_ptr().ok() + pub fn try_to_ptr(&self) -> Option { + self.try_to_scalar()?.to_ptr().ok() } -} - -/// A `Value` represents a single self-contained Rust value. -/// -/// A `Value` can either refer to a block of memory inside an allocation (`ByRef`) or to a primitve -/// value held directly, outside of any allocation (`Scalar`). For `ByRef`-values, we remember -/// whether the pointer is supposed to be aligned or not (also see Place). -/// -/// For optimization of a few very common cases, there is also a representation for a pair of -/// primitive values (`ScalarPair`). It allows Miri to avoid making allocations for checked binary -/// operations and fat pointers. This idea was taken from rustc's codegen. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] -pub enum Value { - ByRef(Scalar, Align), - Scalar(Scalar), - ScalarPair(Scalar, Scalar), -} -impl<'tcx> ty::TypeFoldable<'tcx> for Value { - fn super_fold_with<'gcx: 'tcx, F: ty::fold::TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self { - *self + #[inline] + pub fn new_slice( + val: Scalar, + len: u64, + cx: impl HasDataLayout + ) -> Self { + ConstValue::ScalarPair(val, Scalar::Bits { + bits: len as u128, + size: cx.data_layout().pointer_size.bytes() as u8, + }.into()) } - fn super_visit_with>(&self, _: &mut V) -> bool { - false + + #[inline] + pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self { + ConstValue::ScalarPair(val, Scalar::Ptr(vtable).into()) } } impl<'tcx> Scalar { - pub fn ptr_null(cx: C) -> Self { + #[inline] + pub fn ptr_null(cx: impl HasDataLayout) -> Self { Scalar::Bits { bits: 0, - defined: cx.data_layout().pointer_size.bits() as u8, + size: cx.data_layout().pointer_size.bytes() as u8, } } - pub fn ptr_signed_offset(self, i: i64, cx: C) -> EvalResult<'tcx, Self> { + #[inline] + pub fn zst() -> Self { + Scalar::Bits { bits: 0, size: 0 } + } + + #[inline] + pub fn ptr_signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> { let layout = cx.data_layout(); match self { - Scalar::Bits { bits, defined } => { - let pointer_size = layout.pointer_size.bits() as u8; - if defined < pointer_size { - err!(ReadUndefBytes) - } else { - Ok(Scalar::Bits { - bits: layout.signed_offset(bits as u64, i)? as u128, - defined: pointer_size, - }) - } + Scalar::Bits { bits, size } => { + assert_eq!(size as u64, layout.pointer_size.bytes()); + Ok(Scalar::Bits { + bits: layout.signed_offset(bits as u64, i)? as u128, + size, + }) } Scalar::Ptr(ptr) => ptr.signed_offset(i, layout).map(Scalar::Ptr), } } - pub fn ptr_offset(self, i: Size, cx: C) -> EvalResult<'tcx, Self> { + #[inline] + pub fn ptr_offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> { let layout = cx.data_layout(); match self { - Scalar::Bits { bits, defined } => { - let pointer_size = layout.pointer_size.bits() as u8; - if defined < pointer_size { - err!(ReadUndefBytes) - } else { - Ok(Scalar::Bits { - bits: layout.offset(bits as u64, i.bytes())? as u128, - defined: pointer_size, - }) - } + Scalar::Bits { bits, size } => { + assert_eq!(size as u64, layout.pointer_size.bytes()); + Ok(Scalar::Bits { + bits: layout.offset(bits as u64, i.bytes())? as u128, + size, + }) } Scalar::Ptr(ptr) => ptr.offset(i, layout).map(Scalar::Ptr), } } - pub fn ptr_wrapping_signed_offset(self, i: i64, cx: C) -> EvalResult<'tcx, Self> { + #[inline] + pub fn ptr_wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self { let layout = cx.data_layout(); match self { - Scalar::Bits { bits, defined } => { - let pointer_size = layout.pointer_size.bits() as u8; - if defined < pointer_size { - err!(ReadUndefBytes) - } else { - Ok(Scalar::Bits { - bits: layout.wrapping_signed_offset(bits as u64, i) as u128, - defined: pointer_size, - }) - } + Scalar::Bits { bits, size } => { + assert_eq!(size as u64, layout.pointer_size.bytes()); + Scalar::Bits { + bits: layout.wrapping_signed_offset(bits as u64, i) as u128, + size, + } } - Scalar::Ptr(ptr) => Ok(Scalar::Ptr(ptr.wrapping_signed_offset(i, layout))), + Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_signed_offset(i, layout)), } } - pub fn is_null_ptr(self, cx: C) -> EvalResult<'tcx, bool> { + #[inline] + pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool { match self { - Scalar::Bits { - bits, defined, - } => if defined < cx.data_layout().pointer_size.bits() as u8 { - err!(ReadUndefBytes) - } else { - Ok(bits == 0) + Scalar::Bits { bits, size } => { + assert_eq!(size as u64, cx.data_layout().pointer_size.bytes()); + bits == 0 }, - Scalar::Ptr(_) => Ok(false), + Scalar::Ptr(_) => false, } } - pub fn to_value_with_len(self, len: u64, cx: C) -> Value { - Value::ScalarPair(self, Scalar::Bits { - bits: len as u128, - defined: cx.data_layout().pointer_size.bits() as u8, - }) + #[inline] + pub fn is_null(self) -> bool { + match self { + Scalar::Bits { bits, .. } => bits == 0, + Scalar::Ptr(_) => false + } } - pub fn to_value_with_vtable(self, vtable: Pointer) -> Value { - Value::ScalarPair(self, Scalar::Ptr(vtable)) + #[inline] + pub fn from_bool(b: bool) -> Self { + Scalar::Bits { bits: b as u128, size: 1 } } - pub fn to_value(self) -> Value { - Value::Scalar(self) + #[inline] + pub fn from_char(c: char) -> Self { + Scalar::Bits { bits: c as u128, size: 4 } } -} -impl From for Scalar { - fn from(ptr: Pointer) -> Self { - Scalar::Ptr(ptr) + #[inline] + pub fn from_uint(i: impl Into, size: Size) -> Self { + let i = i.into(); + debug_assert_eq!(truncate(i, size), i, + "Unsigned value {} does not fit in {} bits", i, size.bits()); + Scalar::Bits { bits: i, size: size.bytes() as u8 } } -} - -/// A `Scalar` represents an immediate, primitive value existing outside of a -/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in -/// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes -/// of a simple value or a pointer into another `Allocation` -#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] -pub enum Scalar { - /// The raw bytes of a simple value. - Bits { - /// The first `defined` number of bits are valid - defined: u8, - bits: u128, - }, - - /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of - /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the - /// relocation and its associated offset together as a `Pointer` here. - Ptr(Pointer), -} -impl<'tcx> Scalar { - pub fn undef() -> Self { - Scalar::Bits { bits: 0, defined: 0 } + #[inline] + pub fn from_int(i: impl Into, size: Size) -> Self { + let i = i.into(); + // `into` performed sign extension, we have to truncate + let truncated = truncate(i as u128, size); + debug_assert_eq!(sign_extend(truncated, size) as i128, i, + "Signed value {} does not fit in {} bits", i, size.bits()); + Scalar::Bits { bits: truncated, size: size.bytes() as u8 } } - pub fn from_bool(b: bool) -> Self { - // FIXME: can we make defined `1`? - Scalar::Bits { bits: b as u128, defined: 8 } + #[inline] + pub fn from_f32(f: f32) -> Self { + Scalar::Bits { bits: f.to_bits() as u128, size: 4 } } - pub fn from_char(c: char) -> Self { - Scalar::Bits { bits: c as u128, defined: 32 } + #[inline] + pub fn from_f64(f: f64) -> Self { + Scalar::Bits { bits: f.to_bits() as u128, size: 8 } } - pub fn to_bits(self, size: Size) -> EvalResult<'tcx, u128> { + #[inline] + pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> { match self { - Scalar::Bits { .. } if size.bits() == 0 => bug!("to_bits cannot be used with zsts"), - Scalar::Bits { bits, defined } if size.bits() <= defined as u64 => Ok(bits), - Scalar::Bits { .. } => err!(ReadUndefBytes), + Scalar::Bits { bits, size } => { + assert_eq!(target_size.bytes(), size as u64); + assert_ne!(size, 0, "to_bits cannot be used with zsts"); + Ok(bits) + } Scalar::Ptr(_) => err!(ReadPointerAsBytes), } } + #[inline] pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> { match self { - Scalar::Bits {..} => err!(ReadBytesAsPointer), + Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage), + Scalar::Bits { .. } => err!(ReadBytesAsPointer), Scalar::Ptr(p) => Ok(p), } } + #[inline] pub fn is_bits(self) -> bool { match self { Scalar::Bits { .. } => true, @@ -247,6 +221,7 @@ impl<'tcx> Scalar { } } + #[inline] pub fn is_ptr(self) -> bool { match self { Scalar::Ptr(_) => true, @@ -256,9 +231,205 @@ impl<'tcx> Scalar { pub fn to_bool(self) -> EvalResult<'tcx, bool> { match self { - Scalar::Bits { bits: 0, defined: 8 } => Ok(false), - Scalar::Bits { bits: 1, defined: 8 } => Ok(true), + Scalar::Bits { bits: 0, size: 1 } => Ok(false), + Scalar::Bits { bits: 1, size: 1 } => Ok(true), _ => err!(InvalidBool), } } + + pub fn to_char(self) -> EvalResult<'tcx, char> { + let val = self.to_u32()?; + match ::std::char::from_u32(val) { + Some(c) => Ok(c), + None => err!(InvalidChar(val as u128)), + } + } + + pub fn to_u8(self) -> EvalResult<'static, u8> { + let sz = Size::from_bits(8); + let b = self.to_bits(sz)?; + assert_eq!(b as u8 as u128, b); + Ok(b as u8) + } + + pub fn to_u32(self) -> EvalResult<'static, u32> { + let sz = Size::from_bits(32); + let b = self.to_bits(sz)?; + assert_eq!(b as u32 as u128, b); + Ok(b as u32) + } + + pub fn to_u64(self) -> EvalResult<'static, u64> { + let sz = Size::from_bits(64); + let b = self.to_bits(sz)?; + assert_eq!(b as u64 as u128, b); + Ok(b as u64) + } + + pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> { + let b = self.to_bits(cx.data_layout().pointer_size)?; + assert_eq!(b as u64 as u128, b); + Ok(b as u64) + } + + pub fn to_i8(self) -> EvalResult<'static, i8> { + let sz = Size::from_bits(8); + let b = self.to_bits(sz)?; + let b = sign_extend(b, sz) as i128; + assert_eq!(b as i8 as i128, b); + Ok(b as i8) + } + + pub fn to_i32(self) -> EvalResult<'static, i32> { + let sz = Size::from_bits(32); + let b = self.to_bits(sz)?; + let b = sign_extend(b, sz) as i128; + assert_eq!(b as i32 as i128, b); + Ok(b as i32) + } + + pub fn to_i64(self) -> EvalResult<'static, i64> { + let sz = Size::from_bits(64); + let b = self.to_bits(sz)?; + let b = sign_extend(b, sz) as i128; + assert_eq!(b as i64 as i128, b); + Ok(b as i64) + } + + pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> { + let b = self.to_bits(cx.data_layout().pointer_size)?; + let b = sign_extend(b, cx.data_layout().pointer_size) as i128; + assert_eq!(b as i64 as i128, b); + Ok(b as i64) + } + + #[inline] + pub fn to_f32(self) -> EvalResult<'static, f32> { + Ok(f32::from_bits(self.to_u32()?)) + } + + #[inline] + pub fn to_f64(self) -> EvalResult<'static, f64> { + Ok(f64::from_bits(self.to_u64()?)) + } +} + +impl From for Scalar { + #[inline(always)] + fn from(ptr: Pointer) -> Self { + Scalar::Ptr(ptr) + } +} + +/// A `Scalar` represents an immediate, primitive value existing outside of a +/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in +/// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes +/// of a simple value or a pointer into another `Allocation` +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] +pub enum Scalar { + /// The raw bytes of a simple value. + Bits { + /// The first `size` bytes are the value. + /// Do not try to read less or more bytes that that. The remaining bytes must be 0. + size: u8, + bits: u128, + }, + + /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of + /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the + /// relocation and its associated offset together as a `Pointer` here. + Ptr(Pointer), +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] +pub enum ScalarMaybeUndef { + Scalar(Scalar), + Undef, +} + +impl From for ScalarMaybeUndef { + #[inline(always)] + fn from(s: Scalar) -> Self { + ScalarMaybeUndef::Scalar(s) + } +} + +impl<'tcx> ScalarMaybeUndef { + #[inline] + pub fn not_undef(self) -> EvalResult<'static, Scalar> { + match self { + ScalarMaybeUndef::Scalar(scalar) => Ok(scalar), + ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))), + } + } + + #[inline(always)] + pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> { + self.not_undef()?.to_ptr() + } + + #[inline(always)] + pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> { + self.not_undef()?.to_bits(target_size) + } + + #[inline(always)] + pub fn to_bool(self) -> EvalResult<'tcx, bool> { + self.not_undef()?.to_bool() + } + + #[inline(always)] + pub fn to_char(self) -> EvalResult<'tcx, char> { + self.not_undef()?.to_char() + } + + #[inline(always)] + pub fn to_f32(self) -> EvalResult<'tcx, f32> { + self.not_undef()?.to_f32() + } + + #[inline(always)] + pub fn to_f64(self) -> EvalResult<'tcx, f64> { + self.not_undef()?.to_f64() + } + + #[inline(always)] + pub fn to_u8(self) -> EvalResult<'tcx, u8> { + self.not_undef()?.to_u8() + } + + #[inline(always)] + pub fn to_u32(self) -> EvalResult<'tcx, u32> { + self.not_undef()?.to_u32() + } + + #[inline(always)] + pub fn to_u64(self) -> EvalResult<'tcx, u64> { + self.not_undef()?.to_u64() + } + + #[inline(always)] + pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> { + self.not_undef()?.to_usize(cx) + } + + #[inline(always)] + pub fn to_i8(self) -> EvalResult<'tcx, i8> { + self.not_undef()?.to_i8() + } + + #[inline(always)] + pub fn to_i32(self) -> EvalResult<'tcx, i32> { + self.not_undef()?.to_i32() + } + + #[inline(always)] + pub fn to_i64(self) -> EvalResult<'tcx, i64> { + self.not_undef()?.to_i64() + } + + #[inline(always)] + pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> { + self.not_undef()?.to_isize(cx) + } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 4bfb4c9649..3450eec808 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -17,17 +17,17 @@ use hir::def::CtorKind; use hir::def_id::DefId; use hir::{self, HirId, InlineAsm}; use middle::region; -use mir::interpret::{EvalErrorKind, Scalar, Value}; +use mir::interpret::{ConstValue, EvalErrorKind, Scalar, ScalarMaybeUndef}; use mir::visit::MirVisitable; use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use rustc_data_structures::small_vec::SmallVec; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::sync::ReadGuard; +use rustc_data_structures::sync::MappedReadGuard; use rustc_serialize as serialize; +use smallvec::SmallVec; use std::borrow::Cow; use std::fmt::{self, Debug, Formatter, Write}; use std::ops::{Index, IndexMut}; @@ -131,9 +131,6 @@ pub struct Mir<'tcx> { cache: cache::Cache, } -/// where execution begins -pub const START_BLOCK: BasicBlock = BasicBlock(0); - impl<'tcx> Mir<'tcx> { pub fn new( basic_blocks: IndexVec>, @@ -194,13 +191,42 @@ impl<'tcx> Mir<'tcx> { } #[inline] - pub fn predecessors(&self) -> ReadGuard>> { + pub fn predecessors(&self) -> MappedReadGuard<'_, IndexVec>> { self.cache.predecessors(self) } #[inline] - pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard> { - ReadGuard::map(self.predecessors(), |p| &p[bb]) + pub fn predecessors_for(&self, bb: BasicBlock) -> MappedReadGuard<'_, Vec> { + MappedReadGuard::map(self.predecessors(), |p| &p[bb]) + } + + #[inline] + pub fn predecessor_locations(&self, loc: Location) -> impl Iterator + '_ { + let if_zero_locations = if loc.statement_index == 0 { + let predecessor_blocks = self.predecessors_for(loc.block); + let num_predecessor_blocks = predecessor_blocks.len(); + Some( + (0..num_predecessor_blocks) + .map(move |i| predecessor_blocks[i]) + .map(move |bb| self.terminator_loc(bb)), + ) + } else { + None + }; + + let if_not_zero_locations = if loc.statement_index == 0 { + None + } else { + Some(Location { + block: loc.block, + statement_index: loc.statement_index - 1, + }) + }; + + if_zero_locations + .into_iter() + .flatten() + .chain(if_not_zero_locations) } #[inline] @@ -210,7 +236,7 @@ impl<'tcx> Mir<'tcx> { #[inline] pub fn local_kind(&self, local: Local) -> LocalKind { - let index = local.0 as usize; + let index = local.as_usize(); if index == 0 { debug_assert!( self.local_decls[local].mutability == Mutability::Mut, @@ -223,11 +249,6 @@ impl<'tcx> Mir<'tcx> { } else if self.local_decls[local].name.is_some() { LocalKind::Var } else { - debug_assert!( - self.local_decls[local].mutability == Mutability::Mut, - "temp should be mutable" - ); - LocalKind::Temp } } @@ -328,6 +349,14 @@ impl<'tcx> Mir<'tcx> { pub fn return_ty(&self) -> Ty<'tcx> { self.local_decls[RETURN_PLACE].ty } + + /// Get the location of the terminator for the given block + pub fn terminator_loc(&self, bb: BasicBlock) -> Location { + Location { + block: bb, + statement_index: self[bb].statements.len(), + } + } } #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] @@ -429,8 +458,8 @@ pub enum BorrowKind { /// Data must be immutable but not aliasable. This kind of borrow /// cannot currently be expressed by the user and is used only in - /// implicit closure bindings. It is needed when you the closure - /// is borrowing or mutating a mutable referent, e.g.: + /// implicit closure bindings. It is needed when the closure is + /// borrowing or mutating a mutable referent, e.g.: /// /// let x: &mut isize = ...; /// let y = || *x += 5; @@ -443,7 +472,7 @@ pub enum BorrowKind { /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn /// fn fn_ptr(env: &mut Env) { **env.x += 5; } /// - /// This is then illegal because you cannot mutate a `&mut` found + /// This is then illegal because you cannot mutate an `&mut` found /// in an aliasable location. To solve, you'd have to translate with /// an `&mut` borrow: /// @@ -486,11 +515,12 @@ impl BorrowKind { /////////////////////////////////////////////////////////////////////////// // Variables and temps -newtype_index!(Local - { +newtype_index! { + pub struct Local { DEBUG_FORMAT = "_{}", const RETURN_PLACE = 0, - }); + } +} /// Classifies locals into categories. See `Mir::local_kind`. #[derive(PartialEq, Eq, Debug)] @@ -523,6 +553,8 @@ pub struct VarBindingForm<'tcx> { /// (b) it gives a way to separate this case from the remaining cases /// for diagnostics. pub opt_match_place: Option<(Option>, Span)>, + /// Span of the pattern in which this variable was bound. + pub pat_span: Span, } #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -540,17 +572,20 @@ CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, } impl_stable_hash_for!(struct self::VarBindingForm<'tcx> { binding_mode, opt_ty_info, - opt_match_place + opt_match_place, + pat_span }); mod binding_form_impl { - use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use ich::StableHashingContext; + use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; impl<'a, 'tcx> HashStable> for super::BindingForm<'tcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { use super::BindingForm::*; ::std::mem::discriminant(self).hash_stable(hcx, hasher); @@ -605,6 +640,12 @@ pub struct LocalDecl<'tcx> { /// Type of this local. pub ty: Ty<'tcx>, + /// If the user manually ascribed a type to this variable, + /// e.g. via `let x: T`, then we carry that type here. The MIR + /// borrow checker needs this information since it can affect + /// region inference. + pub user_ty: Option>, + /// Name of the local, used in debuginfo and pretty-printing. /// /// Note that function arguments can also have this set to `Some(_)` @@ -673,7 +714,7 @@ pub struct LocalDecl<'tcx> { /// ROOT SCOPE /// │{ argument x: &str } /// │ - /// │ │{ #[allow(unused_mut] } // this is actually split into 2 scopes + /// │ │{ #[allow(unused_mut)] } // this is actually split into 2 scopes /// │ │ // in practice because I'm lazy. /// │ │ /// │ │← x.source_info.scope @@ -710,6 +751,7 @@ impl<'tcx> LocalDecl<'tcx> { binding_mode: ty::BindingMode::BindByValue(_), opt_ty_info: _, opt_match_place: _, + pat_span: _, }))) => true, // FIXME: might be able to thread the distinction between @@ -729,6 +771,7 @@ impl<'tcx> LocalDecl<'tcx> { binding_mode: ty::BindingMode::BindByValue(_), opt_ty_info: _, opt_match_place: _, + pat_span: _, }))) => true, Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true, @@ -740,33 +783,39 @@ impl<'tcx> LocalDecl<'tcx> { /// Create a new `LocalDecl` for a temporary. #[inline] pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self { - LocalDecl { - mutability: Mutability::Mut, - ty, - name: None, - source_info: SourceInfo { - span, - scope: OUTERMOST_SOURCE_SCOPE, - }, - visibility_scope: OUTERMOST_SOURCE_SCOPE, - internal: false, - is_user_variable: None, - } + Self::new_local(ty, Mutability::Mut, false, span) + } + + /// Create a new immutable `LocalDecl` for a temporary. + #[inline] + pub fn new_immutable_temp(ty: Ty<'tcx>, span: Span) -> Self { + Self::new_local(ty, Mutability::Not, false, span) } /// Create a new `LocalDecl` for a internal temporary. #[inline] pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self { + Self::new_local(ty, Mutability::Mut, true, span) + } + + #[inline] + fn new_local( + ty: Ty<'tcx>, + mutability: Mutability, + internal: bool, + span: Span, + ) -> Self { LocalDecl { - mutability: Mutability::Mut, + mutability, ty, + user_ty: None, name: None, source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE, }, visibility_scope: OUTERMOST_SOURCE_SCOPE, - internal: true, + internal, is_user_variable: None, } } @@ -779,6 +828,7 @@ impl<'tcx> LocalDecl<'tcx> { LocalDecl { mutability: Mutability::Mut, ty: return_ty, + user_ty: None, source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE, @@ -808,7 +858,12 @@ pub struct UpvarDecl { /////////////////////////////////////////////////////////////////////////// // BasicBlock -newtype_index!(BasicBlock { DEBUG_FORMAT = "bb{}" }); +newtype_index! { + pub struct BasicBlock { + DEBUG_FORMAT = "bb{}", + const START_BLOCK = 0, + } +} impl BasicBlock { pub fn start_location(self) -> Location { @@ -906,7 +961,7 @@ pub enum TerminatorKind<'tcx> { /// Drop the Place and assign the new value over it. This ensures /// that the assignment to `P` occurs *even if* the destructor for - /// place unwinds. Its semantics are best explained by by the + /// place unwinds. Its semantics are best explained by the /// elaboration: /// /// ``` @@ -922,11 +977,11 @@ pub enum TerminatorKind<'tcx> { /// Drop(P, goto BB1, unwind BB2) /// } /// BB1 { - /// // P is now unitialized + /// // P is now uninitialized /// P <- V /// } /// BB2 { - /// // P is now unitialized -- its dtor panicked + /// // P is now uninitialized -- its dtor panicked /// P <- V /// } /// ``` @@ -1464,17 +1519,18 @@ impl<'tcx> TerminatorKind<'tcx> { .iter() .map(|&u| { let mut s = String::new(); - print_miri_value( - Value::Scalar(Scalar::Bits { - bits: u, - defined: size.bits() as u8, - }), - switch_ty, - &mut s, - ).unwrap(); + let c = ty::Const { + val: ConstValue::Scalar( + Scalar::Bits { + bits: u, + size: size.bytes() as u8, + }.into(), + ), + ty: switch_ty, + }; + fmt_const_val(&mut s, &c).unwrap(); s.into() - }) - .chain(iter::once(String::from("otherwise").into())) + }).chain(iter::once(String::from("otherwise").into())) .collect() } Call { @@ -1588,22 +1644,19 @@ pub enum StatementKind<'tcx> { /// (The starting point(s) arise implicitly from borrows.) EndRegion(region::Scope), - /// Encodes a user's type assertion. These need to be preserved intact so that NLL can respect - /// them. For example: - /// - /// let (a, b): (T, U) = y; + /// Encodes a user's type ascription. These need to be preserved + /// intact so that NLL can respect them. For example: /// - /// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y` - /// is the right thing. + /// let a: T = y; /// - /// `CanonicalTy` is used to capture "inference variables" from the user's types. For example: + /// The effect of this annotation is to relate the type `T_y` of the place `y` + /// to the user-given type `T`. The effect depends on the specified variance: /// - /// let x: Vec<_> = ...; - /// let y: &u32 = ...; - /// - /// would result in `Vec` and `&'?0 u32` respectively (where `?0` is a canonicalized - /// variable). - UserAssertTy(CanonicalTy<'tcx>, Local), + /// - `Covariant` -- requires that `T_y <: T` + /// - `Contravariant` -- requires that `T_y :> T` + /// - `Invariant` -- requires that `T_y == T` + /// - `Bivariant` -- no effect + AscribeUserType(Place<'tcx>, ty::Variance, CanonicalTy<'tcx>), /// No-op. Useful for deleting instructions without affecting statement indices. Nop, @@ -1680,8 +1733,8 @@ impl<'tcx> Debug for Statement<'tcx> { ref outputs, ref inputs, } => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs), - UserAssertTy(ref c_ty, ref local) => { - write!(fmt, "UserAssertTy({:?}, {:?})", c_ty, local) + AscribeUserType(ref place, ref variance, ref c_ty) => { + write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty) } Nop => write!(fmt, "nop"), } @@ -1777,7 +1830,11 @@ pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>; /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>; -newtype_index!(Field { DEBUG_FORMAT = "field[{}]" }); +newtype_index! { + pub struct Field { + DEBUG_FORMAT = "field[{}]" + } +} impl<'tcx> Place<'tcx> { pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { @@ -1850,11 +1907,12 @@ impl<'tcx> Debug for Place<'tcx> { /////////////////////////////////////////////////////////////////////////// // Scopes -newtype_index!(SourceScope - { +newtype_index! { + pub struct SourceScope { DEBUG_FORMAT = "scope[{}]", const OUTERMOST_SOURCE_SCOPE = 0, - }); + } +} #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct SourceScopeData { @@ -1883,12 +1941,15 @@ pub enum Operand<'tcx> { /// This implies that the type of the place must be `Copy`; this is true /// by construction during build, but also checked by the MIR type checker. Copy(Place<'tcx>), + /// Move: The value (including old borrows of it) will not be used again. /// /// Safe for values of all types (modulo future developments towards `?Move`). /// Correct usage patterns are enforced by the borrow checker for safe code. /// `Copy` may be converted to `Move` to enable "last-use" optimizations. Move(Place<'tcx>), + + /// Synthesizes a constant value. Constant(Box>), } @@ -1904,6 +1965,9 @@ impl<'tcx> Debug for Operand<'tcx> { } impl<'tcx> Operand<'tcx> { + /// Convenience helper to make a constant that refers to the fn + /// with given def-id and substs. Since this is used to synthesize + /// MIR, assumes `user_ty` is None. pub fn function_handle<'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, @@ -1914,6 +1978,7 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(box Constant { span, ty, + user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }) } @@ -1997,7 +2062,13 @@ pub enum AggregateKind<'tcx> { /// active field number and is present only for union expressions /// -- e.g. for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` - Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option), + Adt( + &'tcx AdtDef, + usize, + &'tcx Substs<'tcx>, + Option>, + Option, + ), Closure(DefId, ClosureSubsts<'tcx>), Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), @@ -2100,7 +2171,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { region } else { // Do not even print 'static - "".to_owned() + String::new() }; write!(fmt, "&{}{}{:?}", region, kind_str, place) } @@ -2123,7 +2194,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { _ => fmt_tuple(fmt, places), }, - AggregateKind::Adt(adt_def, variant, substs, _) => { + AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => { let variant_def = &adt_def.variants[variant]; ppaux::parameterized(fmt, substs, variant_def.did, &[])?; @@ -2202,10 +2273,22 @@ impl<'tcx> Debug for Rvalue<'tcx> { pub struct Constant<'tcx> { pub span: Span, pub ty: Ty<'tcx>, + + /// Optional user-given type: for something like + /// `collect::>`, this would be present and would + /// indicate that `Vec<_>` was explicitly specified. + /// + /// Needed for NLL to impose user-given type constraints. + pub user_ty: Option>, + pub literal: &'tcx ty::Const<'tcx>, } -newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" }); +newtype_index! { + pub struct Promoted { + DEBUG_FORMAT = "promoted[{}]" + } +} impl<'tcx> Debug for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { @@ -2215,55 +2298,60 @@ impl<'tcx> Debug for Constant<'tcx> { } /// Write a `ConstValue` in a way closer to the original source code than the `Debug` output. -pub fn fmt_const_val(fmt: &mut W, const_val: &ty::Const) -> fmt::Result { - if let Some(value) = const_val.to_byval_value() { - print_miri_value(value, const_val.ty, fmt) - } else { - write!(fmt, "{:?}:{}", const_val.val, const_val.ty) - } -} - -pub fn print_miri_value(value: Value, ty: Ty, f: &mut W) -> fmt::Result { - use ty::TypeVariants::*; - match (value, &ty.sty) { - (Value::Scalar(Scalar::Bits { bits: 0, .. }), &TyBool) => write!(f, "false"), - (Value::Scalar(Scalar::Bits { bits: 1, .. }), &TyBool) => write!(f, "true"), - (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F32)) => { - write!(f, "{}f32", Single::from_bits(bits)) - } - (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F64)) => { - write!(f, "{}f64", Double::from_bits(bits)) - } - (Value::Scalar(Scalar::Bits { bits, .. }), &TyUint(ui)) => write!(f, "{:?}{}", bits, ui), - (Value::Scalar(Scalar::Bits { bits, .. }), &TyInt(i)) => { - let bit_width = ty::tls::with(|tcx| { - let ty = tcx.lift_to_global(&ty).unwrap(); - tcx.layout_of(ty::ParamEnv::empty().and(ty)) - .unwrap() - .size - .bits() - }); - let shift = 128 - bit_width; - write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i) - } - (Value::Scalar(Scalar::Bits { bits, .. }), &TyChar) => { - write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()) +pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const) -> fmt::Result { + use ty::TyKind::*; + let value = const_val.val; + let ty = const_val.ty; + // print some primitives + if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = value { + match ty.sty { + Bool if bits == 0 => return write!(f, "false"), + Bool if bits == 1 => return write!(f, "true"), + Float(ast::FloatTy::F32) => return write!(f, "{}f32", Single::from_bits(bits)), + Float(ast::FloatTy::F64) => return write!(f, "{}f64", Double::from_bits(bits)), + Uint(ui) => return write!(f, "{:?}{}", bits, ui), + Int(i) => { + let bit_width = ty::tls::with(|tcx| { + let ty = tcx.lift_to_global(&ty).unwrap(); + tcx.layout_of(ty::ParamEnv::empty().and(ty)) + .unwrap() + .size + .bits() + }); + let shift = 128 - bit_width; + return write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i); + } + Char => return write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()), + _ => {} } - (_, &TyFnDef(did, _)) => write!(f, "{}", item_path_str(did)), - ( - Value::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: len, .. }), - &TyRef(_, &ty::TyS { sty: TyStr, .. }, _), - ) => ty::tls::with(|tcx| match tcx.alloc_map.lock().get(ptr.alloc_id) { - Some(interpret::AllocType::Memory(alloc)) => { - assert_eq!(len as usize as u128, len); - let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)]; - let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); - write!(f, "{:?}", s) + } + // print function definitons + if let FnDef(did, _) = ty.sty { + return write!(f, "{}", item_path_str(did)); + } + // print string literals + if let ConstValue::ScalarPair(ptr, len) = value { + if let Scalar::Ptr(ptr) = ptr { + if let ScalarMaybeUndef::Scalar(Scalar::Bits { bits: len, .. }) = len { + if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty { + return ty::tls::with(|tcx| { + let alloc = tcx.alloc_map.lock().get(ptr.alloc_id); + if let Some(interpret::AllocType::Memory(alloc)) = alloc { + assert_eq!(len as usize as u128, len); + let slice = + &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)]; + let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); + write!(f, "{:?}", s) + } else { + write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len) + } + }); + } } - _ => write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len), - }), - _ => write!(f, "{:?}:{}", value, ty), + } } + // just raw dump everything else + write!(f, "{:?}:{}", value, ty) } fn item_path_str(def_id: DefId) -> String { @@ -2359,6 +2447,8 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum UnsafetyViolationKind { General, + /// unsafety is not allowed at all in min const fn + MinConstFn, ExternStatic(ast::NodeId), BorrowPacked(ast::NodeId), } @@ -2531,6 +2621,7 @@ BraceStructTypeFoldableImpl! { is_user_variable, internal, ty, + user_ty, name, source_info, visibility_scope, @@ -2567,7 +2658,7 @@ EnumTypeFoldableImpl! { (StatementKind::InlineAsm) { asm, outputs, inputs }, (StatementKind::Validate)(a, b), (StatementKind::EndRegion)(a), - (StatementKind::UserAssertTy)(a, b), + (StatementKind::AscribeUserType)(a, v, b), (StatementKind::Nop), } } @@ -2786,9 +2877,13 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { let kind = box match **kind { AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), AggregateKind::Tuple => AggregateKind::Tuple, - AggregateKind::Adt(def, v, substs, n) => { - AggregateKind::Adt(def, v, substs.fold_with(folder), n) - } + AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( + def, + v, + substs.fold_with(folder), + user_ty.fold_with(folder), + n, + ), AggregateKind::Closure(id, substs) => { AggregateKind::Closure(id, substs.fold_with(folder)) } @@ -2819,7 +2914,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { (match **kind { AggregateKind::Array(ty) => ty.visit_with(visitor), AggregateKind::Tuple => false, - AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor), + AggregateKind::Adt(_, _, substs, user_ty, _) => { + substs.visit_with(visitor) || user_ty.visit_with(visitor) + } AggregateKind::Closure(_, substs) => substs.visit_with(visitor), AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor), }) || fields.visit_with(visitor) @@ -2890,6 +2987,7 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { Constant { span: self.span.clone(), ty: self.ty.fold_with(folder), + user_ty: self.user_ty.fold_with(folder), literal: self.literal.fold_with(folder), } } diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index f0d6b8170e..4d353a36db 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -8,15 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::DefId; +use hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use syntax::ast::NodeId; -use syntax::symbol::InternedString; +use syntax::symbol::{Symbol, InternedString}; use ty::{Instance, TyCtxt}; use util::nodemap::FxHashMap; use rustc_data_structures::base_n; use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult, StableHasher}; use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode}; +use std::fmt; use std::hash::Hash; #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] @@ -239,3 +240,112 @@ impl Stats { self.fn_stats.extend(stats.fn_stats); } } + +pub struct CodegenUnitNameBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + cache: FxHashMap, +} + +impl<'a, 'gcx: 'tcx, 'tcx: 'a> CodegenUnitNameBuilder<'a, 'gcx, 'tcx> { + + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { + CodegenUnitNameBuilder { + tcx, + cache: FxHashMap(), + } + } + + /// CGU names should fulfill the following requirements: + /// - They should be able to act as a file name on any kind of file system + /// - They should not collide with other CGU names, even for different versions + /// of the same crate. + /// + /// Consequently, we don't use special characters except for '.' and '-' and we + /// prefix each name with the crate-name and crate-disambiguator. + /// + /// This function will build CGU names of the form: + /// + /// ``` + /// .[-in-](-)*[.] + /// = . + /// ``` + /// + /// The '.' before `` makes sure that names with a special + /// suffix can never collide with a name built out of regular Rust + /// identifiers (e.g. module paths). + pub fn build_cgu_name(&mut self, + cnum: CrateNum, + components: I, + special_suffix: Option) + -> InternedString + where I: IntoIterator, + C: fmt::Display, + S: fmt::Display, + { + let cgu_name = self.build_cgu_name_no_mangle(cnum, + components, + special_suffix); + + if self.tcx.sess.opts.debugging_opts.human_readable_cgu_names { + cgu_name + } else { + let cgu_name = &cgu_name.as_str()[..]; + Symbol::intern(&CodegenUnit::mangle_name(cgu_name)).as_interned_str() + } + } + + /// Same as `CodegenUnit::build_cgu_name()` but will never mangle the + /// resulting name. + pub fn build_cgu_name_no_mangle(&mut self, + cnum: CrateNum, + components: I, + special_suffix: Option) + -> InternedString + where I: IntoIterator, + C: fmt::Display, + S: fmt::Display, + { + use std::fmt::Write; + + let mut cgu_name = String::with_capacity(64); + + // Start out with the crate name and disambiguator + let tcx = self.tcx; + let crate_prefix = self.cache.entry(cnum).or_insert_with(|| { + // Whenever the cnum is not LOCAL_CRATE we also mix in the + // local crate's ID. Otherwise there can be collisions between CGUs + // instantiating stuff for upstream crates. + let local_crate_id = if cnum != LOCAL_CRATE { + let local_crate_disambiguator = + format!("{}", tcx.crate_disambiguator(LOCAL_CRATE)); + format!("-in-{}.{}", + tcx.crate_name(LOCAL_CRATE), + &local_crate_disambiguator[0 .. 8]) + } else { + String::new() + }; + + let crate_disambiguator = format!("{}", tcx.crate_disambiguator(cnum)); + // Using a shortened disambiguator of about 40 bits + format!("{}.{}{}", + tcx.crate_name(cnum), + &crate_disambiguator[0 .. 8], + local_crate_id) + }); + + write!(cgu_name, "{}", crate_prefix).unwrap(); + + // Add the components + for component in components { + write!(cgu_name, "-{}", component).unwrap(); + } + + if let Some(special_suffix) = special_suffix { + // We add a dot in here so it cannot clash with anything in a regular + // Rust identifier + write!(cgu_name, ".{}", special_suffix).unwrap(); + } + + Symbol::intern(&cgu_name[..]).as_interned_str() + } +} diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index b55843ac52..c928be4f9d 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -68,12 +68,12 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { let ty = self.to_ty(tcx); PlaceTy::Ty { ty: match ty.sty { - ty::TyArray(inner, size) => { + ty::Array(inner, size) => { let size = size.unwrap_usize(tcx); let len = size - (from as u64) - (to as u64); tcx.mk_array(inner, len) } - ty::TySlice(..) => ty, + ty::Slice(..) => ty, _ => { bug!("cannot subslice non-array type: `{:?}`", self) } @@ -82,7 +82,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { } ProjectionElem::Downcast(adt_def1, index) => match self.to_ty(tcx).sty { - ty::TyAdt(adt_def, substs) => { + ty::Adt(adt_def, substs) => { assert!(adt_def.is_enum()); assert!(index < adt_def.variants.len()); assert_eq!(adt_def, adt_def1); @@ -127,14 +127,14 @@ impl<'tcx> Place<'tcx> { /// of a closure type. pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>, tcx: &TyCtxt<'cx, 'gcx, 'tcx>) -> Option { - let place = if let Place::Projection(ref proj) = self { + let (place, by_ref) = if let Place::Projection(ref proj) = self { if let ProjectionElem::Deref = proj.elem { - &proj.base + (&proj.base, true) } else { - self + (self, false) } } else { - self + (self, false) }; match place { @@ -142,14 +142,16 @@ impl<'tcx> Place<'tcx> { ProjectionElem::Field(field, _ty) => { let base_ty = proj.base.ty(mir, *tcx).to_ty(*tcx); - if base_ty.is_closure() || base_ty.is_generator() { + if (base_ty.is_closure() || base_ty.is_generator()) && + (!by_ref || mir.upvar_decls[field.index()].by_ref) + { Some(field) } else { None } }, _ => None, - }, + } _ => None, } } @@ -197,7 +199,7 @@ impl<'tcx> Rvalue<'tcx> { } Rvalue::Discriminant(ref place) => { let ty = place.ty(local_decls, tcx).to_ty(tcx); - if let ty::TyAdt(adt_def, _) = ty.sty { + if let ty::Adt(adt_def, _) = ty.sty { adt_def.repr.discr_type().to_ty(tcx) } else { // This can only be `0`, for now, so `u8` will suffice. @@ -214,7 +216,7 @@ impl<'tcx> Rvalue<'tcx> { AggregateKind::Tuple => { tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))) } - AggregateKind::Adt(def, _, substs, _) => { + AggregateKind::Adt(def, _, substs, _, _) => { tcx.type_of(def.did).subst(tcx, substs) } AggregateKind::Closure(did, substs) => { diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 86fd825850..c919793fe3 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use super::*; @@ -32,7 +32,7 @@ use super::*; #[derive(Clone)] pub struct Preorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, - visited: BitVector, + visited: BitArray, worklist: Vec, } @@ -42,7 +42,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { Preorder { mir, - visited: BitVector::new(mir.basic_blocks().len()), + visited: BitArray::new(mir.basic_blocks().len()), worklist, } } @@ -104,7 +104,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} /// A Postorder traversal of this graph is `D B C A` or `D C B A` pub struct Postorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, - visited: BitVector, + visited: BitArray, visit_stack: Vec<(BasicBlock, Successors<'a>)> } @@ -112,7 +112,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> { let mut po = Postorder { mir, - visited: BitVector::new(mir.basic_blocks().len()), + visited: BitArray::new(mir.basic_blocks().len()), visit_stack: Vec::new() }; @@ -171,7 +171,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { // (A, [C])] // // Now that the top of the stack has no successors we can traverse, each item will - // be popped off during iteration until we get back to `A`. This yeilds [E, D, B]. + // be popped off during iteration until we get back to `A`. This yields [E, D, B]. // // When we yield `B` and call `traverse_successor`, we push `C` to the stack, but // since we've already visited `E`, that child isn't added to the stack. The last diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index cab6ed0c12..0beb5ac0a3 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -144,11 +144,12 @@ macro_rules! make_mir_visitor { self.super_operand(operand, location); } - fn visit_user_assert_ty(&mut self, - c_ty: & $($mutability)* CanonicalTy<'tcx>, - local: & $($mutability)* Local, - location: Location) { - self.super_user_assert_ty(c_ty, local, location); + fn visit_ascribe_user_ty(&mut self, + place: & $($mutability)* Place<'tcx>, + variance: & $($mutability)* ty::Variance, + c_ty: & $($mutability)* CanonicalTy<'tcx>, + location: Location) { + self.super_ascribe_user_ty(place, variance, c_ty, location); } fn visit_place(&mut self, @@ -213,6 +214,10 @@ macro_rules! make_mir_visitor { self.super_ty(ty); } + fn visit_canonical_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) { + self.super_canonical_ty(ty); + } + fn visit_region(&mut self, region: & $($mutability)* ty::Region<'tcx>, _: Location) { @@ -382,9 +387,12 @@ macro_rules! make_mir_visitor { self.visit_operand(input, location); } } - StatementKind::UserAssertTy(ref $($mutability)* c_ty, - ref $($mutability)* local) => { - self.visit_user_assert_ty(c_ty, local, location); + StatementKind::AscribeUserType( + ref $($mutability)* place, + ref $($mutability)* variance, + ref $($mutability)* c_ty, + ) => { + self.visit_ascribe_user_ty(place, variance, c_ty, location); } StatementKind::Nop => {} } @@ -585,6 +593,7 @@ macro_rules! make_mir_visitor { AggregateKind::Adt(_adt_def, _variant_index, ref $($mutability)* substs, + _user_substs, _active_field_index) => { self.visit_substs(substs, location); } @@ -624,11 +633,13 @@ macro_rules! make_mir_visitor { } } - fn super_user_assert_ty(&mut self, - _c_ty: & $($mutability)* CanonicalTy<'tcx>, - local: & $($mutability)* Local, - location: Location) { - self.visit_local(local, PlaceContext::Validate, location); + fn super_ascribe_user_ty(&mut self, + place: & $($mutability)* Place<'tcx>, + _variance: & $($mutability)* ty::Variance, + c_ty: & $($mutability)* CanonicalTy<'tcx>, + location: Location) { + self.visit_place(place, PlaceContext::Validate, location); + self.visit_canonical_ty(c_ty); } fn super_place(&mut self, @@ -710,6 +721,7 @@ macro_rules! make_mir_visitor { let LocalDecl { mutability: _, ref $($mutability)* ty, + ref $($mutability)* user_ty, name: _, ref $($mutability)* source_info, ref $($mutability)* visibility_scope, @@ -721,6 +733,9 @@ macro_rules! make_mir_visitor { local, source_info: *source_info, }); + if let Some(user_ty) = user_ty { + self.visit_canonical_ty(user_ty); + } self.visit_source_info(source_info); self.visit_source_scope(visibility_scope); } @@ -740,11 +755,13 @@ macro_rules! make_mir_visitor { let Constant { ref $($mutability)* span, ref $($mutability)* ty, + ref $($mutability)* user_ty, ref $($mutability)* literal, } = *constant; self.visit_span(span); self.visit_ty(ty, TyContext::Location(location)); + drop(user_ty); // no visit method for this self.visit_const(literal, location); } @@ -764,6 +781,9 @@ macro_rules! make_mir_visitor { self.visit_source_scope(scope); } + fn super_canonical_ty(&mut self, _ty: & $($mutability)* CanonicalTy<'tcx>) { + } + fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) { } diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs index 1eee6508c5..32865acb29 100644 --- a/src/librustc/session/code_stats.rs +++ b/src/librustc/session/code_stats.rs @@ -8,11 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ty::AdtKind; -use ty::layout::{Align, Size}; - +use rustc_target::abi::{Align, Size}; use rustc_data_structures::fx::{FxHashSet}; - use std::cmp::{self, Ordering}; #[derive(Clone, PartialEq, Eq, Hash, Debug)] @@ -38,16 +35,6 @@ pub struct FieldInfo { pub align: u64, } -impl From for DataTypeKind { - fn from(kind: AdtKind) -> Self { - match kind { - AdtKind::Struct => DataTypeKind::Struct, - AdtKind::Enum => DataTypeKind::Enum, - AdtKind::Union => DataTypeKind::Union, - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum DataTypeKind { Struct, diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 1fe57bc338..4c0eeba744 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -11,25 +11,18 @@ //! Contains infrastructure for configuring the compiler, including parsing //! command line options. -pub use self::EntryFnType::*; -pub use self::CrateType::*; -pub use self::Passes::*; -pub use self::DebugInfoLevel::*; - use std::str::FromStr; use session::{early_error, early_warn, Session}; use session::search_paths::SearchPaths; -use ich::StableHashingContext; use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; use rustc_target::spec::{Target, TargetTriple}; -use rustc_data_structures::stable_hasher::ToStableHashKey; use lint; use middle::cstore; use syntax::ast::{self, IntTy, UintTy, MetaItemKind}; -use syntax::codemap::{FileName, FilePathMapping}; +use syntax::source_map::{FileName, FilePathMapping}; use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION}; use syntax::parse::token; use syntax::parse; @@ -44,10 +37,10 @@ use std::collections::btree_map::Iter as BTreeMapIter; use std::collections::btree_map::Keys as BTreeMapKeysIter; use std::collections::btree_map::Values as BTreeMapValuesIter; +use rustc_data_structures::fx::FxHashSet; use std::{fmt, str}; use std::hash::Hasher; use std::collections::hash_map::DefaultHasher; -use std::collections::HashSet; use std::iter::FromIterator; use std::path::{Path, PathBuf}; @@ -65,7 +58,7 @@ pub enum Sanitizer { Thread, } -#[derive(Clone, Copy, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum OptLevel { No, // -O0 Less, // -O1 @@ -75,15 +68,13 @@ pub enum OptLevel { SizeMin, // -Oz } -#[derive(Clone, Copy, PartialEq, Hash)] +/// This is what the `LtoCli` values get mapped to after resolving defaults and +/// and taking other command line options into account. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Lto { /// Don't do any LTO whatsoever No, - /// Do a full crate graph LTO. The flavor is determined by the compiler - /// (currently the default is "fat"). - Yes, - /// Do a full crate graph LTO with ThinLTO Thin, @@ -95,6 +86,23 @@ pub enum Lto { Fat, } +/// The different settings that the `-C lto` flag can have. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum LtoCli { + /// `-C lto=no` + No, + /// `-C lto=yes` + Yes, + /// `-C lto` + NoParam, + /// `-C lto=thin` + Thin, + /// `-C lto=fat` + Fat, + /// No `-C lto` flag passed + Unspecified, +} + #[derive(Clone, PartialEq, Hash)] pub enum CrossLangLto { LinkerPlugin(PathBuf), @@ -113,10 +121,10 @@ impl CrossLangLto { } #[derive(Clone, Copy, PartialEq, Hash)] -pub enum DebugInfoLevel { - NoDebugInfo, - LimitedDebugInfo, - FullDebugInfo, +pub enum DebugInfo { + None, + Limited, + Full, } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)] @@ -131,25 +139,7 @@ pub enum OutputType { DepInfo, } - -impl_stable_hash_for!(enum self::OutputType { - Bitcode, - Assembly, - LlvmAssembly, - Mir, - Metadata, - Object, - Exe, - DepInfo -}); - -impl<'a, 'tcx> ToStableHashKey> for OutputType { - type KeyType = OutputType; - #[inline] - fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> Self::KeyType { - *self - } -} +impl_stable_hash_via_hash!(OutputType); impl OutputType { fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool { @@ -238,9 +228,7 @@ impl Default for ErrorOutputType { #[derive(Clone, Hash)] pub struct OutputTypes(BTreeMap>); -impl_stable_hash_for!(tuple_struct self::OutputTypes { - map -}); +impl_stable_hash_via_hash!(OutputTypes); impl OutputTypes { pub fn new(entries: &[(OutputType, Option)]) -> OutputTypes { @@ -287,18 +275,18 @@ impl OutputTypes { // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That // would break dependency tracking for commandline arguments. #[derive(Clone, Hash)] -pub struct Externs(BTreeMap>); +pub struct Externs(BTreeMap>>); impl Externs { - pub fn new(data: BTreeMap>) -> Externs { + pub fn new(data: BTreeMap>>) -> Externs { Externs(data) } - pub fn get(&self, key: &str) -> Option<&BTreeSet> { + pub fn get(&self, key: &str) -> Option<&BTreeSet>> { self.0.get(key) } - pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet> { + pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet>> { self.0.iter() } } @@ -381,7 +369,7 @@ top_level_options!( // Include the debug_assertions flag into dependency tracking, since it // can influence whether overflow checks are done or not. debug_assertions: bool [TRACKED], - debuginfo: DebugInfoLevel [TRACKED], + debuginfo: DebugInfo [TRACKED], lint_opts: Vec<(String, lint::Level)> [TRACKED], lint_cap: Option [TRACKED], describe_lints: bool [UNTRACKED], @@ -517,7 +505,7 @@ impl Input { } } -#[derive(Clone)] +#[derive(Clone, Hash)] pub struct OutputFilenames { pub out_directory: PathBuf, pub out_filestem: String, @@ -526,13 +514,7 @@ pub struct OutputFilenames { pub outputs: OutputTypes, } -impl_stable_hash_for!(struct self::OutputFilenames { - out_directory, - out_filestem, - single_output_file, - extra, - outputs -}); +impl_stable_hash_via_hash!(OutputFilenames); pub const RUST_CGU_EXT: &str = "rcgu"; @@ -601,37 +583,38 @@ pub fn host_triple() -> &'static str { (option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE") } -/// Some reasonable defaults -pub fn basic_options() -> Options { - Options { - crate_types: Vec::new(), - optimize: OptLevel::No, - debuginfo: NoDebugInfo, - lint_opts: Vec::new(), - lint_cap: None, - describe_lints: false, - output_types: OutputTypes(BTreeMap::new()), - search_paths: SearchPaths::new(), - maybe_sysroot: None, - target_triple: TargetTriple::from_triple(host_triple()), - test: false, - incremental: None, - debugging_opts: basic_debugging_options(), - prints: Vec::new(), - borrowck_mode: BorrowckMode::Ast, - cg: basic_codegen_options(), - error_format: ErrorOutputType::default(), - externs: Externs(BTreeMap::new()), - crate_name: None, - alt_std_name: None, - libs: Vec::new(), - unstable_features: UnstableFeatures::Disallow, - debug_assertions: true, - actually_rustdoc: false, - cli_forced_codegen_units: None, - cli_forced_thinlto_off: false, - remap_path_prefix: Vec::new(), - edition: DEFAULT_EDITION, +impl Default for Options { + fn default() -> Options { + Options { + crate_types: Vec::new(), + optimize: OptLevel::No, + debuginfo: DebugInfo::None, + lint_opts: Vec::new(), + lint_cap: None, + describe_lints: false, + output_types: OutputTypes(BTreeMap::new()), + search_paths: SearchPaths::new(), + maybe_sysroot: None, + target_triple: TargetTriple::from_triple(host_triple()), + test: false, + incremental: None, + debugging_opts: basic_debugging_options(), + prints: Vec::new(), + borrowck_mode: BorrowckMode::Ast, + cg: basic_codegen_options(), + error_format: ErrorOutputType::default(), + externs: Externs(BTreeMap::new()), + crate_name: None, + alt_std_name: None, + libs: Vec::new(), + unstable_features: UnstableFeatures::Disallow, + debug_assertions: true, + actually_rustdoc: false, + cli_forced_codegen_units: None, + cli_forced_thinlto_off: false, + remap_path_prefix: Vec::new(), + edition: DEFAULT_EDITION, + } } } @@ -657,6 +640,24 @@ impl Options { !self.debugging_opts.parse_only && // The file is just being parsed !self.debugging_opts.ls // The file is just being queried } + + #[inline] + pub fn share_generics(&self) -> bool { + match self.debugging_opts.share_generics { + Some(setting) => setting, + None => { + self.incremental.is_some() || + match self.optimize { + OptLevel::No | + OptLevel::Less | + OptLevel::Size | + OptLevel::SizeMin => true, + OptLevel::Default | + OptLevel::Aggressive => false, + } + } + } + } } // The type of entry function, so @@ -664,31 +665,31 @@ impl Options { // functions #[derive(Copy, Clone, PartialEq)] pub enum EntryFnType { - EntryMain, - EntryStart, + Main, + Start, } #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)] pub enum CrateType { - CrateTypeExecutable, - CrateTypeDylib, - CrateTypeRlib, - CrateTypeStaticlib, - CrateTypeCdylib, - CrateTypeProcMacro, + Executable, + Dylib, + Rlib, + Staticlib, + Cdylib, + ProcMacro, } #[derive(Clone, Hash)] pub enum Passes { - SomePasses(Vec), - AllPasses, + Some(Vec), + All, } impl Passes { pub fn is_empty(&self) -> bool { match *self { - SomePasses(ref v) => v.is_empty(), - AllPasses => false, + Passes::Some(ref v) => v.is_empty(), + Passes::All => false, } } } @@ -815,16 +816,16 @@ macro_rules! options { pub const parse_unpretty: Option<&'static str> = Some("`string` or `string=string`"); pub const parse_lto: Option<&'static str> = - Some("one of `thin`, `fat`, or omitted"); + Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \ + `fat`, or omitted"); pub const parse_cross_lang_lto: Option<&'static str> = - Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `no-link`, \ + Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \ or the path to the linker plugin"); } #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto, - CrossLangLto}; + use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto}; use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; use std::path::PathBuf; @@ -935,13 +936,13 @@ macro_rules! options { fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool { match v { Some("all") => { - *slot = AllPasses; + *slot = Passes::All; true } v => { let mut passes = vec![]; if parse_list(&mut passes, v) { - *slot = SomePasses(passes); + *slot = Passes::Some(passes); true } else { false @@ -1017,11 +1018,23 @@ macro_rules! options { } } - fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool { + fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool { + if v.is_some() { + let mut bool_arg = None; + if parse_opt_bool(&mut bool_arg, v) { + *slot = if bool_arg.unwrap() { + LtoCli::Yes + } else { + LtoCli::No + }; + return true + } + } + *slot = match v { - None => Lto::Yes, - Some("thin") => Lto::Thin, - Some("fat") => Lto::Fat, + None => LtoCli::NoParam, + Some("thin") => LtoCli::Thin, + Some("fat") => LtoCli::Fat, Some(_) => return false, }; true @@ -1062,11 +1075,11 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "extra arguments to append to the linker invocation (space separated)"), link_dead_code: bool = (false, parse_bool, [UNTRACKED], "don't let linker strip dead code (turning it on can be used for code coverage)"), - lto: Lto = (Lto::No, parse_lto, [TRACKED], + lto: LtoCli = (LtoCli::Unspecified, parse_lto, [TRACKED], "perform LLVM link-time optimizations"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (rustc --print target-cpus for details)"), - target_feature: String = ("".to_string(), parse_string, [TRACKED], + target_feature: String = (String::new(), parse_string, [TRACKED], "target specific attributes (rustc --print target-features for details)"), passes: Vec = (Vec::new(), parse_list, [TRACKED], "a list of extra LLVM passes to run (space separated)"), @@ -1100,11 +1113,11 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "choose the code model to use (rustc --print code-models for details)"), metadata: Vec = (Vec::new(), parse_list, [TRACKED], "metadata to mangle symbol names with"), - extra_filename: String = ("".to_string(), parse_string, [UNTRACKED], + extra_filename: String = (String::new(), parse_string, [UNTRACKED], "extra data to put in each output filename"), codegen_units: Option = (None, parse_opt_uint, [UNTRACKED], "divide crate into N units to optimize in parallel"), - remark: Passes = (SomePasses(Vec::new()), parse_passes, [UNTRACKED], + remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED], "print remarks for these optimization passes (space separated, or \"all\")"), no_stack_check: bool = (false, parse_bool, [UNTRACKED], "the --no-stack-check flag is deprecated and does nothing"), @@ -1367,10 +1380,14 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "disables the 'leak check' for subtyping; unsound, but useful for tests"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), + self_profile: bool = (false, parse_bool, [UNTRACKED], + "run the self profiler"), + profile_json: bool = (false, parse_bool, [UNTRACKED], + "output a json file with profiler results"), } pub fn default_lib_output() -> CrateType { - CrateTypeRlib + CrateType::Rlib } pub fn default_configuration(sess: &Session) -> ast::CrateConfig { @@ -1384,7 +1401,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { let max_atomic_width = sess.target.target.max_atomic_width(); let atomic_cas = sess.target.target.options.atomic_cas; - let mut ret = HashSet::new(); + let mut ret = FxHashSet::default(); // Target bindings. ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os)))); if let Some(ref fam) = sess.target.target.options.target_family { @@ -1428,7 +1445,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { if sess.opts.debug_assertions { ret.insert((Symbol::intern("debug_assertions"), None)); } - if sess.opts.crate_types.contains(&CrateTypeProcMacro) { + if sess.opts.crate_types.contains(&CrateType::ProcMacro) { ret.insert((Symbol::intern("proc_macro"), None)); } return ret; @@ -2000,13 +2017,6 @@ pub fn build_session_options_and_crate_config( (&None, &None) => None, }.map(|m| PathBuf::from(m)); - if cg.lto != Lto::No && incremental.is_some() { - early_error( - error_format, - "can't perform LTO when compiling incrementally", - ); - } - if debugging_opts.profile && incremental.is_some() { early_error( error_format, @@ -2021,7 +2031,7 @@ pub fn build_session_options_and_crate_config( }; if cg.target_feature == "help" { prints.push(PrintRequest::TargetFeatures); - cg.target_feature = "".to_string(); + cg.target_feature = String::new(); } if cg.relocation_model.as_ref().map_or(false, |s| s == "help") { prints.push(PrintRequest::RelocationModels); @@ -2091,12 +2101,12 @@ pub fn build_session_options_and_crate_config( if cg.debuginfo.is_some() { early_error(error_format, "-g and -C debuginfo both provided"); } - FullDebugInfo + DebugInfo::Full } else { match cg.debuginfo { - None | Some(0) => NoDebugInfo, - Some(1) => LimitedDebugInfo, - Some(2) => FullDebugInfo, + None | Some(0) => DebugInfo::None, + Some(1) => DebugInfo::Limited, + Some(2) => DebugInfo::Full, Some(arg) => { early_error( error_format, @@ -2159,6 +2169,8 @@ pub fn build_session_options_and_crate_config( let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let test = matches.opt_present("test"); + let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); + prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { "crate-name" => PrintRequest::CrateName, "file-names" => PrintRequest::FileNames, @@ -2172,15 +2184,13 @@ pub fn build_session_options_and_crate_config( "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, "target-spec-json" => { - if nightly_options::is_unstable_enabled(matches) { + if is_unstable_enabled { PrintRequest::TargetSpec } else { early_error( error_format, - &format!( - "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option" - ), + "the `-Z unstable-options` flag must also be passed to \ + enable the target-spec-json print option", ); } } @@ -2195,7 +2205,7 @@ pub fn build_session_options_and_crate_config( Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)), }; - if !cg.remark.is_empty() && debuginfo == NoDebugInfo { + if !cg.remark.is_empty() && debuginfo == DebugInfo::None { early_warn( error_format, "-C remark will not show source locations without \ @@ -2203,25 +2213,26 @@ pub fn build_session_options_and_crate_config( ); } - let mut externs = BTreeMap::new(); + let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new(); for arg in &matches.opt_strs("extern") { let mut parts = arg.splitn(2, '='); let name = match parts.next() { Some(s) => s, None => early_error(error_format, "--extern value must not be empty"), }; - let location = match parts.next() { - Some(s) => s, - None => early_error( + let location = parts.next().map(|s| s.to_string()); + if location.is_none() && !is_unstable_enabled { + early_error( error_format, - "--extern value must be of the format `foo=bar`", - ), + "the `-Z unstable-options` flag must also be passed to \ + enable `--extern crate_name` without `=path`", + ); }; externs .entry(name.to_string()) - .or_insert_with(BTreeSet::new) - .insert(location.to_string()); + .or_default() + .insert(location); } let crate_name = matches.opt_str("crate-name"); @@ -2284,12 +2295,12 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result default_lib_output(), - "rlib" => CrateTypeRlib, - "staticlib" => CrateTypeStaticlib, - "dylib" => CrateTypeDylib, - "cdylib" => CrateTypeCdylib, - "bin" => CrateTypeExecutable, - "proc-macro" => CrateTypeProcMacro, + "rlib" => CrateType::Rlib, + "staticlib" => CrateType::Staticlib, + "dylib" => CrateType::Dylib, + "cdylib" => CrateType::Cdylib, + "bin" => CrateType::Executable, + "proc-macro" => CrateType::ProcMacro, _ => { return Err(format!("unknown crate type: `{}`", part)); } @@ -2367,12 +2378,12 @@ pub mod nightly_options { impl fmt::Display for CrateType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - CrateTypeExecutable => "bin".fmt(f), - CrateTypeDylib => "dylib".fmt(f), - CrateTypeRlib => "rlib".fmt(f), - CrateTypeStaticlib => "staticlib".fmt(f), - CrateTypeCdylib => "cdylib".fmt(f), - CrateTypeProcMacro => "proc-macro".fmt(f), + CrateType::Executable => "bin".fmt(f), + CrateType::Dylib => "dylib".fmt(f), + CrateType::Rlib => "rlib".fmt(f), + CrateType::Staticlib => "staticlib".fmt(f), + CrateType::Cdylib => "cdylib".fmt(f), + CrateType::ProcMacro => "proc-macro".fmt(f), } } } @@ -2402,8 +2413,8 @@ mod dep_tracking { use std::hash::Hash; use std::path::PathBuf; use std::collections::hash_map::DefaultHasher; - use super::{CrateType, DebugInfoLevel, ErrorOutputType, Lto, OptLevel, OutputTypes, - Passes, Sanitizer, CrossLangLto}; + use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes, + Passes, Sanitizer, LtoCli, CrossLangLto}; use syntax::feature_gate::UnstableFeatures; use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple}; use syntax::edition::Edition; @@ -2458,8 +2469,8 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(RelroLevel); impl_dep_tracking_hash_via_hash!(Passes); impl_dep_tracking_hash_via_hash!(OptLevel); - impl_dep_tracking_hash_via_hash!(Lto); - impl_dep_tracking_hash_via_hash!(DebugInfoLevel); + impl_dep_tracking_hash_via_hash!(LtoCli); + impl_dep_tracking_hash_via_hash!(DebugInfo); impl_dep_tracking_hash_via_hash!(UnstableFeatures); impl_dep_tracking_hash_via_hash!(OutputTypes); impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind); @@ -2532,7 +2543,7 @@ mod tests { use lint; use middle::cstore; use session::config::{build_configuration, build_session_options_and_crate_config}; - use session::config::{Lto, CrossLangLto}; + use session::config::{LtoCli, CrossLangLto}; use session::build_session; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; @@ -2542,6 +2553,7 @@ mod tests { use syntax::symbol::Symbol; use syntax::edition::{Edition, DEFAULT_EDITION}; use syntax; + use super::Options; fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); @@ -2626,9 +2638,9 @@ mod tests { #[test] fn test_output_types_tracking_hash_different_paths() { - let mut v1 = super::basic_options(); - let mut v2 = super::basic_options(); - let mut v3 = super::basic_options(); + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); v1.output_types = OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("./some/thing")))]); @@ -2648,8 +2660,8 @@ mod tests { #[test] fn test_output_types_tracking_hash_different_construction_order() { - let mut v1 = super::basic_options(); - let mut v2 = super::basic_options(); + let mut v1 = Options::default(); + let mut v2 = Options::default(); v1.output_types = OutputTypes::new(&[ (OutputType::Exe, Some(PathBuf::from("./some/thing"))), @@ -2669,40 +2681,40 @@ mod tests { #[test] fn test_externs_tracking_hash_different_construction_order() { - let mut v1 = super::basic_options(); - let mut v2 = super::basic_options(); - let mut v3 = super::basic_options(); + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); v1.externs = Externs::new(mk_map(vec![ ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ( String::from("d"), - mk_set(vec![String::from("e"), String::from("f")]), + mk_set(vec![Some(String::from("e")), Some(String::from("f"))]), ), ])); v2.externs = Externs::new(mk_map(vec![ ( String::from("d"), - mk_set(vec![String::from("e"), String::from("f")]), + mk_set(vec![Some(String::from("e")), Some(String::from("f"))]), ), ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ])); v3.externs = Externs::new(mk_map(vec![ ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ( String::from("d"), - mk_set(vec![String::from("f"), String::from("e")]), + mk_set(vec![Some(String::from("f")), Some(String::from("e"))]), ), ])); @@ -2718,9 +2730,9 @@ mod tests { #[test] fn test_lints_tracking_hash_different_values() { - let mut v1 = super::basic_options(); - let mut v2 = super::basic_options(); - let mut v3 = super::basic_options(); + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); v1.lint_opts = vec![ (String::from("a"), lint::Allow), @@ -2755,8 +2767,8 @@ mod tests { #[test] fn test_lints_tracking_hash_different_construction_order() { - let mut v1 = super::basic_options(); - let mut v2 = super::basic_options(); + let mut v1 = Options::default(); + let mut v2 = Options::default(); v1.lint_opts = vec![ (String::from("a"), lint::Allow), @@ -2781,10 +2793,10 @@ mod tests { #[test] fn test_search_paths_tracking_hash_different_order() { - let mut v1 = super::basic_options(); - let mut v2 = super::basic_options(); - let mut v3 = super::basic_options(); - let mut v4 = super::basic_options(); + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); + let mut v4 = Options::default(); // Reference v1.search_paths @@ -2844,10 +2856,10 @@ mod tests { #[test] fn test_native_libs_tracking_hash_different_values() { - let mut v1 = super::basic_options(); - let mut v2 = super::basic_options(); - let mut v3 = super::basic_options(); - let mut v4 = super::basic_options(); + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); + let mut v4 = Options::default(); // Reference v1.libs = vec![ @@ -2894,9 +2906,9 @@ mod tests { #[test] fn test_native_libs_tracking_hash_different_order() { - let mut v1 = super::basic_options(); - let mut v2 = super::basic_options(); - let mut v3 = super::basic_options(); + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let mut v3 = Options::default(); // Reference v1.libs = vec![ @@ -2929,8 +2941,8 @@ mod tests { #[test] fn test_codegen_options_tracking_hash() { - let reference = super::basic_options(); - let mut opts = super::basic_options(); + let reference = Options::default(); + let mut opts = Options::default(); // Make sure the changing an [UNTRACKED] option leaves the hash unchanged opts.cg.ar = Some(String::from("abc")); @@ -2954,7 +2966,7 @@ mod tests { opts.cg.codegen_units = Some(42); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.cg.remark = super::SomePasses(vec![String::from("pass1"), String::from("pass2")]); + opts.cg.remark = super::Passes::Some(vec![String::from("pass1"), String::from("pass2")]); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.cg.save_temps = true; @@ -2965,7 +2977,7 @@ mod tests { // Make sure changing a [TRACKED] option changes the hash opts = reference.clone(); - opts.cg.lto = Lto::Fat; + opts.cg.lto = LtoCli::Fat; assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); @@ -3067,8 +3079,8 @@ mod tests { #[test] fn test_debugging_options_tracking_hash() { - let reference = super::basic_options(); - let mut opts = super::basic_options(); + let reference = Options::default(); + let mut opts = Options::default(); // Make sure the changing an [UNTRACKED] option leaves the hash unchanged opts.debugging_opts.verbose = true; @@ -3197,7 +3209,7 @@ mod tests { #[test] fn test_edition_parsing() { // test default edition - let options = super::basic_options(); + let options = Options::default(); assert!(options.edition == DEFAULT_EDITION); let matches = optgroups() diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs index b636fc6c99..0de5d3d03d 100644 --- a/src/librustc/session/filesearch.rs +++ b/src/librustc/session/filesearch.rs @@ -12,14 +12,14 @@ pub use self::FileMatch::*; +use rustc_data_structures::fx::FxHashSet; use std::borrow::Cow; -use std::collections::HashSet; use std::env; use std::fs; use std::path::{Path, PathBuf}; use session::search_paths::{SearchPaths, PathKind}; -use util::fs as rustcfs; +use rustc_fs_util::fix_windows_verbatim_for_gcc; #[derive(Copy, Clone)] pub enum FileMatch { @@ -40,7 +40,7 @@ impl<'a> FileSearch<'a> { pub fn for_each_lib_search_path(&self, mut f: F) where F: FnMut(&Path, PathKind) { - let mut visited_dirs = HashSet::new(); + let mut visited_dirs = FxHashSet::default(); for (path, kind) in self.search_paths.iter(self.kind) { f(path, kind); @@ -151,7 +151,7 @@ pub fn get_or_default_sysroot() -> PathBuf { // See comments on this target function, but the gist is that // gcc chokes on verbatim paths which fs::canonicalize generates // so we try to avoid those kinds of paths. - Ok(canon) => Some(rustcfs::fix_windows_verbatim_for_gcc(&canon)), + Ok(canon) => Some(fix_windows_verbatim_for_gcc(&canon)), Err(e) => bug!("failed to get realpath: {}", e), } }) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 7b8bbbf4a1..619262abb0 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -8,24 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo}; -pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo}; +pub use self::code_stats::{DataTypeKind, SizeKind, FieldInfo, VariantInfo}; +use self::code_stats::CodeStats; use hir::def_id::CrateNum; -use ich::Fingerprint; +use rustc_data_structures::fingerprint::Fingerprint; -use ich; use lint; use lint::builtin::BuiltinLintDiagnostics; use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{OutputType}; -use ty::tls; +use session::config::{OutputType, Lto}; use util::nodemap::{FxHashMap, FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; use util::common::ProfileQueriesMsg; +use rustc_data_structures::base_n; use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock}; use syntax::ast::NodeId; @@ -34,21 +33,20 @@ use errors::emitter::{Emitter, EmitterWriter}; use syntax::edition::Edition; use syntax::json::JsonEmitter; use syntax::feature_gate; -use syntax::symbol::Symbol; use syntax::parse; use syntax::parse::ParseSess; -use syntax::{ast, codemap}; +use syntax::{ast, source_map}; use syntax::feature_gate::AttributeType; use syntax_pos::{MultiSpan, Span}; +use util::profiling::SelfProfiler; -use rustc_target::spec::{LinkerFlavor, PanicStrategy}; +use rustc_target::spec::PanicStrategy; use rustc_target::spec::{Target, TargetTriple}; use rustc_data_structures::flock; use jobserver::Client; use std; use std::cell::{self, Cell, RefCell}; -use std::collections::HashMap; use std::env; use std::fmt; use std::io::Write; @@ -123,16 +121,16 @@ pub struct Session { /// Map from imported macro spans (which consist of /// the localized span for the macro body) to the /// macro name and definition span in the source crate. - pub imported_macro_spans: OneThread>>, + pub imported_macro_spans: OneThread>>, incr_comp_session: OneThread>, - /// A cache of attributes ignored by StableHashingContext - pub ignored_attr_names: FxHashSet, - /// Used by -Z profile-queries in util::common pub profile_channel: Lock>>, + /// Used by -Z self-profile + pub self_profiling: Lock, + /// Some measurements that are being gathered during compilation. pub perf_stats: PerfStats, @@ -161,6 +159,9 @@ pub struct Session { /// Metadata about the allocators for the current crate being compiled pub has_global_allocator: Once, + /// Metadata about the panic handlers for the current crate being compiled + pub has_panic_handler: Once, + /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap, } @@ -485,8 +486,8 @@ impl Session { ); } - pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { - self.parse_sess.codemap() + pub fn source_map<'a>(&'a self) -> &'a source_map::SourceMap { + self.parse_sess.source_map() } pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose @@ -549,9 +550,27 @@ impl Session { // lto` and we've for whatever reason forced off ThinLTO via the CLI, // then ensure we can't use a ThinLTO. match self.opts.cg.lto { - config::Lto::No => {} - config::Lto::Yes if self.opts.cli_forced_thinlto_off => return config::Lto::Fat, - other => return other, + config::LtoCli::Unspecified => { + // The compiler was invoked without the `-Clto` flag. Fall + // through to the default handling + } + config::LtoCli::No => { + // The user explicitly opted out of any kind of LTO + return config::Lto::No; + } + config::LtoCli::Yes | + config::LtoCli::Fat | + config::LtoCli::NoParam => { + // All of these mean fat LTO + return config::Lto::Fat; + } + config::LtoCli::Thin => { + return if self.opts.cli_forced_thinlto_off { + config::Lto::Fat + } else { + config::Lto::Thin + }; + } } // Ok at this point the target doesn't require anything and the user @@ -582,11 +601,6 @@ impl Session { return config::Lto::No; } - // Right now ThinLTO isn't compatible with incremental compilation. - if self.opts.incremental.is_some() { - return config::Lto::No; - } - // Now we're in "defaults" territory. By default we enable ThinLTO for // optimized compiles (anything greater than O0). match self.opts.optimize { @@ -603,13 +617,6 @@ impl Session { .panic .unwrap_or(self.target.target.options.panic_strategy) } - pub fn linker_flavor(&self) -> LinkerFlavor { - self.opts - .debugging_opts - .linker_flavor - .unwrap_or(self.target.target.linker_flavor) - } - pub fn fewer_names(&self) -> bool { let more_names = self.opts .output_types @@ -657,13 +664,6 @@ impl Session { } } - pub fn target_cpu(&self) -> &str { - match self.opts.cg.target_cpu { - Some(ref s) => &**s, - None => &*self.target.target.options.cpu - } - } - pub fn must_not_eliminate_frame_pointers(&self) -> bool { if let Some(x) = self.opts.cg.force_frame_pointers { x @@ -825,6 +825,21 @@ impl Session { } } + pub fn profiler ()>(&self, f: F) { + let mut profiler = self.self_profiling.borrow_mut(); + f(&mut profiler); + } + + pub fn print_profiler_results(&self) { + let mut profiler = self.self_profiling.borrow_mut(); + profiler.print_results(&self.opts); + } + + pub fn save_json_results(&self) { + let profiler = self.self_profiling.borrow(); + profiler.save_results(&self.opts); + } + pub fn print_perf_stats(&self) { println!( "Total time spent computing symbol hashes: {}", @@ -946,7 +961,7 @@ impl Session { } pub fn teach(&self, code: &DiagnosticId) -> bool { - self.opts.debugging_opts.teach && self.parse_sess.span_diagnostic.must_teach(code) + self.opts.debugging_opts.teach && self.diagnostic().must_teach(code) } /// Are we allowed to use features from the Rust 2018 edition? @@ -966,20 +981,20 @@ pub fn build_session( ) -> Session { let file_path_mapping = sopts.file_path_mapping(); - build_session_with_codemap( + build_session_with_source_map( sopts, local_crate_source_file, registry, - Lrc::new(codemap::CodeMap::new(file_path_mapping)), + Lrc::new(source_map::SourceMap::new(file_path_mapping)), None, ) } -pub fn build_session_with_codemap( +pub fn build_session_with_source_map( sopts: config::Options, local_crate_source_file: Option, registry: errors::registry::Registry, - codemap: Lrc, + source_map: Lrc, emitter_dest: Option>, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override @@ -1006,19 +1021,19 @@ pub fn build_session_with_codemap( (config::ErrorOutputType::HumanReadable(color_config), None) => Box::new( EmitterWriter::stderr( color_config, - Some(codemap.clone()), + Some(source_map.clone()), false, sopts.debugging_opts.teach, ).ui_testing(sopts.debugging_opts.ui_testing), ), (config::ErrorOutputType::HumanReadable(_), Some(dst)) => Box::new( - EmitterWriter::new(dst, Some(codemap.clone()), false, false) + EmitterWriter::new(dst, Some(source_map.clone()), false, false) .ui_testing(sopts.debugging_opts.ui_testing), ), (config::ErrorOutputType::Json(pretty), None) => Box::new( JsonEmitter::stderr( Some(registry), - codemap.clone(), + source_map.clone(), pretty, ).ui_testing(sopts.debugging_opts.ui_testing), ), @@ -1026,15 +1041,15 @@ pub fn build_session_with_codemap( JsonEmitter::new( dst, Some(registry), - codemap.clone(), + source_map.clone(), pretty, ).ui_testing(sopts.debugging_opts.ui_testing), ), (config::ErrorOutputType::Short(color_config), None) => Box::new( - EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false), + EmitterWriter::stderr(color_config, Some(source_map.clone()), true, false), ), (config::ErrorOutputType::Short(_), Some(dst)) => { - Box::new(EmitterWriter::new(dst, Some(codemap.clone()), true, false)) + Box::new(EmitterWriter::new(dst, Some(source_map.clone()), true, false)) } }; @@ -1049,14 +1064,14 @@ pub fn build_session_with_codemap( }, ); - build_session_(sopts, local_crate_source_file, diagnostic_handler, codemap) + build_session_(sopts, local_crate_source_file, diagnostic_handler, source_map) } pub fn build_session_( sopts: config::Options, local_crate_source_file: Option, span_diagnostic: errors::Handler, - codemap: Lrc, + source_map: Lrc, ) -> Session { let host_triple = TargetTriple::from_triple(config::host_triple()); let host = match Target::search(&host_triple) { @@ -1069,7 +1084,7 @@ pub fn build_session_( }; let target_cfg = config::build_target_config(&sopts, &span_diagnostic); - let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap); + let p_s = parse::ParseSess::with_span_handler(span_diagnostic, source_map); let default_sysroot = match sopts.maybe_sysroot { Some(_) => None, None => Some(filesearch::get_or_default_sysroot()), @@ -1122,9 +1137,9 @@ pub fn build_session_( injected_allocator: Once::new(), allocator_kind: Once::new(), injected_panic_runtime: Once::new(), - imported_macro_spans: OneThread::new(RefCell::new(HashMap::new())), + imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), - ignored_attr_names: ich::compute_ignored_attr_names(), + self_profiling: Lock::new(SelfProfiler::new()), profile_channel: Lock::new(None), perf_stats: PerfStats { symbol_hash_time: Lock::new(Duration::from_secs(0)), @@ -1166,12 +1181,47 @@ pub fn build_session_( (*GLOBAL_JOBSERVER).clone() }, has_global_allocator: Once::new(), + has_panic_handler: Once::new(), driver_lint_caps: FxHashMap(), }; + validate_commandline_args_with_session_available(&sess); + sess } +// If it is useful to have a Session available already for validating a +// commandline argument, you can do so here. +fn validate_commandline_args_with_session_available(sess: &Session) { + + if sess.opts.incremental.is_some() { + match sess.lto() { + Lto::Thin | + Lto::Fat => { + sess.err("can't perform LTO when compiling incrementally"); + } + Lto::ThinLocal | + Lto::No => { + // This is fine + } + } + } + + // Since we don't know if code in an rlib will be linked to statically or + // dynamically downstream, rustc generates `__imp_` symbols that help the + // MSVC linker deal with this lack of knowledge (#27438). Unfortunately, + // these manually generated symbols confuse LLD when it tries to merge + // bitcode during ThinLTO. Therefore we disallow dynamic linking on MSVC + // when compiling for LLD ThinLTO. This way we can validly just not generate + // the `dllimport` attributes and `__imp_` symbols in that case. + if sess.opts.debugging_opts.cross_lang_lto.enabled() && + sess.opts.cg.prefer_dynamic && + sess.target.target.options.is_like_msvc { + sess.err("Linker plugin based LTO is not supported together with \ + `-C prefer-dynamic` when targeting MSVC"); + } +} + /// Hash value constructed out of all the `-C metadata` arguments passed to the /// compiler. Together with the crate-name forms a unique global identifier for /// the crate. @@ -1184,13 +1234,21 @@ impl CrateDisambiguator { } } +impl fmt::Display for CrateDisambiguator { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let (a, b) = self.0.as_value(); + let as_u128 = a as u128 | ((b as u128) << 64); + f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE)) + } +} + impl From for CrateDisambiguator { fn from(fingerprint: Fingerprint) -> CrateDisambiguator { CrateDisambiguator(fingerprint) } } -impl_stable_hash_for!(tuple_struct CrateDisambiguator { fingerprint }); +impl_stable_hash_via_hash!(CrateDisambiguator); /// Holds data on the current incremental compilation session, if there is one. #[derive(Debug)] @@ -1262,39 +1320,3 @@ pub fn compile_result_from_err_count(err_count: usize) -> CompileResult { Err(CompileIncomplete::Errored(ErrorReported)) } } - -#[cold] -#[inline(never)] -pub fn bug_fmt(file: &'static str, line: u32, args: fmt::Arguments) -> ! { - // this wrapper mostly exists so I don't have to write a fully - // qualified path of None:: inside the bug!() macro definition - opt_span_bug_fmt(file, line, None::, args); -} - -#[cold] -#[inline(never)] -pub fn span_bug_fmt>( - file: &'static str, - line: u32, - span: S, - args: fmt::Arguments, -) -> ! { - opt_span_bug_fmt(file, line, Some(span), args); -} - -fn opt_span_bug_fmt>( - file: &'static str, - line: u32, - span: Option, - args: fmt::Arguments, -) -> ! { - tls::with_opt(move |tcx| { - let msg = format!("{}:{}: {}", file, line, args); - match (tcx, span) { - (Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg), - (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg), - (None, _) => panic!(msg), - } - }); - unreachable!(); -} diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index f487397992..ed95aa7307 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -264,12 +264,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // The core logic responsible for computing the bounds for our synthesized impl. // // To calculate the bounds, we call SelectionContext.select in a loop. Like FulfillmentContext, - // we recursively select the nested obligations of predicates we encounter. However, whenver we + // we recursively select the nested obligations of predicates we encounter. However, whenever we // encounter an UnimplementedError involving a type parameter, we add it to our ParamEnv. Since // our goal is to determine when a particular type implements an auto trait, Unimplemented // errors tell us what conditions need to be met. // - // This method ends up working somewhat similary to FulfillmentContext, but with a few key + // This method ends up working somewhat similarly to FulfillmentContext, but with a few key // differences. FulfillmentContext works under the assumption that it's dealing with concrete // user code. According, it considers all possible ways that a Predicate could be met - which // isn't always what we want for a synthesized impl. For example, given the predicate 'T: @@ -289,11 +289,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // we'll pick up any nested bounds, without ever inferring that 'T: IntoIterator' needs to // hold. // - // One additonal consideration is supertrait bounds. Normally, a ParamEnv is only ever + // One additional consideration is supertrait bounds. Normally, a ParamEnv is only ever // consutrcted once for a given type. As part of the construction process, the ParamEnv will // have any supertrait bounds normalized - e.g. if we have a type 'struct Foo', the // ParamEnv will contain 'T: Copy' and 'T: Clone', since 'Copy: Clone'. When we construct our - // own ParamEnv, we need to do this outselves, through traits::elaborate_predicates, or else + // own ParamEnv, we need to do this ourselves, through traits::elaborate_predicates, or else // SelectionContext will choke on the missing predicates. However, this should never show up in // the final synthesized generics: we don't want our generated docs page to contain something // like 'T: Copy + Clone', as that's redundant. Therefore, we keep track of a separate @@ -358,7 +358,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { &Err(SelectionError::Unimplemented) => { if self.is_of_param(pred.skip_binder().trait_ref.substs) { already_visited.remove(&pred); - user_computed_preds.insert(ty::Predicate::Trait(pred.clone())); + self.add_user_pred(&mut user_computed_preds, + ty::Predicate::Trait(pred.clone())); predicates.push_back(pred); } else { debug!( @@ -393,6 +394,92 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { return Some((new_env, final_user_env)); } + // This method is designed to work around the following issue: + // When we compute auto trait bounds, we repeatedly call SelectionContext.select, + // progressively building a ParamEnv based on the results we get. + // However, our usage of SelectionContext differs from its normal use within the compiler, + // in that we capture and re-reprocess predicates from Unimplemented errors. + // + // This can lead to a corner case when dealing with region parameters. + // During our selection loop in evaluate_predicates, we might end up with + // two trait predicates that differ only in their region parameters: + // one containing a HRTB lifetime parameter, and one containing a 'normal' + // lifetime parameter. For example: + // + // T as MyTrait<'a> + // T as MyTrait<'static> + // + // If we put both of these predicates in our computed ParamEnv, we'll + // confuse SelectionContext, since it will (correctly) view both as being applicable. + // + // To solve this, we pick the 'more strict' lifetime bound - i.e. the HRTB + // Our end goal is to generate a user-visible description of the conditions + // under which a type implements an auto trait. A trait predicate involving + // a HRTB means that the type needs to work with any choice of lifetime, + // not just one specific lifetime (e.g. 'static). + fn add_user_pred<'c>(&self, user_computed_preds: &mut FxHashSet>, + new_pred: ty::Predicate<'c>) { + let mut should_add_new = true; + user_computed_preds.retain(|&old_pred| { + match (&new_pred, old_pred) { + (&ty::Predicate::Trait(new_trait), ty::Predicate::Trait(old_trait)) => { + if new_trait.def_id() == old_trait.def_id() { + let new_substs = new_trait.skip_binder().trait_ref.substs; + let old_substs = old_trait.skip_binder().trait_ref.substs; + if !new_substs.types().eq(old_substs.types()) { + // We can't compare lifetimes if the types are different, + // so skip checking old_pred + return true + } + + for (new_region, old_region) in new_substs + .regions() + .zip(old_substs.regions()) { + + match (new_region, old_region) { + // If both predicates have an 'ReLateBound' (a HRTB) in the + // same spot, we do nothing + ( + ty::RegionKind::ReLateBound(_, _), + ty::RegionKind::ReLateBound(_, _) + ) => {}, + + (ty::RegionKind::ReLateBound(_, _), _) => { + // The new predicate has a HRTB in a spot where the old + // predicate does not (if they both had a HRTB, the previous + // match arm would have executed). + // + // The means we want to remove the older predicate from + // user_computed_preds, since having both it and the new + // predicate in a ParamEnv would confuse SelectionContext + // We're currently in the predicate passed to 'retain', + // so we return 'false' to remove the old predicate from + // user_computed_preds + return false; + }, + (_, ty::RegionKind::ReLateBound(_, _)) => { + // This is the opposite situation as the previous arm - the + // old predicate has a HRTB lifetime in a place where the + // new predicate does not. We want to leave the old + // predicate in user_computed_preds, and skip adding + // new_pred to user_computed_params. + should_add_new = false + } + _ => {} + } + } + } + }, + _ => {} + } + return true + }); + + if should_add_new { + user_computed_preds.insert(new_pred); + } + } + pub fn region_name(&self, region: Region) -> Option { match region { &ty::ReEarlyBound(r) => Some(r.name.to_string()), @@ -426,26 +513,26 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { { let deps1 = vid_map .entry(RegionTarget::RegionVid(r1)) - .or_insert_with(|| Default::default()); + .or_default(); deps1.larger.insert(RegionTarget::RegionVid(r2)); } let deps2 = vid_map .entry(RegionTarget::RegionVid(r2)) - .or_insert_with(|| Default::default()); + .or_default(); deps2.smaller.insert(RegionTarget::RegionVid(r1)); } &Constraint::RegSubVar(region, vid) => { { let deps1 = vid_map .entry(RegionTarget::Region(region)) - .or_insert_with(|| Default::default()); + .or_default(); deps1.larger.insert(RegionTarget::RegionVid(vid)); } let deps2 = vid_map .entry(RegionTarget::RegionVid(vid)) - .or_insert_with(|| Default::default()); + .or_default(); deps2.smaller.insert(RegionTarget::Region(region)); } &Constraint::VarSubReg(vid, region) => { @@ -455,13 +542,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { { let deps1 = vid_map .entry(RegionTarget::Region(r1)) - .or_insert_with(|| Default::default()); + .or_default(); deps1.larger.insert(RegionTarget::Region(r2)); } let deps2 = vid_map .entry(RegionTarget::Region(r2)) - .or_insert_with(|| Default::default()); + .or_default(); deps2.smaller.insert(RegionTarget::Region(r1)); } } @@ -519,8 +606,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } return match substs.type_at(0).sty { - ty::TyParam(_) => true, - ty::TyProjection(p) => self.is_of_param(p.substs), + ty::Param(_) => true, + ty::Projection(p) => self.is_of_param(p.substs), _ => false, }; } @@ -555,7 +642,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let substs = &p.skip_binder().trait_ref.substs; if self.is_of_param(substs) && !only_projections && is_new_pred { - computed_preds.insert(predicate); + self.add_user_pred(computed_preds, predicate); } predicates.push_back(p.clone()); } @@ -563,7 +650,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // If the projection isn't all type vars, then // we don't want to add it as a bound if self.is_of_param(p.skip_binder().projection_ty.substs) && is_new_pred { - computed_preds.insert(predicate); + self.add_user_pred(computed_preds, predicate); } else { match poly_project_and_unify_type(select, &obligation.with(p.clone())) { Err(e) => { @@ -594,10 +681,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } &ty::Predicate::RegionOutlives(ref binder) => { - if let Err(_) = select - .infcx() - .region_outlives_predicate(&dummy_cause, binder) - { + if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() { return false; } } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 02bfab033e..b8dd2a12fb 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -407,7 +407,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, in_crate: InCrate) fn is_possibly_remote_type(ty: Ty, _in_crate: InCrate) -> bool { match ty.sty { - ty::TyProjection(..) | ty::TyParam(..) => true, + ty::Projection(..) | ty::Param(..) => true, _ => false, } } @@ -419,9 +419,9 @@ fn ty_is_local(tcx: TyCtxt, ty: Ty, in_crate: InCrate) -> bool { fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool { match ty.sty { - ty::TyRef(..) => true, - ty::TyAdt(def, _) => def.is_fundamental(), - ty::TyDynamic(ref data, ..) => { + ty::Ref(..) => true, + ty::Adt(def, _) => def.is_fundamental(), + ty::Dynamic(ref data, ..) => { data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental")) } _ => false @@ -441,49 +441,49 @@ fn ty_is_local_constructor(ty: Ty, in_crate: InCrate) -> bool { debug!("ty_is_local_constructor({:?})", ty); match ty.sty { - ty::TyBool | - ty::TyChar | - ty::TyInt(..) | - ty::TyUint(..) | - ty::TyFloat(..) | - ty::TyStr | - ty::TyFnDef(..) | - ty::TyFnPtr(_) | - ty::TyArray(..) | - ty::TySlice(..) | - ty::TyRawPtr(..) | - ty::TyRef(..) | - ty::TyNever | - ty::TyTuple(..) | - ty::TyParam(..) | - ty::TyProjection(..) => { + ty::Bool | + ty::Char | + ty::Int(..) | + ty::Uint(..) | + ty::Float(..) | + ty::Str | + ty::FnDef(..) | + ty::FnPtr(_) | + ty::Array(..) | + ty::Slice(..) | + ty::RawPtr(..) | + ty::Ref(..) | + ty::Never | + ty::Tuple(..) | + ty::Param(..) | + ty::Projection(..) => { false } - ty::TyInfer(..) => match in_crate { + ty::Infer(..) => match in_crate { InCrate::Local => false, // The inference variable might be unified with a local // type in that remote crate. InCrate::Remote => true, }, - ty::TyAdt(def, _) => def_id_is_local(def.did, in_crate), - ty::TyForeign(did) => def_id_is_local(did, in_crate), + ty::Adt(def, _) => def_id_is_local(def.did, in_crate), + ty::Foreign(did) => def_id_is_local(did, in_crate), - ty::TyDynamic(ref tt, ..) => { + ty::Dynamic(ref tt, ..) => { tt.principal().map_or(false, |p| { def_id_is_local(p.def_id(), in_crate) }) } - ty::TyError => { + ty::Error => { true } - ty::TyClosure(..) | - ty::TyGenerator(..) | - ty::TyGeneratorWitness(..) | - ty::TyAnon(..) => { + ty::Closure(..) | + ty::Generator(..) | + ty::GeneratorWitness(..) | + ty::Opaque(..) => { bug!("ty_is_local invoked on unexpected type: {:?}", ty) } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c04785aac2..466d472cca 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -29,6 +29,7 @@ use super::{ use errors::{Applicability, DiagnosticBuilder}; use hir; +use hir::Node; use hir::def_id::DefId; use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; @@ -57,7 +58,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { index: Option, // None if this is an old error } - let mut error_map : FxHashMap<_, _> = + let mut error_map : FxHashMap<_, Vec<_>> = self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| { (span, predicates.iter().map(|predicate| ErrorDescriptor { predicate: predicate.clone(), @@ -66,14 +67,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }).collect(); for (index, error) in errors.iter().enumerate() { - error_map.entry(error.obligation.cause.span).or_insert(Vec::new()).push( + error_map.entry(error.obligation.cause.span).or_default().push( ErrorDescriptor { predicate: error.obligation.predicate.clone(), index: Some(index) }); self.reported_trait_errors.borrow_mut() - .entry(error.obligation.cause.span).or_insert(Vec::new()) + .entry(error.obligation.cause.span).or_default() .push(error.obligation.predicate.clone()); } @@ -143,7 +144,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Eventually I'll need to implement param-env-aware // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. let param_env = ty::ParamEnv::empty(); - if let Ok(_) = self.can_sub(param_env, error, implication) { + if self.can_sub(param_env, error, implication).is_ok() { debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); return true } @@ -244,36 +245,36 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// if the type can be equated to any type. fn type_category<'tcx>(t: Ty<'tcx>) -> Option { match t.sty { - ty::TyBool => Some(0), - ty::TyChar => Some(1), - ty::TyStr => Some(2), - ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3), - ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4), - ty::TyRef(..) | ty::TyRawPtr(..) => Some(5), - ty::TyArray(..) | ty::TySlice(..) => Some(6), - ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7), - ty::TyDynamic(..) => Some(8), - ty::TyClosure(..) => Some(9), - ty::TyTuple(..) => Some(10), - ty::TyProjection(..) => Some(11), - ty::TyParam(..) => Some(12), - ty::TyAnon(..) => Some(13), - ty::TyNever => Some(14), - ty::TyAdt(adt, ..) => match adt.adt_kind() { + ty::Bool => Some(0), + ty::Char => Some(1), + ty::Str => Some(2), + ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3), + ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4), + ty::Ref(..) | ty::RawPtr(..) => Some(5), + ty::Array(..) | ty::Slice(..) => Some(6), + ty::FnDef(..) | ty::FnPtr(..) => Some(7), + ty::Dynamic(..) => Some(8), + ty::Closure(..) => Some(9), + ty::Tuple(..) => Some(10), + ty::Projection(..) => Some(11), + ty::Param(..) => Some(12), + ty::Opaque(..) => Some(13), + ty::Never => Some(14), + ty::Adt(adt, ..) => match adt.adt_kind() { AdtKind::Struct => Some(15), AdtKind::Union => Some(16), AdtKind::Enum => Some(17), }, - ty::TyGenerator(..) => Some(18), - ty::TyForeign(..) => Some(19), - ty::TyGeneratorWitness(..) => Some(20), - ty::TyInfer(..) | ty::TyError => None + ty::Generator(..) => Some(18), + ty::Foreign(..) => Some(19), + ty::GeneratorWitness(..) => Some(20), + ty::Infer(..) | ty::Error => None } } match (type_category(a), type_category(b)) { (Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) { - (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => def_a == def_b, + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b, _ => cat_a == cat_b }, // infer and error can be equated to all types @@ -435,13 +436,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } fn report_similar_impl_candidates(&self, - impl_candidates: Vec>, + mut impl_candidates: Vec>, err: &mut DiagnosticBuilder) { if impl_candidates.is_empty() { return; } + let len = impl_candidates.len(); let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { @@ -459,12 +461,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } }); + // Sort impl candidates so that ordering is consistent for UI tests. + let normalized_impl_candidates = &mut impl_candidates[0..end] + .iter() + .map(normalize) + .collect::>(); + normalized_impl_candidates.sort(); + err.help(&format!("the following implementations were found:{}{}", - &impl_candidates[0..end].iter().map(normalize).collect::(), - if impl_candidates.len() > 5 { - format!("\nand {} others", impl_candidates.len() - 4) + normalized_impl_candidates.join(""), + if len > 5 { + format!("\nand {} others", len - 4) } else { - "".to_owned() + String::new() } )); } @@ -520,12 +529,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { -> DiagnosticBuilder<'tcx> { let msg = "impl has stricter requirements than trait"; - let sp = self.tcx.sess.codemap().def_span(error_span); + let sp = self.tcx.sess.source_map().def_span(error_span); let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg); if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) { - let span = self.tcx.sess.codemap().def_span(trait_item_span); + let span = self.tcx.sess.source_map().def_span(trait_item_span); err.span_label(span, format!("definition of `{}` from trait", item_name)); } @@ -644,7 +653,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } // If this error is due to `!: Trait` not implemented but `(): Trait` is - // implemented, and fallback has occured, then it could be due to a + // implemented, and fallback has occurred, then it could be due to a // variable that used to fallback to `()` now falling back to `!`. Issue a // note informing about the change in behaviour. if trait_predicate.skip_binder().self_ty().is_never() @@ -652,7 +661,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { let predicate = trait_predicate.map_bound(|mut trait_pred| { trait_pred.trait_ref.substs = self.tcx.mk_substs_trait( - self.tcx.mk_nil(), + self.tcx.mk_unit(), &trait_pred.trait_ref.substs[1..], ); trait_pred @@ -707,7 +716,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap(); - let closure_span = self.tcx.sess.codemap() + let closure_span = self.tcx.sess.source_map() .def_span(self.tcx.hir.span_if_local(closure_def_id).unwrap()); let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap(); let mut err = struct_span_err!( @@ -776,25 +785,25 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let found_trait_ty = found_trait_ref.self_ty(); let found_did = match found_trait_ty.sty { - ty::TyClosure(did, _) | - ty::TyForeign(did) | - ty::TyFnDef(did, _) => Some(did), - ty::TyAdt(def, _) => Some(def.did), + ty::Closure(did, _) | + ty::Foreign(did) | + ty::FnDef(did, _) => Some(did), + ty::Adt(def, _) => Some(def.did), _ => None, }; let found_span = found_did.and_then(|did| { self.tcx.hir.span_if_local(did) - }).map(|sp| self.tcx.sess.codemap().def_span(sp)); // the sp could be an fn def + }).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def let found = match found_trait_ref.skip_binder().substs.type_at(1).sty { - ty::TyTuple(ref tys) => tys.iter() + ty::Tuple(ref tys) => tys.iter() .map(|_| ArgKind::empty()).collect::>(), _ => vec![ArgKind::empty()], }; let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty { - ty::TyTuple(ref tys) => tys.iter() + ty::Tuple(ref tys) => tys.iter() .map(|t| match t.sty { - ty::TypeVariants::TyTuple(ref tys) => ArgKind::Tuple( + ty::Tuple(ref tys) => ArgKind::Tuple( Some(span), tys.iter() .map(|ty| ("_".to_owned(), ty.sty.to_string())) @@ -856,10 +865,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err: &mut DiagnosticBuilder<'tcx>) { if let &ObligationCauseCode::VariableType(node_id) = code { let parent_node = self.tcx.hir.get_parent_node(node_id); - if let Some(hir::map::NodeLocal(ref local)) = self.tcx.hir.find(parent_node) { + if let Some(Node::Local(ref local)) = self.tcx.hir.find(parent_node) { if let Some(ref expr) = local.init { if let hir::ExprKind::Index(_, _) = expr.node { - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(expr.span) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) { err.span_suggestion_with_applicability( expr.span, "consider borrowing here", @@ -882,7 +891,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let trait_ref = trait_ref.skip_binder(); let span = obligation.cause.span; - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let refs_number = snippet.chars() .filter(|c| !c.is_whitespace()) .take_while(|c| *c == '&') @@ -891,7 +900,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut trait_type = trait_ref.self_ty(); for refs_remaining in 0..refs_number { - if let ty::TypeVariants::TyRef(_, t_type, _) = trait_type.sty { + if let ty::Ref(_, t_type, _) = trait_type.sty { trait_type = t_type; let substs = self.tcx.mk_substs_trait(trait_type, &[]); @@ -901,7 +910,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { new_trait_ref.to_predicate()); if self.predicate_may_hold(&new_obligation) { - let sp = self.tcx.sess.codemap() + let sp = self.tcx.sess.source_map() .span_take_while(span, |c| c.is_whitespace() || *c == '&'); let remove_refs = refs_remaining + 1; @@ -909,7 +918,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { remove_refs); err.span_suggestion_short_with_applicability( - sp, &format_str, String::from(""), Applicability::MachineApplicable + sp, &format_str, String::new(), Applicability::MachineApplicable ); break; } @@ -924,13 +933,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// returns a span and `ArgKind` information that describes the /// arguments it expects. This can be supplied to /// `report_arg_count_mismatch`. - pub fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec) { + pub fn get_fn_like_arguments(&self, node: Node) -> (Span, Vec) { match node { - hir::map::NodeExpr(&hir::Expr { + Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(_, ref _decl, id, span, _), .. }) => { - (self.tcx.sess.codemap().def_span(span), self.tcx.hir.body(id).arguments.iter() + (self.tcx.sess.source_map().def_span(span), self.tcx.hir.body(id).arguments.iter() .map(|arg| { if let hir::Pat { node: hir::PatKind::Tuple(args, _), @@ -940,35 +949,35 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ArgKind::Tuple( Some(span), args.iter().map(|pat| { - let snippet = self.tcx.sess.codemap() + let snippet = self.tcx.sess.source_map() .span_to_snippet(pat.span).unwrap(); (snippet, "_".to_owned()) }).collect::>(), ) } else { - let name = self.tcx.sess.codemap() + let name = self.tcx.sess.source_map() .span_to_snippet(arg.pat.span).unwrap(); ArgKind::Arg(name, "_".to_owned()) } }) .collect::>()) } - hir::map::NodeItem(&hir::Item { + Node::Item(&hir::Item { span, node: hir::ItemKind::Fn(ref decl, ..), .. }) | - hir::map::NodeImplItem(&hir::ImplItem { + Node::ImplItem(&hir::ImplItem { span, node: hir::ImplItemKind::Method(hir::MethodSig { ref decl, .. }, _), .. }) | - hir::map::NodeTraitItem(&hir::TraitItem { + Node::TraitItem(&hir::TraitItem { span, node: hir::TraitItemKind::Method(hir::MethodSig { ref decl, .. }, _), .. }) => { - (self.tcx.sess.codemap().def_span(span), decl.inputs.iter() + (self.tcx.sess.source_map().def_span(span), decl.inputs.iter() .map(|arg| match arg.clone().node { hir::TyKind::Tup(ref tys) => ArgKind::Tuple( Some(arg.span), @@ -979,7 +988,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => ArgKind::Arg("_".to_owned(), "_".to_owned()) }).collect::>()) } - hir::map::NodeVariant(&hir::Variant { + Node::Variant(&hir::Variant { span, node: hir::VariantKind { data: hir::VariantData::Tuple(ref fields, _), @@ -987,13 +996,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }, .. }) => { - (self.tcx.sess.codemap().def_span(span), + (self.tcx.sess.source_map().def_span(span), fields.iter().map(|field| { ArgKind::Arg(field.ident.to_string(), "_".to_string()) }).collect::>()) } - hir::map::NodeStructCtor(ref variant_data) => { - (self.tcx.sess.codemap().def_span(self.tcx.hir.span(variant_data.id())), + Node::StructCtor(ref variant_data) => { + (self.tcx.sess.source_map().def_span(self.tcx.hir.span(variant_data.id())), variant_data.fields() .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned())) .collect()) @@ -1108,7 +1117,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .collect::>() .join(", ")) } else { - "".to_owned() + String::new() }, ); err.span_suggestion_with_applicability( @@ -1135,7 +1144,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> String { let inputs = trait_ref.substs.type_at(1); - let sig = if let ty::TyTuple(inputs) = inputs.sty { + let sig = if let ty::Tuple(inputs) = inputs.sty { tcx.mk_fn_sig( inputs.iter().map(|&x| x), tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), @@ -1184,7 +1193,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { assert!(type_def_id.is_local()); let span = self.hir.span_if_local(type_def_id).unwrap(); - let span = self.sess.codemap().def_span(span); + let span = self.sess.source_map().def_span(span); let mut err = struct_span_err!(self.sess, span, E0072, "recursive type `{}` has infinite size", self.item_path_str(type_def_id)); @@ -1202,7 +1211,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { -> DiagnosticBuilder<'tcx> { let trait_str = self.item_path_str(trait_def_id); - let span = self.sess.codemap().def_span(span); + let span = self.sess.source_map().def_span(span); let mut err = struct_span_err!( self.sess, span, E0038, "the trait `{}` cannot be made into an object", @@ -1340,7 +1349,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::TyParam(ty::ParamTy {name, ..}) = ty.sty { + if let ty::Param(ty::ParamTy {name, ..}) = ty.sty { let infcx = self.infcx; self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var( @@ -1430,7 +1439,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let item_name = tcx.item_path_str(item_def_id); let msg = format!("required by `{}`", item_name); if let Some(sp) = tcx.hir.span_if_local(item_def_id) { - let sp = tcx.sess.codemap().def_span(sp); + let sp = tcx.sess.source_map().def_span(sp); err.span_note(sp, &msg); } else { err.note(&msg); @@ -1446,6 +1455,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } ObligationCauseCode::VariableType(_) => { err.note("all local variables must have a statically known size"); + if !self.tcx.features().unsized_locals { + err.help("unsized locals are gated as an unstable feature"); + } + } + ObligationCauseCode::SizedArgumentType => { + err.note("all function arguments must have a statically known size"); + if !self.tcx.features().unsized_locals { + err.help("unsized locals are gated as an unstable feature"); + } } ObligationCauseCode::SizedReturnType => { err.note("the return type of a function must have a \ @@ -1464,11 +1482,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::StructInitializerSized => { err.note("structs must have a statically known size to be initialized"); } - ObligationCauseCode::FieldSized(ref item) => { + ObligationCauseCode::FieldSized { adt_kind: ref item, last } => { match *item { AdtKind::Struct => { - err.note("only the last field of a struct may have a dynamically \ - sized type"); + if last { + err.note("the last field of a packed struct may only have a \ + dynamically sized type if it does not need drop to be run"); + } else { + err.note("only the last field of a struct may have a dynamically \ + sized type"); + } } AdtKind::Union => { err.note("no field of a union may have a dynamically sized type"); @@ -1572,7 +1595,7 @@ impl ArgKind { /// argument. This has no name (`_`) and no source spans.. pub fn from_expected_ty(t: Ty<'_>) -> ArgKind { match t.sty { - ty::TyTuple(ref tys) => ArgKind::Tuple( + ty::Tuple(ref tys) => ArgKind::Tuple( None, tys.iter() .map(|ty| ("_".to_owned(), ty.sty.to_string())) diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index b7d3ad7658..9998db4ad1 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -146,7 +146,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { debug!("normalize_projection_type(projection_ty={:?})", projection_ty); - assert!(!projection_ty.has_escaping_regions()); + debug_assert!(!projection_ty.has_escaping_regions()); // FIXME(#20304) -- cache @@ -269,7 +269,8 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, // doing more work yet if !pending_obligation.stalled_on.is_empty() { if pending_obligation.stalled_on.iter().all(|&ty| { - let resolved_ty = self.selcx.infcx().shallow_resolve(&ty); + // Use the force-inlined variant of shallow_resolve() because this code is hot. + let resolved_ty = self.selcx.infcx().inlined_shallow_resolve(&ty); resolved_ty == ty // nothing changed here }) { debug!("process_predicate: pending obligation {:?} still stalled on {:?}", @@ -540,7 +541,7 @@ fn trait_ref_type_vars<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 't .map(|t| selcx.infcx().resolve_type_vars_if_possible(&t)) .filter(|t| t.has_infer_types()) .flat_map(|t| t.walk()) - .filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false }) + .filter(|t| match t.sty { ty::Infer(_) => true, _ => false }) .collect() } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 0290f2e3b1..e2dbe88354 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -24,7 +24,7 @@ use infer::outlives::env::OutlivesEnvironment; use middle::region; use mir::interpret::ConstEvalErr; use ty::subst::Substs; -use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, ToPredicate}; +use ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate}; use ty::error::{ExpectedFound, TypeError}; use ty::fold::{TypeFolder, TypeFoldable, TypeVisitor}; use infer::{InferCtxt}; @@ -142,7 +142,7 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::CompareImplMethodObligation { .. } | ObligationCauseCode::MainFunctionType | ObligationCauseCode::StartFunctionType => { - tcx.sess.codemap().def_span(self.span) + tcx.sess.source_map().def_span(self.span) } _ => self.span, } @@ -185,6 +185,8 @@ pub enum ObligationCauseCode<'tcx> { StructInitializerSized, /// Type of each variable must be Sized VariableType(ast::NodeId), + /// Argument type must be Sized + SizedArgumentType, /// Return type must be Sized SizedReturnType, /// Yield type must be Sized @@ -192,8 +194,8 @@ pub enum ObligationCauseCode<'tcx> { /// [T,..n] --> T must be Copy RepeatVec, - /// Types of fields (other than the last) in a struct must be sized. - FieldSized(AdtKind), + /// Types of fields (other than the last, except for packed structs) in a struct must be sized. + FieldSized { adt_kind: AdtKind, last: bool }, /// Constant expressions must be sized. ConstSized, @@ -323,7 +325,7 @@ pub enum Goal<'tcx> { CannotProve, } -pub type Goals<'tcx> = &'tcx Slice>; +pub type Goals<'tcx> = &'tcx List>; impl<'tcx> DomainGoal<'tcx> { pub fn into_goal(self) -> Goal<'tcx> { @@ -355,7 +357,7 @@ pub enum Clause<'tcx> { } /// Multiple clauses. -pub type Clauses<'tcx> = &'tcx Slice>; +pub type Clauses<'tcx> = &'tcx List>; /// A "program clause" has the form `D :- G1, ..., Gn`. It is saying /// that the domain goal `D` is true if `G1...Gn` are provable. This diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index aa4f63675d..17d55b7762 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -371,7 +371,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut error = false; ty.maybe_walk(|ty| { match ty.sty { - ty::TyParam(ref param_ty) => { + ty::Param(ref param_ty) => { if param_ty.is_self() { error = true; } @@ -379,7 +379,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { false // no contained types to walk } - ty::TyProjection(ref data) => { + ty::Projection(ref data) => { // This is a projected type `::X`. // Compute supertraits of current trait lazily. diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index e1395c3fa4..280ce75720 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { parse_error(tcx, item.span, "this attribute must have a valid value", "expected value here", - Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#)); + Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#)); } if errored { @@ -170,7 +170,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { return Err(parse_error(tcx, attr.span, "`#[rustc_on_unimplemented]` requires a value", "value required here", - Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#))); + Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#))); }; debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result); result @@ -213,10 +213,13 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { } } + let options: FxHashMap = options.into_iter() + .filter_map(|(k, v)| v.as_ref().map(|v| (k.to_owned(), v.to_owned()))) + .collect(); OnUnimplementedNote { - label: label.map(|l| l.format(tcx, trait_ref)), - message: message.map(|m| m.format(tcx, trait_ref)), - note: note.map(|n| n.format(tcx, trait_ref)), + label: label.map(|l| l.format(tcx, trait_ref, &options)), + message: message.map(|m| m.format(tcx, trait_ref, &options)), + note: note.map(|n| n.format(tcx, trait_ref, &options)), } } } @@ -251,6 +254,10 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { Position::ArgumentNamed(s) if s == "Self" => (), // `{ThisTraitsName}` is allowed Position::ArgumentNamed(s) if s == name => (), + // `{from_method}` is allowed + Position::ArgumentNamed(s) if s == "from_method" => (), + // `{from_desugaring}` is allowed + Position::ArgumentNamed(s) if s == "from_desugaring" => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match generics.params.iter().find(|param| { param.name == s @@ -258,17 +265,14 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { Some(_) => (), None => { span_err!(tcx.sess, span, E0230, - "there is no parameter \ - {} on trait {}", - s, name); + "there is no parameter `{}` on trait `{}`", s, name); result = Err(ErrorReported); } }, // `{:1}` and `{}` are not to be used Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => { span_err!(tcx.sess, span, E0231, - "only named substitution \ - parameters are allowed"); + "only named substitution parameters are allowed"); result = Err(ErrorReported); } } @@ -280,7 +284,8 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { pub fn format(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - trait_ref: ty::TraitRef<'tcx>) + trait_ref: ty::TraitRef<'tcx>, + options: &FxHashMap) -> String { let name = tcx.item_name(trait_ref.def_id); @@ -296,6 +301,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { let name = param.name.to_string(); Some((name, value)) }).collect::>(); + let empty_string = String::new(); let parser = Parser::new(&self.0, None); parser.map(|p| { @@ -308,14 +314,20 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { &trait_str } None => { - bug!("broken on_unimplemented {:?} for {:?}: \ - no argument matching {:?}", - self.0, trait_ref, s) + if let Some(val) = options.get(s) { + val + } else if s == "from_desugaring" || s == "from_method" { + // don't break messages using these two arguments incorrectly + &empty_string + } else { + bug!("broken on_unimplemented {:?} for {:?}: \ + no argument matching {:?}", + self.0, trait_ref, s) + } } }, _ => { - bug!("broken on_unimplemented {:?} - bad \ - format arg", self.0) + bug!("broken on_unimplemented {:?} - bad format arg", self.0) } } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 1ce60d8f05..e50f59cbc8 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -366,7 +366,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, let ty = ty.super_fold_with(self); match ty.sty { - ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*) + ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { Reveal::UserFacing => ty, @@ -393,7 +393,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, } } - ty::TyProjection(ref data) if !data.has_escaping_regions() => { // (*) + ty::Projection(ref data) if !data.has_escaping_regions() => { // (*) // (*) This is kind of hacky -- we need to be able to // handle normalization within binders because @@ -812,10 +812,10 @@ fn get_paranoid_cache_value_obligation<'a, 'gcx, 'tcx>( /// return an associated obligation that, when fulfilled, will lead to /// an error. /// -/// Note that we used to return `TyError` here, but that was quite +/// Note that we used to return `Error` here, but that was quite /// dubious -- the premise was that an error would *eventually* be /// reported, when the obligation was processed. But in general once -/// you see a `TyError` you are supposed to be able to assume that an +/// you see a `Error` you are supposed to be able to assume that an /// error *has been* reported, so that you can take whatever heuristic /// paths you want to take. To make things worse, it was possible for /// cycles to arise, where you basically had a setup like ` @@ -983,11 +983,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( let tcx = selcx.tcx(); // Check whether the self-type is itself a projection. let (def_id, substs) = match obligation_trait_ref.self_ty().sty { - ty::TyProjection(ref data) => { + ty::Projection(ref data) => { (data.trait_ref(tcx).def_id, data.substs) } - ty::TyAnon(def_id, substs) => (def_id, substs), - ty::TyInfer(ty::TyVar(_)) => { + ty::Opaque(def_id, substs) => (def_id, substs), + ty::Infer(ty::TyVar(_)) => { // If the self-type is an inference variable, then it MAY wind up // being a projected type, so induce an ambiguity. candidate_set.mark_ambiguous(); @@ -1142,7 +1142,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( if !is_default { true } else if obligation.param_env.reveal == Reveal::All { - assert!(!poly_trait_ref.needs_infer()); + debug_assert!(!poly_trait_ref.needs_infer()); if !poly_trait_ref.needs_subst() { true } else { @@ -1265,7 +1265,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( debug!("confirm_object_candidate(object_ty={:?})", object_ty); let data = match object_ty.sty { - ty::TyDynamic(ref data, ..) => data, + ty::Dynamic(ref data, ..) => data, _ => { span_bug!( obligation.cause.span, @@ -1506,7 +1506,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( // This means that the impl is missing a definition for the // associated type. This error will be reported by the type // checker method `check_impl_items_against_trait`, so here we - // just return TyError. + // just return Error. debug!("confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.ident, obligation.predicate); @@ -1518,7 +1518,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node); let ty = if let ty::AssociatedKind::Existential = assoc_ty.item.kind { let item_substs = Substs::identity_for_item(tcx, assoc_ty.item.def_id); - tcx.mk_anon(assoc_ty.item.def_id, item_substs) + tcx.mk_opaque(assoc_ty.item.def_id, item_substs) } else { tcx.type_of(assoc_ty.item.def_id) }; @@ -1668,15 +1668,15 @@ impl<'tcx> ProjectionCache<'tcx> { } pub fn rollback_to(&mut self, snapshot: ProjectionCacheSnapshot) { - self.map.rollback_to(snapshot.snapshot); + self.map.rollback_to(&snapshot.snapshot); } pub fn rollback_skolemized(&mut self, snapshot: &ProjectionCacheSnapshot) { self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_skol()); } - pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) { - self.map.commit(snapshot.snapshot); + pub fn commit(&mut self, snapshot: &ProjectionCacheSnapshot) { + self.map.commit(&snapshot.snapshot); } /// Try to start normalize `key`; returns an error if diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index a48d24bb97..fd8898dffd 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -10,9 +10,9 @@ use infer::at::At; use infer::InferOk; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; use std::iter::FromIterator; -use syntax::codemap::Span; +use syntax::source_map::Span; use ty::subst::Kind; use ty::{self, Ty, TyCtxt}; @@ -82,7 +82,7 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { // Errors and ambiuity in dropck occur in two cases: // - unresolved inference variables at the end of typeck // - non well-formed types where projections cannot be resolved - // Either of these should hvae created an error before. + // Either of these should have created an error before. tcx.sess .delay_span_bug(span, "dtorck encountered internal error"); return InferOk { @@ -214,54 +214,52 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> // None of these types have a destructor and hence they do not // require anything in particular to outlive the dtor's // execution. - ty::TyInfer(ty::FreshIntTy(_)) - | ty::TyInfer(ty::FreshFloatTy(_)) - | ty::TyBool - | ty::TyInt(_) - | ty::TyUint(_) - | ty::TyFloat(_) - | ty::TyNever - | ty::TyFnDef(..) - | ty::TyFnPtr(_) - | ty::TyChar - | ty::TyGeneratorWitness(..) - | ty::TyRawPtr(_) - | ty::TyRef(..) - | ty::TyStr - | ty::TyForeign(..) - | ty::TyError => true, + ty::Infer(ty::FreshIntTy(_)) + | ty::Infer(ty::FreshFloatTy(_)) + | ty::Bool + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Never + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Char + | ty::GeneratorWitness(..) + | ty::RawPtr(_) + | ty::Ref(..) + | ty::Str + | ty::Foreign(..) + | ty::Error => true, // [T; N] and [T] have same properties as T. - ty::TyArray(ty, _) | ty::TySlice(ty) => trivial_dropck_outlives(tcx, ty), + ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty), // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::TyTuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)), - ty::TyClosure(def_id, ref substs) => substs + ty::Tuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)), + ty::Closure(def_id, ref substs) => substs .upvar_tys(def_id, tcx) .all(|t| trivial_dropck_outlives(tcx, t)), - ty::TyAdt(def, _) => { - if def.is_union() { - // Unions never have a dtor. - true - } else if Some(def.did) == tcx.lang_items().manually_drop() { + ty::Adt(def, _) => { + if Some(def.did) == tcx.lang_items().manually_drop() { // `ManuallyDrop` never has a dtor. true } else { // Other types might. Moreover, PhantomData doesn't // have a dtor, but it is considered to own its - // content, so it is non-trivial. + // content, so it is non-trivial. Unions can have `impl Drop`, + // and hence are non-trivial as well. false } } // The following *might* require a destructor: it would deeper inspection to tell. - ty::TyDynamic(..) - | ty::TyProjection(..) - | ty::TyParam(_) - | ty::TyAnon(..) - | ty::TyInfer(_) - | ty::TyGenerator(..) => false, + ty::Dynamic(..) + | ty::Projection(..) + | ty::Param(_) + | ty::Opaque(..) + | ty::Infer(_) + | ty::Generator(..) => false, } } diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 93fcadceb1..6bd9267836 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -9,7 +9,7 @@ // except according to those terms. use infer::InferCtxt; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; use traits::{EvaluationResult, PredicateObligation, SelectionContext, TraitQueryMode, OverflowError}; diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 2203aefa31..ea8bc3b20a 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -12,15 +12,15 @@ //! which folds deeply, invoking the underlying //! `normalize_projection_ty` query when it encounters projections. -use infer::{InferCtxt, InferOk}; use infer::at::At; -use mir::interpret::{GlobalId, ConstValue}; -use rustc_data_structures::small_vec::SmallVec; -use traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; +use infer::{InferCtxt, InferOk}; +use mir::interpret::{ConstValue, GlobalId}; +use smallvec::SmallVec; use traits::project::Normalized; -use ty::{self, Ty, TyCtxt}; +use traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use ty::fold::{TypeFoldable, TypeFolder}; use ty::subst::{Subst, Substs}; +use ty::{self, Ty, TyCtxt}; use super::NoSolution; @@ -99,7 +99,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { let ty = ty.super_fold_with(self); match ty.sty { - ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { + ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { @@ -121,9 +121,14 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx let concrete_ty = generic_ty.subst(self.tcx(), substs); self.anon_depth += 1; if concrete_ty == ty { - bug!("infinite recursion generic_ty: {:#?}, substs: {:#?}, \ - concrete_ty: {:#?}, ty: {:#?}", generic_ty, substs, concrete_ty, - ty); + bug!( + "infinite recursion generic_ty: {:#?}, substs: {:#?}, \ + concrete_ty: {:#?}, ty: {:#?}", + generic_ty, + substs, + concrete_ty, + ty + ); } let folded_ty = self.fold_ty(concrete_ty); self.anon_depth -= 1; @@ -132,7 +137,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx } } - ty::TyProjection(ref data) if !data.has_escaping_regions() => { + ty::Projection(ref data) if !data.has_escaping_regions() => { // (*) // (*) This is kind of hacky -- we need to be able to // handle normalization within binders because @@ -149,8 +154,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx let gcx = self.infcx.tcx.global_tcx(); let mut orig_values = SmallVec::new(); - let c_data = - self.infcx.canonicalize_query(&self.param_env.and(*data), &mut orig_values); + let c_data = self.infcx + .canonicalize_query(&self.param_env.and(*data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); match gcx.normalize_projection_ty(c_data) { diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs index f79ce73ad9..47c8ee357f 100644 --- a/src/librustc/traits/query/outlives_bounds.rs +++ b/src/librustc/traits/query/outlives_bounds.rs @@ -10,8 +10,8 @@ use infer::InferCtxt; use syntax::ast; -use syntax::codemap::Span; -use rustc_data_structures::small_vec::SmallVec; +use syntax::source_map::Span; +use smallvec::SmallVec; use traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt}; use traits::query::NoSolution; use ty::{self, Ty, TyCtxt}; @@ -137,7 +137,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // variables. Process these constraints. let mut fulfill_cx = FulfillmentContext::new(); fulfill_cx.register_predicate_obligations(self, result.obligations); - if let Err(_) = fulfill_cx.select_all_or_error(self) { + if fulfill_cx.select_all_or_error(self).is_err() { self.tcx.sess.delay_span_bug( span, "implied_outlives_bounds failed to solve obligations from instantiation" diff --git a/src/librustc/traits/query/type_op/custom.rs b/src/librustc/traits/query/type_op/custom.rs index cc752d21ab..6a5ef75a66 100644 --- a/src/librustc/traits/query/type_op/custom.rs +++ b/src/librustc/traits/query/type_op/custom.rs @@ -15,7 +15,7 @@ use traits::query::Fallible; use infer::canonical::query_result; use infer::canonical::QueryRegionConstraint; use std::rc::Rc; -use syntax::codemap::DUMMY_SP; +use syntax::source_map::DUMMY_SP; use traits::{ObligationCause, TraitEngine, TraitEngineExt}; pub struct CustomTypeOp { @@ -102,8 +102,14 @@ fn scrape_region_constraints<'gcx, 'tcx, R>( let region_constraint_data = infcx.take_and_reset_region_constraints(); - let outlives = - query_result::make_query_outlives(infcx.tcx, region_obligations, ®ion_constraint_data); + let outlives = query_result::make_query_outlives( + infcx.tcx, + region_obligations + .iter() + .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)) + .map(|(ty, r)| (infcx.resolve_type_vars_if_possible(&ty), r)), + ®ion_constraint_data, + ); if outlives.is_empty() { Ok((value, None)) diff --git a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs new file mode 100644 index 0000000000..27534bc8c3 --- /dev/null +++ b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs @@ -0,0 +1,80 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult}; +use traits::query::outlives_bounds::OutlivesBound; +use traits::query::Fallible; +use ty::{ParamEnvAnd, Ty, TyCtxt}; + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub struct ImpliedOutlivesBounds<'tcx> { + pub ty: Ty<'tcx>, +} + +impl<'tcx> ImpliedOutlivesBounds<'tcx> { + pub fn new(ty: Ty<'tcx>) -> Self { + ImpliedOutlivesBounds { ty } + } +} + +impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ImpliedOutlivesBounds<'tcx> { + type QueryResult = Vec>; + + fn try_fast_path( + _tcx: TyCtxt<'_, 'gcx, 'tcx>, + _key: &ParamEnvAnd<'tcx, Self>, + ) -> Option { + None + } + + fn perform_query( + tcx: TyCtxt<'_, 'gcx, 'tcx>, + canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>, + ) -> Fallible> { + // FIXME the query should take a `ImpliedOutlivesBounds` + let Canonical { + variables, + value: + ParamEnvAnd { + param_env, + value: ImpliedOutlivesBounds { ty }, + }, + } = canonicalized; + let canonicalized = Canonical { + variables, + value: param_env.and(ty), + }; + + tcx.implied_outlives_bounds(canonicalized) + } + + fn shrink_to_tcx_lifetime( + v: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>, + ) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>> { + v + } +} + +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ImpliedOutlivesBounds<'tcx> { + ty, + } +} + +BraceStructLiftImpl! { + impl<'a, 'tcx> Lift<'tcx> for ImpliedOutlivesBounds<'a> { + type Lifted = ImpliedOutlivesBounds<'tcx>; + ty, + } +} + +impl_stable_hash_for! { + struct ImpliedOutlivesBounds<'tcx> { ty } +} diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs index be5e283896..8e4236d175 100644 --- a/src/librustc/traits/query/type_op/mod.rs +++ b/src/librustc/traits/query/type_op/mod.rs @@ -11,7 +11,7 @@ use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint, QueryResult}; use infer::{InferCtxt, InferOk}; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; use std::fmt; use std::rc::Rc; use traits::query::Fallible; @@ -21,6 +21,7 @@ use ty::{Lift, ParamEnvAnd, TyCtxt}; pub mod custom; pub mod eq; +pub mod implied_outlives_bounds; pub mod normalize; pub mod outlives; pub mod prove_predicate; diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs index 33dc3210f0..e1b3b3c436 100644 --- a/src/librustc/traits/query/type_op/prove_predicate.rs +++ b/src/librustc/traits/query/type_op/prove_predicate.rs @@ -27,9 +27,23 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> { type QueryResult = (); fn try_fast_path( - _tcx: TyCtxt<'_, 'gcx, 'tcx>, - _key: &ParamEnvAnd<'tcx, Self>, + tcx: TyCtxt<'_, 'gcx, 'tcx>, + key: &ParamEnvAnd<'tcx, Self>, ) -> Option { + // Proving Sized, very often on "obviously sized" types like + // `&T`, accounts for about 60% percentage of the predicates + // we have to prove. No need to canonicalize and all that for + // such cases. + if let Predicate::Trait(trait_ref) = key.value.predicate { + if let Some(sized_def_id) = tcx.lang_items().sized_trait() { + if trait_ref.def_id() == sized_def_id { + if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) { + return Some(()); + } + } + } + } + None } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 40171345f5..232ef10853 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -45,7 +45,7 @@ use middle::lang_items; use mir::interpret::{GlobalId}; use rustc_data_structures::sync::Lock; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use std::iter; use std::cmp; use std::fmt; @@ -120,13 +120,13 @@ impl IntercrateAmbiguityCause { &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => { let self_desc = if let &Some(ref ty) = self_desc { format!(" for type `{}`", ty) - } else { "".to_string() }; + } else { String::new() }; format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc) } &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => { let self_desc = if let &Some(ref ty) = self_desc { format!(" for type `{}`", ty) - } else { "".to_string() }; + } else { String::new() }; format!("upstream crates may add new impl of trait `{}`{} \ in future versions", trait_desc, self_desc) @@ -226,6 +226,7 @@ pub struct SelectionCache<'tcx> { /// parameter environment. #[derive(PartialEq,Eq,Debug,Clone)] enum SelectionCandidate<'tcx> { + /// If has_nested is false, there are no *further* obligations BuiltinCandidate { has_nested: bool }, ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(DefId), @@ -563,7 +564,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { pub fn select(&mut self, obligation: &TraitObligation<'tcx>) -> SelectionResult<'tcx, Selection<'tcx>> { debug!("select({:?})", obligation); - assert!(!obligation.predicate.has_escaping_regions()); + debug_assert!(!obligation.predicate.has_escaping_regions()); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); @@ -662,7 +663,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match obligation.predicate { ty::Predicate::Trait(ref t) => { - assert!(!t.has_escaping_regions()); + debug_assert!(!t.has_escaping_regions()); let obligation = obligation.with(t.clone()); self.evaluate_trait_predicate_recursively(previous_stack, obligation) } @@ -1076,7 +1077,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})", cache_fresh_trait_pred, stack); - assert!(!stack.obligation.predicate.has_escaping_regions()); + debug_assert!(!stack.obligation.predicate.has_escaping_regions()); if let Some(c) = self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred) { @@ -1127,7 +1128,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { if stack.obligation.predicate.references_error() { - // If we encounter a `TyError`, we generally prefer the + // If we encounter a `Error`, we generally prefer the // most "optimistic" result in response -- that is, the // one least likely to report downstream errors. But // because this routine is shared by coherence and by @@ -1491,8 +1492,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // before we go into the whole skolemization thing, just // quickly check if the self-type is a projection at all. match obligation.predicate.skip_binder().trait_ref.self_ty().sty { - ty::TyProjection(_) | ty::TyAnon(..) => {} - ty::TyInfer(ty::TyVar(_)) => { + ty::Projection(_) | ty::Opaque(..) => {} + ty::Infer(ty::TyVar(_)) => { span_bug!(obligation.cause.span, "Self=_ should have been handled by assemble_candidates"); } @@ -1525,9 +1526,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { skol_map); let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { - ty::TyProjection(ref data) => + ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs), - ty::TyAnon(def_id, substs) => (def_id, substs), + ty::Opaque(def_id, substs) => (def_id, substs), _ => { span_bug!( obligation.cause.span, @@ -1586,9 +1587,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { snapshot: &infer::CombinedSnapshot<'cx, 'tcx>) -> bool { - assert!(!skol_trait_ref.has_escaping_regions()); - if let Err(_) = self.infcx.at(&obligation.cause, obligation.param_env) - .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) { + debug_assert!(!skol_trait_ref.has_escaping_regions()); + if self.infcx.at(&obligation.cause, obligation.param_env) + .sup(ty::Binder::dummy(skol_trait_ref), trait_bound).is_err() { return false; } @@ -1660,7 +1661,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // type/region parameters let self_ty = *obligation.self_ty().skip_binder(); match self_ty.sty { - ty::TyGenerator(..) => { + ty::Generator(..) => { debug!("assemble_generator_candidates: self_ty={:?} obligation={:?}", self_ty, obligation); @@ -1668,7 +1669,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidates.vec.push(GeneratorCandidate); Ok(()) } - ty::TyInfer(ty::TyVar(_)) => { + ty::Infer(ty::TyVar(_)) => { debug!("assemble_generator_candidates: ambiguous self-type"); candidates.ambiguous = true; return Ok(()); @@ -1697,7 +1698,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters match obligation.self_ty().skip_binder().sty { - ty::TyClosure(closure_def_id, closure_substs) => { + ty::Closure(closure_def_id, closure_substs) => { debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}", kind, obligation); match self.infcx.closure_kind(closure_def_id, closure_substs) { @@ -1714,7 +1715,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }; Ok(()) } - ty::TyInfer(ty::TyVar(_)) => { + ty::Infer(ty::TyVar(_)) => { debug!("assemble_unboxed_closure_candidates: ambiguous self-type"); candidates.ambiguous = true; return Ok(()); @@ -1737,13 +1738,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // ok to skip binder because what we are inspecting doesn't involve bound regions let self_ty = *obligation.self_ty().skip_binder(); match self_ty.sty { - ty::TyInfer(ty::TyVar(_)) => { + ty::Infer(ty::TyVar(_)) => { debug!("assemble_fn_pointer_candidates: ambiguous self-type"); candidates.ambiguous = true; // could wind up being a fn() type } // provide an impl, but only for suitable `fn` pointers - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { if let ty::FnSig { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, @@ -1803,20 +1804,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if self.tcx().trait_is_auto(def_id) { match self_ty.sty { - ty::TyDynamic(..) => { + ty::Dynamic(..) => { // For object types, we don't know what the closed // over types are. This means we conservatively // say nothing; a candidate may be added by // `assemble_candidates_from_object_ty`. } - ty::TyForeign(..) => { + ty::Foreign(..) => { // Since the contents of foreign types is unknown, // we don't add any `..` impl. Default traits could // still be provided by a manual implementation for // this trait and type. } - ty::TyParam(..) | - ty::TyProjection(..) => { + ty::Param(..) | + ty::Projection(..) => { // In these cases, we don't know what the actual // type is. Therefore, we cannot break it down // into its constituent types. So we don't @@ -1831,7 +1832,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // for an example of a test case that exercises // this path. } - ty::TyInfer(ty::TyVar(_)) => { + ty::Infer(ty::TyVar(_)) => { // the auto impl might apply, we don't know candidates.ambiguous = true; } @@ -1870,7 +1871,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // any LBR. let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty()); let poly_trait_ref = match self_ty.sty { - ty::TyDynamic(ref data, ..) => { + ty::Dynamic(ref data, ..) => { if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate"); @@ -1883,7 +1884,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { None => return, } } - ty::TyInfer(ty::TyVar(_)) => { + ty::Infer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); candidates.ambiguous = true; // could wind up being an object type return; @@ -1952,7 +1953,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let may_apply = match (&source.sty, &target.sty) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). - (&ty::TyDynamic(ref data_a, ..), &ty::TyDynamic(ref data_b, ..)) => { + (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { // Upcasts permit two things: // // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo` @@ -1974,28 +1975,28 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // T -> Trait. - (_, &ty::TyDynamic(..)) => true, + (_, &ty::Dynamic(..)) => true, // Ambiguous handling is below T -> Trait, because inference // variables can still implement Unsize and nested // obligations will have the final say (likely deferred). - (&ty::TyInfer(ty::TyVar(_)), _) | - (_, &ty::TyInfer(ty::TyVar(_))) => { + (&ty::Infer(ty::TyVar(_)), _) | + (_, &ty::Infer(ty::TyVar(_))) => { debug!("assemble_candidates_for_unsizing: ambiguous"); candidates.ambiguous = true; false } // [T; n] -> [T]. - (&ty::TyArray(..), &ty::TySlice(_)) => true, + (&ty::Array(..), &ty::Slice(_)) => true, // Struct -> Struct. - (&ty::TyAdt(def_id_a, _), &ty::TyAdt(def_id_b, _)) if def_id_a.is_struct() => { + (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => { def_id_a == def_id_b } // (.., T) -> (.., U). - (&ty::TyTuple(tys_a), &ty::TyTuple(tys_b)) => { + (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => { tys_a.len() == tys_b.len() } @@ -2039,12 +2040,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } match other.candidate { + // Prefer BuiltinCandidate { has_nested: false } to anything else. + // This is a fix for #53123 and prevents winnowing from accidentally extending the + // lifetime of a variable. + BuiltinCandidate { has_nested: false } => true, ParamCandidate(ref cand) => match victim.candidate { AutoImplCandidate(..) => { bug!( "default implementations shouldn't be recorded \ when there are other valid candidates"); } + // Prefer BuiltinCandidate { has_nested: false } to anything else. + // This is a fix for #53123 and prevents winnowing from accidentally extending the + // lifetime of a variable. + BuiltinCandidate { has_nested: false } => false, ImplCandidate(..) | ClosureCandidate | GeneratorCandidate | @@ -2072,6 +2081,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { "default implementations shouldn't be recorded \ when there are other valid candidates"); } + // Prefer BuiltinCandidate { has_nested: false } to anything else. + // This is a fix for #53123 and prevents winnowing from accidentally extending the + // lifetime of a variable. + BuiltinCandidate { has_nested: false } => false, ImplCandidate(..) | ClosureCandidate | GeneratorCandidate | @@ -2115,7 +2128,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { FnPointerCandidate | BuiltinObjectCandidate | BuiltinUnsizeCandidate | - BuiltinCandidate { .. } => { + BuiltinCandidate { has_nested: true } => { match victim.candidate { ParamCandidate(ref cand) => { // Prefer these to a global where-clause bound @@ -2166,23 +2179,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.skip_binder().self_ty()); match self_ty.sty { - ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | - ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | - ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) | - ty::TyChar | ty::TyRef(..) | ty::TyGenerator(..) | - ty::TyGeneratorWitness(..) | ty::TyArray(..) | ty::TyClosure(..) | - ty::TyNever | ty::TyError => { + ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | + ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | + ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) | + ty::Char | ty::Ref(..) | ty::Generator(..) | + ty::GeneratorWitness(..) | ty::Array(..) | ty::Closure(..) | + ty::Never | ty::Error => { // safe for everything Where(ty::Binder::dummy(Vec::new())) } - ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => None, + ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None, - ty::TyTuple(tys) => { + ty::Tuple(tys) => { Where(ty::Binder::bind(tys.last().into_iter().cloned().collect())) } - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { let sized_crit = def.sized_constraint(self.tcx()); // (*) binder moved here Where(ty::Binder::bind( @@ -2190,13 +2203,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { )) } - ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None, - ty::TyInfer(ty::TyVar(_)) => Ambiguous, + ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None, + ty::Infer(ty::TyVar(_)) => Ambiguous, - ty::TyInfer(ty::CanonicalTy(_)) | - ty::TyInfer(ty::FreshTy(_)) | - ty::TyInfer(ty::FreshIntTy(_)) | - ty::TyInfer(ty::FreshFloatTy(_)) => { + ty::Infer(ty::CanonicalTy(_)) | + ty::Infer(ty::FreshTy(_)) | + ty::Infer(ty::FreshIntTy(_)) | + ty::Infer(ty::FreshFloatTy(_)) => { bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty); } @@ -2213,35 +2226,35 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { use self::BuiltinImplConditions::{Ambiguous, None, Where}; match self_ty.sty { - ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | - ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyError => { + ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | + ty::FnDef(..) | ty::FnPtr(_) | ty::Error => { Where(ty::Binder::dummy(Vec::new())) } - ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | - ty::TyChar | ty::TyRawPtr(..) | ty::TyNever | - ty::TyRef(_, _, hir::MutImmutable) => { + ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | + ty::Char | ty::RawPtr(..) | ty::Never | + ty::Ref(_, _, hir::MutImmutable) => { // Implementations provided in libcore None } - ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) | - ty::TyGenerator(..) | ty::TyGeneratorWitness(..) | ty::TyForeign(..) | - ty::TyRef(_, _, hir::MutMutable) => { + ty::Dynamic(..) | ty::Str | ty::Slice(..) | + ty::Generator(..) | ty::GeneratorWitness(..) | ty::Foreign(..) | + ty::Ref(_, _, hir::MutMutable) => { None } - ty::TyArray(element_ty, _) => { + ty::Array(element_ty, _) => { // (*) binder moved here Where(ty::Binder::bind(vec![element_ty])) } - ty::TyTuple(tys) => { + ty::Tuple(tys) => { // (*) binder moved here Where(ty::Binder::bind(tys.to_vec())) } - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { let trait_id = obligation.predicate.def_id(); let is_copy_trait = Some(trait_id) == self.tcx().lang_items().copy_trait(); let is_clone_trait = Some(trait_id) == self.tcx().lang_items().clone_trait(); @@ -2252,22 +2265,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - ty::TyAdt(..) | ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => { + ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => { // Fallback to whatever user-defined impls exist in this case. None } - ty::TyInfer(ty::TyVar(_)) => { + ty::Infer(ty::TyVar(_)) => { // Unbound type variable. Might or might not have // applicable impls and so forth, depending on what // those type variables wind up being bound to. Ambiguous } - ty::TyInfer(ty::CanonicalTy(_)) | - ty::TyInfer(ty::FreshTy(_)) | - ty::TyInfer(ty::FreshIntTy(_)) | - ty::TyInfer(ty::FreshFloatTy(_)) => { + ty::Infer(ty::CanonicalTy(_)) | + ty::Infer(ty::FreshTy(_)) | + ty::Infer(ty::FreshIntTy(_)) | + ty::Infer(ty::FreshFloatTy(_)) => { bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty); } @@ -2287,58 +2300,58 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// ``` fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec> { match t.sty { - ty::TyUint(_) | - ty::TyInt(_) | - ty::TyBool | - ty::TyFloat(_) | - ty::TyFnDef(..) | - ty::TyFnPtr(_) | - ty::TyStr | - ty::TyError | - ty::TyInfer(ty::IntVar(_)) | - ty::TyInfer(ty::FloatVar(_)) | - ty::TyNever | - ty::TyChar => { + ty::Uint(_) | + ty::Int(_) | + ty::Bool | + ty::Float(_) | + ty::FnDef(..) | + ty::FnPtr(_) | + ty::Str | + ty::Error | + ty::Infer(ty::IntVar(_)) | + ty::Infer(ty::FloatVar(_)) | + ty::Never | + ty::Char => { Vec::new() } - ty::TyDynamic(..) | - ty::TyParam(..) | - ty::TyForeign(..) | - ty::TyProjection(..) | - ty::TyInfer(ty::CanonicalTy(_)) | - ty::TyInfer(ty::TyVar(_)) | - ty::TyInfer(ty::FreshTy(_)) | - ty::TyInfer(ty::FreshIntTy(_)) | - ty::TyInfer(ty::FreshFloatTy(_)) => { + ty::Dynamic(..) | + ty::Param(..) | + ty::Foreign(..) | + ty::Projection(..) | + ty::Infer(ty::CanonicalTy(_)) | + ty::Infer(ty::TyVar(_)) | + ty::Infer(ty::FreshTy(_)) | + ty::Infer(ty::FreshIntTy(_)) | + ty::Infer(ty::FreshFloatTy(_)) => { bug!("asked to assemble constituent types of unexpected type: {:?}", t); } - ty::TyRawPtr(ty::TypeAndMut { ty: element_ty, ..}) | - ty::TyRef(_, element_ty, _) => { + ty::RawPtr(ty::TypeAndMut { ty: element_ty, ..}) | + ty::Ref(_, element_ty, _) => { vec![element_ty] }, - ty::TyArray(element_ty, _) | ty::TySlice(element_ty) => { + ty::Array(element_ty, _) | ty::Slice(element_ty) => { vec![element_ty] } - ty::TyTuple(ref tys) => { + ty::Tuple(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet tys.to_vec() } - ty::TyClosure(def_id, ref substs) => { + ty::Closure(def_id, ref substs) => { substs.upvar_tys(def_id, self.tcx()).collect() } - ty::TyGenerator(def_id, ref substs, _) => { + ty::Generator(def_id, ref substs, _) => { let witness = substs.witness(def_id, self.tcx()); substs.upvar_tys(def_id, self.tcx()).chain(iter::once(witness)).collect() } - ty::TyGeneratorWitness(types) => { + ty::GeneratorWitness(types) => { // This is sound because no regions in the witness can refer to // the binder outside the witness. So we'll effectivly reuse // the implicit binder around the witness. @@ -2346,17 +2359,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // for `PhantomData`, we pass `T` - ty::TyAdt(def, substs) if def.is_phantom_data() => { + ty::Adt(def, substs) if def.is_phantom_data() => { substs.types().collect() } - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { def.all_fields() .map(|f| f.ty(self.tcx(), substs)) .collect() } - ty::TyAnon(def_id, substs) => { + ty::Opaque(def_id, substs) => { // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. @@ -2715,7 +2728,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // case that results. -nmatsakis let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { - ty::TyDynamic(ref data, ..) => { + ty::Dynamic(ref data, ..) => { data.principal().unwrap().with_self_ty(self.tcx(), self_ty) } _ => { @@ -2810,7 +2823,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // type/region parameters let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let (generator_def_id, substs) = match self_ty.sty { - ty::TyGenerator(id, substs, _) => (id, substs), + ty::Generator(id, substs, _) => (id, substs), _ => bug!("closure candidate for non-closure {:?}", obligation) }; @@ -2866,7 +2879,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // type/region parameters let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let (closure_def_id, substs) = match self_ty.sty { - ty::TyClosure(id, substs) => (id, substs), + ty::Closure(id, substs) => (id, substs), _ => bug!("closure candidate for non-closure {:?}", obligation) }; @@ -2963,7 +2976,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let mut nested = vec![]; match (&source.sty, &target.sty) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). - (&ty::TyDynamic(ref data_a, r_a), &ty::TyDynamic(ref data_b, r_b)) => { + (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => { // See assemble_candidates_for_unsizing for more info. let existential_predicates = data_a.map_bound(|data_a| { let principal = data_a.principal(); @@ -2992,7 +3005,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // T -> Trait. - (_, &ty::TyDynamic(ref data, r)) => { + (_, &ty::Dynamic(ref data, r)) => { let mut object_dids = data.auto_traits().chain(data.principal().map(|p| p.def_id())); if let Some(did) = object_dids.find(|did| { @@ -3035,7 +3048,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // [T; n] -> [T]. - (&ty::TyArray(a, _), &ty::TySlice(b)) => { + (&ty::Array(a, _), &ty::Slice(b)) => { let InferOk { obligations, .. } = self.infcx.at(&obligation.cause, obligation.param_env) .eq(b, a) @@ -3044,7 +3057,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // Struct -> Struct. - (&ty::TyAdt(def, substs_a), &ty::TyAdt(_, substs_b)) => { + (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => { let fields = def .all_fields() .map(|f| tcx.type_of(f.did)) @@ -3056,10 +3069,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } else { return Err(Unimplemented); }; - let mut ty_params = BitVector::new(substs_a.types().count()); + let mut ty_params = BitArray::new(substs_a.types().count()); let mut found = false; for ty in field.walk() { - if let ty::TyParam(p) = ty.sty { + if let ty::Param(p) = ty.sty { ty_params.insert(p.idx as usize); found = true; } @@ -3069,7 +3082,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // Replace type parameters used in unsizing with - // TyError and ensure they do not affect any other fields. + // Error and ensure they do not affect any other fields. // This could be checked after type collection for any struct // with a potentially unsized trailing field. let params = substs_a.iter().enumerate().map(|(i, &k)| { @@ -3117,7 +3130,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // (.., T) -> (.., U). - (&ty::TyTuple(tys_a), &ty::TyTuple(tys_b)) => { + (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => { assert_eq!(tys_a.len(), tys_b.len()); // The last field of the tuple has to exist. diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 06f9b44614..9343eff9e7 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -90,7 +90,7 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, .unwrap() .subst(infcx.tcx, &source_substs); - // translate the Self and TyParam parts of the substitution, since those + // translate the Self and Param parts of the substitution, since those // vary across impls let target_substs = match target_node { specialization_graph::Node::Impl(target_impl) => { @@ -344,7 +344,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx }), if used_to_be_allowed { " (E0119)" } else { "" } ); - let impl_span = tcx.sess.codemap().def_span( + let impl_span = tcx.sess.source_map().def_span( tcx.span_of_impl(impl_def_id).unwrap() ); let mut err = if used_to_be_allowed { @@ -363,7 +363,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx match tcx.span_of_impl(overlap.with_impl) { Ok(span) => { - err.span_label(tcx.sess.codemap().def_span(span), + err.span_label(tcx.sess.source_map().def_span(span), "first implementation here".to_string()); err.span_label(impl_span, format!("conflicting implementation{}", diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index f9c0581d3c..a7652574c1 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -49,7 +49,7 @@ pub struct Graph { /// Children of a given impl, grouped into blanket/non-blanket varieties as is /// done in `TraitDef`. -#[derive(RustcEncodable, RustcDecodable)] +#[derive(Default, RustcEncodable, RustcDecodable)] struct Children { // Impls of a trait (or specializations of a given impl). To allow for // quicker lookup, the impls are indexed by a simplified version of their @@ -81,13 +81,6 @@ enum Inserted { } impl<'a, 'gcx, 'tcx> Children { - fn new() -> Children { - Children { - nonblanket_impls: FxHashMap(), - blanket_impls: vec![], - } - } - /// Insert an impl into this set of children without comparing to any existing impls fn insert_blindly(&mut self, tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -95,7 +88,7 @@ impl<'a, 'gcx, 'tcx> Children { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); if let Some(sty) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { debug!("insert_blindly: impl_def_id={:?} sty={:?}", impl_def_id, sty); - self.nonblanket_impls.entry(sty).or_insert(vec![]).push(impl_def_id) + self.nonblanket_impls.entry(sty).or_default().push(impl_def_id) } else { debug!("insert_blindly: impl_def_id={:?} sty=None", impl_def_id); self.blanket_impls.push(impl_def_id) @@ -230,7 +223,7 @@ impl<'a, 'gcx, 'tcx> Children { } fn filtered(&mut self, sty: SimplifiedType) -> Box + '_> { - let nonblanket = self.nonblanket_impls.entry(sty).or_insert(vec![]).iter(); + let nonblanket = self.nonblanket_impls.entry(sty).or_default().iter(); Box::new(self.blanket_impls.iter().chain(nonblanket).cloned()) } } @@ -268,7 +261,7 @@ impl<'a, 'gcx, 'tcx> Graph { trait_ref, impl_def_id, trait_def_id); self.parent.insert(impl_def_id, trait_def_id); - self.children.entry(trait_def_id).or_insert(Children::new()) + self.children.entry(trait_def_id).or_default() .insert_blindly(tcx, impl_def_id); return Ok(None); } @@ -281,7 +274,7 @@ impl<'a, 'gcx, 'tcx> Graph { loop { use self::Inserted::*; - let insert_result = self.children.entry(parent).or_insert(Children::new()) + let insert_result = self.children.entry(parent).or_default() .insert(tcx, impl_def_id, simplified)?; match insert_result { @@ -318,9 +311,8 @@ impl<'a, 'gcx, 'tcx> Graph { self.parent.insert(impl_def_id, parent); // Add G as N's child. - let mut grand_children = Children::new(); - grand_children.insert_blindly(tcx, grand_child_to_be); - self.children.insert(impl_def_id, grand_children); + self.children.entry(impl_def_id).or_default() + .insert_blindly(tcx, grand_child_to_be); break; } ShouldRecurseOn(new_parent) => { @@ -343,7 +335,7 @@ impl<'a, 'gcx, 'tcx> Graph { was already present."); } - self.children.entry(parent).or_insert(Children::new()).insert_blindly(tcx, child); + self.children.entry(parent).or_default().insert_blindly(tcx, child); } /// The parent of a given impl, which is the def id of the trait when the diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 39e358803c..10e930d1c9 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -9,7 +9,7 @@ // except according to those terms. use chalk_engine; -use rustc_data_structures::accumulate_vec::AccumulateVec; +use smallvec::SmallVec; use traits; use traits::project::Normalized; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -203,10 +203,11 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::StructInitializerSized => Some(super::StructInitializerSized), super::VariableType(id) => Some(super::VariableType(id)), super::ReturnType(id) => Some(super::ReturnType(id)), + super::SizedArgumentType => Some(super::SizedArgumentType), super::SizedReturnType => Some(super::SizedReturnType), super::SizedYieldType => Some(super::SizedYieldType), super::RepeatVec => Some(super::RepeatVec), - super::FieldSized(item) => Some(super::FieldSized(item)), + super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }), super::ConstSized => Some(super::ConstSized), super::SharedStatic => Some(super::SharedStatic), super::BuiltinDerivedObligation(ref cause) => { @@ -619,11 +620,11 @@ EnumLiftImpl! { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { let v = self.iter() .map(|t| t.fold_with(folder)) - .collect::>(); + .collect::>(); folder.tcx().intern_goals(&v) } @@ -657,11 +658,11 @@ EnumTypeFoldableImpl! { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { let v = self.iter() .map(|t| t.fold_with(folder)) - .collect::>(); + .collect::>(); folder.tcx().intern_clauses(&v) } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 875c7199f6..40f13ac06f 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -239,6 +239,10 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> { type Item = ty::Predicate<'tcx>; + fn size_hint(&self) -> (usize, Option) { + (self.stack.len(), None) + } + fn next(&mut self) -> Option> { // Extract next item from top-most stack frame, if any. let next_predicate = match self.stack.pop() { diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs index 047bfcc8c6..c9b0e97c9b 100644 --- a/src/librustc/ty/_match.rs +++ b/src/librustc/ty/_match.rs @@ -67,18 +67,18 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Match<'a, 'gcx, 'tcx> { if a == b { return Ok(a); } match (&a.sty, &b.sty) { - (_, &ty::TyInfer(ty::FreshTy(_))) | - (_, &ty::TyInfer(ty::FreshIntTy(_))) | - (_, &ty::TyInfer(ty::FreshFloatTy(_))) => { + (_, &ty::Infer(ty::FreshTy(_))) | + (_, &ty::Infer(ty::FreshIntTy(_))) | + (_, &ty::Infer(ty::FreshFloatTy(_))) => { Ok(a) } - (&ty::TyInfer(_), _) | - (_, &ty::TyInfer(_)) => { + (&ty::Infer(_), _) | + (_, &ty::Infer(_)) => { Err(TypeError::Sorts(relate::expected_found(self, &a, &b))) } - (&ty::TyError, _) | (_, &ty::TyError) => { + (&ty::Error, _) | (_, &ty::Error) => { Ok(self.tcx().types.err) } diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index 7593d4ed24..c0861abb77 100644 --- a/src/librustc/ty/cast.rs +++ b/src/librustc/ty/cast.rs @@ -60,18 +60,18 @@ pub enum CastKind { impl<'tcx> CastTy<'tcx> { pub fn from_ty(t: Ty<'tcx>) -> Option> { match t.sty { - ty::TyBool => Some(CastTy::Int(IntTy::Bool)), - ty::TyChar => Some(CastTy::Int(IntTy::Char)), - ty::TyInt(_) => Some(CastTy::Int(IntTy::I)), - ty::TyInfer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)), - ty::TyInfer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float), - ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))), - ty::TyFloat(_) => Some(CastTy::Float), - ty::TyAdt(d,_) if d.is_enum() && d.is_payloadfree() => + ty::Bool => Some(CastTy::Int(IntTy::Bool)), + ty::Char => Some(CastTy::Int(IntTy::Char)), + ty::Int(_) => Some(CastTy::Int(IntTy::I)), + ty::Infer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)), + ty::Infer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float), + ty::Uint(u) => Some(CastTy::Int(IntTy::U(u))), + ty::Float(_) => Some(CastTy::Float), + ty::Adt(d,_) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)), - ty::TyRawPtr(mt) => Some(CastTy::Ptr(mt)), - ty::TyRef(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })), - ty::TyFnPtr(..) => Some(CastTy::FnPtr), + ty::RawPtr(mt) => Some(CastTy::Ptr(mt)), + ty::Ref(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })), + ty::FnPtr(..) => Some(CastTy::FnPtr), _ => None, } } diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 967a3324cf..cc3e8a458a 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -37,7 +37,7 @@ pub trait EncodableWithShorthand: Clone + Eq + Hash { } impl<'tcx> EncodableWithShorthand for Ty<'tcx> { - type Variant = ty::TypeVariants<'tcx>; + type Variant = ty::TyKind<'tcx>; fn variant(&self) -> &Self::Variant { &self.sty } @@ -164,7 +164,7 @@ pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result, D::Error> }) } else { let tcx = decoder.tcx(); - Ok(tcx.mk_ty(ty::TypeVariants::decode(decoder)?)) + Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?)) } } @@ -212,7 +212,7 @@ pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result, D #[inline] pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D) - -> Result<&'tcx ty::Slice>, D::Error> + -> Result<&'tcx ty::List>, D::Error> where D: TyDecoder<'a, 'tcx>, 'tcx: 'a, { @@ -232,7 +232,7 @@ pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D) #[inline] pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D) - -> Result<&'tcx ty::Slice>, D::Error> + -> Result<&'tcx ty::List>, D::Error> where D: TyDecoder<'a, 'tcx>, 'tcx: 'a, { @@ -366,10 +366,10 @@ macro_rules! implement_ty_decoder { } } - impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice>> + impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List>> for $DecoderName<$($typaram),*> { fn specialized_decode(&mut self) - -> Result<&'tcx ty::Slice>, Self::Error> { + -> Result<&'tcx ty::List>, Self::Error> { decode_ty_slice(self) } } @@ -381,10 +381,10 @@ macro_rules! implement_ty_decoder { } } - impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice>> + impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List>> for $DecoderName<$($typaram),*> { fn specialized_decode(&mut self) - -> Result<&'tcx ty::Slice>, Self::Error> { + -> Result<&'tcx ty::List>, Self::Error> { decode_existential_predicate_slice(self) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 98568f860a..6738267b5b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -14,8 +14,8 @@ use dep_graph::DepGraph; use dep_graph::{DepNode, DepConstructor}; use errors::DiagnosticBuilder; use session::Session; -use session::config::{BorrowckMode, OutputFilenames, OptLevel}; -use session::config::CrateType::*; +use session::config::{BorrowckMode, OutputFilenames}; +use session::config::CrateType; use middle; use hir::{TraitCandidate, HirId, ItemLocalId}; use hir::def::{Def, Export}; @@ -26,24 +26,24 @@ use lint::{self, Lint}; use ich::{StableHashingContext, NodeIdHashingMode}; use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use infer::outlives::free_region_map::FreeRegionMap; -use middle::cstore::{CrateStoreDyn, LinkMeta}; +use middle::cstore::CrateStoreDyn; use middle::cstore::EncodedMetadata; use middle::lang_items; use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::stability; use mir::{self, Mir, interpret}; use mir::interpret::Allocation; -use ty::subst::{Kind, Substs, Subst}; +use ty::subst::{CanonicalSubsts, Kind, Substs, Subst}; use ty::ReprOptions; use traits; use traits::{Clause, Clauses, Goal, Goals}; use ty::{self, Ty, TypeAndMut}; -use ty::{TyS, TypeVariants, Slice}; +use ty::{TyS, TyKind, List}; use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const}; use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; use ty::RegionKind; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; -use ty::TypeVariants::*; +use ty::TyKind::*; use ty::GenericParamDefKind; use ty::layout::{LayoutDetails, TargetDataLayout}; use ty::query; @@ -52,7 +52,7 @@ use ty::BindingMode; use ty::CanonicalTy; use util::nodemap::{DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; -use rustc_data_structures::accumulate_vec::AccumulateVec; +use smallvec::SmallVec; use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, StableHasher, StableHasherResult, StableVec}; @@ -66,14 +66,14 @@ use std::collections::hash_map::{self, Entry}; use std::hash::{Hash, Hasher}; use std::fmt; use std::mem; -use std::ops::Deref; +use std::ops::{Deref, Bound}; use std::iter; use std::sync::mpsc; use std::sync::Arc; use rustc_target::spec::abi; use syntax::ast::{self, NodeId}; use syntax::attr; -use syntax::codemap::MultiSpan; +use syntax::source_map::MultiSpan; use syntax::edition::Edition; use syntax::feature_gate; use syntax::symbol::{Symbol, keywords, InternedString}; @@ -135,15 +135,15 @@ pub struct CtxtInterners<'tcx> { /// Specifically use a speedy hash algorithm for these hash sets, /// they're accessed quite often. type_: InternedSet<'tcx, TyS<'tcx>>, - type_list: InternedSet<'tcx, Slice>>, + type_list: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, Substs<'tcx>>, - canonical_var_infos: InternedSet<'tcx, Slice>, + canonical_var_infos: InternedSet<'tcx, List>, region: InternedSet<'tcx, RegionKind>, - existential_predicates: InternedSet<'tcx, Slice>>, - predicates: InternedSet<'tcx, Slice>>, + existential_predicates: InternedSet<'tcx, List>>, + predicates: InternedSet<'tcx, List>>, const_: InternedSet<'tcx, Const<'tcx>>, - clauses: InternedSet<'tcx, Slice>>, - goals: InternedSet<'tcx, Slice>>, + clauses: InternedSet<'tcx, List>>, + goals: InternedSet<'tcx, List>>, } impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { @@ -167,7 +167,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { fn intern_ty( local: &CtxtInterners<'tcx>, global: &CtxtInterners<'gcx>, - st: TypeVariants<'tcx> + st: TyKind<'tcx> ) -> Ty<'tcx> { let flags = super::flags::FlagComputation::for_sty(&st); @@ -356,8 +356,8 @@ pub struct TypeckTables<'tcx> { /// belongs, but it may not exist if it's a tuple field (`tuple.0`). field_indices: ItemLocalMap, - /// Stores the canonicalized types provided by the user. See also `UserAssertTy` statement in - /// MIR. + /// Stores the canonicalized types provided by the user. See also + /// `AscribeUserType` statement in MIR. user_provided_tys: ItemLocalMap>, /// Stores the types for various nodes in the AST. Note that this table @@ -371,6 +371,18 @@ pub struct TypeckTables<'tcx> { /// other items. node_substs: ItemLocalMap<&'tcx Substs<'tcx>>, + /// Stores the substitutions that the user explicitly gave (if any) + /// attached to `id`. These will not include any inferred + /// values. The canonical form is used to capture things like `_` + /// or other unspecified values. + /// + /// Example: + /// + /// If the user wrote `foo.collect::>()`, then the + /// canonical substitutions would include only `for { Vec + /// }`. + user_substs: ItemLocalMap>, + adjustments: ItemLocalMap>>, /// Stores the actual binding mode for all instances of hir::BindingAnnotation. @@ -444,6 +456,7 @@ impl<'tcx> TypeckTables<'tcx> { user_provided_tys: ItemLocalMap(), node_types: ItemLocalMap(), node_substs: ItemLocalMap(), + user_substs: ItemLocalMap(), adjustments: ItemLocalMap(), pat_binding_modes: ItemLocalMap(), pat_adjustments: ItemLocalMap(), @@ -561,6 +574,18 @@ impl<'tcx> TypeckTables<'tcx> { self.node_substs.get(&id.local_id).cloned() } + pub fn user_substs_mut(&mut self) -> LocalTableInContextMut> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.user_substs + } + } + + pub fn user_substs(&self, id: hir::HirId) -> Option> { + validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + self.user_substs.get(&id.local_id).cloned() + } + // Returns the type of a pattern as a monotype. Like @expr_ty, this function // doesn't provide type parameter substitutions. pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { @@ -740,6 +765,7 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { ref user_provided_tys, ref node_types, ref node_substs, + ref user_substs, ref adjustments, ref pat_binding_modes, ref pat_adjustments, @@ -762,6 +788,7 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { user_provided_tys.hash_stable(hcx, hasher); node_types.hash_stable(hcx, hasher); node_substs.hash_stable(hcx, hasher); + user_substs.hash_stable(hcx, hasher); adjustments.hash_stable(hcx, hasher); pat_binding_modes.hash_stable(hcx, hasher); pat_adjustments.hash_stable(hcx, hasher); @@ -802,10 +829,12 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { // Ensure our type representation does not grow - #[cfg(target_pointer_width = "64")] - assert!(mem::size_of::() <= 24); - #[cfg(target_pointer_width = "64")] - assert!(mem::size_of::() <= 32); + #[cfg(all(not(stage0), target_pointer_width = "64"))] + #[allow(dead_code)] + static ASSERT_TY_KIND: () = [()][!(::std::mem::size_of::() <= 24) as usize]; + #[cfg(all(not(stage0), target_pointer_width = "64"))] + #[allow(dead_code)] + static ASSERT_TYS: () = [()][!(::std::mem::size_of::() <= 32) as usize]; let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); let mk_region = |r| { @@ -817,24 +846,24 @@ impl<'tcx> CommonTypes<'tcx> { &*r }; CommonTypes { - bool: mk(TyBool), - char: mk(TyChar), - never: mk(TyNever), - err: mk(TyError), - isize: mk(TyInt(ast::IntTy::Isize)), - i8: mk(TyInt(ast::IntTy::I8)), - i16: mk(TyInt(ast::IntTy::I16)), - i32: mk(TyInt(ast::IntTy::I32)), - i64: mk(TyInt(ast::IntTy::I64)), - i128: mk(TyInt(ast::IntTy::I128)), - usize: mk(TyUint(ast::UintTy::Usize)), - u8: mk(TyUint(ast::UintTy::U8)), - u16: mk(TyUint(ast::UintTy::U16)), - u32: mk(TyUint(ast::UintTy::U32)), - u64: mk(TyUint(ast::UintTy::U64)), - u128: mk(TyUint(ast::UintTy::U128)), - f32: mk(TyFloat(ast::FloatTy::F32)), - f64: mk(TyFloat(ast::FloatTy::F64)), + bool: mk(Bool), + char: mk(Char), + never: mk(Never), + err: mk(Error), + isize: mk(Int(ast::IntTy::Isize)), + i8: mk(Int(ast::IntTy::I8)), + i16: mk(Int(ast::IntTy::I16)), + i32: mk(Int(ast::IntTy::I32)), + i64: mk(Int(ast::IntTy::I64)), + i128: mk(Int(ast::IntTy::I128)), + usize: mk(Uint(ast::UintTy::Usize)), + u8: mk(Uint(ast::UintTy::U8)), + u16: mk(Uint(ast::UintTy::U16)), + u32: mk(Uint(ast::UintTy::U32)), + u64: mk(Uint(ast::UintTy::U64)), + u128: mk(Uint(ast::UintTy::U128)), + f32: mk(Float(ast::FloatTy::F32)), + f64: mk(Float(ast::FloatTy::F64)), re_empty: mk_region(RegionKind::ReEmpty), re_static: mk_region(RegionKind::ReStatic), @@ -892,7 +921,7 @@ pub struct GlobalCtxt<'tcx> { pub(crate) queries: query::Queries<'tcx>, - // Records the free variables refrenced by every closure + // Records the free variables referenced by every closure // expression. Do not track deps for this, just recompute it from // scratch every time. freevars: FxHashMap>>, @@ -1016,13 +1045,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } let interned = self.global_arenas.const_allocs.alloc(alloc); - if let Some(prev) = allocs.replace(interned) { + if let Some(prev) = allocs.replace(interned) { // insert into interner bug!("Tried to overwrite interned Allocation: {:#?}", prev) } interned } - /// Allocates a byte or string literal for `mir::interpret` + /// Allocates a byte or string literal for `mir::interpret`, read-only pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { // create an allocation that just contains these bytes let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes); @@ -1056,6 +1085,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { interned } + /// Returns a range of the start/end indices specified with the + /// `rustc_layout_scalar_valid_range` attribute. + pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound, Bound) { + let attrs = self.get_attrs(def_id); + let get = |name| { + let attr = match attrs.iter().find(|a| a.check_name(name)) { + Some(attr) => attr, + None => return Bound::Unbounded, + }; + for meta in attr.meta_item_list().expect("rustc_layout_scalar_valid_range takes args") { + match meta.literal().expect("attribute takes lit").node { + ast::LitKind::Int(a, _) => return Bound::Included(a), + _ => span_bug!(attr.span, "rustc_layout_scalar_valid_range expects int arg"), + } + } + span_bug!(attr.span, "no arguments to `rustc_layout_scalar_valid_range` attribute"); + }; + (get("rustc_layout_scalar_valid_range_start"), get("rustc_layout_scalar_valid_range_end")) + } + pub fn lift>(self, value: &T) -> Option { value.lift_to_tcx(self) } @@ -1072,6 +1121,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { local as usize == global as usize } + /// Returns true if this function must conform to `min_const_fn` + pub fn is_min_const_fn(self, def_id: DefId) -> bool { + if self.features().staged_api { + // some intrinsics are waved through if called inside the + // standard library. Users never need to call them directly + if let abi::Abi::RustIntrinsic = self.fn_sig(def_id).abi() { + assert!(!self.is_const_fn(def_id)); + match &self.item_name(def_id).as_str()[..] { + | "size_of" + | "min_align_of" + => return true, + _ => {}, + } + } + // in order for a libstd function to be considered min_const_fn + // it needs to be stable and have no `rustc_const_unstable` attribute + match self.lookup_stability(def_id) { + // stable functions with unstable const fn aren't `min_const_fn` + Some(&attr::Stability { const_stability: Some(_), .. }) => false, + // unstable functions don't need to conform + Some(&attr::Stability { ref level, .. }) if level.is_unstable() => false, + // everything else needs to conform, because it would be callable from + // other `min_const_fn` functions + _ => true, + } + } else { + // users enabling the `const_fn` can do what they want + !self.sess.features_untracked().const_fn + } + } + /// Create a type context and call the closure with a `TyCtxt` reference /// to the context. The closure enforces that the type context and any interned /// value (types, substs, etc.) can only be used while `ty::tls` has a valid @@ -1132,11 +1212,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { None }; - let mut trait_map = FxHashMap(); + let mut trait_map: FxHashMap<_, Lrc>> = FxHashMap(); for (k, v) in resolutions.trait_map { let hir_id = hir.node_to_hir_id(k); - let map = trait_map.entry(hir_id.owner) - .or_insert_with(|| Lrc::new(FxHashMap())); + let map = trait_map.entry(hir_id.owner).or_default(); Lrc::get_mut(map).unwrap() .insert(hir_id.local_id, Lrc::new(StableVec::new(v))); @@ -1168,7 +1247,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .collect(), hir, def_path_hash_to_def_id, - queries: query::Queries::new(providers, on_disk_query_result_cache), + queries: query::Queries::new( + providers, + extern_providers, + on_disk_query_result_cache, + ), rcache: Lock::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), @@ -1192,6 +1275,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.sess.consider_optimizing(&cname, msg) } + pub fn lib_features(self) -> Lrc { + self.get_lib_features(LOCAL_CRATE) + } + pub fn lang_items(self) -> Lrc { self.get_lang_items(LOCAL_CRATE) } @@ -1395,10 +1482,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// If true, we should enable two-phase borrows checks. This is - /// done with either `-Ztwo-phase-borrows` or with - /// `#![feature(nll)]`. + /// done with either: `-Ztwo-phase-borrows`, `#![feature(nll)]`, + /// or by opting into an edition after 2015. pub fn two_phase_borrows(self) -> bool { - self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows + if self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows { + return true; + } + + match self.sess.edition() { + Edition::Edition2015 => false, + Edition::Edition2018 => true, + _ => true, + } } /// What mode(s) of borrowck should we run? AST? MIR? both? @@ -1461,46 +1556,28 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.use_mir_borrowck() } - #[inline] - pub fn share_generics(self) -> bool { - match self.sess.opts.debugging_opts.share_generics { - Some(setting) => setting, - None => { - self.sess.opts.incremental.is_some() || - match self.sess.opts.optimize { - OptLevel::No | - OptLevel::Less | - OptLevel::Size | - OptLevel::SizeMin => true, - OptLevel::Default | - OptLevel::Aggressive => false, - } - } - } - } - #[inline] pub fn local_crate_exports_generics(self) -> bool { - debug_assert!(self.share_generics()); + debug_assert!(self.sess.opts.share_generics()); self.sess.crate_types.borrow().iter().any(|crate_type| { match crate_type { - CrateTypeExecutable | - CrateTypeStaticlib | - CrateTypeProcMacro | - CrateTypeCdylib => false, - CrateTypeRlib | - CrateTypeDylib => true, + CrateType::Executable | + CrateType::Staticlib | + CrateType::ProcMacro | + CrateType::Cdylib => false, + CrateType::Rlib | + CrateType::Dylib => true, } }) } } impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { - pub fn encode_metadata(self, link_meta: &LinkMeta) + pub fn encode_metadata(self) -> EncodedMetadata { - self.cstore.encode_metadata(self, link_meta) + self.cstore.encode_metadata(self) } } @@ -1547,7 +1624,7 @@ impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { /// None is returned if the value or one of the components is not part /// of the provided context. /// For Ty, None can be returned if either the type interner doesn't -/// contain the TypeVariants key or if the address of the interned +/// contain the TyKind key or if the address of the interned /// pointer differs. The latter case is possible if a primitive type, /// e.g. `()` or `u8`, was interned in a different context. pub trait Lift<'tcx>: fmt::Debug { @@ -1600,12 +1677,12 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Goal<'a> { } } -impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { - type Lifted = &'tcx Slice>; +impl<'a, 'tcx> Lift<'tcx> for &'a List> { + type Lifted = &'tcx List>; fn lift_to_tcx<'b, 'gcx>( &self, tcx: TyCtxt<'b, 'gcx, 'tcx>, - ) -> Option<&'tcx Slice>> { + ) -> Option<&'tcx List>> { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } @@ -1618,12 +1695,12 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { } } -impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { - type Lifted = &'tcx Slice>; +impl<'a, 'tcx> Lift<'tcx> for &'a List> { + type Lifted = &'tcx List>; fn lift_to_tcx<'b, 'gcx>( &self, tcx: TyCtxt<'b, 'gcx, 'tcx>, - ) -> Option<&'tcx Slice>> { + ) -> Option<&'tcx List>> { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } @@ -1655,7 +1732,7 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { type Lifted = &'tcx Substs<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> { if self.len() == 0 { - return Some(Slice::empty()); + return Some(List::empty()); } if tcx.interners.arena.in_arena(&self[..] as *const _) { return Some(unsafe { mem::transmute(*self) }); @@ -1669,12 +1746,12 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { } } -impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { - type Lifted = &'tcx Slice>; +impl<'a, 'tcx> Lift<'tcx> for &'a List> { + type Lifted = &'tcx List>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx Slice>> { + -> Option<&'tcx List>> { if self.len() == 0 { - return Some(Slice::empty()); + return Some(List::empty()); } if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); @@ -1688,12 +1765,12 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { } } -impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { - type Lifted = &'tcx Slice>; +impl<'a, 'tcx> Lift<'tcx> for &'a List> { + type Lifted = &'tcx List>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx Slice>> { + -> Option<&'tcx List>> { if self.is_empty() { - return Some(Slice::empty()); + return Some(List::empty()); } if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); @@ -1707,12 +1784,12 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { } } -impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { - type Lifted = &'tcx Slice>; +impl<'a, 'tcx> Lift<'tcx> for &'a List> { + type Lifted = &'tcx List>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx Slice>> { + -> Option<&'tcx List>> { if self.is_empty() { - return Some(Slice::empty()); + return Some(List::empty()); } if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); @@ -1726,11 +1803,11 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { } } -impl<'a, 'tcx> Lift<'tcx> for &'a Slice { - type Lifted = &'tcx Slice; +impl<'a, 'tcx> Lift<'tcx> for &'a List { + type Lifted = &'tcx List; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { if self.len() == 0 { - return Some(Slice::empty()); + return Some(List::empty()); } if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); @@ -1825,7 +1902,7 @@ pub mod tls { /// in librustc otherwise fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter) -> fmt::Result { with(|tcx| { - write!(f, "{}", tcx.sess.codemap().span_to_string(span)) + write!(f, "{}", tcx.sess.source_map().span_to_string(span)) }) } @@ -2042,9 +2119,9 @@ macro_rules! sty_debug_print { for &Interned(t) in tcx.interners.type_.borrow().iter() { let variant = match t.sty { - ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | - ty::TyFloat(..) | ty::TyStr | ty::TyNever => continue, - ty::TyError => /* unimportant */ continue, + ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | + ty::Float(..) | ty::Str | ty::Never => continue, + ty::Error => /* unimportant */ continue, $(ty::$variant(..) => &mut $variant,)* }; let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER); @@ -2083,9 +2160,9 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { pub fn print_debug_stats(self) { sty_debug_print!( self, - TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, - TyGenerator, TyGeneratorWitness, TyDynamic, TyClosure, TyTuple, - TyParam, TyInfer, TyProjection, TyAnon, TyForeign); + Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, + Generator, GeneratorWitness, Dynamic, Closure, Tuple, + Param, Infer, Projection, Opaque, Foreign); println!("Substs interner: #{}", self.interners.substs.borrow().len()); println!("Region interner: #{}", self.interners.region.borrow().len()); @@ -2114,34 +2191,34 @@ impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { } } -impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, TyS<'tcx>> { - fn borrow<'a>(&'a self) -> &'a TypeVariants<'lcx> { +impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, TyS<'tcx>> { + fn borrow<'a>(&'a self) -> &'a TyKind<'lcx> { &self.0.sty } } -// NB: An Interned> compares and hashes as its elements. -impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, Slice> { - fn eq(&self, other: &Interned<'tcx, Slice>) -> bool { +// NB: An Interned> compares and hashes as its elements. +impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List> { + fn eq(&self, other: &Interned<'tcx, List>) -> bool { self.0[..] == other.0[..] } } -impl<'tcx, T: Eq> Eq for Interned<'tcx, Slice> {} +impl<'tcx, T: Eq> Eq for Interned<'tcx, List> {} -impl<'tcx, T: Hash> Hash for Interned<'tcx, Slice> { +impl<'tcx, T: Hash> Hash for Interned<'tcx, List> { fn hash(&self, s: &mut H) { self.0[..].hash(s) } } -impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, Slice>> { +impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, List>> { fn borrow<'a>(&'a self) -> &'a [Ty<'lcx>] { &self.0[..] } } -impl<'tcx: 'lcx, 'lcx> Borrow<[CanonicalVarInfo]> for Interned<'tcx, Slice> { +impl<'tcx: 'lcx, 'lcx> Borrow<[CanonicalVarInfo]> for Interned<'tcx, List> { fn borrow<'a>(&'a self) -> &'a [CanonicalVarInfo] { &self.0[..] } @@ -2160,14 +2237,14 @@ impl<'tcx> Borrow for Interned<'tcx, RegionKind> { } impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]> - for Interned<'tcx, Slice>> { + for Interned<'tcx, List>> { fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] { &self.0[..] } } impl<'tcx: 'lcx, 'lcx> Borrow<[Predicate<'lcx>]> - for Interned<'tcx, Slice>> { + for Interned<'tcx, List>> { fn borrow<'a>(&'a self) -> &'a [Predicate<'lcx>] { &self.0[..] } @@ -2180,14 +2257,14 @@ impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, Const<'tcx>> { } impl<'tcx: 'lcx, 'lcx> Borrow<[Clause<'lcx>]> -for Interned<'tcx, Slice>> { +for Interned<'tcx, List>> { fn borrow<'a>(&'a self) -> &'a [Clause<'lcx>] { &self.0[..] } } impl<'tcx: 'lcx, 'lcx> Borrow<[Goal<'lcx>]> -for Interned<'tcx, Slice>> { +for Interned<'tcx, List>> { fn borrow<'a>(&'a self) -> &'a [Goal<'lcx>] { &self.0[..] } @@ -2281,9 +2358,9 @@ macro_rules! slice_interners { ($($field:ident: $method:ident($ty:ident)),+) => ( $(intern_method!( 'tcx, $field: $method( &[$ty<'tcx>], - |a, v| Slice::from_arena(a, v), + |a, v| List::from_arena(a, v), Deref::deref, - |xs: &[$ty]| xs.iter().any(keep_local)) -> Slice<$ty<'tcx>>);)+ + |xs: &[$ty]| xs.iter().any(keep_local)) -> List<$ty<'tcx>>);)+ ) } @@ -2305,10 +2382,10 @@ intern_method! { 'tcx, canonical_var_infos: _intern_canonical_var_infos( &[CanonicalVarInfo], - |a, v| Slice::from_arena(a, v), + |a, v| List::from_arena(a, v), Deref::deref, |_xs: &[CanonicalVarInfo]| -> bool { false } - ) -> Slice + ) -> List } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -2330,7 +2407,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { let converted_sig = sig.map_bound(|s| { let params_iter = match s.inputs()[0].sty { - ty::TyTuple(params) => { + ty::Tuple(params) => { params.into_iter().cloned() } _ => bug!(), @@ -2347,7 +2424,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_fn_ptr(converted_sig) } - pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> { + pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> { CtxtInterners::intern_ty(&self.interners, &self.global_interners, st) } @@ -2381,7 +2458,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_str(self) -> Ty<'tcx> { - self.mk_ty(TyStr) + self.mk_ty(Str) } pub fn mk_static_str(self) -> Ty<'tcx> { @@ -2390,11 +2467,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { // take a copy of substs so that we own the vectors inside - self.mk_ty(TyAdt(def, substs)) + self.mk_ty(Adt(def, substs)) } pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> { - self.mk_ty(TyForeign(def_id)) + self.mk_ty(Foreign(def_id)) } pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -2413,15 +2490,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } }); - self.mk_ty(TyAdt(adt_def, substs)) + self.mk_ty(Adt(adt_def, substs)) } pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyRawPtr(tm)) + self.mk_ty(RawPtr(tm)) } pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyRef(r, tm.ty, tm.mutbl)) + self.mk_ty(Ref(r, tm.ty, tm.mutbl)) } pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -2441,26 +2518,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_nil_ptr(self) -> Ty<'tcx> { - self.mk_imm_ptr(self.mk_nil()) + self.mk_imm_ptr(self.mk_unit()) } pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { - self.mk_ty(TyArray(ty, ty::Const::from_usize(self, n))) + self.mk_ty(Array(ty, ty::Const::from_usize(self, n))) } pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ty(TySlice(ty)) + self.mk_ty(Slice(ty)) } pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - self.mk_ty(TyTuple(self.intern_type_list(ts))) + self.mk_ty(Tuple(self.intern_type_list(ts))) } pub fn mk_tup], Ty<'tcx>>>(self, iter: I) -> I::Output { - iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts)))) + iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(ts)))) } - pub fn mk_nil(self) -> Ty<'tcx> { + pub fn mk_unit(self) -> Ty<'tcx> { self.intern_tup(&[]) } @@ -2473,31 +2550,31 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_bool(self) -> Ty<'tcx> { - self.mk_ty(TyBool) + self.mk_ty(Bool) } pub fn mk_fn_def(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyFnDef(def_id, substs)) + self.mk_ty(FnDef(def_id, substs)) } pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyFnPtr(fty)) + self.mk_ty(FnPtr(fty)) } pub fn mk_dynamic( self, - obj: ty::Binder<&'tcx Slice>>, + obj: ty::Binder<&'tcx List>>, reg: ty::Region<'tcx> ) -> Ty<'tcx> { - self.mk_ty(TyDynamic(obj, reg)) + self.mk_ty(Dynamic(obj, reg)) } pub fn mk_projection(self, item_def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyProjection(ProjectionTy { + self.mk_ty(Projection(ProjectionTy { item_def_id, substs, })) @@ -2505,7 +2582,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn mk_closure(self, closure_id: DefId, closure_substs: ClosureSubsts<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyClosure(closure_id, closure_substs)) + self.mk_ty(Closure(closure_id, closure_substs)) } pub fn mk_generator(self, @@ -2513,11 +2590,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { generator_substs: GeneratorSubsts<'tcx>, movability: hir::GeneratorMovability) -> Ty<'tcx> { - self.mk_ty(TyGenerator(id, generator_substs, movability)) + self.mk_ty(Generator(id, generator_substs, movability)) } - pub fn mk_generator_witness(self, types: ty::Binder<&'tcx Slice>>) -> Ty<'tcx> { - self.mk_ty(TyGeneratorWitness(types)) + pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List>>) -> Ty<'tcx> { + self.mk_ty(GeneratorWitness(types)) } pub fn mk_var(self, v: TyVid) -> Ty<'tcx> { @@ -2533,13 +2610,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> { - self.mk_ty(TyInfer(it)) + self.mk_ty(Infer(it)) } pub fn mk_ty_param(self, index: u32, name: InternedString) -> Ty<'tcx> { - self.mk_ty(TyParam(ParamTy { idx: index, name: name })) + self.mk_ty(Param(ParamTy { idx: index, name: name })) } pub fn mk_self_type(self) -> Ty<'tcx> { @@ -2555,41 +2632,41 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyAnon(def_id, substs)) + pub fn mk_opaque(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { + self.mk_ty(Opaque(def_id, substs)) } pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>]) - -> &'tcx Slice> { + -> &'tcx List> { assert!(!eps.is_empty()); assert!(eps.windows(2).all(|w| w[0].stable_cmp(self, &w[1]) != Ordering::Greater)); self._intern_existential_predicates(eps) } pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) - -> &'tcx Slice> { + -> &'tcx List> { // FIXME consider asking the input slice to be sorted to avoid // re-interning permutations, in which case that would be asserted // here. if preds.len() == 0 { // The macro-generated method below asserts we don't intern an empty slice. - Slice::empty() + List::empty() } else { self._intern_predicates(preds) } } - pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice> { + pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List> { if ts.len() == 0 { - Slice::empty() + List::empty() } else { self._intern_type_list(ts) } } - pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx Slice> { + pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx List> { if ts.len() == 0 { - Slice::empty() + List::empty() } else { self._intern_substs(ts) } @@ -2597,7 +2674,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVarInfos<'gcx> { if ts.len() == 0 { - Slice::empty() + List::empty() } else { self.global_tcx()._intern_canonical_var_infos(ts) } @@ -2605,7 +2682,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> Clauses<'tcx> { if ts.len() == 0 { - Slice::empty() + List::empty() } else { self._intern_clauses(ts) } @@ -2613,7 +2690,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> Goals<'tcx> { if ts.len() == 0 { - Slice::empty() + List::empty() } else { self._intern_goals(ts) } @@ -2636,24 +2713,24 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_existential_predicates], - &'tcx Slice>>>(self, iter: I) + &'tcx List>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_existential_predicates(xs)) } pub fn mk_predicates], - &'tcx Slice>>>(self, iter: I) + &'tcx List>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_predicates(xs)) } pub fn mk_type_list], - &'tcx Slice>>>(self, iter: I) -> I::Output { + &'tcx List>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_type_list(xs)) } pub fn mk_substs], - &'tcx Slice>>>(self, iter: I) -> I::Output { + &'tcx List>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_substs(xs)) } @@ -2820,7 +2897,7 @@ pub trait InternIteratorElement: Sized { impl InternIteratorElement for T { type Output = R; fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { - f(&iter.collect::>()) + f(&iter.collect::>()) } } @@ -2829,14 +2906,14 @@ impl<'a, T, R> InternIteratorElement for &'a T { type Output = R; fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { - f(&iter.cloned().collect::>()) + f(&iter.cloned().collect::>()) } } impl InternIteratorElement for Result { type Output = Result; fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { - Ok(f(&iter.collect::, _>>()?)) + Ok(f(&iter.collect::, _>>()?)) } } @@ -2850,17 +2927,13 @@ pub fn provide(providers: &mut ty::query::Providers) { assert_eq!(id, LOCAL_CRATE); tcx.crate_name }; + providers.get_lib_features = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + Lrc::new(middle::lib_features::collect(tcx)) + }; providers.get_lang_items = |tcx, id| { assert_eq!(id, LOCAL_CRATE); - // FIXME(#42293) Right now we insert a `with_ignore` node in the dep - // graph here to ignore the fact that `get_lang_items` below depends on - // the entire crate. For now this'll prevent false positives of - // recompiling too much when anything changes. - // - // Once red/green incremental compilation lands we should be able to - // remove this because while the crate changes often the lint level map - // will change rarely. - tcx.dep_graph.with_ignore(|| Lrc::new(middle::lang_items::collect(tcx))) + Lrc::new(middle::lang_items::collect(tcx)) }; providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).cloned(); providers.maybe_unused_trait_import = |tcx, id| { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index bcbd8a529f..2b833c5714 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -13,7 +13,7 @@ use ty::{self, BoundRegion, Region, Ty, TyCtxt}; use std::fmt; use rustc_target::spec::abi; use syntax::ast; -use errors::DiagnosticBuilder; +use errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; use hir; @@ -51,7 +51,7 @@ pub enum TypeError<'tcx> { CyclicTy(Ty<'tcx>), ProjectionMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), - ExistentialMismatch(ExpectedFound<&'tcx ty::Slice>>), + ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), OldStyleLUB(Box>), } @@ -175,21 +175,21 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String { match self.sty { - ty::TyBool | ty::TyChar | ty::TyInt(_) | - ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(), - ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(), + ty::Bool | ty::Char | ty::Int(_) | + ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string(), + ty::Tuple(ref tys) if tys.is_empty() => self.to_string(), - ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)), - ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)), - ty::TyArray(_, n) => { + ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)), + ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)), + ty::Array(_, n) => { match n.assert_usize(tcx) { Some(n) => format!("array of {} elements", n), None => "array".to_string(), } } - ty::TySlice(_) => "slice".to_string(), - ty::TyRawPtr(_) => "*-ptr".to_string(), - ty::TyRef(region, ty, mutbl) => { + ty::Slice(_) => "slice".to_string(), + ty::RawPtr(_) => "*-ptr".to_string(), + ty::Ref(region, ty, mutbl) => { let tymut = ty::TypeAndMut { ty, mutbl }; let tymut_string = tymut.to_string(); if tymut_string == "_" || //unknown type name, @@ -204,33 +204,33 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { format!("&{}", tymut_string) } } - ty::TyFnDef(..) => "fn item".to_string(), - ty::TyFnPtr(_) => "fn pointer".to_string(), - ty::TyDynamic(ref inner, ..) => { + ty::FnDef(..) => "fn item".to_string(), + ty::FnPtr(_) => "fn pointer".to_string(), + ty::Dynamic(ref inner, ..) => { inner.principal().map_or_else(|| "trait".to_string(), |p| format!("trait {}", tcx.item_path_str(p.def_id()))) } - ty::TyClosure(..) => "closure".to_string(), - ty::TyGenerator(..) => "generator".to_string(), - ty::TyGeneratorWitness(..) => "generator witness".to_string(), - ty::TyTuple(..) => "tuple".to_string(), - ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(), - ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(), - ty::TyInfer(ty::FloatVar(_)) => "floating-point variable".to_string(), - ty::TyInfer(ty::CanonicalTy(_)) | - ty::TyInfer(ty::FreshTy(_)) => "skolemized type".to_string(), - ty::TyInfer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(), - ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(), - ty::TyProjection(_) => "associated type".to_string(), - ty::TyParam(ref p) => { + ty::Closure(..) => "closure".to_string(), + ty::Generator(..) => "generator".to_string(), + ty::GeneratorWitness(..) => "generator witness".to_string(), + ty::Tuple(..) => "tuple".to_string(), + ty::Infer(ty::TyVar(_)) => "inferred type".to_string(), + ty::Infer(ty::IntVar(_)) => "integral variable".to_string(), + ty::Infer(ty::FloatVar(_)) => "floating-point variable".to_string(), + ty::Infer(ty::CanonicalTy(_)) | + ty::Infer(ty::FreshTy(_)) => "skolemized type".to_string(), + ty::Infer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(), + ty::Infer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(), + ty::Projection(_) => "associated type".to_string(), + ty::Param(ref p) => { if p.is_self() { "Self".to_string() } else { "type parameter".to_string() } } - ty::TyAnon(..) => "anonymized type".to_string(), - ty::TyError => "type error".to_string(), + ty::Opaque(..) => "opaque type".to_string(), + ty::Error => "type error".to_string(), } } } @@ -250,6 +250,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { db.note("no two closures, even if identical, have the same type"); db.help("consider boxing your closure and/or using it as a trait object"); } + match (&values.found.sty, &values.expected.sty) { // Issue #53280 + (ty::Infer(ty::IntVar(_)), ty::Float(_)) => { + if let Ok(snippet) = self.sess.source_map().span_to_snippet(sp) { + if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') { + db.span_suggestion_with_applicability( + sp, + "use a float literal", + format!("{}.0", snippet), + Applicability::MachineApplicable + ); + } + } + }, + _ => {} + } }, OldStyleLUB(err) => { db.note("this was previously accepted by the compiler but has been phased out"); diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index cf5e55a59f..22a77bd625 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -47,7 +47,7 @@ pub enum SimplifiedTypeGen ClosureSimplifiedType(D), GeneratorSimplifiedType(D), GeneratorWitnessSimplifiedType(usize), - AnonSimplifiedType(D), + OpaqueSimplifiedType(D), FunctionSimplifiedType(usize), ParameterSimplifiedType, ForeignSimplifiedType(DefId), @@ -68,42 +68,42 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, -> Option { match ty.sty { - ty::TyBool => Some(BoolSimplifiedType), - ty::TyChar => Some(CharSimplifiedType), - ty::TyInt(int_type) => Some(IntSimplifiedType(int_type)), - ty::TyUint(uint_type) => Some(UintSimplifiedType(uint_type)), - ty::TyFloat(float_type) => Some(FloatSimplifiedType(float_type)), - ty::TyAdt(def, _) => Some(AdtSimplifiedType(def.did)), - ty::TyStr => Some(StrSimplifiedType), - ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType), - ty::TyRawPtr(_) => Some(PtrSimplifiedType), - ty::TyDynamic(ref trait_info, ..) => { + ty::Bool => Some(BoolSimplifiedType), + ty::Char => Some(CharSimplifiedType), + ty::Int(int_type) => Some(IntSimplifiedType(int_type)), + ty::Uint(uint_type) => Some(UintSimplifiedType(uint_type)), + ty::Float(float_type) => Some(FloatSimplifiedType(float_type)), + ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)), + ty::Str => Some(StrSimplifiedType), + ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType), + ty::RawPtr(_) => Some(PtrSimplifiedType), + ty::Dynamic(ref trait_info, ..) => { trait_info.principal().map(|p| TraitSimplifiedType(p.def_id())) } - ty::TyRef(_, ty, _) => { + ty::Ref(_, ty, _) => { // since we introduce auto-refs during method lookup, we // just treat &T and T as equivalent from the point of // view of possibly unifying simplify_type(tcx, ty, can_simplify_params) } - ty::TyFnDef(def_id, _) | - ty::TyClosure(def_id, _) => { + ty::FnDef(def_id, _) | + ty::Closure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) } - ty::TyGenerator(def_id, _, _) => { + ty::Generator(def_id, _, _) => { Some(GeneratorSimplifiedType(def_id)) } - ty::TyGeneratorWitness(ref tys) => { + ty::GeneratorWitness(ref tys) => { Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())) } - ty::TyNever => Some(NeverSimplifiedType), - ty::TyTuple(ref tys) => { + ty::Never => Some(NeverSimplifiedType), + ty::Tuple(ref tys) => { Some(TupleSimplifiedType(tys.len())) } - ty::TyFnPtr(ref f) => { + ty::FnPtr(ref f) => { Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) } - ty::TyProjection(_) | ty::TyParam(_) => { + ty::Projection(_) | ty::Param(_) => { if can_simplify_params { // In normalized types, projections don't unify with // anything. when lazy normalization happens, this @@ -115,13 +115,13 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, None } } - ty::TyAnon(def_id, _) => { - Some(AnonSimplifiedType(def_id)) + ty::Opaque(def_id, _) => { + Some(OpaqueSimplifiedType(def_id)) } - ty::TyForeign(def_id) => { + ty::Foreign(def_id) => { Some(ForeignSimplifiedType(def_id)) } - ty::TyInfer(_) | ty::TyError => None, + ty::Infer(_) | ty::Error => None, } } @@ -146,7 +146,7 @@ impl SimplifiedTypeGen { ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)), GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)), GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n), - AnonSimplifiedType(d) => AnonSimplifiedType(map(d)), + OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)), FunctionSimplifiedType(n) => FunctionSimplifiedType(n), ParameterSimplifiedType => ParameterSimplifiedType, ForeignSimplifiedType(d) => ForeignSimplifiedType(d), @@ -181,7 +181,7 @@ impl<'a, 'gcx, D> HashStable> for SimplifiedTypeGen ClosureSimplifiedType(d) => d.hash_stable(hcx, hasher), GeneratorSimplifiedType(d) => d.hash_stable(hcx, hasher), GeneratorWitnessSimplifiedType(n) => n.hash_stable(hcx, hasher), - AnonSimplifiedType(d) => d.hash_stable(hcx, hasher), + OpaqueSimplifiedType(d) => d.hash_stable(hcx, hasher), FunctionSimplifiedType(n) => n.hash_stable(hcx, hasher), ForeignSimplifiedType(d) => d.hash_stable(hcx, hasher), } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 3718c436b3..341ce40d15 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -28,7 +28,7 @@ impl FlagComputation { } } - pub fn for_sty(st: &ty::TypeVariants) -> FlagComputation { + pub fn for_sty(st: &ty::TyKind) -> FlagComputation { let mut result = FlagComputation::new(); result.add_sty(st); result @@ -67,30 +67,30 @@ impl FlagComputation { } } - fn add_sty(&mut self, st: &ty::TypeVariants) { + fn add_sty(&mut self, st: &ty::TyKind) { match st { - &ty::TyBool | - &ty::TyChar | - &ty::TyInt(_) | - &ty::TyFloat(_) | - &ty::TyUint(_) | - &ty::TyNever | - &ty::TyStr | - &ty::TyForeign(..) => { + &ty::Bool | + &ty::Char | + &ty::Int(_) | + &ty::Float(_) | + &ty::Uint(_) | + &ty::Never | + &ty::Str | + &ty::Foreign(..) => { } - // You might think that we could just return TyError for - // any type containing TyError as a component, and get + // You might think that we could just return Error for + // any type containing Error as a component, and get // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with // the exception of function types that return bot). // But doing so caused sporadic memory corruption, and // neither I (tjc) nor nmatsakis could figure out why, // so we're doing it this way. - &ty::TyError => { + &ty::Error => { self.add_flags(TypeFlags::HAS_TY_ERR) } - &ty::TyParam(ref p) => { + &ty::Param(ref p) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); if p.is_self() { self.add_flags(TypeFlags::HAS_SELF); @@ -99,25 +99,25 @@ impl FlagComputation { } } - &ty::TyGenerator(_, ref substs, _) => { + &ty::Generator(_, ref substs, _) => { self.add_flags(TypeFlags::HAS_TY_CLOSURE); self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); self.add_substs(&substs.substs); } - &ty::TyGeneratorWitness(ref ts) => { + &ty::GeneratorWitness(ref ts) => { let mut computation = FlagComputation::new(); computation.add_tys(&ts.skip_binder()[..]); self.add_bound_computation(&computation); } - &ty::TyClosure(_, ref substs) => { + &ty::Closure(_, ref substs) => { self.add_flags(TypeFlags::HAS_TY_CLOSURE); self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); self.add_substs(&substs.substs); } - &ty::TyInfer(infer) => { + &ty::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right? self.add_flags(TypeFlags::HAS_TY_INFER); match infer { @@ -136,11 +136,11 @@ impl FlagComputation { } } - &ty::TyAdt(_, substs) => { + &ty::Adt(_, substs) => { self.add_substs(substs); } - &ty::TyProjection(ref data) => { + &ty::Projection(ref data) => { // currently we can't normalize projections that // include bound regions, so track those separately. if !data.has_escaping_regions() { @@ -150,12 +150,12 @@ impl FlagComputation { self.add_projection_ty(data); } - &ty::TyAnon(_, substs) => { + &ty::Opaque(_, substs) => { self.add_flags(TypeFlags::HAS_PROJECTION); self.add_substs(substs); } - &ty::TyDynamic(ref obj, r) => { + &ty::Dynamic(ref obj, r) => { let mut computation = FlagComputation::new(); for predicate in obj.skip_binder().iter() { match *predicate { @@ -172,33 +172,33 @@ impl FlagComputation { self.add_region(r); } - &ty::TyArray(tt, len) => { + &ty::Array(tt, len) => { self.add_ty(tt); self.add_const(len); } - &ty::TySlice(tt) => { + &ty::Slice(tt) => { self.add_ty(tt) } - &ty::TyRawPtr(ref m) => { + &ty::RawPtr(ref m) => { self.add_ty(m.ty); } - &ty::TyRef(r, ty, _) => { + &ty::Ref(r, ty, _) => { self.add_region(r); self.add_ty(ty); } - &ty::TyTuple(ref ts) => { + &ty::Tuple(ref ts) => { self.add_tys(&ts[..]); } - &ty::TyFnDef(_, substs) => { + &ty::FnDef(_, substs) => { self.add_substs(substs); } - &ty::TyFnPtr(f) => { + &ty::FnPtr(f) => { self.add_fn_sig(f); } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index e4484041b0..a661125d1c 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -771,7 +771,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // in the normalized form if self.just_constrained { match t.sty { - ty::TyProjection(..) | ty::TyAnon(..) => { return false; } + ty::Projection(..) | ty::Opaque(..) => { return false; } _ => { } } } diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index 3629709e6a..c152c0fb8e 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::mem; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; use syntax::ast::CRATE_NODE_ID; use ty::context::TyCtxt; use ty::{DefId, DefIdTree}; @@ -83,14 +83,14 @@ impl<'a, 'gcx, 'tcx> DefIdForest { let mut next_ret = SmallVec::new(); let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new(); for next_forest in iter { - 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()); for id in next_forest.root_ids { if ret.contains(tcx, id) { @@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest { } mem::swap(&mut next_ret, &mut ret.root_ids); - next_ret.drain(..); + next_ret.drain(); } ret } @@ -112,7 +112,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest { let mut ret = DefIdForest::empty(); let mut next_ret = SmallVec::new(); for next_forest in iter { - for id in ret.root_ids.drain(..) { + for id in ret.root_ids.drain() { if !next_forest.contains(tcx, id) { next_ret.push(id); } @@ -125,7 +125,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest { } mem::swap(&mut next_ret, &mut ret.root_ids); - next_ret.drain(..); + next_ret.drain(); } ret } diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 19e5406cd0..ef5b223620 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -13,7 +13,7 @@ use ty::context::TyCtxt; use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS}; use ty::{DefId, Substs}; use ty::{AdtKind, Visibility}; -use ty::TypeVariants::*; +use ty::TyKind::*; pub use self::def_id_forest::DefIdForest; @@ -226,9 +226,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest { match self.sty { - TyAdt(def, substs) => { + Adt(def, substs) => { { - let substs_set = visited.entry(def.did).or_insert(FxHashSet::default()); + let substs_set = visited.entry(def.did).or_default(); if !substs_set.insert(substs) { // We are already calculating the inhabitedness of this type. // The type must contain a reference to itself. Break the @@ -255,13 +255,13 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { ret }, - TyNever => DefIdForest::full(tcx), - TyTuple(ref tys) => { + Never => DefIdForest::full(tcx), + Tuple(ref tys) => { DefIdForest::union(tcx, tys.iter().map(|ty| { ty.uninhabited_from(visited, tcx) })) }, - TyArray(ty, len) => { + Array(ty, len) => { match len.assert_usize(tcx) { // If the array is definitely non-empty, it's uninhabited if // the type of its elements is uninhabited. @@ -269,7 +269,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { _ => DefIdForest::empty() } } - TyRef(_, ty, _) => { + Ref(_, ty, _) => { ty.uninhabited_from(visited, tcx) } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 66edbeff74..68996f52b8 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -194,7 +194,7 @@ impl<'a, 'b, 'tcx> Instance<'tcx> { ); let def = match item_type.sty { - ty::TyFnDef(..) if { + ty::FnDef(..) if { let f = item_type.fn_sig(tcx); f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic @@ -294,7 +294,7 @@ fn resolve_associated_item<'a, 'tcx>( }) } traits::VtableBuiltin(..) => { - if let Some(_) = tcx.lang_items().clone_trait() { + if tcx.lang_items().clone_trait().is_some() { Some(Instance { def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), substs: rcvr_substs diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index c44b7327a0..0272865bda 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -299,7 +299,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // impl on `Foo`, but fallback to `::bar` if self-type is // anything other than a simple path. match self_ty.sty { - ty::TyAdt(adt_def, substs) => { + ty::Adt(adt_def, substs) => { if substs.types().next().is_none() { // ignore regions self.push_item_path(buffer, adt_def.did); } else { @@ -307,14 +307,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - ty::TyForeign(did) => self.push_item_path(buffer, did), + ty::Foreign(did) => self.push_item_path(buffer, did), - ty::TyBool | - ty::TyChar | - ty::TyInt(_) | - ty::TyUint(_) | - ty::TyFloat(_) | - ty::TyStr => { + ty::Bool | + ty::Char | + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Str => { buffer.push(&self_ty.to_string()); } @@ -336,7 +336,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.push_item_path(buffer, parent_def_id); let node_id = self.hir.as_local_node_id(impl_def_id).unwrap(); let item = self.hir.expect_item(node_id); - let span_str = self.sess.codemap().span_to_string(item.span); + let span_str = self.sess.source_map().span_to_string(item.span); buffer.push(&format!("", span_str)); } @@ -357,40 +357,40 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// decisions and we may want to adjust it later. pub fn characteristic_def_id_of_type(ty: Ty) -> Option { match ty.sty { - ty::TyAdt(adt_def, _) => Some(adt_def.did), + ty::Adt(adt_def, _) => Some(adt_def.did), - ty::TyDynamic(data, ..) => data.principal().map(|p| p.def_id()), + ty::Dynamic(data, ..) => data.principal().map(|p| p.def_id()), - ty::TyArray(subty, _) | - ty::TySlice(subty) => characteristic_def_id_of_type(subty), + ty::Array(subty, _) | + ty::Slice(subty) => characteristic_def_id_of_type(subty), - ty::TyRawPtr(mt) => characteristic_def_id_of_type(mt.ty), + ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty), - ty::TyRef(_, ty, _) => characteristic_def_id_of_type(ty), + ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty), - ty::TyTuple(ref tys) => tys.iter() + ty::Tuple(ref tys) => tys.iter() .filter_map(|ty| characteristic_def_id_of_type(ty)) .next(), - ty::TyFnDef(def_id, _) | - ty::TyClosure(def_id, _) | - ty::TyGenerator(def_id, _, _) | - ty::TyForeign(def_id) => Some(def_id), - - ty::TyBool | - ty::TyChar | - ty::TyInt(_) | - ty::TyUint(_) | - ty::TyStr | - ty::TyFnPtr(_) | - ty::TyProjection(_) | - ty::TyParam(_) | - ty::TyAnon(..) | - ty::TyInfer(_) | - ty::TyError | - ty::TyGeneratorWitness(..) | - ty::TyNever | - ty::TyFloat(_) => None, + ty::FnDef(def_id, _) | + ty::Closure(def_id, _) | + ty::Generator(def_id, _, _) | + ty::Foreign(def_id) => Some(def_id), + + ty::Bool | + ty::Char | + ty::Int(_) | + ty::Uint(_) | + ty::Str | + ty::FnPtr(_) | + ty::Projection(_) | + ty::Param(_) | + ty::Opaque(..) | + ty::Infer(_) | + ty::Error | + ty::GeneratorWitness(..) | + ty::Never | + ty::Float(_) => None, } } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index cded81ce23..4e37a34a0c 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -20,6 +20,7 @@ use std::fmt; use std::i128; use std::iter; use std::mem; +use std::ops::Bound; use ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, @@ -132,7 +133,7 @@ impl PrimitiveExt for Primitive { Int(i, signed) => i.to_ty(tcx, signed), Float(FloatTy::F32) => tcx.types.f32, Float(FloatTy::F64) => tcx.types.f64, - Pointer => tcx.mk_mut_ptr(tcx.mk_nil()), + Pointer => tcx.mk_mut_ptr(tcx.mk_unit()), } } } @@ -466,37 +467,37 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let univariant = |fields: &[TyLayout], repr: &ReprOptions, kind| { Ok(tcx.intern_layout(univariant_uninterned(fields, repr, kind)?)) }; - assert!(!ty.has_infer_types()); + debug_assert!(!ty.has_infer_types()); Ok(match ty.sty { // Basic scalars. - ty::TyBool => { + ty::Bool => { tcx.intern_layout(LayoutDetails::scalar(self, Scalar { value: Int(I8, false), valid_range: 0..=1 })) } - ty::TyChar => { + ty::Char => { tcx.intern_layout(LayoutDetails::scalar(self, Scalar { value: Int(I32, false), valid_range: 0..=0x10FFFF })) } - ty::TyInt(ity) => { + ty::Int(ity) => { scalar(Int(Integer::from_attr(dl, attr::SignedInt(ity)), true)) } - ty::TyUint(ity) => { + ty::Uint(ity) => { scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity)), false)) } - ty::TyFloat(fty) => scalar(Float(fty)), - ty::TyFnPtr(_) => { + ty::Float(fty) => scalar(Float(fty)), + ty::FnPtr(_) => { let mut ptr = scalar_unit(Pointer); ptr.valid_range = 1..=*ptr.valid_range.end(); tcx.intern_layout(LayoutDetails::scalar(self, ptr)) } // The never type. - ty::TyNever => { + ty::Never => { tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: 0 }, fields: FieldPlacement::Union(0), @@ -507,8 +508,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // Potentially-fat pointers. - ty::TyRef(_, pointee, _) | - ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => { + ty::Ref(_, pointee, _) | + ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { let mut data_ptr = scalar_unit(Pointer); if !ty.is_unsafe_ptr() { data_ptr.valid_range = 1..=*data_ptr.valid_range.end(); @@ -521,13 +522,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let unsized_part = tcx.struct_tail(pointee); let metadata = match unsized_part.sty { - ty::TyForeign(..) => { + ty::Foreign(..) => { return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr))); } - ty::TySlice(_) | ty::TyStr => { + ty::Slice(_) | ty::Str => { scalar_unit(Int(dl.ptr_sized_integer(), false)) } - ty::TyDynamic(..) => { + ty::Dynamic(..) => { let mut vtable = scalar_unit(Pointer); vtable.valid_range = 1..=*vtable.valid_range.end(); vtable @@ -540,7 +541,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // Arrays and slices. - ty::TyArray(element, mut count) => { + ty::Array(element, mut count) => { if count.has_projections() { count = tcx.normalize_erasing_regions(param_env, count); if count.has_projections() { @@ -564,7 +565,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { size }) } - ty::TySlice(element) => { + ty::Slice(element) => { let element = self.layout_of(element)?; tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: 0 }, @@ -577,7 +578,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { size: Size::ZERO }) } - ty::TyStr => { + ty::Str => { tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: 0 }, fields: FieldPlacement::Array { @@ -591,10 +592,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // Odd unit types. - ty::TyFnDef(..) => { + ty::FnDef(..) => { univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)? } - ty::TyDynamic(..) | ty::TyForeign(..) => { + ty::Dynamic(..) | ty::Foreign(..) => { let mut unit = univariant_uninterned(&[], &ReprOptions::default(), StructKind::AlwaysSized)?; match unit.abi { @@ -605,21 +606,21 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // Tuples, generators and closures. - ty::TyGenerator(def_id, ref substs, _) => { + ty::Generator(def_id, ref substs, _) => { let tys = substs.field_tys(def_id, tcx); univariant(&tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized)? } - ty::TyClosure(def_id, ref substs) => { + ty::Closure(def_id, ref substs) => { let tys = substs.upvar_tys(def_id, tcx); univariant(&tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized)? } - ty::TyTuple(tys) => { + ty::Tuple(tys) => { let kind = if tys.len() == 0 { StructKind::AlwaysSized } else { @@ -631,7 +632,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // SIMD vector types. - ty::TyAdt(def, ..) if def.repr.simd() => { + ty::Adt(def, ..) if def.repr.simd() => { let element = self.layout_of(ty.simd_type(tcx))?; let count = ty.simd_size(tcx) as u64; assert!(count > 0); @@ -664,7 +665,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // ADTs. - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { // Cache the field layouts. let variants = def.variants.iter().map(|v| { v.fields.iter().map(|field| { @@ -761,17 +762,29 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?; st.variants = Variants::Single { index: v }; - // Exclude 0 from the range of a newtype ABI NonZero. - if Some(def.did) == self.tcx.lang_items().non_zero() { - match st.abi { - Abi::Scalar(ref mut scalar) | - Abi::ScalarPair(ref mut scalar, _) => { - if *scalar.valid_range.start() == 0 { - scalar.valid_range = 1..=*scalar.valid_range.end(); - } + let (start, end) = self.tcx.layout_scalar_valid_range(def.did); + match st.abi { + Abi::Scalar(ref mut scalar) | + Abi::ScalarPair(ref mut scalar, _) => { + // the asserts ensure that we are not using the + // `#[rustc_layout_scalar_valid_range(n)]` + // attribute to widen the range of anything as that would probably + // result in UB somewhere + if let Bound::Included(start) = start { + assert!(*scalar.valid_range.start() <= start); + scalar.valid_range = start..=*scalar.valid_range.end(); + } + if let Bound::Included(end) = end { + assert!(*scalar.valid_range.end() >= end); + scalar.valid_range = *scalar.valid_range.start()..=end; } - _ => {} } + _ => assert!( + start == Bound::Unbounded && end == Bound::Unbounded, + "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}", + def, + st, + ), } return Ok(tcx.intern_layout(st)); } @@ -1103,17 +1116,17 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // Types with no meaningful known layout. - ty::TyProjection(_) | ty::TyAnon(..) => { + ty::Projection(_) | ty::Opaque(..) => { let normalized = tcx.normalize_erasing_regions(param_env, ty); if ty == normalized { return Err(LayoutError::Unknown(ty)); } tcx.layout_raw(param_env.and(normalized))? } - ty::TyGeneratorWitness(..) | ty::TyInfer(_) => { + ty::GeneratorWitness(..) | ty::Infer(_) => { bug!("LayoutDetails::compute: unexpected type `{}`", ty) } - ty::TyParam(_) | ty::TyError => { + ty::Param(_) | ty::Error => { return Err(LayoutError::Unknown(ty)); } }) @@ -1153,12 +1166,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { }; let adt_def = match layout.ty.sty { - ty::TyAdt(ref adt_def, _) => { + ty::Adt(ref adt_def, _) => { debug!("print-type-size t: `{:?}` process adt", layout.ty); adt_def } - ty::TyClosure(..) => { + ty::Closure(..) => { debug!("print-type-size t: `{:?}` record closure", layout.ty); record(DataTypeKind::Closure, false, None, vec![]); return; @@ -1283,7 +1296,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>) -> Result, LayoutError<'tcx>> { - assert!(!ty.has_infer_types()); + debug_assert!(!ty.has_infer_types()); // First try computing a static layout. let err = match tcx.layout_of(param_env.and(ty)) { @@ -1294,13 +1307,13 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { }; match ty.sty { - ty::TyRef(_, pointee, _) | - ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => { + ty::Ref(_, pointee, _) | + ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { let non_zero = !ty.is_unsafe_ptr(); let tail = tcx.struct_tail(pointee); match tail.sty { - ty::TyParam(_) | ty::TyProjection(_) => { - assert!(tail.has_param_types() || tail.has_self_ty()); + ty::Param(_) | ty::Projection(_) => { + debug_assert!(tail.has_param_types() || tail.has_self_ty()); Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(&tail) @@ -1314,7 +1327,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { } } - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { // Only newtypes and enums w/ nullable pointer optimization. if def.is_union() || def.variants.is_empty() || def.variants.len() > 2 { return Err(err); @@ -1350,8 +1363,12 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { if def.variants.len() == 1 { if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 { return Ok(SizeSkeleton::Pointer { - non_zero: non_zero || - Some(def.did) == tcx.lang_items().non_zero(), + non_zero: non_zero || match tcx.layout_scalar_valid_range(def.did) { + (Bound::Included(start), Bound::Unbounded) => start > 0, + (Bound::Included(start), Bound::Included(end)) => + 0 < start && start < end, + _ => false, + }, tail, }); } else { @@ -1373,7 +1390,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { } } - ty::TyProjection(_) | ty::TyAnon(..) => { + ty::Projection(_) | ty::Opaque(..) => { let normalized = tcx.normalize_erasing_regions(param_env, ty); if ty == normalized { Err(err) @@ -1552,7 +1569,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> }); let fields = match this.ty.sty { - ty::TyAdt(def, _) => def.variants[variant_index].fields.len(), + ty::Adt(def, _) => def.variants[variant_index].fields.len(), _ => bug!() }; let tcx = cx.tcx(); @@ -1582,23 +1599,23 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout { let tcx = cx.tcx(); cx.layout_of(match this.ty.sty { - ty::TyBool | - ty::TyChar | - ty::TyInt(_) | - ty::TyUint(_) | - ty::TyFloat(_) | - ty::TyFnPtr(_) | - ty::TyNever | - ty::TyFnDef(..) | - ty::TyGeneratorWitness(..) | - ty::TyForeign(..) | - ty::TyDynamic(..) => { + ty::Bool | + ty::Char | + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::FnPtr(_) | + ty::Never | + ty::FnDef(..) | + ty::GeneratorWitness(..) | + ty::Foreign(..) | + ty::Dynamic(..) => { bug!("TyLayout::field_type({:?}): not applicable", this) } // Potentially-fat pointers. - ty::TyRef(_, pointee, _) | - ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => { + ty::Ref(_, pointee, _) | + ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { assert!(i < this.fields.count()); // Reuse the fat *T type as its own thin pointer data field. @@ -1606,7 +1623,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> // (which may have no non-DST form), and will work as long // as the `Abi` or `FieldPlacement` is checked by users. if i == 0 { - let nil = tcx.mk_nil(); + let nil = tcx.mk_unit(); let ptr_ty = if this.ty.is_unsafe_ptr() { tcx.mk_mut_ptr(nil) } else { @@ -1619,41 +1636,54 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } match tcx.struct_tail(pointee).sty { - ty::TySlice(_) | - ty::TyStr => tcx.types.usize, - ty::TyDynamic(_, _) => { + ty::Slice(_) | + ty::Str => tcx.types.usize, + ty::Dynamic(_, _) => { tcx.mk_imm_ref( tcx.types.re_static, tcx.mk_array(tcx.types.usize, 3), ) + /* FIXME use actual fn pointers + Warning: naively computing the number of entries in the + vtable by counting the methods on the trait + methods on + all parent traits does not work, because some methods can + be not object safe and thus excluded from the vtable. + Increase this counter if you tried to implement this but + failed to do it without duplicating a lot of code from + other places in the compiler: 2 + tcx.mk_tup(&[ + tcx.mk_array(tcx.types.usize, 3), + tcx.mk_array(Option), + ]) + */ } _ => bug!("TyLayout::field_type({:?}): not applicable", this) } } // Arrays and slices. - ty::TyArray(element, _) | - ty::TySlice(element) => element, - ty::TyStr => tcx.types.u8, + ty::Array(element, _) | + ty::Slice(element) => element, + ty::Str => tcx.types.u8, // Tuples, generators and closures. - ty::TyClosure(def_id, ref substs) => { + ty::Closure(def_id, ref substs) => { substs.upvar_tys(def_id, tcx).nth(i).unwrap() } - ty::TyGenerator(def_id, ref substs, _) => { + ty::Generator(def_id, ref substs, _) => { substs.field_tys(def_id, tcx).nth(i).unwrap() } - ty::TyTuple(tys) => tys[i], + ty::Tuple(tys) => tys[i], // SIMD vector types. - ty::TyAdt(def, ..) if def.repr.simd() => { + ty::Adt(def, ..) if def.repr.simd() => { this.ty.simd_type(tcx) } // ADTs. - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { match this.variants { Variants::Single { index } => { def.variants[index].fields[i].ty(tcx, substs) @@ -1672,8 +1702,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } - ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) | - ty::TyInfer(_) | ty::TyError => { + ty::Projection(_) | ty::Opaque(..) | ty::Param(_) | + ty::Infer(_) | ty::Error => { bug!("TyLayout::field_type: unexpected type `{}`", this.ty) } }) @@ -1735,7 +1765,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // Locals variables which live across yields are stored // in the generator type as fields. These may be uninitialized // so we don't look for niches there. - if let ty::TyGenerator(..) = layout.ty.sty { + if let ty::Generator(..) = layout.ty.sty { return Ok(None); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4fda3bdca3..d9e3bdaf26 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -15,10 +15,11 @@ pub use self::IntVarValue::*; pub use self::fold::TypeFoldable; use hir::{map as hir_map, FreevarMap, TraitMap}; +use hir::Node; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use hir::map::DefPathData; -use hir::svh::Svh; +use rustc_data_structures::svh::Svh; use ich::Fingerprint; use ich::StableHashingContext; use infer::canonical::Canonical; @@ -37,6 +38,7 @@ use ty::walk::TypeWalker; use util::captures::Captures; use util::nodemap::{NodeSet, DefIdMap, FxHashMap}; use arena::SyncDroplessArena; +use session::DataTypeKind; use serialize::{self, Encodable, Encoder}; use std::cell::RefCell; @@ -51,10 +53,10 @@ use std::{mem, ptr}; use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::Mark; -use syntax::symbol::{Symbol, LocalInternedString, InternedString}; +use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString}; use syntax_pos::{DUMMY_SP, Span}; -use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; +use smallvec; use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, HashStable}; @@ -64,7 +66,7 @@ pub use self::sty::{Binder, CanonicalVar, DebruijnIndex, INNERMOST}; pub use self::sty::{FnSig, GenSig, PolyFnSig, PolyGenSig}; pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut}; -pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef}; +pub use self::sty::{TraitRef, TyKind, PolyTraitRef}; pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const}; pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; @@ -73,7 +75,7 @@ pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid}; pub use self::sty::BoundRegion::*; pub use self::sty::InferTy::*; pub use self::sty::RegionKind::*; -pub use self::sty::TypeVariants::*; +pub use self::sty::TyKind::*; pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; @@ -449,7 +451,7 @@ bitflags! { const HAS_FREE_LOCAL_NAMES = 1 << 10; // Present if the type belongs in a local type context. - // Only set for TyInfer other than Fresh. + // Only set for Infer other than Fresh. const KEEP_IN_LOCAL_TCX = 1 << 11; // Is there a projection that does not involve a bound region? @@ -489,7 +491,7 @@ bitflags! { } pub struct TyS<'tcx> { - pub sty: TypeVariants<'tcx>, + pub sty: TyKind<'tcx>, pub flags: TypeFlags, /// This is a kind of confusing thing: it stores the smallest @@ -541,29 +543,29 @@ impl<'tcx> Hash for TyS<'tcx> { impl<'tcx> TyS<'tcx> { pub fn is_primitive_ty(&self) -> bool { match self.sty { - TypeVariants::TyBool | - TypeVariants::TyChar | - TypeVariants::TyInt(_) | - TypeVariants::TyUint(_) | - TypeVariants::TyFloat(_) | - TypeVariants::TyInfer(InferTy::IntVar(_)) | - TypeVariants::TyInfer(InferTy::FloatVar(_)) | - TypeVariants::TyInfer(InferTy::FreshIntTy(_)) | - TypeVariants::TyInfer(InferTy::FreshFloatTy(_)) => true, - TypeVariants::TyRef(_, x, _) => x.is_primitive_ty(), + TyKind::Bool | + TyKind::Char | + TyKind::Int(_) | + TyKind::Uint(_) | + TyKind::Float(_) | + TyKind::Infer(InferTy::IntVar(_)) | + TyKind::Infer(InferTy::FloatVar(_)) | + TyKind::Infer(InferTy::FreshIntTy(_)) | + TyKind::Infer(InferTy::FreshFloatTy(_)) => true, + TyKind::Ref(_, x, _) => x.is_primitive_ty(), _ => false, } } pub fn is_suggestable(&self) -> bool { match self.sty { - TypeVariants::TyAnon(..) | - TypeVariants::TyFnDef(..) | - TypeVariants::TyFnPtr(..) | - TypeVariants::TyDynamic(..) | - TypeVariants::TyClosure(..) | - TypeVariants::TyInfer(..) | - TypeVariants::TyProjection(..) => false, + TyKind::Opaque(..) | + TyKind::FnDef(..) | + TyKind::FnPtr(..) | + TyKind::Dynamic(..) | + TyKind::Closure(..) | + TyKind::Infer(..) | + TyKind::Projection(..) => false, _ => true, } } @@ -595,8 +597,8 @@ impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {} pub type CanonicalTy<'gcx> = Canonical<'gcx, Ty<'gcx>>; extern { - /// A dummy type used to force Slice to by unsized without requiring fat pointers - type OpaqueSliceContents; + /// A dummy type used to force List to by unsized without requiring fat pointers + type OpaqueListContents; } /// A wrapper for slices with the additional invariant @@ -604,18 +606,19 @@ extern { /// the same contents can exist in the same context. /// This means we can use pointer for both /// equality comparisons and hashing. +/// Note: `Slice` was already taken by the `Ty`. #[repr(C)] -pub struct Slice { +pub struct List { len: usize, data: [T; 0], - opaque: OpaqueSliceContents, + opaque: OpaqueListContents, } -unsafe impl Sync for Slice {} +unsafe impl Sync for List {} -impl Slice { +impl List { #[inline] - fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx Slice { + fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx List { assert!(!mem::needs_drop::()); assert!(mem::size_of::() != 0); assert!(slice.len() != 0); @@ -632,7 +635,7 @@ impl Slice { size, cmp::max(mem::align_of::(), mem::align_of::())); unsafe { - let result = &mut *(mem.as_mut_ptr() as *mut Slice); + let result = &mut *(mem.as_mut_ptr() as *mut List); // Write the length result.len = slice.len(); @@ -645,51 +648,51 @@ impl Slice { } } -impl fmt::Debug for Slice { +impl fmt::Debug for List { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } -impl Encodable for Slice { +impl Encodable for List { #[inline] fn encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).encode(s) } } -impl Ord for Slice where T: Ord { - fn cmp(&self, other: &Slice) -> Ordering { +impl Ord for List where T: Ord { + fn cmp(&self, other: &List) -> Ordering { if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) } } } -impl PartialOrd for Slice where T: PartialOrd { - fn partial_cmp(&self, other: &Slice) -> Option { +impl PartialOrd for List where T: PartialOrd { + fn partial_cmp(&self, other: &List) -> Option { if self == other { Some(Ordering::Equal) } else { <[T] as PartialOrd>::partial_cmp(&**self, &**other) } } } -impl PartialEq for Slice { +impl PartialEq for List { #[inline] - fn eq(&self, other: &Slice) -> bool { + fn eq(&self, other: &List) -> bool { ptr::eq(self, other) } } -impl Eq for Slice {} +impl Eq for List {} -impl Hash for Slice { +impl Hash for List { #[inline] fn hash(&self, s: &mut H) { - (self as *const Slice).hash(s) + (self as *const List).hash(s) } } -impl Deref for Slice { +impl Deref for List { type Target = [T]; #[inline(always)] fn deref(&self) -> &[T] { @@ -699,7 +702,7 @@ impl Deref for Slice { } } -impl<'a, T> IntoIterator for &'a Slice { +impl<'a, T> IntoIterator for &'a List { type Item = &'a T; type IntoIter = <&'a [T] as IntoIterator>::IntoIter; #[inline(always)] @@ -708,17 +711,17 @@ impl<'a, T> IntoIterator for &'a Slice { } } -impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice> {} +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List> {} -impl Slice { +impl List { #[inline(always)] - pub fn empty<'a>() -> &'a Slice { + pub fn empty<'a>() -> &'a List { #[repr(align(64), C)] struct EmptySlice([u8; 64]); static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]); assert!(mem::align_of::() <= 64); unsafe { - &*(&EMPTY_SLICE as *const _ as *const Slice) + &*(&EMPTY_SLICE as *const _ as *const List) } } } @@ -824,6 +827,12 @@ impl ty::EarlyBoundRegion { pub fn to_bound_region(&self) -> ty::BoundRegion { ty::BoundRegion::BrNamed(self.def_id, self.name) } + + /// Does this early bound region have a name? Early bound regions normally + /// always have names except when using anonymous lifetimes (`'_`). + pub fn has_name(&self) -> bool { + self.name != keywords::UnderscoreLifetime.name().as_interned_str() + } } #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] @@ -874,6 +883,7 @@ impl GenericParamDef { } } +#[derive(Default)] pub struct GenericParamCount { pub lifetimes: usize, pub types: usize, @@ -906,15 +916,12 @@ impl<'a, 'gcx, 'tcx> Generics { // We could cache this as a property of `GenericParamCount`, but // the aim is to refactor this away entirely eventually and the // presence of this method will be a constant reminder. - let mut own_counts = GenericParamCount { - lifetimes: 0, - types: 0, - }; + let mut own_counts: GenericParamCount = Default::default(); for param in &self.params { match param.kind { GenericParamDefKind::Lifetime => own_counts.lifetimes += 1, - GenericParamDefKind::Type {..} => own_counts.types += 1, + GenericParamDefKind::Type { .. } => own_counts.types += 1, }; } @@ -924,7 +931,7 @@ impl<'a, 'gcx, 'tcx> Generics { pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { for param in &self.params { match param.kind { - GenericParamDefKind::Type {..} => return true, + GenericParamDefKind::Type { .. } => return true, GenericParamDefKind::Lifetime => {} } } @@ -1496,7 +1503,7 @@ impl UniverseIndex { /// Creates a universe index from the given integer. Not to be /// used lightly lest you pick a bad value. But sometimes we - /// convert universe indicies into integers and back for various + /// convert universe indices into integers and back for various /// reasons. pub fn from_u32(index: u32) -> Self { UniverseIndex(index) @@ -1551,7 +1558,7 @@ pub struct ParamEnv<'tcx> { /// Obligations that the caller must satisfy. This is basically /// the set of bounds on the in-scope type parameters, translated /// into Obligations, and elaborated and normalized. - pub caller_bounds: &'tcx Slice>, + pub caller_bounds: &'tcx List>, /// Typically, this is `Reveal::UserFacing`, but during codegen we /// want `Reveal::All` -- note that this is always paired with an @@ -1565,7 +1572,7 @@ impl<'tcx> ParamEnv<'tcx> { /// Trait`) are left hidden, so this is suitable for ordinary /// type-checking. pub fn empty() -> Self { - Self::new(ty::Slice::empty(), Reveal::UserFacing) + Self::new(List::empty(), Reveal::UserFacing) } /// Construct a trait environment with no where clauses in scope @@ -1576,11 +1583,11 @@ impl<'tcx> ParamEnv<'tcx> { /// NB. If you want to have predicates in scope, use `ParamEnv::new`, /// or invoke `param_env.with_reveal_all()`. pub fn reveal_all() -> Self { - Self::new(ty::Slice::empty(), Reveal::All) + Self::new(List::empty(), Reveal::All) } /// Construct a trait environment with the given set of predicates. - pub fn new(caller_bounds: &'tcx ty::Slice>, + pub fn new(caller_bounds: &'tcx List>, reveal: Reveal) -> Self { ty::ParamEnv { caller_bounds, reveal } @@ -1598,7 +1605,7 @@ impl<'tcx> ParamEnv<'tcx> { /// Returns this same environment but with no caller bounds. pub fn without_caller_bounds(self) -> Self { - ty::ParamEnv { caller_bounds: ty::Slice::empty(), ..self } + ty::ParamEnv { caller_bounds: List::empty(), ..self } } /// Creates a suitable environment in which to perform trait @@ -1685,12 +1692,17 @@ bitflags! { const IS_FUNDAMENTAL = 1 << 2; const IS_UNION = 1 << 3; const IS_BOX = 1 << 4; - /// Indicates whether this abstract data type will be expanded on in future (new - /// fields/variants) and as such, whether downstream crates must match exhaustively on the - /// fields/variants of this data type. - /// - /// See RFC 2008 (). - const IS_NON_EXHAUSTIVE = 1 << 5; + /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`. + /// (i.e., this flag is never set unless this ADT is an enum). + const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 5; + } +} + +bitflags! { + pub struct VariantFlags: u32 { + const NO_VARIANT_FLAGS = 0; + /// Indicates whether the field list of this variant is `#[non_exhaustive]`. + const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; } } @@ -1703,8 +1715,56 @@ pub struct VariantDef { pub discr: VariantDiscr, pub fields: Vec, pub ctor_kind: CtorKind, + flags: VariantFlags, } +impl<'a, 'gcx, 'tcx> VariantDef { + /// Create a new `VariantDef`. + /// + /// - `did` is the DefId used for the variant - for tuple-structs, it is the constructor DefId, + /// and for everything else, it is the variant DefId. + /// - `attribute_def_id` is the DefId that has the variant's attributes. + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, + did: DefId, + name: Name, + discr: VariantDiscr, + fields: Vec, + adt_kind: AdtKind, + ctor_kind: CtorKind) + -> Self + { + debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, name, discr, fields, + adt_kind, ctor_kind); + let mut flags = VariantFlags::NO_VARIANT_FLAGS; + if adt_kind == AdtKind::Struct && tcx.has_attr(did, "non_exhaustive") { + debug!("found non-exhaustive field list for {:?}", did); + flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; + } + VariantDef { + did, + name, + discr, + fields, + ctor_kind, + flags + } + } + + #[inline] + pub fn is_field_list_non_exhaustive(&self) -> bool { + self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) + } +} + +impl_stable_hash_for!(struct VariantDef { + did, + name, + discr, + fields, + ctor_kind, + flags +}); + #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum VariantDiscr { /// Explicit value for this variant, i.e. `X = 123`. @@ -1810,6 +1870,16 @@ impl<'a> HashStable> for AdtDef { #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum AdtKind { Struct, Union, Enum } +impl Into for AdtKind { + fn into(self) -> DataTypeKind { + match self { + AdtKind::Struct => DataTypeKind::Struct, + AdtKind::Union => DataTypeKind::Union, + AdtKind::Enum => DataTypeKind::Enum, + } + } +} + bitflags! { #[derive(RustcEncodable, RustcDecodable, Default)] pub struct ReprFlags: u8 { @@ -1833,7 +1903,7 @@ impl_stable_hash_for!(struct ReprFlags { /// Represents the repr options provided by the user, -#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] pub struct ReprOptions { pub int: Option, pub align: u32, @@ -1922,6 +1992,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { kind: AdtKind, variants: Vec, repr: ReprOptions) -> Self { + debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; let attrs = tcx.get_attrs(did); if attr::contains_name(&attrs, "fundamental") { @@ -1933,8 +2004,9 @@ impl<'a, 'gcx, 'tcx> AdtDef { if Some(did) == tcx.lang_items().owned_box() { flags = flags | AdtFlags::IS_BOX; } - if tcx.has_attr(did, "non_exhaustive") { - flags = flags | AdtFlags::IS_NON_EXHAUSTIVE; + if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") { + debug!("found non-exhaustive variant list for {:?}", did); + flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; } match kind { AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM, @@ -1965,8 +2037,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { } #[inline] - pub fn is_non_exhaustive(&self) -> bool { - self.flags.intersects(AdtFlags::IS_NON_EXHAUSTIVE) + pub fn is_variant_list_non_exhaustive(&self) -> bool { + self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) } /// Returns the kind of the ADT - Struct or Enum. @@ -2062,7 +2134,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { match def { Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid), Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.non_enum_variant(), + Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | + Def::SelfCtor(..) => self.non_enum_variant(), _ => bug!("unexpected def {:?} in variant_of_def", def) } } @@ -2214,30 +2287,30 @@ impl<'a, 'gcx, 'tcx> AdtDef { ty: Ty<'tcx>) -> Vec> { let result = match ty.sty { - TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | - TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | - TyArray(..) | TyClosure(..) | TyGenerator(..) | TyNever => { + Bool | Char | Int(..) | Uint(..) | Float(..) | + RawPtr(..) | Ref(..) | FnDef(..) | FnPtr(_) | + Array(..) | Closure(..) | Generator(..) | Never => { vec![] } - TyStr | - TyDynamic(..) | - TySlice(_) | - TyForeign(..) | - TyError | - TyGeneratorWitness(..) => { + Str | + Dynamic(..) | + Slice(_) | + Foreign(..) | + Error | + GeneratorWitness(..) => { // these are never sized - return the target type vec![ty] } - TyTuple(ref tys) => { + Tuple(ref tys) => { match tys.last() { None => vec![], Some(ty) => self.sized_constraint_for_ty(tcx, ty) } } - TyAdt(adt, substs) => { + Adt(adt, substs) => { // recursive case let adt_tys = adt.sized_constraint(tcx); debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", @@ -2248,13 +2321,13 @@ impl<'a, 'gcx, 'tcx> AdtDef { .collect() } - TyProjection(..) | TyAnon(..) => { + Projection(..) | Opaque(..) => { // must calculate explicitly. // FIXME: consider special-casing always-Sized projections vec![ty] } - TyParam(..) => { + Param(..) => { // perf hack: if there is a `T: Sized` bound, then // we know that `T` is Sized and do not need to check // it on the impl. @@ -2275,7 +2348,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } - TyInfer(..) => { + Infer(..) => { bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty) } @@ -2366,7 +2439,7 @@ impl<'tcx> TyS<'tcx> { /// Iterator that walks the immediate children of `self`. Hence /// `Foo, u32>` yields the sequence `[Bar, u32]` /// (but not `i32`, like `walk`). - pub fn walk_shallow(&'tcx self) -> AccIntoIter> { + pub fn walk_shallow(&'tcx self) -> smallvec::IntoIter> { walk::walk_shallow(self) } @@ -2462,7 +2535,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn expr_span(self, id: NodeId) -> Span { match self.hir.find(id) { - Some(hir_map::NodeExpr(e)) => { + Some(Node::Expr(e)) => { e.span } Some(f) => { @@ -2489,7 +2562,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn opt_associated_item(self, def_id: DefId) -> Option { let is_associated_item = if let Some(node_id) = self.hir.as_local_node_id(def_id) { match self.hir.get(node_id) { - hir_map::NodeTraitItem(_) | hir_map::NodeImplItem(_) => true, + Node::TraitItem(_) | Node::ImplItem(_) => true, _ => false, } } else { @@ -2817,7 +2890,7 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) /// - a type parameter or projection whose Sizedness can't be known /// - a tuple of type parameters or projections, if there are multiple /// such. -/// - a TyError, if a type contained itself. The representability +/// - a Error, if a type contained itself. The representability /// check should catch this case. fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) @@ -2879,7 +2952,7 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition pub fn is_impl_trait_defn(tcx: TyCtxt, def_id: DefId) -> Option { if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - if let hir::map::NodeItem(item) = tcx.hir.get(node_id) { + if let Node::Item(item) = tcx.hir.get(node_id) { if let hir::ItemKind::Existential(ref exist_ty) = item.node { return exist_ty.impl_trait_fn; } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index ff99a4b7ff..68f6707087 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -72,14 +72,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // in the `subtys` iterator (e.g., when encountering a // projection). match ty.sty { - ty::TyClosure(def_id, ref substs) => { + ty::Closure(def_id, ref substs) => { for upvar_ty in substs.upvar_tys(def_id, *self) { self.compute_components(upvar_ty, out); } } - ty::TyGenerator(def_id, ref substs, _) => { + ty::Generator(def_id, ref substs, _) => { // Same as the closure case for upvar_ty in substs.upvar_tys(def_id, *self) { self.compute_components(upvar_ty, out); @@ -90,11 +90,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // All regions are bound inside a witness - ty::TyGeneratorWitness(..) => (), + ty::GeneratorWitness(..) => (), // OutlivesTypeParameterEnv -- the actual checking that `X:'a` // is implied by the environment is done in regionck. - ty::TyParam(p) => { + ty::Param(p) => { out.push(Component::Param(p)); } @@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // trait-ref. Therefore, if we see any higher-ranke regions, // we simply fallback to the most restrictive rule, which // requires that `Pi: 'a` for all `i`. - ty::TyProjection(ref data) => { + ty::Projection(ref data) => { if !data.has_escaping_regions() { // best case: no escaping regions, so push the // projection and skip the subtree (thus generating no @@ -127,7 +127,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // We assume that inference variables are fully resolved. // So, if we encounter an inference variable, just record // the unresolved variable as a component. - ty::TyInfer(infer_ty) => { + ty::Infer(infer_ty) => { out.push(Component::UnresolvedInferenceVariable(infer_ty)); } @@ -137,25 +137,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // the type and then visits the types that are lexically // contained within. (The comments refer to relevant rules // from RFC1214.) - ty::TyBool | // OutlivesScalar - ty::TyChar | // OutlivesScalar - ty::TyInt(..) | // OutlivesScalar - ty::TyUint(..) | // OutlivesScalar - ty::TyFloat(..) | // OutlivesScalar - ty::TyNever | // ... - ty::TyAdt(..) | // OutlivesNominalType - ty::TyAnon(..) | // OutlivesNominalType (ish) - ty::TyForeign(..) | // OutlivesNominalType - ty::TyStr | // OutlivesScalar (ish) - ty::TyArray(..) | // ... - ty::TySlice(..) | // ... - ty::TyRawPtr(..) | // ... - ty::TyRef(..) | // OutlivesReference - ty::TyTuple(..) | // ... - ty::TyFnDef(..) | // OutlivesFunction (*) - ty::TyFnPtr(_) | // OutlivesFunction (*) - ty::TyDynamic(..) | // OutlivesObject, OutlivesFragment (*) - ty::TyError => { + ty::Bool | // OutlivesScalar + ty::Char | // OutlivesScalar + ty::Int(..) | // OutlivesScalar + ty::Uint(..) | // OutlivesScalar + ty::Float(..) | // OutlivesScalar + ty::Never | // ... + ty::Adt(..) | // OutlivesNominalType + ty::Opaque(..) | // OutlivesNominalType (ish) + ty::Foreign(..) | // OutlivesNominalType + ty::Str | // OutlivesScalar (ish) + ty::Array(..) | // ... + ty::Slice(..) | // ... + ty::RawPtr(..) | // ... + ty::Ref(..) | // OutlivesReference + ty::Tuple(..) | // ... + ty::FnDef(..) | // OutlivesFunction (*) + ty::FnPtr(_) | // OutlivesFunction (*) + ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*) + ty::Error => { // (*) Bare functions and traits are both binders. In the // RFC, this means we would add the bound regions to the // "bound regions list". In our representation, no such diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index fedf090b9e..2bbf5aacc1 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -21,6 +21,7 @@ use ty::subst::Substs; use ty::query::queries; use ty::query::Query; use ty::query::QueryCache; +use util::profiling::ProfileCategory; use std::hash::Hash; use std::fmt::Debug; @@ -33,6 +34,7 @@ use ich::StableHashingContext; pub trait QueryConfig<'tcx> { const NAME: &'static str; + const CATEGORY: ProfileCategory; type Key: Eq + Hash + Clone + Debug; type Value: Clone + for<'a> HashStable>; @@ -196,12 +198,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::const_value_to_allocation<'tcx> { - fn describe(_tcx: TyCtxt, val: &'tcx ty::Const<'tcx>) -> String { - format!("converting value `{:?}` to an allocation", val) - } -} - impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> { fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String { format!("erasing regions from `{:?}`", ty) @@ -468,6 +464,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::has_global_allocator<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::has_panic_handler<'tcx> { + fn describe(_: TyCtxt, _: CrateNum) -> String { + "checking if the crate has_panic_handler".to_string() + } +} + impl<'tcx> QueryDescription<'tcx> for queries::extern_crate<'tcx> { fn describe(_: TyCtxt, _: DefId) -> String { "getting crate's ExternCrateData".to_string() @@ -624,6 +626,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::crate_name<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::get_lib_features<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("calculating the lib features map") + } +} + +impl<'tcx> QueryDescription<'tcx> for queries::defined_lib_features<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("calculating the lib features defined in a crate") + } +} + impl<'tcx> QueryDescription<'tcx> for queries::get_lang_items<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { "calculating the lang items map".to_string() @@ -708,12 +722,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::codegen_unit<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::compile_codegen_unit<'tcx> { - fn describe(_tcx: TyCtxt, _: InternedString) -> String { - "compile_codegen_unit".to_string() - } -} - impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { "output_filenames".to_string() diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index 56a8c13a8d..d07891fca1 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -11,6 +11,7 @@ #![allow(warnings)] use std::mem; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak}; use rustc_data_structures::OnDrop; use syntax_pos::Span; @@ -21,7 +22,7 @@ use ty::context::TyCtxt; use errors::Diagnostic; use std::process; use std::{fmt, ptr}; -use std::collections::HashSet; + #[cfg(parallel_queries)] use { rayon_core, @@ -262,7 +263,7 @@ where } } - // Visit the explict waiters which use condvars and are resumable + // Visit the explicit waiters which use condvars and are resumable for (i, waiter) in query.latch.info.lock().waiters.iter().enumerate() { if let Some(ref waiter_query) = waiter.query { if visit(waiter.span, waiter_query.clone()).is_some() { @@ -282,7 +283,7 @@ where fn cycle_check<'tcx>(query: Lrc>, span: Span, stack: &mut Vec<(Span, Lrc>)>, - visited: &mut HashSet<*const QueryJob<'tcx>> + visited: &mut FxHashSet<*const QueryJob<'tcx>> ) -> Option>> { if visited.contains(&query.as_ptr()) { return if let Some(p) = stack.iter().position(|q| q.1.as_ptr() == query.as_ptr()) { @@ -321,7 +322,7 @@ fn cycle_check<'tcx>(query: Lrc>, #[cfg(parallel_queries)] fn connected_to_root<'tcx>( query: Lrc>, - visited: &mut HashSet<*const QueryJob<'tcx>> + visited: &mut FxHashSet<*const QueryJob<'tcx>> ) -> bool { // We already visited this or we're deliberately ignoring it if visited.contains(&query.as_ptr()) { @@ -357,7 +358,7 @@ fn remove_cycle<'tcx>( wakelist: &mut Vec>>, tcx: TyCtxt<'_, 'tcx, '_> ) -> bool { - let mut visited = HashSet::new(); + let mut visited = FxHashSet::default(); let mut stack = Vec::new(); // Look for a cycle starting with the last query in `jobs` if let Some(waiter) = cycle_check(jobs.pop().unwrap(), @@ -389,7 +390,7 @@ fn remove_cycle<'tcx>( // connected to queries outside the cycle let entry_points: Vec>> = stack.iter().filter_map(|query| { // Mark all the other queries in the cycle as already visited - let mut visited = HashSet::from_iter(stack.iter().filter_map(|q| { + let mut visited = FxHashSet::from_iter(stack.iter().filter_map(|q| { if q.1.as_ptr() != query.1.as_ptr() { Some(q.1.as_ptr()) } else { diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 1b1020c9bd..f0ca168e9e 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -13,7 +13,7 @@ use errors::DiagnosticBuilder; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::def::{Def, Export}; use hir::{self, TraitCandidate, ItemLocalId, CodegenFnAttrs}; -use hir::svh::Svh; +use rustc_data_structures::svh::Svh; use infer::canonical::{self, Canonical}; use lint; use middle::borrowck::BorrowCheckResult; @@ -24,12 +24,13 @@ use middle::reachable::ReachableSet; use middle::region; use middle::resolve_lifetime::{ResolveLifetimes, Region, ObjectLifetimeDefault}; use middle::stability::{self, DeprecationEntry}; +use middle::lib_features::LibFeatures; use middle::lang_items::{LanguageItems, LangItem}; use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol}; use mir::interpret::ConstEvalResult; -use mir::mono::{CodegenUnit, Stats}; +use mir::mono::CodegenUnit; use mir; -use mir::interpret::{GlobalId, Allocation}; +use mir::interpret::GlobalId; use session::{CompileResult, CrateDisambiguator}; use session::config::OutputFilenames; use traits::{self, Vtable}; @@ -46,8 +47,9 @@ use ty::steal::Steal; use ty::subst::Substs; use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet}; use util::common::{ErrorReported}; +use util::profiling::ProfileCategory::*; -use rustc_data_structures::indexed_set::IdxSetBuf; +use rustc_data_structures::indexed_set::IdxSet; use rustc_target::spec::PanicStrategy; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -206,7 +208,7 @@ define_queries! { <'tcx> /// Maps DefId's that have an associated Mir to the result /// of the MIR qualify_consts pass. The actual meaning of /// the value isn't known except to the pass itself. - [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc>), + [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc>), /// Fetch the MIR for a given def-id right after it's built - this includes /// unreachable code. @@ -284,11 +286,6 @@ define_queries! { <'tcx> /// other items (such as enum variant explicit discriminants). [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> ConstEvalResult<'tcx>, - - /// Converts a constant value to an constant allocation - [] fn const_value_to_allocation: const_value_to_allocation( - &'tcx ty::Const<'tcx> - ) -> &'tcx Allocation, }, TypeChecking { @@ -384,6 +381,7 @@ define_queries! { <'tcx> [fatal_cycle] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool, [fatal_cycle] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool, [fatal_cycle] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool, + [fatal_cycle] fn has_panic_handler: HasPanicHandler(CrateNum) -> bool, [fatal_cycle] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool, [fatal_cycle] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool, [fatal_cycle] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy, @@ -491,6 +489,9 @@ define_queries! { <'tcx> [] fn item_children: ItemChildren(DefId) -> Lrc>, [] fn extern_mod_stmt_cnum: ExternModStmtCnum(DefId) -> Option, + [] fn get_lib_features: get_lib_features_node(CrateNum) -> Lrc, + [] fn defined_lib_features: DefinedLibFeatures(CrateNum) + -> Lrc)>>, [] fn get_lang_items: get_lang_items_node(CrateNum) -> Lrc, [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Lrc>, [] fn missing_lang_items: MissingLangItems(CrateNum) -> Lrc>, @@ -525,7 +526,6 @@ define_queries! { <'tcx> -> (Arc, Arc>>>), [] fn is_codegened_item: IsCodegenedItem(DefId) -> bool, [] fn codegen_unit: CodegenUnit(InternedString) -> Arc>, - [] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats, }, Other { @@ -701,12 +701,6 @@ fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> { DepConstructor::EraseRegionsTy { ty } } -fn const_value_to_allocation<'tcx>( - val: &'tcx ty::Const<'tcx>, -) -> DepConstructor<'tcx> { - DepConstructor::ConstValueToAllocation { val } -} - fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { DepConstructor::TypeParamPredicates { item_id, @@ -799,6 +793,10 @@ fn link_args_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::LinkArgs } +fn get_lib_features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::GetLibFeatures +} + fn get_lang_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::GetLangItems } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index aa42b4072b..0e4d2f1f64 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -11,10 +11,9 @@ use dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use errors::Diagnostic; use hir; -use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId, - RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE}; +use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId, LOCAL_CRATE}; use hir::map::definitions::DefPathHash; -use ich::{CachingCodemapView, Fingerprint}; +use ich::{CachingSourceMapView, Fingerprint}; use mir::{self, interpret}; use mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_data_structures::fx::FxHashMap; @@ -26,8 +25,8 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque, use session::{CrateDisambiguator, Session}; use std::mem; use syntax::ast::NodeId; -use syntax::codemap::{CodeMap, StableFilemapId}; -use syntax_pos::{BytePos, Span, DUMMY_SP, FileMap}; +use syntax::source_map::{SourceMap, StableFilemapId}; +use syntax_pos::{BytePos, Span, DUMMY_SP, SourceFile}; use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo}; use ty; use ty::codec::{self as ty_codec, TyDecoder, TyEncoder}; @@ -62,11 +61,11 @@ pub struct OnDiskCache<'sess> { prev_cnums: Vec<(u32, String, CrateDisambiguator)>, cnum_map: Once>>, - codemap: &'sess CodeMap, - file_index_to_stable_id: FxHashMap, + source_map: &'sess SourceMap, + file_index_to_stable_id: FxHashMap, // These two fields caches that are populated lazily during decoding. - file_index_to_file: Lock>>, + file_index_to_file: Lock>>, synthetic_expansion_infos: Lock>, // A map from dep-node to the position of the cached query result in @@ -83,7 +82,7 @@ pub struct OnDiskCache<'sess> { // This type is used only for (de-)serialization. #[derive(RustcEncodable, RustcDecodable)] struct Footer { - file_index_to_stable_id: FxHashMap, + file_index_to_stable_id: FxHashMap, prev_cnums: Vec<(u32, String, CrateDisambiguator)>, query_result_index: EncodedQueryResultIndex, diagnostics_index: EncodedQueryResultIndex, @@ -96,7 +95,7 @@ type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; type EncodedDiagnostics = Vec; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] -struct FileMapIndex(u32); +struct SourceFileIndex(u32); #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, RustcEncodable, RustcDecodable)] struct AbsoluteBytePos(u32); @@ -140,7 +139,7 @@ impl<'sess> OnDiskCache<'sess> { file_index_to_file: Lock::new(FxHashMap()), prev_cnums: footer.prev_cnums, cnum_map: Once::new(), - codemap: sess.codemap(), + source_map: sess.source_map(), current_diagnostics: Lock::new(FxHashMap()), query_result_index: footer.query_result_index.into_iter().collect(), prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(), @@ -149,14 +148,14 @@ impl<'sess> OnDiskCache<'sess> { } } - pub fn new_empty(codemap: &'sess CodeMap) -> OnDiskCache<'sess> { + pub fn new_empty(source_map: &'sess SourceMap) -> OnDiskCache<'sess> { OnDiskCache { serialized_data: Vec::new(), file_index_to_stable_id: FxHashMap(), file_index_to_file: Lock::new(FxHashMap()), prev_cnums: vec![], cnum_map: Once::new(), - codemap, + source_map, current_diagnostics: Lock::new(FxHashMap()), query_result_index: FxHashMap(), prev_diagnostics_index: FxHashMap(), @@ -173,14 +172,14 @@ impl<'sess> OnDiskCache<'sess> { { // Serializing the DepGraph should not modify it: tcx.dep_graph.with_ignore(|| { - // Allocate FileMapIndices + // Allocate SourceFileIndices let (file_to_file_index, file_index_to_stable_id) = { let mut file_to_file_index = FxHashMap(); let mut file_index_to_stable_id = FxHashMap(); - for (index, file) in tcx.sess.codemap().files().iter().enumerate() { - let index = FileMapIndex(index as u32); - let file_ptr: *const FileMap = &**file as *const _; + for (index, file) in tcx.sess.source_map().files().iter().enumerate() { + let index = SourceFileIndex(index as u32); + let file_ptr: *const SourceFile = &**file as *const _; file_to_file_index.insert(file_ptr, index); file_index_to_stable_id.insert(index, StableFilemapId::new(&file)); } @@ -196,7 +195,7 @@ impl<'sess> OnDiskCache<'sess> { expn_info_shorthands: FxHashMap(), interpret_allocs: FxHashMap(), interpret_allocs_inverse: Vec::new(), - codemap: CachingCodemapView::new(tcx.sess.codemap()), + source_map: CachingSourceMapView::new(tcx.sess.source_map()), file_to_file_index, }; @@ -413,7 +412,7 @@ impl<'sess> OnDiskCache<'sess> { let mut decoder = CacheDecoder { tcx, opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()), - codemap: self.codemap, + source_map: self.source_map, cnum_map: self.cnum_map.get(), file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, @@ -475,27 +474,27 @@ impl<'sess> OnDiskCache<'sess> { struct CacheDecoder<'a, 'tcx: 'a, 'x> { tcx: TyCtxt<'a, 'tcx, 'tcx>, opaque: opaque::Decoder<'x>, - codemap: &'x CodeMap, + source_map: &'x SourceMap, cnum_map: &'x IndexVec>, synthetic_expansion_infos: &'x Lock>, - file_index_to_file: &'x Lock>>, - file_index_to_stable_id: &'x FxHashMap, + file_index_to_file: &'x Lock>>, + file_index_to_stable_id: &'x FxHashMap, alloc_decoding_session: AllocDecodingSession<'x>, } impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> { - fn file_index_to_file(&self, index: FileMapIndex) -> Lrc { + fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc { let CacheDecoder { ref file_index_to_file, ref file_index_to_stable_id, - ref codemap, + ref source_map, .. } = *self; file_index_to_file.borrow_mut().entry(index).or_insert_with(|| { let stable_id = file_index_to_stable_id[&index]; - codemap.filemap_by_stable_id(stable_id) - .expect("Failed to lookup FileMap in new context.") + source_map.source_file_by_stable_id(stable_id) + .expect("Failed to lookup SourceFile in new context.") }).clone() } } @@ -566,7 +565,7 @@ impl<'a, 'tcx: 'a, 'x> ty_codec::TyDecoder<'a, 'tcx> for CacheDecoder<'a, 'tcx, let tcx = self.tcx(); let cache_key = ty::CReaderCacheKey { - cnum: RESERVED_FOR_INCR_COMP_CACHE, + cnum: CrateNum::ReservedForIncrCompCache, pos: shorthand, }; @@ -617,7 +616,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder for CacheDecoder<'a, 'tcx, 'x> { debug_assert_eq!(tag, TAG_VALID_SPAN); } - let file_lo_index = FileMapIndex::decode(self)?; + let file_lo_index = SourceFileIndex::decode(self)?; let line_lo = usize::decode(self)?; let col_lo = BytePos::decode(self)?; let len = BytePos::decode(self)?; @@ -770,15 +769,15 @@ struct CacheEncoder<'enc, 'a, 'tcx, E> expn_info_shorthands: FxHashMap, interpret_allocs: FxHashMap, interpret_allocs_inverse: Vec, - codemap: CachingCodemapView<'tcx>, - file_to_file_index: FxHashMap<*const FileMap, FileMapIndex>, + source_map: CachingSourceMapView<'tcx>, + file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>, } impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E> where E: 'enc + ty_codec::TyEncoder { - fn filemap_index(&mut self, filemap: Lrc) -> FileMapIndex { - self.file_to_file_index[&(&*filemap as *const FileMap)] + fn source_file_index(&mut self, source_file: Lrc) -> SourceFileIndex { + self.file_to_file_index[&(&*source_file as *const SourceFile)] } /// Encode something with additional information that allows to do some @@ -836,7 +835,7 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'enc, 'a, 'tcx return TAG_INVALID_SPAN.encode(self); } - let (file_lo, line_lo, col_lo) = match self.codemap + let (file_lo, line_lo, col_lo) = match self.source_map .byte_pos_to_line_and_col(span_data.lo) { Some(pos) => pos, None => { @@ -850,10 +849,10 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'enc, 'a, 'tcx let len = span_data.hi - span_data.lo; - let filemap_index = self.filemap_index(file_lo); + let source_file_index = self.source_file_index(file_lo); TAG_VALID_SPAN.encode(self)?; - filemap_index.encode(self)?; + source_file_index.encode(self)?; line_lo.encode(self)?; col_lo.encode(self)?; len.encode(self)?; @@ -1020,7 +1019,7 @@ impl<'enc, 'a, 'tcx, E> Encoder for CacheEncoder<'enc, 'a, 'tcx, E> { type Error = E::Error; - fn emit_nil(&mut self) -> Result<(), Self::Error> { + fn emit_unit(&mut self) -> Result<(), Self::Error> { Ok(()) } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 7a9827b50a..25e72f462e 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -32,7 +32,7 @@ use std::mem; use std::ptr; use std::collections::hash_map::Entry; use syntax_pos::Span; -use syntax::codemap::DUMMY_SP; +use syntax::source_map::DUMMY_SP; pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> { pub(super) results: FxHashMap>, @@ -118,6 +118,11 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { let mut lock = cache.borrow_mut(); if let Some(value) = lock.results.get(key) { profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + tcx.sess.profiler(|p| { + p.record_query(Q::CATEGORY); + p.record_query_hit(Q::CATEGORY); + }); + let result = Ok((value.value.clone(), value.index)); return TryGetJob::JobCompleted(result); } @@ -246,7 +251,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { assert!(!stack.is_empty()); let fix_span = |span: Span, query: &Query<'gcx>| { - self.sess.codemap().def_span(query.default_span(self, span)) + self.sess.source_map().def_span(query.default_span(self, span)) }; // Disable naming impls with types in this path, since that @@ -294,7 +299,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { i, query.info.query.name(), query.info.query.describe(icx.tcx))); - db.set_span(icx.tcx.sess.codemap().def_span(query.info.span)); + db.set_span(icx.tcx.sess.source_map().def_span(query.info.span)); icx.tcx.sess.diagnostic().force_print_db(db); current_query = query.parent.clone(); @@ -358,10 +363,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ) ); + self.sess.profiler(|p| p.record_query(Q::CATEGORY)); + let job = match JobOwner::try_get(self, span, &key) { TryGetJob::NotYetStarted(job) => job, TryGetJob::JobCompleted(result) => { return result.map(|(v, index)| { + self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY)); self.dep_graph.read_index(index); v }) @@ -379,6 +387,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if dep_node.kind.is_anon() { profq_msg!(self, ProfileQueriesMsg::ProviderBegin); + self.sess.profiler(|p| p.start_activity(Q::CATEGORY)); let res = job.start(self, |tcx| { tcx.dep_graph.with_anon_task(dep_node.kind, || { @@ -386,6 +395,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }) }); + self.sess.profiler(|p| p.end_activity(Q::CATEGORY)); profq_msg!(self, ProfileQueriesMsg::ProviderEnd); let ((result, dep_node_index), diagnostics) = res; @@ -402,6 +412,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if !dep_node.kind.is_input() { if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) { profq_msg!(self, ProfileQueriesMsg::CacheHit); + self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY)); + return self.load_from_disk_and_cache_in_memory::(key, job, dep_node_index, @@ -523,6 +535,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { key, dep_node); profq_msg!(self, ProfileQueriesMsg::ProviderBegin); + self.sess.profiler(|p| { + p.start_activity(Q::CATEGORY); + p.record_query(Q::CATEGORY); + }); + let res = job.start(self, |tcx| { if dep_node.kind.is_eval_always() { tcx.dep_graph.with_eval_always_task(dep_node, @@ -536,6 +553,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Q::compute) } }); + + self.sess.profiler(|p| p.end_activity(Q::CATEGORY)); profq_msg!(self, ProfileQueriesMsg::ProviderEnd); let ((result, dep_node_index), diagnostics) = res; @@ -574,7 +593,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // DepNodeIndex. We must invoke the query itself. The performance cost // this introduces should be negligible as we'll immediately hit the // in-memory cache, or another query down the line will. + + self.sess.profiler(|p| { + p.start_activity(Q::CATEGORY); + p.record_query(Q::CATEGORY); + }); + let _ = self.get_query::(DUMMY_SP, key); + + self.sess.profiler(|p| p.end_activity(Q::CATEGORY)); } } @@ -655,6 +682,7 @@ macro_rules! define_queries_inner { rustc_data_structures::stable_hasher::StableHasher, ich::StableHashingContext }; + use util::profiling::ProfileCategory; define_queries_struct! { tcx: $tcx, @@ -664,10 +692,12 @@ macro_rules! define_queries_inner { impl<$tcx> Queries<$tcx> { pub fn new( providers: IndexVec>, + fallback_extern_providers: Providers<$tcx>, on_disk_cache: OnDiskCache<'tcx>, ) -> Self { Queries { providers, + fallback_extern_providers: Box::new(fallback_extern_providers), on_disk_cache, $($name: Lock::new(QueryCache::new())),* } @@ -690,7 +720,7 @@ macro_rules! define_queries_inner { } } - #[allow(bad_style)] + #[allow(nonstandard_style)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum Query<$tcx> { $($(#[$attr])* $name($K)),* @@ -747,7 +777,7 @@ macro_rules! define_queries_inner { pub mod queries { use std::marker::PhantomData; - $(#[allow(bad_style)] + $(#[allow(nonstandard_style)] pub struct $name<$tcx> { data: PhantomData<&$tcx ()> })* @@ -768,6 +798,7 @@ macro_rules! define_queries_inner { type Value = $V; const NAME: &'static str = stringify!($name); + const CATEGORY: ProfileCategory = $category; } impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> { @@ -789,7 +820,13 @@ macro_rules! define_queries_inner { #[inline] fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value { __query_compute::$name(move || { - let provider = tcx.queries.providers[key.query_crate()].$name; + let provider = tcx.queries.providers.get(key.query_crate()) + // HACK(eddyb) it's possible crates may be loaded after + // the query engine is created, and because crate loading + // is not yet integrated with the query engine, such crates + // would be be missing appropriate entries in `providers`. + .unwrap_or(&tcx.queries.fallback_extern_providers) + .$name; provider(tcx.global_tcx(), key) }) } @@ -870,6 +907,7 @@ macro_rules! define_queries_struct { pub(crate) on_disk_cache: OnDiskCache<'tcx>, providers: IndexVec>, + fallback_extern_providers: Box>, $($(#[$attr])* $name: Lock>>,)* } @@ -1033,7 +1071,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::FulfillObligation | DepKind::VtableMethods | DepKind::EraseRegionsTy | - DepKind::ConstValueToAllocation | DepKind::NormalizeProjectionTy | DepKind::NormalizeTyAfterErasingRegions | DepKind::ImpliedOutlivesBounds | @@ -1140,6 +1177,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); } DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); } DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); } + DepKind::HasPanicHandler => { force!(has_panic_handler, krate!()); } DepKind::ExternCrate => { force!(extern_crate, def_id!()); } DepKind::LintLevels => { force!(lint_levels, LOCAL_CRATE); } DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); } @@ -1189,6 +1227,8 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::CrateName => { force!(crate_name, krate!()); } DepKind::ItemChildren => { force!(item_children, def_id!()); } DepKind::ExternModStmtCnum => { force!(extern_mod_stmt_cnum, def_id!()); } + DepKind::GetLibFeatures => { force!(get_lib_features, LOCAL_CRATE); } + DepKind::DefinedLibFeatures => { force!(defined_lib_features, krate!()); } DepKind::GetLangItems => { force!(get_lang_items, LOCAL_CRATE); } DepKind::DefinedLangItems => { force!(defined_lang_items, krate!()); } DepKind::MissingLangItems => { force!(missing_lang_items, krate!()); } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 4e8f33d6a4..8f84fb7e39 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -316,7 +316,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { } #[derive(Debug, Clone)] -struct GeneratorWitness<'tcx>(&'tcx ty::Slice>); +struct GeneratorWitness<'tcx>(&'tcx ty::List>); TupleStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for GeneratorWitness<'tcx> { @@ -363,50 +363,50 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, let b_sty = &b.sty; debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty); match (a_sty, b_sty) { - (&ty::TyInfer(_), _) | - (_, &ty::TyInfer(_)) => + (&ty::Infer(_), _) | + (_, &ty::Infer(_)) => { // The caller should handle these cases! bug!("var types encountered in super_relate_tys") } - (&ty::TyError, _) | (_, &ty::TyError) => + (&ty::Error, _) | (_, &ty::Error) => { Ok(tcx.types.err) } - (&ty::TyNever, _) | - (&ty::TyChar, _) | - (&ty::TyBool, _) | - (&ty::TyInt(_), _) | - (&ty::TyUint(_), _) | - (&ty::TyFloat(_), _) | - (&ty::TyStr, _) + (&ty::Never, _) | + (&ty::Char, _) | + (&ty::Bool, _) | + (&ty::Int(_), _) | + (&ty::Uint(_), _) | + (&ty::Float(_), _) | + (&ty::Str, _) if a == b => { Ok(a) } - (&ty::TyParam(ref a_p), &ty::TyParam(ref b_p)) + (&ty::Param(ref a_p), &ty::Param(ref b_p)) if a_p.idx == b_p.idx => { Ok(a) } - (&ty::TyAdt(a_def, a_substs), &ty::TyAdt(b_def, b_substs)) + (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => { let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?; Ok(tcx.mk_adt(a_def, substs)) } - (&ty::TyForeign(a_id), &ty::TyForeign(b_id)) + (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => { Ok(tcx.mk_foreign(a_id)) } - (&ty::TyDynamic(ref a_obj, ref a_region), &ty::TyDynamic(ref b_obj, ref b_region)) => { + (&ty::Dynamic(ref a_obj, ref a_region), &ty::Dynamic(ref b_obj, ref b_region)) => { let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { relation.relate_with_variance( @@ -417,18 +417,18 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound)) } - (&ty::TyGenerator(a_id, a_substs, movability), - &ty::TyGenerator(b_id, b_substs, _)) + (&ty::Generator(a_id, a_substs, movability), + &ty::Generator(b_id, b_substs, _)) if a_id == b_id => { - // All TyGenerator types with the same id represent + // All Generator types with the same id represent // the (anonymous) type of the same generator expression. So // all of their regions should be equated. let substs = relation.relate(&a_substs, &b_substs)?; Ok(tcx.mk_generator(a_id, substs, movability)) } - (&ty::TyGeneratorWitness(a_types), &ty::TyGeneratorWitness(b_types)) => + (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { // Wrap our types with a temporary GeneratorWitness struct // inside the binder so we can related them @@ -439,24 +439,24 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_generator_witness(types)) } - (&ty::TyClosure(a_id, a_substs), - &ty::TyClosure(b_id, b_substs)) + (&ty::Closure(a_id, a_substs), + &ty::Closure(b_id, b_substs)) if a_id == b_id => { - // All TyClosure types with the same id represent + // All Closure types with the same id represent // the (anonymous) type of the same closure expression. So // all of their regions should be equated. let substs = relation.relate(&a_substs, &b_substs)?; Ok(tcx.mk_closure(a_id, substs)) } - (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) => + (&ty::RawPtr(ref a_mt), &ty::RawPtr(ref b_mt)) => { let mt = relation.relate(a_mt, b_mt)?; Ok(tcx.mk_ptr(mt)) } - (&ty::TyRef(a_r, a_ty, a_mutbl), &ty::TyRef(b_r, b_ty, b_mutbl)) => + (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { let r = relation.relate_with_variance(ty::Contravariant, &a_r, &b_r)?; let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; @@ -465,7 +465,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_ref(r, mt)) } - (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) => + (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { let t = relation.relate(&a_t, &b_t)?; assert_eq!(sz_a.ty, tcx.types.usize); @@ -514,26 +514,26 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, match (to_u64(sz_a), to_u64(sz_b)) { (Ok(sz_a_u64), Ok(sz_b_u64)) => { if sz_a_u64 == sz_b_u64 { - Ok(tcx.mk_ty(ty::TyArray(t, sz_a))) + Ok(tcx.mk_ty(ty::Array(t, sz_a))) } else { Err(TypeError::FixedArraySize( expected_found(relation, &sz_a_u64, &sz_b_u64))) } } - // We reported an error or will ICE, so we can return TyError. + // We reported an error or will ICE, so we can return Error. (Err(ErrorReported), _) | (_, Err(ErrorReported)) => { Ok(tcx.types.err) } } } - (&ty::TySlice(a_t), &ty::TySlice(b_t)) => + (&ty::Slice(a_t), &ty::Slice(b_t)) => { let t = relation.relate(&a_t, &b_t)?; Ok(tcx.mk_slice(t)) } - (&ty::TyTuple(as_), &ty::TyTuple(bs)) => + (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?) @@ -545,30 +545,30 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } } - (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs)) + (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs)) if a_def_id == b_def_id => { let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?; Ok(tcx.mk_fn_def(a_def_id, substs)) } - (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) => + (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => { let fty = relation.relate(&a_fty, &b_fty)?; Ok(tcx.mk_fn_ptr(fty)) } - (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) => + (&ty::Projection(ref a_data), &ty::Projection(ref b_data)) => { let projection_ty = relation.relate(a_data, b_data)?; Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) } - (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs)) + (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs)) if a_def_id == b_def_id => { let substs = relate_substs(relation, None, a_substs, b_substs)?; - Ok(tcx.mk_anon(a_def_id, substs)) + Ok(tcx.mk_opaque(a_def_id, substs)) } _ => @@ -578,7 +578,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } } -impl<'tcx> Relate<'tcx> for &'tcx ty::Slice> { +impl<'tcx> Relate<'tcx> for &'tcx ty::List> { fn relate<'a, 'gcx, R>(relation: &mut R, a: &Self, b: &Self) diff --git a/src/librustc/ty/steal.rs b/src/librustc/ty/steal.rs index 842c0d6573..3ff3cb4cae 100644 --- a/src/librustc/ty/steal.rs +++ b/src/librustc/ty/steal.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_data_structures::sync::{RwLock, ReadGuard}; +use rustc_data_structures::sync::{RwLock, ReadGuard, MappedReadGuard}; use std::mem; /// The `Steal` struct is intended to used as the value for a query. @@ -42,7 +42,7 @@ impl Steal { } } - pub fn borrow(&self) -> ReadGuard { + pub fn borrow(&self) -> MappedReadGuard { ReadGuard::map(self.value.borrow(), |opt| match *opt { None => bug!("attempted to read from stolen value"), Some(ref v) => v diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index ad29f80828..bd9dfc6b85 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -16,8 +16,8 @@ use mir::interpret::{ConstValue, ConstEvalErr}; use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use rustc_data_structures::accumulate_vec::AccumulateVec; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use smallvec::SmallVec; use mir::interpret; use std::rc::Rc; @@ -57,6 +57,7 @@ CloneTypeFoldableAndLiftImpls! { ::ty::ClosureKind, ::ty::IntVarValue, ::ty::ParamTy, + ::ty::Variance, ::syntax_pos::Span, } @@ -487,10 +488,12 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> { use ::mir::interpret::EvalErrorKind::*; Some(match *self { MachineError(ref err) => MachineError(err.clone()), - FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch( + FunctionAbiMismatch(a, b) => FunctionAbiMismatch(a, b), + FunctionArgMismatch(a, b) => FunctionArgMismatch( tcx.lift(&a)?, tcx.lift(&b)?, ), + FunctionArgCountMismatch => FunctionArgCountMismatch, NoMirFor(ref s) => NoMirFor(s.clone()), UnterminatedCString(ptr) => UnterminatedCString(ptr), DanglingPointerDeref => DanglingPointerDeref, @@ -498,7 +501,7 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> { InvalidMemoryAccess => InvalidMemoryAccess, InvalidFunctionPointer => InvalidFunctionPointer, InvalidBool => InvalidBool, - InvalidDiscriminant => InvalidDiscriminant, + InvalidDiscriminant(val) => InvalidDiscriminant(val), PointerOutOfBounds { ptr, access, @@ -509,7 +512,7 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> { ReadBytesAsPointer => ReadBytesAsPointer, ReadForeignStatic => ReadForeignStatic, InvalidPointerMath => InvalidPointerMath, - ReadUndefBytes => ReadUndefBytes, + ReadUndefBytes(offset) => ReadUndefBytes(offset), DeadLocal => DeadLocal, InvalidBoolOp(bop) => InvalidBoolOp(bop), Unimplemented(ref s) => Unimplemented(s.clone()), @@ -574,7 +577,11 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> { HeapAllocZeroBytes => HeapAllocZeroBytes, HeapAllocNonPowerOfTwoAlignment(n) => HeapAllocNonPowerOfTwoAlignment(n), Unreachable => Unreachable, - Panic => Panic, + Panic { ref msg, ref file, line, col } => Panic { + msg: msg.clone(), + file: file.clone(), + line, col, + }, ReadFromReturnPointer => ReadFromReturnPointer, PathNotFound(ref v) => PathNotFound(v.clone()), UnimplementedTraitSelection => UnimplementedTraitSelection, @@ -735,9 +742,9 @@ BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> { reveal, caller_bounds } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); + let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); folder.tcx().intern_existential_predicates(&v) } @@ -754,9 +761,9 @@ EnumTypeFoldableImpl! { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); + let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); folder.tcx().intern_type_list(&v) } @@ -836,33 +843,33 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { let sty = match self.sty { - ty::TyRawPtr(tm) => ty::TyRawPtr(tm.fold_with(folder)), - ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz.fold_with(folder)), - ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)), - ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)), - ty::TyDynamic(ref trait_ty, ref region) => - ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)), - ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)), - ty::TyFnDef(def_id, substs) => { - ty::TyFnDef(def_id, substs.fold_with(folder)) + ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)), + ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), + ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), + ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)), + ty::Dynamic(ref trait_ty, ref region) => + ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder)), + ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)), + ty::FnDef(def_id, substs) => { + ty::FnDef(def_id, substs.fold_with(folder)) } - ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)), - ty::TyRef(ref r, ty, mutbl) => { - ty::TyRef(r.fold_with(folder), ty.fold_with(folder), mutbl) + ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)), + ty::Ref(ref r, ty, mutbl) => { + ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl) } - ty::TyGenerator(did, substs, movability) => { - ty::TyGenerator( + ty::Generator(did, substs, movability) => { + ty::Generator( did, substs.fold_with(folder), movability) } - ty::TyGeneratorWitness(types) => ty::TyGeneratorWitness(types.fold_with(folder)), - ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)), - ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)), - ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)), - ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) | - ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) | - ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => return self + ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)), + ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)), + ty::Projection(ref data) => ty::Projection(data.fold_with(folder)), + ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), + ty::Bool | ty::Char | ty::Str | ty::Int(_) | + ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | + ty::Param(..) | ty::Never | ty::Foreign(..) => return self }; if self.sty == sty { @@ -878,26 +885,26 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { match self.sty { - ty::TyRawPtr(ref tm) => tm.visit_with(visitor), - ty::TyArray(typ, sz) => typ.visit_with(visitor) || sz.visit_with(visitor), - ty::TySlice(typ) => typ.visit_with(visitor), - ty::TyAdt(_, substs) => substs.visit_with(visitor), - ty::TyDynamic(ref trait_ty, ref reg) => + ty::RawPtr(ref tm) => tm.visit_with(visitor), + ty::Array(typ, sz) => typ.visit_with(visitor) || sz.visit_with(visitor), + ty::Slice(typ) => typ.visit_with(visitor), + ty::Adt(_, substs) => substs.visit_with(visitor), + ty::Dynamic(ref trait_ty, ref reg) => trait_ty.visit_with(visitor) || reg.visit_with(visitor), - ty::TyTuple(ts) => ts.visit_with(visitor), - ty::TyFnDef(_, substs) => substs.visit_with(visitor), - ty::TyFnPtr(ref f) => f.visit_with(visitor), - ty::TyRef(r, ty, _) => r.visit_with(visitor) || ty.visit_with(visitor), - ty::TyGenerator(_did, ref substs, _) => { + ty::Tuple(ts) => ts.visit_with(visitor), + ty::FnDef(_, substs) => substs.visit_with(visitor), + ty::FnPtr(ref f) => f.visit_with(visitor), + ty::Ref(r, ty, _) => r.visit_with(visitor) || ty.visit_with(visitor), + ty::Generator(_did, ref substs, _) => { substs.visit_with(visitor) } - ty::TyGeneratorWitness(ref types) => types.visit_with(visitor), - ty::TyClosure(_did, ref substs) => substs.visit_with(visitor), - ty::TyProjection(ref data) => data.visit_with(visitor), - ty::TyAnon(_, ref substs) => substs.visit_with(visitor), - ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) | - ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) | - ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => false, + ty::GeneratorWitness(ref types) => types.visit_with(visitor), + ty::Closure(_did, ref substs) => substs.visit_with(visitor), + ty::Projection(ref data) => data.visit_with(visitor), + ty::Opaque(_, ref substs) => substs.visit_with(visitor), + ty::Bool | ty::Char | ty::Str | ty::Int(_) | + ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | + ty::Param(..) | ty::Never | ty::Foreign(..) => false, } } @@ -1010,9 +1017,9 @@ BraceStructTypeFoldableImpl! { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); + let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); folder.tcx().intern_predicates(&v) } @@ -1135,7 +1142,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { match *self { ConstValue::Scalar(v) => ConstValue::Scalar(v), ConstValue::ScalarPair(a, b) => ConstValue::ScalarPair(a, b), - ConstValue::ByRef(alloc, offset) => ConstValue::ByRef(alloc, offset), + ConstValue::ByRef(id, alloc, offset) => ConstValue::ByRef(id, alloc, offset), ConstValue::Unevaluated(def_id, substs) => { ConstValue::Unevaluated(def_id, substs.fold_with(folder)) } @@ -1146,7 +1153,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { match *self { ConstValue::Scalar(_) | ConstValue::ScalarPair(_, _) | - ConstValue::ByRef(_, _) => false, + ConstValue::ByRef(_, _, _) => false, ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor), } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index dd38188824..ea547c592d 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! This module contains TypeVariants and its major components +//! This module contains TyKind and its major components use hir::def_id::DefId; @@ -18,9 +18,9 @@ use polonius_engine::Atom; use rustc_data_structures::indexed_vec::Idx; use ty::subst::{Substs, Subst, Kind, UnpackedKind}; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; -use ty::{Slice, TyS, ParamEnvAnd, ParamEnv}; +use ty::{List, TyS, ParamEnvAnd, ParamEnv}; use util::captures::Captures; -use mir::interpret::{Scalar, Pointer, Value}; +use mir::interpret::{Scalar, Pointer}; use std::iter; use std::cmp::Ordering; @@ -33,7 +33,7 @@ use serialize; use hir; use self::InferTy::*; -use self::TypeVariants::*; +use self::TyKind::*; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct TypeAndMut<'tcx> { @@ -82,98 +82,98 @@ impl BoundRegion { /// NB: If you change this, you'll probably want to change the corresponding /// AST structure in libsyntax/ast.rs as well. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] -pub enum TypeVariants<'tcx> { +pub enum TyKind<'tcx> { /// The primitive boolean type. Written as `bool`. - TyBool, + Bool, /// The primitive character type; holds a Unicode scalar value /// (a non-surrogate code point). Written as `char`. - TyChar, + Char, /// A primitive signed integer type. For example, `i32`. - TyInt(ast::IntTy), + Int(ast::IntTy), /// A primitive unsigned integer type. For example, `u32`. - TyUint(ast::UintTy), + Uint(ast::UintTy), /// A primitive floating-point type. For example, `f64`. - TyFloat(ast::FloatTy), + Float(ast::FloatTy), /// Structures, enumerations and unions. /// - /// Substs here, possibly against intuition, *may* contain `TyParam`s. + /// Substs here, possibly against intuition, *may* contain `Param`s. /// That is, even after substitution it is possible that there are type - /// variables. This happens when the `TyAdt` corresponds to an ADT + /// variables. This happens when the `Adt` corresponds to an ADT /// definition and not a concrete use of it. - TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>), + Adt(&'tcx AdtDef, &'tcx Substs<'tcx>), - TyForeign(DefId), + Foreign(DefId), /// The pointee of a string slice. Written as `str`. - TyStr, + Str, /// An array with the given length. Written as `[T; n]`. - TyArray(Ty<'tcx>, &'tcx ty::Const<'tcx>), + Array(Ty<'tcx>, &'tcx ty::Const<'tcx>), /// The pointee of an array slice. Written as `[T]`. - TySlice(Ty<'tcx>), + Slice(Ty<'tcx>), /// A raw pointer. Written as `*mut T` or `*const T` - TyRawPtr(TypeAndMut<'tcx>), + RawPtr(TypeAndMut<'tcx>), /// A reference; a pointer with an associated lifetime. Written as /// `&'a mut T` or `&'a T`. - TyRef(Region<'tcx>, Ty<'tcx>, hir::Mutability), + Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability), /// The anonymous type of a function declaration/definition. Each /// function has a unique type. - TyFnDef(DefId, &'tcx Substs<'tcx>), + FnDef(DefId, &'tcx Substs<'tcx>), /// A pointer to a function. Written as `fn() -> i32`. - TyFnPtr(PolyFnSig<'tcx>), + FnPtr(PolyFnSig<'tcx>), /// A trait, defined with `trait`. - TyDynamic(Binder<&'tcx Slice>>, ty::Region<'tcx>), + Dynamic(Binder<&'tcx List>>, ty::Region<'tcx>), /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. - TyClosure(DefId, ClosureSubsts<'tcx>), + Closure(DefId, ClosureSubsts<'tcx>), /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. - TyGenerator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), + Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), /// A type representin the types stored inside a generator. /// This should only appear in GeneratorInteriors. - TyGeneratorWitness(Binder<&'tcx Slice>>), + GeneratorWitness(Binder<&'tcx List>>), /// The never type `!` - TyNever, + Never, /// A tuple type. For example, `(i32, bool)`. - TyTuple(&'tcx Slice>), + Tuple(&'tcx List>), /// The projection of an associated type. For example, /// `>::N`. - TyProjection(ProjectionTy<'tcx>), + Projection(ProjectionTy<'tcx>), - /// Anonymized (`impl Trait`) type found in a return type. + /// Opaque (`impl Trait`) type found in a return type. /// The DefId comes either from /// * the `impl Trait` ast::Ty node, /// * or the `existential type` declaration /// The substitutions are for the generics of the function in question. /// After typeck, the concrete type can be found in the `types` map. - TyAnon(DefId, &'tcx Substs<'tcx>), + Opaque(DefId, &'tcx Substs<'tcx>), /// A type parameter; for example, `T` in `fn f(x: T) {} - TyParam(ParamTy), + Param(ParamTy), /// A type variable used during type-checking. - TyInfer(InferTy), + Infer(InferTy), /// A placeholder for a type which could not be computed; this is /// propagated to avoid useless error messages. - TyError, + Error, } /// A closure can be modeled as a struct that looks like: @@ -348,7 +348,7 @@ impl<'tcx> ClosureSubsts<'tcx> { /// If you have an inference context, use `infcx.closure_sig()`. pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { match self.closure_sig_ty(def_id, tcx).sty { - ty::TyFnPtr(sig) => sig, + ty::FnPtr(sig) => sig, ref t => bug!("closure_sig_ty is not a fn-ptr: {:?}", t), } } @@ -536,9 +536,9 @@ impl<'a, 'gcx, 'tcx> Binder> { } } -impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice> {} +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List> {} -impl<'tcx> Slice> { +impl<'tcx> List> { pub fn principal(&self) -> Option> { match self.get(0) { Some(&ExistentialPredicate::Trait(tr)) => Some(tr), @@ -568,7 +568,7 @@ impl<'tcx> Slice> { } } -impl<'tcx> Binder<&'tcx Slice>> { +impl<'tcx> Binder<&'tcx List>> { pub fn principal(&self) -> Option> { self.skip_binder().principal().map(Binder::bind) } @@ -708,7 +708,7 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { // otherwise the escaping regions would be captured by the binder - assert!(!self_ty.has_escaping_regions()); + debug_assert!(!self_ty.has_escaping_regions()); ty::TraitRef { def_id: self.def_id, @@ -753,7 +753,7 @@ impl Binder { pub fn dummy<'tcx>(value: T) -> Binder where T: TypeFoldable<'tcx> { - assert!(!value.has_escaping_regions()); + debug_assert!(!value.has_escaping_regions()); Binder(value) } @@ -918,7 +918,7 @@ impl<'tcx> PolyGenSig<'tcx> { /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns) #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct FnSig<'tcx> { - pub inputs_and_output: &'tcx Slice>, + pub inputs_and_output: &'tcx List>, pub variadic: bool, pub unsafety: hir::Unsafety, pub abi: abi::Abi, @@ -943,7 +943,7 @@ impl<'tcx> PolyFnSig<'tcx> { pub fn input(&self, index: usize) -> ty::Binder> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } - pub fn inputs_and_output(&self) -> ty::Binder<&'tcx Slice>> { + pub fn inputs_and_output(&self) -> ty::Binder<&'tcx List>> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } pub fn output(&self) -> ty::Binder> { @@ -1034,11 +1034,12 @@ impl<'a, 'gcx, 'tcx> ParamTy { /// is the outer fn. /// /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index -newtype_index!(DebruijnIndex - { +newtype_index! { + pub struct DebruijnIndex { DEBUG_FORMAT = "DebruijnIndex({})", const INNERMOST = 0, - }); + } +} pub type Region<'tcx> = &'tcx RegionKind; @@ -1058,7 +1059,7 @@ pub type Region<'tcx> = &'tcx RegionKind; /// the likes of `liberate_late_bound_regions`. The distinction exists /// because higher-ranked lifetimes aren't supported in all places. See [1][2]. /// -/// Unlike TyParam-s, bound regions are not supposed to exist "in the wild" +/// Unlike Param-s, bound regions are not supposed to exist "in the wild" /// outside their binder, e.g. in types passed to type inference, and /// should first be substituted (by skolemized regions, free regions, /// or region variables). @@ -1176,11 +1177,11 @@ pub struct FloatVid { pub index: u32, } -newtype_index!(RegionVid - { - pub idx +newtype_index! { + pub struct RegionVid { DEBUG_FORMAT = custom, - }); + } +} impl Atom for RegionVid { fn index(self) -> usize { @@ -1188,18 +1189,6 @@ impl Atom for RegionVid { } } -impl From for RegionVid { - fn from(i: usize) -> RegionVid { - RegionVid::new(i) - } -} - -impl From for usize { - fn from(vid: RegionVid) -> usize { - Idx::index(vid) - } -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub enum InferTy { TyVar(TyVid), @@ -1217,7 +1206,9 @@ pub enum InferTy { CanonicalTy(CanonicalVar), } -newtype_index!(CanonicalVar); +newtype_index! { + pub struct CanonicalVar { .. } +} /// A `ProjectionPredicate` for an `ExistentialTraitRef`. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -1247,7 +1238,7 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { -> ty::ProjectionPredicate<'tcx> { // otherwise the escaping regions would be captured by the binders - assert!(!self_ty.has_escaping_regions()); + debug_assert!(!self_ty.has_escaping_regions()); ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { @@ -1282,8 +1273,8 @@ impl DebruijnIndex { /// /// you would need to shift the index for `'a` into 1 new binder. #[must_use] - pub const fn shifted_in(self, amount: u32) -> DebruijnIndex { - DebruijnIndex(self.0 + amount) + pub fn shifted_in(self, amount: u32) -> DebruijnIndex { + DebruijnIndex::from_u32(self.as_u32() + amount) } /// Update this index in place by shifting it "in" through @@ -1295,8 +1286,8 @@ impl DebruijnIndex { /// Returns the resulting index when this value is moved out from /// `amount` number of new binders. #[must_use] - pub const fn shifted_out(self, amount: u32) -> DebruijnIndex { - DebruijnIndex(self.0 - amount) + pub fn shifted_out(self, amount: u32) -> DebruijnIndex { + DebruijnIndex::from_u32(self.as_u32() - amount) } /// Update in place by shifting out from `amount` binders. @@ -1325,11 +1316,11 @@ impl DebruijnIndex { /// bound by one of the binders we are shifting out of, that is an /// error (and should fail an assertion failure). pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self { - self.shifted_out((to_binder.0 - INNERMOST.0) as u32) + self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32()) } } -impl_stable_hash_for!(tuple_struct DebruijnIndex { index }); +impl_stable_hash_for!(struct DebruijnIndex { private }); /// Region utilities impl RegionKind { @@ -1467,69 +1458,69 @@ impl RegionKind { /// Type utilities impl<'a, 'gcx, 'tcx> TyS<'tcx> { - pub fn is_nil(&self) -> bool { + pub fn is_unit(&self) -> bool { match self.sty { - TyTuple(ref tys) => tys.is_empty(), + Tuple(ref tys) => tys.is_empty(), _ => false, } } pub fn is_never(&self) -> bool { match self.sty { - TyNever => true, + Never => true, _ => false, } } pub fn is_primitive(&self) -> bool { match self.sty { - TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true, + Bool | Char | Int(_) | Uint(_) | Float(_) => true, _ => false, } } pub fn is_ty_var(&self) -> bool { match self.sty { - TyInfer(TyVar(_)) => true, + Infer(TyVar(_)) => true, _ => false, } } pub fn is_ty_infer(&self) -> bool { match self.sty { - TyInfer(_) => true, + Infer(_) => true, _ => false, } } pub fn is_phantom_data(&self) -> bool { - if let TyAdt(def, _) = self.sty { + if let Adt(def, _) = self.sty { def.is_phantom_data() } else { false } } - pub fn is_bool(&self) -> bool { self.sty == TyBool } + pub fn is_bool(&self) -> bool { self.sty == Bool } pub fn is_param(&self, index: u32) -> bool { match self.sty { - ty::TyParam(ref data) => data.idx == index, + ty::Param(ref data) => data.idx == index, _ => false, } } pub fn is_self(&self) -> bool { match self.sty { - TyParam(ref p) => p.is_self(), + Param(ref p) => p.is_self(), _ => false, } } pub fn is_slice(&self) -> bool { match self.sty { - TyRawPtr(TypeAndMut { ty, .. }) | TyRef(_, ty, _) => match ty.sty { - TySlice(_) | TyStr => true, + RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.sty { + Slice(_) | Str => true, _ => false, }, _ => false @@ -1539,22 +1530,22 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { #[inline] pub fn is_simd(&self) -> bool { match self.sty { - TyAdt(def, _) => def.repr.simd(), + Adt(def, _) => def.repr.simd(), _ => false, } } pub fn sequence_element_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { match self.sty { - TyArray(ty, _) | TySlice(ty) => ty, - TyStr => tcx.mk_mach_uint(ast::UintTy::U8), + Array(ty, _) | Slice(ty) => ty, + Str => tcx.mk_mach_uint(ast::UintTy::U8), _ => bug!("sequence_element_type called on non-sequence value: {}", self), } } pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { match self.sty { - TyAdt(def, substs) => { + Adt(def, substs) => { def.non_enum_variant().fields[0].ty(tcx, substs) } _ => bug!("simd_type called on invalid type") @@ -1563,36 +1554,36 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn simd_size(&self, _cx: TyCtxt) -> usize { match self.sty { - TyAdt(def, _) => def.non_enum_variant().fields.len(), + Adt(def, _) => def.non_enum_variant().fields.len(), _ => bug!("simd_size called on invalid type") } } pub fn is_region_ptr(&self) -> bool { match self.sty { - TyRef(..) => true, + Ref(..) => true, _ => false, } } pub fn is_mutable_pointer(&self) -> bool { match self.sty { - TyRawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) | - TyRef(_, _, hir::Mutability::MutMutable) => true, + RawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) | + Ref(_, _, hir::Mutability::MutMutable) => true, _ => false } } pub fn is_unsafe_ptr(&self) -> bool { match self.sty { - TyRawPtr(_) => return true, + RawPtr(_) => return true, _ => return false, } } pub fn is_box(&self) -> bool { match self.sty { - TyAdt(def, _) => def.is_box(), + Adt(def, _) => def.is_box(), _ => false, } } @@ -1600,19 +1591,19 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// panics if called on any type other than `Box` pub fn boxed_ty(&self) -> Ty<'tcx> { match self.sty { - TyAdt(def, substs) if def.is_box() => substs.type_at(0), + Adt(def, substs) if def.is_box() => substs.type_at(0), _ => bug!("`boxed_ty` is called on non-box type {:?}", self), } } /// A scalar type is one that denotes an atomic datum, with no sub-components. - /// (A TyRawPtr is scalar because it represents a non-managed pointer, so its + /// (A RawPtr is scalar because it represents a non-managed pointer, so its /// contents are abstract to rustc.) pub fn is_scalar(&self) -> bool { match self.sty { - TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) | - TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) | - TyFnDef(..) | TyFnPtr(_) | TyRawPtr(_) => true, + Bool | Char | Int(_) | Float(_) | Uint(_) | + Infer(IntVar(_)) | Infer(FloatVar(_)) | + FnDef(..) | FnPtr(_) | RawPtr(_) => true, _ => false } } @@ -1620,22 +1611,22 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// Returns true if this type is a floating point type and false otherwise. pub fn is_floating_point(&self) -> bool { match self.sty { - TyFloat(_) | - TyInfer(FloatVar(_)) => true, + Float(_) | + Infer(FloatVar(_)) => true, _ => false, } } pub fn is_trait(&self) -> bool { match self.sty { - TyDynamic(..) => true, + Dynamic(..) => true, _ => false, } } pub fn is_enum(&self) -> bool { match self.sty { - TyAdt(adt_def, _) => { + Adt(adt_def, _) => { adt_def.is_enum() } _ => false, @@ -1644,51 +1635,51 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_closure(&self) -> bool { match self.sty { - TyClosure(..) => true, + Closure(..) => true, _ => false, } } pub fn is_generator(&self) -> bool { match self.sty { - TyGenerator(..) => true, + Generator(..) => true, _ => false, } } pub fn is_integral(&self) -> bool { match self.sty { - TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true, + Infer(IntVar(_)) | Int(_) | Uint(_) => true, _ => false } } pub fn is_fresh_ty(&self) -> bool { match self.sty { - TyInfer(FreshTy(_)) => true, + Infer(FreshTy(_)) => true, _ => false, } } pub fn is_fresh(&self) -> bool { match self.sty { - TyInfer(FreshTy(_)) => true, - TyInfer(FreshIntTy(_)) => true, - TyInfer(FreshFloatTy(_)) => true, + Infer(FreshTy(_)) => true, + Infer(FreshIntTy(_)) => true, + Infer(FreshFloatTy(_)) => true, _ => false, } } pub fn is_char(&self) -> bool { match self.sty { - TyChar => true, + Char => true, _ => false, } } pub fn is_fp(&self) -> bool { match self.sty { - TyInfer(FloatVar(_)) | TyFloat(_) => true, + Infer(FloatVar(_)) | Float(_) => true, _ => false } } @@ -1699,22 +1690,22 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_signed(&self) -> bool { match self.sty { - TyInt(_) => true, + Int(_) => true, _ => false, } } pub fn is_machine(&self) -> bool { match self.sty { - TyInt(ast::IntTy::Isize) | TyUint(ast::UintTy::Usize) => false, - TyInt(..) | TyUint(..) | TyFloat(..) => true, + Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => false, + Int(..) | Uint(..) | Float(..) => true, _ => false, } } pub fn has_concrete_skeleton(&self) -> bool { match self.sty { - TyParam(_) | TyInfer(_) | TyError => false, + Param(_) | Infer(_) | Error => false, _ => true, } } @@ -1725,14 +1716,14 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// Some types---notably unsafe ptrs---can only be dereferenced explicitly. pub fn builtin_deref(&self, explicit: bool) -> Option> { match self.sty { - TyAdt(def, _) if def.is_box() => { + Adt(def, _) if def.is_box() => { Some(TypeAndMut { ty: self.boxed_ty(), mutbl: hir::MutImmutable, }) }, - TyRef(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl }), - TyRawPtr(mt) if explicit => Some(mt), + Ref(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl }), + RawPtr(mt) if explicit => Some(mt), _ => None, } } @@ -1740,38 +1731,38 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// Returns the type of `ty[i]`. pub fn builtin_index(&self) -> Option> { match self.sty { - TyArray(ty, _) | TySlice(ty) => Some(ty), + Array(ty, _) | Slice(ty) => Some(ty), _ => None, } } pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> { match self.sty { - TyFnDef(def_id, substs) => { + FnDef(def_id, substs) => { tcx.fn_sig(def_id).subst(tcx, substs) } - TyFnPtr(f) => f, + FnPtr(f) => f, _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) } } pub fn is_fn(&self) -> bool { match self.sty { - TyFnDef(..) | TyFnPtr(_) => true, + FnDef(..) | FnPtr(_) => true, _ => false, } } pub fn is_impl_trait(&self) -> bool { match self.sty { - TyAnon(..) => true, + Opaque(..) => true, _ => false, } } pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> { match self.sty { - TyAdt(adt, _) => Some(adt), + Adt(adt, _) => Some(adt), _ => None, } } @@ -1781,44 +1772,44 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// ignores late-bound regions binders. pub fn regions(&self) -> Vec> { match self.sty { - TyRef(region, _, _) => { + Ref(region, _, _) => { vec![region] } - TyDynamic(ref obj, region) => { + Dynamic(ref obj, region) => { let mut v = vec![region]; if let Some(p) = obj.principal() { v.extend(p.skip_binder().substs.regions()); } v } - TyAdt(_, substs) | TyAnon(_, substs) => { + Adt(_, substs) | Opaque(_, substs) => { substs.regions().collect() } - TyClosure(_, ClosureSubsts { ref substs }) | - TyGenerator(_, GeneratorSubsts { ref substs }, _) => { + Closure(_, ClosureSubsts { ref substs }) | + Generator(_, GeneratorSubsts { ref substs }, _) => { substs.regions().collect() } - TyProjection(ref data) => { + Projection(ref data) => { data.substs.regions().collect() } - TyFnDef(..) | - TyFnPtr(_) | - TyGeneratorWitness(..) | - TyBool | - TyChar | - TyInt(_) | - TyUint(_) | - TyFloat(_) | - TyStr | - TyArray(..) | - TySlice(_) | - TyRawPtr(_) | - TyNever | - TyTuple(..) | - TyForeign(..) | - TyParam(_) | - TyInfer(_) | - TyError => { + FnDef(..) | + FnPtr(_) | + GeneratorWitness(..) | + Bool | + Char | + Int(_) | + Uint(_) | + Float(_) | + Str | + Array(..) | + Slice(_) | + RawPtr(_) | + Never | + Tuple(..) | + Foreign(..) | + Param(_) | + Infer(_) | + Error => { vec![] } } @@ -1838,20 +1829,55 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// is complete, that type variable will be unified. pub fn to_opt_closure_kind(&self) -> Option { match self.sty { - TyInt(int_ty) => match int_ty { + Int(int_ty) => match int_ty { ast::IntTy::I8 => Some(ty::ClosureKind::Fn), ast::IntTy::I16 => Some(ty::ClosureKind::FnMut), ast::IntTy::I32 => Some(ty::ClosureKind::FnOnce), _ => bug!("cannot convert type `{:?}` to a closure kind", self), }, - TyInfer(_) => None, + Infer(_) => None, - TyError => Some(ty::ClosureKind::Fn), + Error => Some(ty::ClosureKind::Fn), _ => bug!("cannot convert type `{:?}` to a closure kind", self), } } + + /// Fast path helper for testing if a type is `Sized`. + /// + /// Returning true means the type is known to be sized. Returning + /// `false` means nothing -- could be sized, might not be. + pub fn is_trivially_sized(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> bool { + match self.sty { + ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | + ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | + ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) | + ty::Char | ty::Ref(..) | ty::Generator(..) | + ty::GeneratorWitness(..) | ty::Array(..) | ty::Closure(..) | + ty::Never | ty::Error => + true, + + ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => + false, + + ty::Tuple(tys) => + tys.iter().all(|ty| ty.is_trivially_sized(tcx)), + + ty::Adt(def, _substs) => + def.sized_constraint(tcx).is_empty(), + + ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false, + + ty::Infer(ty::TyVar(_)) => false, + + ty::Infer(ty::CanonicalTy(_)) | + ty::Infer(ty::FreshTy(_)) | + ty::Infer(ty::FreshIntTy(_)) | + ty::Infer(ty::FreshFloatTy(_)) => + bug!("is_trivially_sized applied to unexpected type: {:?}", self), + } + } } /// Typed constant value. @@ -1887,22 +1913,13 @@ impl<'tcx> Const<'tcx> { }) } - #[inline] - pub fn from_byval_value( - tcx: TyCtxt<'_, '_, 'tcx>, - val: Value, - ty: Ty<'tcx>, - ) -> &'tcx Self { - Self::from_const_value(tcx, ConstValue::from_byval_value(val), ty) - } - #[inline] pub fn from_scalar( tcx: TyCtxt<'_, '_, 'tcx>, val: Scalar, ty: Ty<'tcx>, ) -> &'tcx Self { - Self::from_const_value(tcx, ConstValue::from_scalar(val), ty) + Self::from_const_value(tcx, ConstValue::Scalar(val), ty) } #[inline] @@ -1918,12 +1935,12 @@ impl<'tcx> Const<'tcx> { let shift = 128 - size.bits(); let truncated = (bits << shift) >> shift; assert_eq!(truncated, bits, "from_bits called with untruncated value"); - Self::from_scalar(tcx, Scalar::Bits { bits, defined: size.bits() as u8 }, ty.value) + Self::from_scalar(tcx, Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value) } #[inline] pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self { - Self::from_scalar(tcx, Scalar::undef(), ty) + Self::from_scalar(tcx, Scalar::Bits { bits: 0, size: 0 }, ty) } #[inline] @@ -1947,22 +1964,12 @@ impl<'tcx> Const<'tcx> { } let ty = tcx.lift_to_global(&ty).unwrap(); let size = tcx.layout_of(ty).ok()?.size; - self.val.to_bits(size) + self.val.try_to_bits(size) } #[inline] pub fn to_ptr(&self) -> Option { - self.val.to_ptr() - } - - #[inline] - pub fn to_byval_value(&self) -> Option { - self.val.to_byval_value() - } - - #[inline] - pub fn to_scalar(&self) -> Option { - self.val.to_scalar() + self.val.try_to_ptr() } #[inline] @@ -1974,7 +1981,7 @@ impl<'tcx> Const<'tcx> { assert_eq!(self.ty, ty.value); let ty = tcx.lift_to_global(&ty).unwrap(); let size = tcx.layout_of(ty).ok()?.size; - self.val.to_bits(size) + self.val.try_to_bits(size) } #[inline] diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 2e3c6df975..696c4d0043 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -11,13 +11,14 @@ // Type substitutions. use hir::def_id::DefId; -use ty::{self, Lift, Slice, Ty, TyCtxt}; +use infer::canonical::Canonical; +use ty::{self, CanonicalVar, Lift, List, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use serialize::{self, Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; -use rustc_data_structures::accumulate_vec::AccumulateVec; -use rustc_data_structures::array_vec::ArrayVec; +use rustc_data_structures::indexed_vec::Idx; +use smallvec::SmallVec; use core::intrinsics; use std::cmp::Ordering; @@ -41,7 +42,7 @@ const TAG_MASK: usize = 0b11; const TYPE_TAG: usize = 0b00; const REGION_TAG: usize = 0b01; -#[derive(Debug, RustcEncodable, RustcDecodable)] +#[derive(Debug, RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord)] pub enum UnpackedKind<'tcx> { Lifetime(ty::Region<'tcx>), Type(Ty<'tcx>), @@ -73,17 +74,7 @@ impl<'tcx> UnpackedKind<'tcx> { impl<'tcx> Ord for Kind<'tcx> { fn cmp(&self, other: &Kind) -> Ordering { - match (self.unpack(), other.unpack()) { - (UnpackedKind::Type(_), UnpackedKind::Lifetime(_)) => Ordering::Greater, - - (UnpackedKind::Type(ty1), UnpackedKind::Type(ty2)) => { - ty1.sty.cmp(&ty2.sty) - } - - (UnpackedKind::Lifetime(reg1), UnpackedKind::Lifetime(reg2)) => reg1.cmp(reg2), - - (UnpackedKind::Lifetime(_), UnpackedKind::Type(_)) => Ordering::Less, - } + self.unpack().cmp(&other.unpack()) } } @@ -177,7 +168,7 @@ impl<'tcx> Decodable for Kind<'tcx> { } /// A substitution mapping generic parameters to new values. -pub type Substs<'tcx> = Slice>; +pub type Substs<'tcx> = List>; impl<'a, 'gcx, 'tcx> Substs<'tcx> { /// Creates a Substs that maps each generic parameter to itself. @@ -201,11 +192,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { { let defs = tcx.generics_of(def_id); let count = defs.count(); - let mut substs = if count <= 8 { - AccumulateVec::Array(ArrayVec::new()) - } else { - AccumulateVec::Heap(Vec::with_capacity(count)) - }; + let mut substs = SmallVec::with_capacity(count); Substs::fill_item(&mut substs, tcx, defs, &mut mk_kind); tcx.intern_substs(&substs) } @@ -225,13 +212,12 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { }) } - fn fill_item(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, + fn fill_item(substs: &mut SmallVec<[Kind<'tcx>; 8]>, tcx: TyCtxt<'a, 'gcx, 'tcx>, defs: &ty::Generics, mk_kind: &mut F) where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx> { - if let Some(def_id) = defs.parent { let parent_defs = tcx.generics_of(def_id); Substs::fill_item(substs, tcx, parent_defs, mk_kind); @@ -239,7 +225,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { Substs::fill_single(substs, defs, mk_kind) } - fn fill_single(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, + fn fill_single(substs: &mut SmallVec<[Kind<'tcx>; 8]>, defs: &ty::Generics, mk_kind: &mut F) where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx> @@ -247,10 +233,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { for param in &defs.params { let kind = mk_kind(param, substs); assert_eq!(param.index as usize, substs.len()); - match *substs { - AccumulateVec::Array(ref mut arr) => arr.push(kind), - AccumulateVec::Heap(ref mut vec) => vec.push(kind), - } + substs.push(kind); } } @@ -324,7 +307,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let params: AccumulateVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); + let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); // If folding doesn't change the substs, it's faster to avoid // calling `mk_substs` and instead reuse the existing substs. @@ -340,6 +323,33 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { } } +pub type CanonicalSubsts<'gcx> = Canonical<'gcx, &'gcx Substs<'gcx>>; + +impl<'gcx> CanonicalSubsts<'gcx> { + /// True if this represents a substitution like + /// + /// ```text + /// [?0, ?1, ?2] + /// ``` + /// + /// i.e., each thing is mapped to a canonical variable with the same index. + pub fn is_identity(&self) -> bool { + self.value.iter().zip(CanonicalVar::new(0)..).all(|(kind, cvar)| { + match kind.unpack() { + UnpackedKind::Type(ty) => match ty.sty { + ty::Infer(ty::CanonicalTy(cvar1)) => cvar == cvar1, + _ => false, + }, + + UnpackedKind::Lifetime(r) => match r { + ty::ReCanonical(cvar1) => cvar == *cvar1, + _ => false, + }, + } + }) + } +} + impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {} /////////////////////////////////////////////////////////////////////////// @@ -450,7 +460,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { self.ty_stack_depth += 1; let t1 = match t.sty { - ty::TyParam(p) => { + ty::Param(p) => { self.ty_for_param(p, t) } _ => { diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 32f0d3384c..6332080a18 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -41,6 +41,7 @@ pub struct TraitDef { pub def_path_hash: DefPathHash, } +#[derive(Default)] pub struct TraitImpls { blanket_impls: Vec, /// Impls indexed by their simplified self-type, for fast lookup. @@ -143,47 +144,43 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_id: DefId) -> Lrc { - let mut remote_impls = Vec::new(); - - // Traits defined in the current crate can't have impls in upstream - // crates, so we don't bother querying the cstore. - if !trait_id.is_local() { - for &cnum in tcx.crates().iter() { - let impls = tcx.implementations_of_trait((cnum, trait_id)); - remote_impls.extend(impls.iter().cloned()); - } - } - - let mut blanket_impls = Vec::new(); - let mut non_blanket_impls = FxHashMap(); + let mut impls = TraitImpls::default(); - let local_impls = tcx.hir - .trait_impls(trait_id) - .into_iter() - .map(|&node_id| tcx.hir.local_def_id(node_id)); + { + let mut add_impl = |impl_def_id| { + let impl_self_ty = tcx.type_of(impl_def_id); + if impl_def_id.is_local() && impl_self_ty.references_error() { + return; + } - for impl_def_id in local_impls.chain(remote_impls.into_iter()) { - let impl_self_ty = tcx.type_of(impl_def_id); - if impl_def_id.is_local() && impl_self_ty.references_error() { - continue + if let Some(simplified_self_ty) = + fast_reject::simplify_type(tcx, impl_self_ty, false) + { + impls.non_blanket_impls + .entry(simplified_self_ty) + .or_default() + .push(impl_def_id); + } else { + impls.blanket_impls.push(impl_def_id); + } + }; + + // Traits defined in the current crate can't have impls in upstream + // crates, so we don't bother querying the cstore. + if !trait_id.is_local() { + for &cnum in tcx.crates().iter() { + for &def_id in tcx.implementations_of_trait((cnum, trait_id)).iter() { + add_impl(def_id); + } + } } - if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, impl_self_ty, false) - { - non_blanket_impls - .entry(simplified_self_ty) - .or_insert(vec![]) - .push(impl_def_id); - } else { - blanket_impls.push(impl_def_id); + for &node_id in tcx.hir.trait_impls(trait_id) { + add_impl(tcx.hir.local_def_id(node_id)); } } - Lrc::new(TraitImpls { - blanket_impls: blanket_impls, - non_blanket_impls: non_blanket_impls, - }) + Lrc::new(impls) } impl<'a> HashStable> for TraitImpls { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 95caa0c185..cc0429de2f 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -12,14 +12,14 @@ use hir::def::Def; use hir::def_id::DefId; -use hir::map::{DefPathData, Node}; -use hir; +use hir::map::DefPathData; +use hir::{self, Node}; use ich::NodeIdHashingMode; use traits::{self, ObligationCause}; use ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; use ty::subst::{Substs, UnpackedKind}; use ty::query::TyCtxtAt; -use ty::TypeVariants::*; +use ty::TyKind::*; use ty::layout::{Integer, IntegerExt}; use util::common::ErrorReported; use middle::lang_items; @@ -41,7 +41,7 @@ pub struct Discr<'tcx> { impl<'tcx> fmt::Display for Discr<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self.ty.sty { - ty::TyInt(ity) => { + ty::Int(ity) => { let bits = ty::tls::with(|tcx| { Integer::from_attr(tcx, SignedInt(ity)).size().bits() }); @@ -62,8 +62,8 @@ impl<'tcx> Discr<'tcx> { } pub fn checked_add<'a, 'gcx>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, n: u128) -> (Self, bool) { let (int, signed) = match self.ty.sty { - TyInt(ity) => (Integer::from_attr(tcx, SignedInt(ity)), true), - TyUint(uty) => (Integer::from_attr(tcx, UnsignedInt(uty)), false), + Int(ity) => (Integer::from_attr(tcx, SignedInt(ity)), true), + Uint(uty) => (Integer::from_attr(tcx, UnsignedInt(uty)), false), _ => bug!("non integer discriminant"), }; @@ -193,11 +193,11 @@ impl<'tcx> ty::ParamEnv<'tcx> { let (adt, substs) = match self_type.sty { // These types used to have a builtin impl. // Now libcore provides that impl. - ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | - ty::TyChar | ty::TyRawPtr(..) | ty::TyNever | - ty::TyRef(_, _, hir::MutImmutable) => return Ok(()), + ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | + ty::Char | ty::RawPtr(..) | ty::Never | + ty::Ref(_, _, hir::MutImmutable) => return Ok(()), - ty::TyAdt(adt, substs) => (adt, substs), + ty::Adt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt), }; @@ -258,10 +258,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn has_error_field(self, ty: Ty<'tcx>) -> bool { match ty.sty { - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { for field in def.all_fields() { let field_ty = field.ty(self, substs); - if let TyError = field_ty.sty { + if let Error = field_ty.sty { return true; } } @@ -277,7 +277,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn struct_tail(self, mut ty: Ty<'tcx>) -> Ty<'tcx> { loop { match ty.sty { - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { if !def.is_struct() { break; } @@ -287,7 +287,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - ty::TyTuple(tys) => { + ty::Tuple(tys) => { if let Some((&last_ty, _)) = tys.split_last() { ty = last_ty; } else { @@ -315,7 +315,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let (mut a, mut b) = (source, target); loop { match (&a.sty, &b.sty) { - (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) + (&Adt(a_def, a_substs), &Adt(b_def, b_substs)) if a_def == b_def && a_def.is_struct() => { if let Some(f) = a_def.non_enum_variant().fields.last() { a = f.ty(self, a_substs); @@ -324,7 +324,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { break; } }, - (&TyTuple(a_tys), &TyTuple(b_tys)) + (&Tuple(a_tys), &Tuple(b_tys)) if a_tys.len() == b_tys.len() => { if let Some(a_last) = a_tys.last() { a = a_last; @@ -487,12 +487,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // parameters marked as pure. let impl_substs = match self.type_of(impl_def_id).sty { - ty::TyAdt(def_, substs) if def_ == def => substs, + ty::Adt(def_, substs) if def_ == def => substs, _ => bug!() }; let item_substs = match self.type_of(def.did).sty { - ty::TyAdt(def_, substs) if def_ == def => substs, + ty::Adt(def_, substs) if def_ == def => substs, _ => bug!() }; @@ -503,7 +503,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { !impl_generics.region_param(ebr, self).pure_wrt_drop } UnpackedKind::Type(&ty::TyS { - sty: ty::TypeVariants::TyParam(ref pt), .. + sty: ty::Param(ref pt), .. }) => { !impl_generics.type_param(pt, self).pure_wrt_drop } @@ -604,10 +604,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn is_static(&self, def_id: DefId) -> Option { if let Some(node) = self.hir.get_if_local(def_id) { match node { - Node::NodeItem(&hir::Item { + Node::Item(&hir::Item { node: hir::ItemKind::Static(_, mutbl, _), .. }) => Some(mutbl), - Node::NodeForeignItem(&hir::ForeignItem { + Node::ForeignItem(&hir::ForeignItem { node: hir::ForeignItemKind::Static(_, is_mutbl), .. }) => Some(if is_mutbl { @@ -697,7 +697,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { -> Representability { match ty.sty { - TyTuple(ref ts) => { + Tuple(ref ts) => { // Find non representable fold_repr(ts.iter().map(|ty| { is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) @@ -705,10 +705,10 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } // Fixed-length vectors. // FIXME(#11924) Behavior undecided for zero-length vectors. - TyArray(ty, _) => { + Array(ty, _) => { is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty) } - TyAdt(def, substs) => { + Adt(def, substs) => { // Find non representable fields with their spans fold_repr(def.all_fields().map(|field| { let ty = field.ty(tcx, substs); @@ -723,7 +723,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } })) } - TyClosure(..) => { + Closure(..) => { // this check is run on type definitions, so we don't expect // to see closure types bug!("requires check invoked on inapplicable type: {:?}", ty) @@ -734,7 +734,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool { match ty.sty { - TyAdt(ty_def, _) => { + Adt(ty_def, _) => { ty_def == def } _ => false @@ -743,7 +743,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { match (&a.sty, &b.sty) { - (&TyAdt(did_a, substs_a), &TyAdt(did_b, substs_b)) => { + (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => { if did_a != did_b { return false; } @@ -785,7 +785,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { ty: Ty<'tcx>) -> Representability { match ty.sty { - TyAdt(def, _) => { + Adt(def, _) => { { // Iterate through stack of previously seen types. let mut iter = seen.iter(); @@ -924,16 +924,16 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match ty.sty { // Fast-path for primitive types - ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) | - ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever | - ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar | ty::TyGeneratorWitness(..) | - ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false, + ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) | + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Never | + ty::FnDef(..) | ty::FnPtr(_) | ty::Char | ty::GeneratorWitness(..) | + ty::RawPtr(_) | ty::Ref(..) | ty::Str => false, // Foreign types can never have destructors - ty::TyForeign(..) => false, + ty::Foreign(..) => false, // `ManuallyDrop` doesn't have a destructor regardless of field types. - ty::TyAdt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false, + ty::Adt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false, // Issue #22536: We first query type_moves_by_default. It sees a // normalized version of the type, and therefore will definitely @@ -951,30 +951,30 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // (see above), it is sound to treat it as having a destructor. // User destructors are the only way to have concrete drop types. - ty::TyAdt(def, _) if def.has_dtor(tcx) => true, + ty::Adt(def, _) if def.has_dtor(tcx) => true, // Can refer to a type which may drop. // FIXME(eddyb) check this against a ParamEnv. - ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) | - ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true, + ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | + ty::Opaque(..) | ty::Infer(_) | ty::Error => true, // Structural recursion. - ty::TyArray(ty, _) | ty::TySlice(ty) => needs_drop(ty), + ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty), - ty::TyClosure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop), + ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop), // Pessimistically assume that all generators will require destructors // as we don't know if a destructor is a noop or not until after the MIR // state transformation pass - ty::TyGenerator(..) => true, + ty::Generator(..) => true, - ty::TyTuple(ref tys) => tys.iter().cloned().any(needs_drop), + ty::Tuple(ref tys) => tys.iter().cloned().any(needs_drop), // unions don't have destructors because of the child types, // only if they manually implement `Drop` (handled above). - ty::TyAdt(def, _) if def.is_union() => false, + ty::Adt(def, _) if def.is_union() => false, - ty::TyAdt(def, substs) => + ty::Adt(def, substs) => def.variants.iter().any( |variant| variant.fields.iter().any( |field| needs_drop(field.ty(tcx, substs)))), @@ -1025,13 +1025,13 @@ impl<'tcx> ExplicitSelf<'tcx> { match self_arg_ty.sty { _ if is_self_ty(self_arg_ty) => ByValue, - ty::TyRef(region, ty, mutbl) if is_self_ty(ty) => { + ty::Ref(region, ty, mutbl) if is_self_ty(ty) => { ByReference(region, mutbl) } - ty::TyRawPtr(ty::TypeAndMut { ty, mutbl }) if is_self_ty(ty) => { + ty::RawPtr(ty::TypeAndMut { ty, mutbl }) if is_self_ty(ty) => { ByRawPointer(mutbl) } - ty::TyAdt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => { + ty::Adt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => { ByBox } _ => Other diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index d12f731442..cf87c2d457 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -13,8 +13,7 @@ use mir::interpret::ConstValue; use ty::{self, Ty}; -use rustc_data_structures::small_vec::SmallVec; -use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; +use smallvec::{self, SmallVec}; // The TypeWalker's stack is hot enough that it's worth going to some effort to // avoid heap allocations. @@ -28,7 +27,7 @@ pub struct TypeWalker<'tcx> { impl<'tcx> TypeWalker<'tcx> { pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> { - TypeWalker { stack: SmallVec::one(ty), last_subtree: 1, } + TypeWalker { stack: smallvec![ty], last_subtree: 1, } } /// Skips the subtree of types corresponding to the last type @@ -67,7 +66,7 @@ impl<'tcx> Iterator for TypeWalker<'tcx> { } } -pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter> { +pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> smallvec::IntoIter> { let mut stack = SmallVec::new(); push_subtypes(&mut stack, ty); stack.into_iter() @@ -81,27 +80,27 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter> { // types as they are written). fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { match parent_ty.sty { - ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | - ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError | - ty::TyForeign(..) => { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | + ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error | + ty::Foreign(..) => { } - ty::TyArray(ty, len) => { + ty::Array(ty, len) => { push_const(stack, len); stack.push(ty); } - ty::TySlice(ty) => { + ty::Slice(ty) => { stack.push(ty); } - ty::TyRawPtr(ref mt) => { + ty::RawPtr(ref mt) => { stack.push(mt.ty); } - ty::TyRef(_, ty, _) => { + ty::Ref(_, ty, _) => { stack.push(ty); } - ty::TyProjection(ref data) => { + ty::Projection(ref data) => { stack.extend(data.substs.types().rev()); } - ty::TyDynamic(ref obj, ..) => { + ty::Dynamic(ref obj, ..) => { stack.extend(obj.iter().rev().flat_map(|predicate| { let (substs, opt_ty) = match *predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), @@ -115,25 +114,25 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { substs.types().rev().chain(opt_ty) })); } - ty::TyAdt(_, substs) | ty::TyAnon(_, substs) => { + ty::Adt(_, substs) | ty::Opaque(_, substs) => { stack.extend(substs.types().rev()); } - ty::TyClosure(_, ref substs) => { + ty::Closure(_, ref substs) => { stack.extend(substs.substs.types().rev()); } - ty::TyGenerator(_, ref substs, _) => { + ty::Generator(_, ref substs, _) => { stack.extend(substs.substs.types().rev()); } - ty::TyGeneratorWitness(ts) => { + ty::GeneratorWitness(ts) => { stack.extend(ts.skip_binder().iter().cloned().rev()); } - ty::TyTuple(ts) => { + ty::Tuple(ts) => { stack.extend(ts.iter().cloned().rev()); } - ty::TyFnDef(_, substs) => { + ty::FnDef(_, substs) => { stack.extend(substs.types().rev()); } - ty::TyFnPtr(sig) => { + ty::FnPtr(sig) => { stack.push(sig.skip_binder().output()); stack.extend(sig.skip_binder().inputs().iter().cloned().rev()); } diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index b99cdd5977..63206a660d 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -248,31 +248,31 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let param_env = self.param_env; while let Some(ty) = subtys.next() { match ty.sty { - ty::TyBool | - ty::TyChar | - ty::TyInt(..) | - ty::TyUint(..) | - ty::TyFloat(..) | - ty::TyError | - ty::TyStr | - ty::TyGeneratorWitness(..) | - ty::TyNever | - ty::TyParam(_) | - ty::TyForeign(..) => { + ty::Bool | + ty::Char | + ty::Int(..) | + ty::Uint(..) | + ty::Float(..) | + ty::Error | + ty::Str | + ty::GeneratorWitness(..) | + ty::Never | + ty::Param(_) | + ty::Foreign(..) => { // WfScalar, WfParameter, etc } - ty::TySlice(subty) => { + ty::Slice(subty) => { self.require_sized(subty, traits::SliceOrArrayElem); } - ty::TyArray(subty, len) => { + ty::Array(subty, len) => { self.require_sized(subty, traits::SliceOrArrayElem); assert_eq!(len.ty, self.infcx.tcx.types.usize); self.compute_const(len); } - ty::TyTuple(ref tys) => { + ty::Tuple(ref tys) => { if let Some((_last, rest)) = tys.split_last() { for elem in rest { self.require_sized(elem, traits::TupleElem); @@ -280,22 +280,22 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } } - ty::TyRawPtr(_) => { + ty::RawPtr(_) => { // simple cases that are WF if their type args are WF } - ty::TyProjection(data) => { + ty::Projection(data) => { subtys.skip_current_subtree(); // subtree handled by compute_projection self.compute_projection(data); } - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { // WfNominalType let obligations = self.nominal_obligations(def.did, substs); self.out.extend(obligations); } - ty::TyRef(r, rty, _) => { + ty::Ref(r, rty, _) => { // WfReference if !r.has_escaping_regions() && !rty.has_escaping_regions() { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); @@ -309,7 +309,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } } - ty::TyGenerator(..) => { + ty::Generator(..) => { // Walk ALL the types in the generator: this will // include the upvar types as well as the yield // type. Note that this is mildly distinct from @@ -319,7 +319,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // generators don't take arguments. } - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { // Only check the upvar types for WF, not the rest // of the types within. This is needed because we // capture the signature and it may not be WF @@ -355,12 +355,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } } - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { // let the loop iterate into the argument/return // types appearing in the fn signature } - ty::TyAnon(did, substs) => { + ty::Opaque(did, substs) => { // all of the requirements on type parameters // should've been checked by the instantiation // of whatever returned this exact `impl Trait`. @@ -372,7 +372,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } } - ty::TyDynamic(data, r) => { + ty::Dynamic(data, r) => { // WfObject // // Here, we defer WF checking due to higher-ranked @@ -408,9 +408,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // register a pending obligation and keep // moving. (Goal is that an "inductive hypothesis" // is satisfied to ensure termination.) - ty::TyInfer(_) => { + ty::Infer(_) => { let ty = self.infcx.shallow_resolve(ty); - if let ty::TyInfer(_) = ty.sty { // not yet resolved... + if let ty::Infer(_) = ty.sty { // not yet resolved... if ty == ty0 { // ...this is the type we started from! no progress. return false; } @@ -423,7 +423,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } else { // Yes, resolved, proceed with the // result. Should never return false because - // `ty` is not a TyInfer. + // `ty` is not a Infer. assert!(self.compute(ty)); } } @@ -453,7 +453,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } fn from_object_ty(&mut self, ty: Ty<'tcx>, - data: ty::Binder<&'tcx ty::Slice>>, + data: ty::Binder<&'tcx ty::List>>, region: ty::Region<'tcx>) { // Imagine a type like this: // @@ -513,7 +513,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// `ty::required_region_bounds`, see that for more information. pub fn object_region_bounds<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - existential_predicates: ty::Binder<&'tcx ty::Slice>>) + existential_predicates: ty::Binder<&'tcx ty::List>>) -> Vec> { // Since we don't actually *know* the self type for an object, diff --git a/src/librustc/util/bug.rs b/src/librustc/util/bug.rs new file mode 100644 index 0000000000..f2593e4d4b --- /dev/null +++ b/src/librustc/util/bug.rs @@ -0,0 +1,51 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// These functions are used by macro expansion for bug! and span_bug! + +use ty::tls; +use std::fmt; +use syntax_pos::{Span, MultiSpan}; + +#[cold] +#[inline(never)] +pub fn bug_fmt(file: &'static str, line: u32, args: fmt::Arguments) -> ! { + // this wrapper mostly exists so I don't have to write a fully + // qualified path of None:: inside the bug!() macro definition + opt_span_bug_fmt(file, line, None::, args); +} + +#[cold] +#[inline(never)] +pub fn span_bug_fmt>( + file: &'static str, + line: u32, + span: S, + args: fmt::Arguments, +) -> ! { + opt_span_bug_fmt(file, line, Some(span), args); +} + +fn opt_span_bug_fmt>( + file: &'static str, + line: u32, + span: Option, + args: fmt::Arguments, +) -> ! { + tls::with_opt(move |tcx| { + let msg = format!("{}:{}: {}", file, line, args); + match (tcx, span) { + (Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg), + (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg), + (None, _) => panic!(msg), + } + }); + unreachable!(); +} diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 990fbc4bc9..02bdc5f41b 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -14,12 +14,10 @@ use rustc_data_structures::sync::Lock; use std::cell::{RefCell, Cell}; use std::collections::HashMap; -use std::ffi::CString; use std::fmt::Debug; use std::hash::{Hash, BuildHasher}; use std::panic; use std::env; -use std::path::Path; use std::time::{Duration, Instant}; use std::sync::mpsc::{Sender}; @@ -86,7 +84,7 @@ pub struct ProfQDumpParams { pub dump_profq_msg_log:bool, } -#[allow(bad_style)] +#[allow(nonstandard_style)] #[derive(Clone, Debug, PartialEq, Eq)] pub struct QueryMsg { pub query: &'static str, @@ -215,7 +213,7 @@ fn print_time_passes_entry_internal(what: &str, dur: Duration) { let mb = n as f64 / 1_000_000.0; format!("; rss: {}MB", mb.round() as usize) } - None => "".to_owned(), + None => String::new(), }; println!("{}time: {}{}\t{}", " ".repeat(indentation), @@ -376,19 +374,6 @@ impl MemoizationMap for RefCell> } } -#[cfg(unix)] -pub fn path2cstr(p: &Path) -> CString { - use std::os::unix::prelude::*; - use std::ffi::OsStr; - let p: &OsStr = p.as_ref(); - CString::new(p.as_bytes()).unwrap() -} -#[cfg(windows)] -pub fn path2cstr(p: &Path) -> CString { - CString::new(p.to_str().unwrap()).unwrap() -} - - #[test] fn test_to_readable_str() { assert_eq!("0", to_readable_str(0)); diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs deleted file mode 100644 index 090753b18c..0000000000 --- a/src/librustc/util/fs.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::path::{self, Path, PathBuf}; -use std::ffi::OsString; -use std::fs; -use std::io; - -// Unfortunately, on windows, it looks like msvcrt.dll is silently translating -// verbatim paths under the hood to non-verbatim paths! This manifests itself as -// gcc looking like it cannot accept paths of the form `\\?\C:\...`, but the -// real bug seems to lie in msvcrt.dll. -// -// Verbatim paths are generally pretty rare, but the implementation of -// `fs::canonicalize` currently generates paths of this form, meaning that we're -// going to be passing quite a few of these down to gcc, so we need to deal with -// this case. -// -// For now we just strip the "verbatim prefix" of `\\?\` from the path. This -// will probably lose information in some cases, but there's not a whole lot -// more we can do with a buggy msvcrt... -// -// For some more information, see this comment: -// https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737 -pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { - if !cfg!(windows) { - return p.to_path_buf(); - } - let mut components = p.components(); - let prefix = match components.next() { - Some(path::Component::Prefix(p)) => p, - _ => return p.to_path_buf(), - }; - match prefix.kind() { - path::Prefix::VerbatimDisk(disk) => { - let mut base = OsString::from(format!("{}:", disk as char)); - base.push(components.as_path()); - PathBuf::from(base) - } - path::Prefix::VerbatimUNC(server, share) => { - let mut base = OsString::from(r"\\"); - base.push(server); - base.push(r"\"); - base.push(share); - base.push(components.as_path()); - PathBuf::from(base) - } - _ => p.to_path_buf(), - } -} - -pub enum LinkOrCopy { - Link, - Copy, -} - -/// Copy `p` into `q`, preferring to use hard-linking if possible. If -/// `q` already exists, it is removed first. -/// The result indicates which of the two operations has been performed. -pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result { - let p = p.as_ref(); - let q = q.as_ref(); - if q.exists() { - fs::remove_file(&q)?; - } - - match fs::hard_link(p, q) { - Ok(()) => Ok(LinkOrCopy::Link), - Err(_) => { - match fs::copy(p, q) { - Ok(_) => Ok(LinkOrCopy::Copy), - Err(e) => Err(e), - } - } - } -} - -#[derive(Debug)] -pub enum RenameOrCopyRemove { - Rename, - CopyRemove, -} - -/// Rename `p` into `q`, preferring to use `rename` if possible. -/// If `rename` fails (rename may fail for reasons such as crossing -/// filesystem), fallback to copy & remove -pub fn rename_or_copy_remove, Q: AsRef>(p: P, - q: Q) - -> io::Result { - let p = p.as_ref(); - let q = q.as_ref(); - match fs::rename(p, q) { - Ok(()) => Ok(RenameOrCopyRemove::Rename), - Err(_) => { - match fs::copy(p, q) { - Ok(_) => { - fs::remove_file(p)?; - Ok(RenameOrCopyRemove::CopyRemove) - } - Err(e) => Err(e), - } - } - } -} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index bb54e18360..9a1add26bb 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -11,14 +11,14 @@ use hir::def_id::DefId; use hir::map::definitions::DefPathData; use mir::interpret::ConstValue; -use middle::region::{self, BlockRemainder}; +use middle::region; use ty::subst::{self, Subst}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; -use ty::{TyBool, TyChar, TyAdt}; -use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; -use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; -use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon}; -use ty::{TyDynamic, TyInt, TyUint, TyInfer}; +use ty::{Bool, Char, Adt}; +use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; +use ty::{Param, RawPtr, Ref, Never, Tuple}; +use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; +use ty::{Dynamic, Int, Uint, Infer}; use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; use util::nodemap::FxHashSet; @@ -26,7 +26,6 @@ use std::cell::Cell; use std::fmt; use std::usize; -use rustc_data_structures::indexed_vec::Idx; use rustc_target::spec::abi::Abi; use syntax::ast::CRATE_NODE_ID; use syntax::symbol::{Symbol, InternedString}; @@ -235,7 +234,7 @@ impl PrintContext { } } write!(f, ")")?; - if !output.is_nil() { + if !output.is_unit() { print!(f, self, write(" -> "), print_display(output))?; } @@ -262,10 +261,7 @@ impl PrintContext { let verbose = self.is_verbose; let mut num_supplied_defaults = 0; let mut has_self = false; - let mut own_counts = GenericParamCount { - lifetimes: 0, - types: 0, - }; + let mut own_counts: GenericParamCount = Default::default(); let mut is_value_path = false; let fn_trait_kind = ty::tls::with(|tcx| { // Unfortunately, some kinds of items (e.g., closures) don't have @@ -374,7 +370,7 @@ impl PrintContext { if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; - if let TyTuple(ref args) = substs.type_at(1).sty { + if let Tuple(ref args) = substs.type_at(1).sty { return self.fn_sig(f, args, false, projection_ty); } } @@ -589,7 +585,7 @@ impl<'a, T: Print> Print for &'a T { } define_print! { - ('tcx) &'tcx ty::Slice>, (self, f, cx) { + ('tcx) &'tcx ty::List>, (self, f, cx) { display { // Generate the main trait ref, including associated types. ty::tls::with(|tcx| { @@ -675,7 +671,7 @@ impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { } define_print! { - ('tcx) &'tcx ty::Slice>, (self, f, cx) { + ('tcx) &'tcx ty::List>, (self, f, cx) { display { write!(f, "{{")?; let mut tys = self.iter(); @@ -773,18 +769,21 @@ define_print! { write!(f, "{}", br) } ty::ReScope(scope) if cx.identify_regions => { - match scope.data() { - region::ScopeData::Node(id) => - write!(f, "'{}s", id.as_usize()), - region::ScopeData::CallSite(id) => - write!(f, "'{}cs", id.as_usize()), - region::ScopeData::Arguments(id) => - write!(f, "'{}as", id.as_usize()), - region::ScopeData::Destruction(id) => - write!(f, "'{}ds", id.as_usize()), - region::ScopeData::Remainder(BlockRemainder - { block, first_statement_index }) => - write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()), + match scope.data { + region::ScopeData::Node => + write!(f, "'{}s", scope.item_local_id().as_usize()), + region::ScopeData::CallSite => + write!(f, "'{}cs", scope.item_local_id().as_usize()), + region::ScopeData::Arguments => + write!(f, "'{}as", scope.item_local_id().as_usize()), + region::ScopeData::Destruction => + write!(f, "'{}ds", scope.item_local_id().as_usize()), + region::ScopeData::Remainder(first_statement_index) => write!( + f, + "'{}_{}rs", + scope.item_local_id().as_usize(), + first_statement_index.index() + ), } } ty::ReVar(region_vid) if cx.identify_regions => { @@ -996,7 +995,7 @@ impl fmt::Debug for ty::FloatVarValue { define_print_multi! { [ - ('tcx) ty::Binder<&'tcx ty::Slice>>, + ('tcx) ty::Binder<&'tcx ty::List>>, ('tcx) ty::Binder>, ('tcx) ty::Binder>, ('tcx) ty::Binder>, @@ -1032,22 +1031,22 @@ define_print! { } define_print! { - ('tcx) ty::TypeVariants<'tcx>, (self, f, cx) { + ('tcx) ty::TyKind<'tcx>, (self, f, cx) { display { match *self { - TyBool => write!(f, "bool"), - TyChar => write!(f, "char"), - TyInt(t) => write!(f, "{}", t.ty_to_string()), - TyUint(t) => write!(f, "{}", t.ty_to_string()), - TyFloat(t) => write!(f, "{}", t.ty_to_string()), - TyRawPtr(ref tm) => { + Bool => write!(f, "bool"), + Char => write!(f, "char"), + Int(t) => write!(f, "{}", t.ty_to_string()), + Uint(t) => write!(f, "{}", t.ty_to_string()), + Float(t) => write!(f, "{}", t.ty_to_string()), + RawPtr(ref tm) => { write!(f, "*{} ", match tm.mutbl { hir::MutMutable => "mut", hir::MutImmutable => "const", })?; tm.ty.print(f, cx) } - TyRef(r, ty, mutbl) => { + Ref(r, ty, mutbl) => { write!(f, "&")?; let s = r.print_to_string(cx); if s != "'_" { @@ -1058,8 +1057,8 @@ define_print! { } ty::TypeAndMut { ty, mutbl }.print(f, cx) } - TyNever => write!(f, "!"), - TyTuple(ref tys) => { + Never => write!(f, "!"), + Tuple(ref tys) => { write!(f, "(")?; let mut tys = tys.iter(); if let Some(&ty) = tys.next() { @@ -1073,7 +1072,7 @@ define_print! { } write!(f, ")") } - TyFnDef(def_id, substs) => { + FnDef(def_id, substs) => { ty::tls::with(|tcx| { let mut sig = tcx.fn_sig(def_id); if let Some(substs) = tcx.lift(&substs) { @@ -1084,14 +1083,14 @@ define_print! { cx.parameterized(f, substs, def_id, &[])?; write!(f, "}}") } - TyFnPtr(ref bare_fn) => { + FnPtr(ref bare_fn) => { bare_fn.print(f, cx) } - TyInfer(infer_ty) => write!(f, "{}", infer_ty), - TyError => write!(f, "[type error]"), - TyParam(ref param_ty) => write!(f, "{}", param_ty), - TyAdt(def, substs) => cx.parameterized(f, substs, def.did, &[]), - TyDynamic(data, r) => { + Infer(infer_ty) => write!(f, "{}", infer_ty), + Error => write!(f, "[type error]"), + Param(ref param_ty) => write!(f, "{}", param_ty), + Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]), + Dynamic(data, r) => { let r = r.print_to_string(cx); if !r.is_empty() { write!(f, "(")?; @@ -1104,11 +1103,11 @@ define_print! { Ok(()) } } - TyForeign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]), - TyProjection(ref data) => data.print(f, cx), - TyAnon(def_id, substs) => { + Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]), + Projection(ref data) => data.print(f, cx), + Opaque(def_id, substs) => { if cx.is_verbose { - return write!(f, "TyAnon({:?}, {:?})", def_id, substs); + return write!(f, "Opaque({:?}, {:?})", def_id, substs); } ty::tls::with(|tcx| { @@ -1157,8 +1156,8 @@ define_print! { Ok(()) }) } - TyStr => write!(f, "str"), - TyGenerator(did, substs, movability) => ty::tls::with(|tcx| { + Str => write!(f, "str"), + Generator(did, substs, movability) => ty::tls::with(|tcx| { let upvar_tys = substs.upvar_tys(did, tcx); let witness = substs.witness(did, tcx); if movability == hir::GeneratorMovability::Movable { @@ -1196,10 +1195,10 @@ define_print! { print!(f, cx, write(" "), print(witness), write("]")) }), - TyGeneratorWitness(types) => { + GeneratorWitness(types) => { ty::tls::with(|tcx| cx.in_binder(f, tcx, &types, tcx.lift(&types))) } - TyClosure(did, substs) => ty::tls::with(|tcx| { + Closure(did, substs) => ty::tls::with(|tcx| { let upvar_tys = substs.upvar_tys(did, tcx); write!(f, "[closure")?; @@ -1236,7 +1235,7 @@ define_print! { write!(f, "]") }), - TyArray(ty, sz) => { + Array(ty, sz) => { print!(f, cx, write("["), print(ty), write("; "))?; match sz.val { ConstValue::Unevaluated(_def_id, _substs) => { @@ -1248,7 +1247,7 @@ define_print! { } write!(f, "]") } - TySlice(ty) => { + Slice(ty) => { print!(f, cx, write("["), print(ty), write("]")) } } diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs new file mode 100644 index 0000000000..70760d35f7 --- /dev/null +++ b/src/librustc/util/profiling.rs @@ -0,0 +1,248 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use session::config::Options; + +use std::fs; +use std::io::{self, StdoutLock, Write}; +use std::time::Instant; + +macro_rules! define_categories { + ($($name:ident,)*) => { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + pub enum ProfileCategory { + $($name),* + } + + #[allow(nonstandard_style)] + struct Categories { + $($name: T),* + } + + impl Categories { + fn new() -> Categories { + Categories { + $($name: T::default()),* + } + } + } + + impl Categories { + fn get(&self, category: ProfileCategory) -> &T { + match category { + $(ProfileCategory::$name => &self.$name),* + } + } + + fn set(&mut self, category: ProfileCategory, value: T) { + match category { + $(ProfileCategory::$name => self.$name = value),* + } + } + } + + struct CategoryData { + times: Categories, + query_counts: Categories<(u64, u64)>, + } + + impl CategoryData { + fn new() -> CategoryData { + CategoryData { + times: Categories::new(), + query_counts: Categories::new(), + } + } + + fn print(&self, lock: &mut StdoutLock) { + writeln!(lock, "| Phase | Time (ms) | Queries | Hits (%) |") + .unwrap(); + writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |") + .unwrap(); + + $( + let (hits, total) = self.query_counts.$name; + let (hits, total) = if total > 0 { + (format!("{:.2}", + (((hits as f32) / (total as f32)) * 100.0)), total.to_string()) + } else { + (String::new(), String::new()) + }; + + writeln!( + lock, + "| {0: <16} | {1: <14} | {2: <14} | {3: <8} |", + stringify!($name), + self.times.$name / 1_000_000, + total, + hits + ).unwrap(); + )* + } + + fn json(&self) -> String { + let mut json = String::from("["); + + $( + let (hits, total) = self.query_counts.$name; + + json.push_str(&format!( + "{{ \"category\": {}, \"time_ms\": {}, + \"query_count\": {}, \"query_hits\": {} }}", + stringify!($name), + self.times.$name / 1_000_000, + total, + format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0)) + )); + )* + + json.push(']'); + + json + } + } + } +} + +define_categories! { + Parsing, + Expansion, + TypeChecking, + BorrowChecking, + Codegen, + Linking, + Other, +} + +pub struct SelfProfiler { + timer_stack: Vec, + data: CategoryData, + current_timer: Instant, +} + +impl SelfProfiler { + pub fn new() -> SelfProfiler { + let mut profiler = SelfProfiler { + timer_stack: Vec::new(), + data: CategoryData::new(), + current_timer: Instant::now(), + }; + + profiler.start_activity(ProfileCategory::Other); + + profiler + } + + pub fn start_activity(&mut self, category: ProfileCategory) { + match self.timer_stack.last().cloned() { + None => { + self.current_timer = Instant::now(); + }, + Some(current_category) if current_category == category => { + //since the current category is the same as the new activity's category, + //we don't need to do anything with the timer, we just need to push it on the stack + } + Some(current_category) => { + let elapsed = self.stop_timer(); + + //record the current category's time + let new_time = self.data.times.get(current_category) + elapsed; + self.data.times.set(current_category, new_time); + } + } + + //push the new category + self.timer_stack.push(category); + } + + pub fn record_query(&mut self, category: ProfileCategory) { + let (hits, total) = *self.data.query_counts.get(category); + self.data.query_counts.set(category, (hits, total + 1)); + } + + pub fn record_query_hit(&mut self, category: ProfileCategory) { + let (hits, total) = *self.data.query_counts.get(category); + self.data.query_counts.set(category, (hits + 1, total)); + } + + pub fn end_activity(&mut self, category: ProfileCategory) { + match self.timer_stack.pop() { + None => bug!("end_activity() was called but there was no running activity"), + Some(c) => + assert!( + c == category, + "end_activity() was called but a different activity was running"), + } + + //check if the new running timer is in the same category as this one + //if it is, we don't need to do anything + if let Some(c) = self.timer_stack.last() { + if *c == category { + return; + } + } + + //the new timer is different than the previous, + //so record the elapsed time and start a new timer + let elapsed = self.stop_timer(); + let new_time = self.data.times.get(category) + elapsed; + self.data.times.set(category, new_time); + } + + fn stop_timer(&mut self) -> u64 { + let elapsed = self.current_timer.elapsed(); + + self.current_timer = Instant::now(); + + (elapsed.as_secs() * 1_000_000_000) + (elapsed.subsec_nanos() as u64) + } + + pub fn print_results(&mut self, opts: &Options) { + self.end_activity(ProfileCategory::Other); + + assert!( + self.timer_stack.is_empty(), + "there were timers running when print_results() was called"); + + let out = io::stdout(); + let mut lock = out.lock(); + + let crate_name = + opts.crate_name + .as_ref() + .map(|n| format!(" for {}", n)) + .unwrap_or_default(); + + writeln!(lock, "Self profiling results{}:", crate_name).unwrap(); + writeln!(lock).unwrap(); + + self.data.print(&mut lock); + + writeln!(lock).unwrap(); + writeln!(lock, "Optimization level: {:?}", opts.optimize).unwrap(); + + let incremental = if opts.incremental.is_some() { "on" } else { "off" }; + writeln!(lock, "Incremental: {}", incremental).unwrap(); + } + + pub fn save_results(&self, opts: &Options) { + let category_data = self.data.json(); + let compilation_options = + format!("{{ \"optimization_level\": \"{:?}\", \"incremental\": {} }}", + opts.optimize, + if opts.incremental.is_some() { "true" } else { "false" }); + + let json = format!("{{ \"category_data\": {}, \"compilation_options\": {} }}", + category_data, + compilation_options); + + fs::write("self_profiler_results.json", json).unwrap(); + } +} diff --git a/src/librustc/util/time_graph.rs b/src/librustc/util/time_graph.rs index a8502682a8..3ba4e4ddbb 100644 --- a/src/librustc/util/time_graph.rs +++ b/src/librustc/util/time_graph.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashMap; +use rustc_data_structures::fx::FxHashMap; use std::fs::File; use std::io::prelude::*; use std::marker::PhantomData; @@ -40,7 +40,7 @@ struct PerThread { #[derive(Clone)] pub struct TimeGraph { - data: Arc>>, + data: Arc>>, } #[derive(Clone, Copy)] @@ -68,7 +68,7 @@ impl Drop for RaiiToken { impl TimeGraph { pub fn new() -> TimeGraph { TimeGraph { - data: Arc::new(Mutex::new(HashMap::new())) + data: Arc::new(Mutex::new(FxHashMap::default())) } } diff --git a/src/librustc_allocator/Cargo.toml b/src/librustc_allocator/Cargo.toml index 1cbde181ca..cd3ef6a1f0 100644 --- a/src/librustc_allocator/Cargo.toml +++ b/src/librustc_allocator/Cargo.toml @@ -10,8 +10,10 @@ test = false [dependencies] rustc = { path = "../librustc" } +rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } log = "0.4" +smallvec = { version = "0.6.5", features = ["union"] } diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index ffbbd8a33a..11e8c30760 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -9,14 +9,15 @@ // except according to those terms. use rustc::middle::allocator::AllocatorKind; +use rustc_data_structures::small_vec::OneVector; use rustc_errors; use syntax::{ ast::{ self, Arg, Attribute, Crate, Expr, FnHeader, Generics, Ident, Item, ItemKind, - LitKind, Mac, Mod, Mutability, StrStyle, Ty, TyKind, Unsafety, VisibilityKind, + Mac, Mod, Mutability, Ty, TyKind, Unsafety, VisibilityKind, }, attr, - codemap::{ + source_map::{ respan, ExpnInfo, MacroAttribute, }, ext::{ @@ -28,8 +29,7 @@ use syntax::{ fold::{self, Folder}, parse::ParseSess, ptr::P, - symbol::Symbol, - util::small_vector::SmallVector, + symbol::Symbol }; use syntax_pos::Span; @@ -65,7 +65,7 @@ struct ExpandAllocatorDirectives<'a> { } impl<'a> Folder for ExpandAllocatorDirectives<'a> { - fn fold_item(&mut self, item: P) -> SmallVector> { + fn fold_item(&mut self, item: P) -> OneVector> { debug!("in submodule {}", self.in_submod); let name = if attr::contains_name(&item.attrs, "global_allocator") { @@ -78,20 +78,20 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> { _ => { self.handler .span_err(item.span, "allocators must be statics"); - return SmallVector::one(item); + return smallvec![item]; } } if self.in_submod > 0 { self.handler .span_err(item.span, "`global_allocator` cannot be used in submodules"); - return SmallVector::one(item); + return smallvec![item]; } if self.found { self.handler .span_err(item.span, "cannot define more than one #[global_allocator]"); - return SmallVector::one(item); + return smallvec![item]; } self.found = true; @@ -152,7 +152,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> { let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap(); // Return the item and new submodule - let mut ret = SmallVector::with_capacity(2); + let mut ret = OneVector::with_capacity(2); ret.push(item); ret.push(module); @@ -236,20 +236,9 @@ impl<'a> AllocFnFactory<'a> { } fn attrs(&self) -> Vec { - let key = Symbol::intern("linkage"); - let value = LitKind::Str(Symbol::intern("external"), StrStyle::Cooked); - let linkage = self.cx.meta_name_value(self.span, key, value); - - let no_mangle = Symbol::intern("no_mangle"); - let no_mangle = self.cx.meta_word(self.span, no_mangle); - let special = Symbol::intern("rustc_std_internal_symbol"); let special = self.cx.meta_word(self.span, special); - vec![ - self.cx.attribute(self.span, linkage), - self.cx.attribute(self.span, no_mangle), - self.cx.attribute(self.span, special), - ] + vec![self.cx.attribute(self.span, special)] } fn arg_ty( diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs index b217d3665a..2a3404ee83 100644 --- a/src/librustc_allocator/lib.rs +++ b/src/librustc_allocator/lib.rs @@ -8,14 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![cfg_attr(not(stage0), feature(nll))] #![feature(rustc_private)] #[macro_use] extern crate log; extern crate rustc; +extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_target; extern crate syntax; extern crate syntax_pos; +#[macro_use] +extern crate smallvec; pub mod expand; diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index b21448df58..87d59d2e76 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -536,23 +536,21 @@ impl fmt::Display for IeeeFloat { // Check whether we should use scientific notation. let scientific = if width == 0 { true + } else if exp >= 0 { + // 765e3 --> 765000 + // ^^^ + // But we shouldn't make the number look more precise than it is. + exp as usize > width || digits + exp as usize > precision } else { - if exp >= 0 { - // 765e3 --> 765000 - // ^^^ - // But we shouldn't make the number look more precise than it is. - exp as usize > width || digits + exp as usize > precision + // Power of the most significant digit. + let msd = exp + (digits - 1) as ExpInt; + if msd >= 0 { + // 765e-2 == 7.65 + false } else { - // Power of the most significant digit. - let msd = exp + (digits - 1) as ExpInt; - if msd >= 0 { - // 765e-2 == 7.65 - false - } else { - // 765e-5 == 0.00765 - // ^ ^^ - -msd as usize > width - } + // 765e-5 == 0.00765 + // ^ ^^ + -msd as usize > width } }; @@ -702,7 +700,7 @@ impl Float for IeeeFloat { // exponent = 1..10 // significand = 1..1 IeeeFloat { - sig: [!0 & ((1 << S::PRECISION) - 1)], + sig: [(1 << S::PRECISION) - 1], exp: S::MAX_EXP, category: Category::Normal, sign: false, @@ -1507,10 +1505,11 @@ impl FloatConvert> for IeeeFloat { } // If this is a truncation, perform the shift. - let mut loss = Loss::ExactlyZero; - if shift < 0 && (r.is_finite_non_zero() || r.category == Category::NaN) { - loss = sig::shift_right(&mut r.sig, &mut 0, -shift as usize); - } + let loss = if shift < 0 && (r.is_finite_non_zero() || r.category == Category::NaN) { + sig::shift_right(&mut r.sig, &mut 0, -shift as usize) + } else { + Loss::ExactlyZero + }; // If this is an extension, perform the shift. if shift > 0 && (r.is_finite_non_zero() || r.category == Category::NaN) { @@ -1738,27 +1737,25 @@ impl IeeeFloat { bit_pos -= 4; if bit_pos >= 0 { r.sig[0] |= (hex_value as Limb) << bit_pos; - } else { - // If zero or one-half (the hexadecimal digit 8) are followed - // by non-zero, they're a little more than zero or one-half. - if let Some(ref mut loss) = loss { - if hex_value != 0 { - if *loss == Loss::ExactlyZero { - *loss = Loss::LessThanHalf; - } - if *loss == Loss::ExactlyHalf { - *loss = Loss::MoreThanHalf; - } + // If zero or one-half (the hexadecimal digit 8) are followed + // by non-zero, they're a little more than zero or one-half. + } else if let Some(ref mut loss) = loss { + if hex_value != 0 { + if *loss == Loss::ExactlyZero { + *loss = Loss::LessThanHalf; + } + if *loss == Loss::ExactlyHalf { + *loss = Loss::MoreThanHalf; } - } else { - loss = Some(match hex_value { - 0 => Loss::ExactlyZero, - 1..=7 => Loss::LessThanHalf, - 8 => Loss::ExactlyHalf, - 9..=15 => Loss::MoreThanHalf, - _ => unreachable!(), - }); } + } else { + loss = Some(match hex_value { + 0 => Loss::ExactlyZero, + 1..=7 => Loss::LessThanHalf, + 8 => Loss::ExactlyHalf, + 9..=15 => Loss::MoreThanHalf, + _ => unreachable!(), + }); } } else if c == 'p' || c == 'P' { if !any_digits { @@ -2309,24 +2306,14 @@ mod sig { /// One, not zero, based LSB. That is, returns 0 for a zeroed significand. pub(super) fn olsb(limbs: &[Limb]) -> usize { - for i in 0..limbs.len() { - if limbs[i] != 0 { - return i * LIMB_BITS + limbs[i].trailing_zeros() as usize + 1; - } - } - - 0 + limbs.iter().enumerate().find(|(_, &limb)| limb != 0).map_or(0, + |(i, limb)| i * LIMB_BITS + limb.trailing_zeros() as usize + 1) } /// One, not zero, based MSB. That is, returns 0 for a zeroed significand. pub(super) fn omsb(limbs: &[Limb]) -> usize { - for i in (0..limbs.len()).rev() { - if limbs[i] != 0 { - return (i + 1) * LIMB_BITS - limbs[i].leading_zeros() as usize; - } - } - - 0 + limbs.iter().enumerate().rfind(|(_, &limb)| limb != 0).map_or(0, + |(i, limb)| (i + 1) * LIMB_BITS - limb.leading_zeros() as usize) } /// Comparison (unsigned) of two significands. @@ -2378,7 +2365,7 @@ mod sig { limb = dst[i - jump]; if shift > 0 { limb <<= shift; - if i >= jump + 1 { + if i > jump { limb |= dst[i - jump - 1] >> (LIMB_BITS - shift); } } @@ -2448,7 +2435,7 @@ mod sig { let n = dst_limbs * LIMB_BITS - shift; if n < src_bits { let mask = (1 << (src_bits - n)) - 1; - dst[dst_limbs - 1] |= (src[dst_limbs] & mask) << n % LIMB_BITS; + dst[dst_limbs - 1] |= (src[dst_limbs] & mask) << (n % LIMB_BITS); } else if n > src_bits && src_bits % LIMB_BITS > 0 { dst[dst_limbs - 1] &= (1 << (src_bits % LIMB_BITS)) - 1; } diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 08438805a7..d6e821d427 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -45,6 +45,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![forbid(unsafe_code)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(try_from)] // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs index 0c78fd74a2..b3ba86ad8a 100644 --- a/src/librustc_asan/lib.rs +++ b/src/librustc_asan/lib.rs @@ -10,6 +10,7 @@ #![sanitizer_runtime] #![feature(alloc_system)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 49bd69f826..40bfbf1596 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -16,6 +16,7 @@ // 2. loans made in overlapping scopes do not conflict // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way + use self::UseError::*; use borrowck::*; @@ -29,6 +30,7 @@ use rustc::ty::{self, TyCtxt, RegionKind}; use syntax::ast; use syntax_pos::Span; use rustc::hir; +use rustc::hir::Node; use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; use std::rc::Rc; @@ -91,7 +93,6 @@ struct CheckLoanCtxt<'a, 'tcx: 'a> { dfcx_loans: &'a LoanDataFlow<'a, 'tcx>, move_data: &'a move_data::FlowedMoveData<'a, 'tcx>, all_loans: &'a [Loan<'tcx>], - param_env: ty::ParamEnv<'tcx>, movable_generator: bool, } @@ -202,7 +203,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let node_id = bccx.tcx.hir.as_local_node_id(def_id).unwrap(); let movable_generator = !match bccx.tcx.hir.get(node_id) { - hir::map::Node::NodeExpr(&hir::Expr { + Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(.., Some(hir::GeneratorMovability::Static)), .. }) => true, @@ -215,7 +216,6 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, dfcx_loans, move_data, all_loans, - param_env, movable_generator, }; let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id); @@ -596,7 +596,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // 3. Where does old loan expire. let previous_end_span = - Some(self.tcx().sess.codemap().end_point( + Some(self.tcx().sess.source_map().end_point( old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree))); let mut err = match (new_loan.kind, old_loan.kind) { @@ -767,8 +767,12 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let mut ret = UseOk; + let scope = region::Scope { + id: expr_id, + data: region::ScopeData::Node + }; self.each_in_scope_loan_affecting_path( - region::Scope::Node(expr_id), use_path, |loan| { + scope, use_path, |loan| { if !compatible_borrow_kinds(loan.kind, borrow_kind) { ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span); false @@ -801,8 +805,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { use_kind, &lp, the_move, - moved_lp, - self.param_env); + moved_lp); false }); } @@ -846,7 +849,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => { match lp_base.to_type().sty { - ty::TyAdt(def, _) if def.has_dtor(self.tcx()) => { + ty::Adt(def, _) if def.has_dtor(self.tcx()) => { // In the case where the owner implements drop, then // the path must be initialized to prevent a case of // partial reinitialization @@ -887,7 +890,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // Check that we don't invalidate any outstanding loans if let Some(loan_path) = opt_loan_path(assignee_cmt) { - let scope = region::Scope::Node(assignment_id); + let scope = region::Scope { + id: assignment_id, + data: region::ScopeData::Node + }; self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| { self.report_illegal_mutation(assignment_span, &loan_path, loan); false diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 7ce6863a7c..ffc4fbfb4c 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -24,7 +24,7 @@ use std::rc::Rc; use syntax::ast; use syntax_pos::Span; use rustc::hir::*; -use rustc::hir::map::Node::*; +use rustc::hir::Node; struct GatherMoveInfo<'c, 'tcx: 'c> { id: hir::ItemLocalId, @@ -60,7 +60,7 @@ fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> Patte let parent = tcx.hir.get_parent_node(pat.id); match tcx.hir.get(parent) { - NodeExpr(ref e) => { + Node::Expr(ref e) => { // the enclosing expression must be a `match` or something else assert!(match e.node { ExprKind::Match(..) => true, @@ -68,7 +68,7 @@ fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> Patte }); PatternSource::MatchExpr(e) } - NodeLocal(local) => PatternSource::LetDecl(local), + Node::Local(local) => PatternSource::LetDecl(local), _ => return PatternSource::Other, } @@ -163,15 +163,11 @@ pub fn gather_assignment<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, assignment_id: hir::ItemLocalId, assignment_span: Span, - assignee_loan_path: Rc>, - assignee_id: hir::ItemLocalId, - mode: euv::MutateMode) { + assignee_loan_path: Rc>) { move_data.add_assignment(bccx.tcx, assignee_loan_path, assignment_id, - assignment_span, - assignee_id, - mode); + assignment_span); } // (keep in sync with move_error::report_cannot_move_out_of ) @@ -195,14 +191,14 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, Categorization::Interior(ref b, mc::InteriorField(_)) | Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern)) => { match b.ty.sty { - ty::TyAdt(def, _) => { + ty::Adt(def, _) => { if def.has_dtor(bccx.tcx) { Some(cmt.clone()) } else { check_and_get_illegal_move_origin(bccx, b) } } - ty::TySlice(..) => Some(cmt.clone()), + ty::Slice(..) => Some(cmt.clone()), _ => { check_and_get_illegal_move_origin(bccx, b) } diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 323e0997e3..c9dcc0d9fa 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -28,8 +28,7 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, span: Span, cause: euv::LoanCause, cmt: &'a mc::cmt_<'tcx>, - loan_region: ty::Region<'tcx>, - _: ty::BorrowKind) + loan_region: ty::Region<'tcx>) -> Result<(),()> { //! Reports error if `loan_region` is larger than S //! where S is `item_scope` if `cmt` is an upvar, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index d088141387..dc400c6ef3 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -43,7 +43,10 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let mut glcx = GatherLoanCtxt { bccx, all_loans: Vec::new(), - item_ub: region::Scope::Node(bccx.tcx.hir.body(body).value.hir_id.local_id), + item_ub: region::Scope { + id: bccx.tcx.hir.body(body).value.hir_id.local_id, + data: region::ScopeData::Node + }, move_data: MoveData::default(), move_error_collector: move_error::MoveErrorCollector::new(), }; @@ -145,12 +148,11 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { assignment_id: ast::NodeId, assignment_span: Span, assignee_cmt: &mc::cmt_<'tcx>, - mode: euv::MutateMode) + _: euv::MutateMode) { self.guarantee_assignment_valid(assignment_id, assignment_span, - assignee_cmt, - mode); + assignee_cmt); } fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) { @@ -246,8 +248,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { fn guarantee_assignment_valid(&mut self, assignment_id: ast::NodeId, assignment_span: Span, - cmt: &mc::cmt_<'tcx>, - mode: euv::MutateMode) { + cmt: &mc::cmt_<'tcx>) { let opt_lp = opt_loan_path(cmt); debug!("guarantee_assignment_valid(assignment_id={}, cmt={:?}) opt_lp={:?}", @@ -282,9 +283,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { self.bccx.tcx.hir.node_to_hir_id(assignment_id) .local_id, assignment_span, - lp, - cmt.hir_id.local_id, - mode); + lp); } None => { // This can occur with e.g. `*foo() = 5`. In such @@ -320,7 +319,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { // Check that the lifetime of the borrow does not exceed // the lifetime of the data being borrowed. if lifetime::guarantee_lifetime(self.bccx, self.item_ub, - borrow_span, cause, cmt, loan_region, req_kind).is_err() { + borrow_span, cause, cmt, loan_region).is_err() { return; // reported an error, no sense in reporting more. } @@ -379,7 +378,10 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { }; debug!("loan_scope = {:?}", loan_scope); - let borrow_scope = region::Scope::Node(borrow_id); + let borrow_scope = region::Scope { + id: borrow_id, + data: region::ScopeData::Node + }; let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope); debug!("gen_scope = {:?}", gen_scope); diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index b217e6a856..b29ab55f9b 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -17,7 +17,7 @@ use rustc::ty; use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; use syntax::ast; use syntax_pos; -use errors::DiagnosticBuilder; +use errors::{DiagnosticBuilder, Applicability}; use borrowck::gather_loans::gather_moves::PatternSource; pub struct MoveErrorCollector<'tcx> { @@ -79,10 +79,13 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &[MoveErr // see `get_pattern_source()` for details let initializer = e.init.as_ref().expect("should have an initializer to get an error"); - if let Ok(snippet) = bccx.tcx.sess.codemap().span_to_snippet(initializer.span) { - err.span_suggestion(initializer.span, - "consider using a reference instead", - format!("&{}", snippet)); + if let Ok(snippet) = bccx.tcx.sess.source_map().span_to_snippet(initializer.span) { + err.span_suggestion_with_applicability( + initializer.span, + "consider using a reference instead", + format!("&{}", snippet), + Applicability::MaybeIncorrect // using a reference may not be the right fix + ); } } _ => { @@ -154,7 +157,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, Categorization::Downcast(ref b, _) | Categorization::Interior(ref b, mc::InteriorField(_)) => { match b.ty.sty { - ty::TyAdt(def, _) if def.has_dtor(bccx.tcx) => { + ty::Adt(def, _) if def.has_dtor(bccx.tcx) => { bccx.cannot_move_out_of_interior_of_drop( move_from.span, b.ty, Origin::Ast) } diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs index e332f68327..d9784cc217 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs @@ -104,7 +104,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { let result = self.restrict(&cmt_base); // Borrowing one union field automatically borrows all its fields. match base_ty.sty { - ty::TyAdt(adt_def, _) if adt_def.is_union() => match result { + ty::Adt(adt_def, _) if adt_def.is_union() => match result { RestrictionResult::Safe => RestrictionResult::Safe, RestrictionResult::SafeIf(base_lp, mut base_vec) => { for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index aef8b58fa8..56187c09b4 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -21,13 +21,9 @@ pub use self::MovedValueUseKind::*; use self::InteriorKind::*; use rustc::hir::HirId; -use rustc::hir::map as hir_map; +use rustc::hir::Node; use rustc::hir::map::blocks::FnLikeNode; use rustc::cfg; -use rustc::middle::dataflow::DataFlowContext; -use rustc::middle::dataflow::BitwiseOperator; -use rustc::middle::dataflow::DataFlowOperator; -use rustc::middle::dataflow::KillFrom; use rustc::middle::borrowck::{BorrowCheckResult, SignalledError}; use rustc::hir::def_id::{DefId, LocalDefId}; use rustc::middle::expr_use_visitor as euv; @@ -49,11 +45,13 @@ use rustc_data_structures::sync::Lrc; use std::hash::{Hash, Hasher}; use syntax::ast; use syntax_pos::{MultiSpan, Span}; -use errors::{DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc::hir; use rustc::hir::intravisit::{self, Visitor}; +use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; + pub mod check_loans; pub mod gather_loans; @@ -97,8 +95,8 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) let owner_id = tcx.hir.as_local_node_id(owner_def_id).unwrap(); match tcx.hir.get(owner_id) { - hir_map::NodeStructCtor(_) | - hir_map::NodeVariant(_) => { + Node::StructCtor(_) | + Node::Variant(_) => { // We get invoked with anything that has MIR, but some of // those things (notably the synthesized constructors from // tuple structs/variants) do not have an associated body @@ -421,7 +419,7 @@ fn closure_to_block(closure_id: LocalDefId, tcx: TyCtxt) -> ast::NodeId { let closure_id = tcx.hir.local_def_id_to_node_id(closure_id); match tcx.hir.get(closure_id) { - hir_map::NodeExpr(expr) => match expr.node { + Node::Expr(expr) => match expr.node { hir::ExprKind::Closure(.., body_id, _, _) => { body_id.node_id } @@ -443,7 +441,7 @@ impl<'a, 'tcx> LoanPath<'tcx> { LpUpvar(upvar_id) => { let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx); let hir_id = bccx.tcx.hir.node_to_hir_id(block_id); - region::Scope::Node(hir_id.local_id) + region::Scope { id: hir_id.local_id, data: region::ScopeData::Node } } LpDowncast(ref base, _) | LpExtend(ref base, ..) => base.kill_scope(bccx), @@ -640,8 +638,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { use_kind: MovedValueUseKind, lp: &LoanPath<'tcx>, the_move: &move_data::Move, - moved_lp: &LoanPath<'tcx>, - _param_env: ty::ParamEnv<'tcx>) { + moved_lp: &LoanPath<'tcx>) { let (verb, verb_participle) = match use_kind { MovedInUse => ("use", "used"), MovedInCapture => ("capture", "captured"), @@ -700,7 +697,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { Some(nl.to_string()), Origin::Ast); let need_note = match lp.ty.sty { - ty::TypeVariants::TyClosure(id, _) => { + ty::Closure(id, _) => { let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); let hir_id = self.tcx.hir.node_to_hir_id(node_id); if let Some((span, name)) = self.tables.closure_kind_origins().get(hir_id) { @@ -806,23 +803,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.signal_error(); } - pub fn struct_span_err_with_code>(&self, - s: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'a> { - self.tcx.sess.struct_span_err_with_code(s, msg, code) - } - - pub fn span_err_with_code>( - &self, - s: S, - msg: &str, - code: DiagnosticId, - ) { - self.tcx.sess.span_err_with_code(s, msg, code); - } - fn report_bckerr(&self, err: &BckError<'a, 'tcx>) { let error_span = err.span.clone(); @@ -868,7 +848,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let sp = self.tcx.hir.span(node_id); let fn_closure_msg = "`Fn` closures cannot capture their enclosing \ environment for modifications"; - match (self.tcx.sess.codemap().span_to_snippet(sp), &err.cmt.cat) { + match (self.tcx.sess.source_map().span_to_snippet(sp), &err.cmt.cat) { (_, &Categorization::Upvar(mc::Upvar { kind: ty::ClosureKind::Fn, .. })) => { @@ -898,6 +878,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } } } + db } BorrowViolation(euv::ClosureCapture(_)) => { @@ -918,6 +899,28 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } }; + // We add a special note about `IndexMut`, if the source of this error + // is the fact that `Index` is implemented, but `IndexMut` is not. Needing + // to implement two traits for "one operator" is not very intuitive for + // many programmers. + if err.cmt.note == mc::NoteIndex { + let node_id = self.tcx.hir.hir_to_node_id(err.cmt.hir_id); + let node = self.tcx.hir.get(node_id); + + // This pattern probably always matches. + if let Node::Expr( + hir::Expr { node: hir::ExprKind::Index(lhs, _), ..} + ) = node { + let ty = self.tables.expr_ty(lhs); + + db.help(&format!( + "trait `IndexMut` is required to modify indexed content, but \ + it is not implemented for `{}`", + ty + )); + } + } + self.note_and_explain_mutbl_error(&mut db, &err, &error_span); self.note_immutability_blame( &mut db, @@ -1029,7 +1032,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let ty::ReScope(scope) = *super_scope { let node_id = scope.node_id(self.tcx, &self.region_scope_tree); match self.tcx.hir.find(node_id) { - Some(hir_map::NodeStmt(_)) => { + Some(Node::Stmt(_)) => { if *sub_scope != ty::ReStatic { db.note("consider using a `let` binding to increase its lifetime"); } @@ -1157,13 +1160,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { ref ty }) = pty.node { // Account for existing lifetimes when generating the message - let pointee_snippet = match self.tcx.sess.codemap().span_to_snippet(ty.span) { + let pointee_snippet = match self.tcx.sess.source_map().span_to_snippet(ty.span) { Ok(snippet) => snippet, _ => return None }; let lifetime_snippet = if !lifetime.is_elided() { - format!("{} ", match self.tcx.sess.codemap().span_to_snippet(lifetime.span) { + format!("{} ", match self.tcx.sess.source_map().span_to_snippet(lifetime.span) { Ok(lifetime_snippet) => lifetime_snippet, _ => return None }) @@ -1180,7 +1183,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { fn local_binding_mode(&self, node_id: ast::NodeId) -> ty::BindingMode { let pat = match self.tcx.hir.get(node_id) { - hir_map::Node::NodeBinding(pat) => pat, + Node::Binding(pat) => pat, node => bug!("bad node for local: {:?}", node) }; @@ -1232,7 +1235,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { ty::BindByReference(..) => { let let_span = self.tcx.hir.span(node_id); let suggestion = suggest_ref_mut(self.tcx, let_span); - if let Some((let_span, replace_str)) = suggestion { + if let Some(replace_str) = suggestion { db.span_suggestion( let_span, "use a mutable reference instead", @@ -1256,7 +1259,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { None => return }; - if let hir_map::Node::NodeField(ref field) = self.tcx.hir.get(node_id) { + if let Node::Field(ref field) = self.tcx.hir.get(node_id) { if let Some(msg) = self.suggest_mut_for_immutable(&field.ty, false) { db.span_label(field.ty.span, msg); } @@ -1274,7 +1277,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { binding_node_id: ast::NodeId) { let let_span = self.tcx.hir.span(binding_node_id); if let ty::BindByValue(..) = self.local_binding_mode(binding_node_id) { - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(let_span) { let (ty, is_implicit_self) = self.local_ty(binding_node_id); if is_implicit_self && snippet != "self" { // avoid suggesting `mut &self`. @@ -1296,9 +1299,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { snippet ); } else { - db.span_label( + db.span_suggestion_with_applicability( let_span, - format!("consider changing this to `mut {}`", snippet), + "make this binding mutable", + format!("mut {}", snippet), + Applicability::MachineApplicable, ); } } @@ -1312,7 +1317,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let cmt_path_or_string = self.cmt_to_path_or_string(&err.cmt); let suggestion = - match self.tcx.sess.codemap().span_to_snippet(err.span) { + match self.tcx.sess.source_map().span_to_snippet(err.span) { Ok(string) => format!("move {}", string), Err(_) => "move || ".to_string() }; @@ -1334,7 +1339,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { fn region_end_span(&self, region: ty::Region<'tcx>) -> Option { match *region { ty::ReScope(scope) => { - Some(self.tcx.sess.codemap().end_point( + Some(self.tcx.sess.source_map().end_point( scope.span(self.tcx, &self.region_scope_tree))) } _ => None @@ -1365,7 +1370,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { db.span_label(*error_span, "cannot borrow as mutable"); } else if let Categorization::Local(local_id) = err.cmt.cat { let span = self.tcx.hir.span(local_id); - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if snippet.starts_with("ref mut ") || snippet.starts_with("&mut ") { db.span_label(*error_span, "cannot reborrow mutably"); db.span_label(*error_span, "try removing `&mut` here"); diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 4091ca046f..d9f223daf6 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -13,16 +13,12 @@ pub use self::MoveKind::*; +use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; + use borrowck::*; use rustc::cfg; -use rustc::middle::dataflow::DataFlowContext; -use rustc::middle::dataflow::BitwiseOperator; -use rustc::middle::dataflow::DataFlowOperator; -use rustc::middle::dataflow::KillFrom; -use rustc::middle::expr_use_visitor as euv; -use rustc::middle::expr_use_visitor::MutateMode; use rustc::ty::{self, TyCtxt}; -use rustc::util::nodemap::{FxHashMap, FxHashSet}; +use rustc::util::nodemap::FxHashMap; use std::cell::RefCell; use std::rc::Rc; @@ -51,9 +47,6 @@ pub struct MoveData<'tcx> { /// assigned dataflow bits, but we track them because they still /// kill move bits. pub path_assignments: RefCell>, - - /// Assignments to a variable or path, like `x = foo`, but not `x += foo`. - pub assignee_ids: RefCell>, } pub struct FlowedMoveData<'a, 'tcx: 'a> { @@ -151,9 +144,6 @@ pub struct Assignment { /// span of node where assignment occurs pub span: Span, - - /// id for place expression on lhs of assignment - pub assignee_id: hir::ItemLocalId, } #[derive(Clone, Copy)] @@ -339,7 +329,7 @@ impl<'a, 'tcx> MoveData<'tcx> { // all parent union fields, moves do not propagate upwards automatically. let mut lp = orig_lp.clone(); while let LpExtend(ref base_lp, mutbl, lp_elem) = lp.clone().kind { - if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior)) + if let (&ty::Adt(adt_def, _), LpInterior(opt_variant_id, interior)) = (&base_lp.ty.sty, lp_elem) { if adt_def.is_union() { for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() { @@ -388,12 +378,10 @@ impl<'a, 'tcx> MoveData<'tcx> { pub fn add_assignment(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, lp: Rc>, assign_id: hir::ItemLocalId, - span: Span, - assignee_id: hir::ItemLocalId, - mode: euv::MutateMode) { + span: Span) { // Assigning to one union field automatically assigns to all its fields. if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind { - if let ty::TyAdt(adt_def, _) = base_lp.ty.sty { + if let ty::Adt(adt_def, _) = base_lp.ty.sty { if adt_def.is_union() { for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() { let field = @@ -407,39 +395,28 @@ impl<'a, 'tcx> MoveData<'tcx> { LpInterior(opt_variant_id, field)); let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty)); self.add_assignment_helper(tcx, sibling_lp, assign_id, - span, assignee_id, mode); + span); } return; } } } - self.add_assignment_helper(tcx, lp.clone(), assign_id, span, assignee_id, mode); + self.add_assignment_helper(tcx, lp.clone(), assign_id, span); } fn add_assignment_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, lp: Rc>, assign_id: hir::ItemLocalId, - span: Span, - assignee_id: hir::ItemLocalId, - mode: euv::MutateMode) { - debug!("add_assignment(lp={:?}, assign_id={:?}, assignee_id={:?}", - lp, assign_id, assignee_id); + span: Span) { + debug!("add_assignment(lp={:?}, assign_id={:?}", lp, assign_id); let path_index = self.move_path(tcx, lp.clone()); - match mode { - MutateMode::Init | MutateMode::JustWrite => { - self.assignee_ids.borrow_mut().insert(assignee_id); - } - MutateMode::WriteAndRead => { } - } - let assignment = Assignment { path: path_index, id: assign_id, span, - assignee_id, }; if self.is_var_path(path_index) { diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs index 475ff0b744..f10361cb07 100644 --- a/src/librustc_borrowck/borrowck/unused.rs +++ b/src/librustc_borrowck/borrowck/unused.rs @@ -13,6 +13,7 @@ use rustc::hir::{self, HirId}; use rustc::lint::builtin::UNUSED_MUT; use rustc::ty; use rustc::util::nodemap::{FxHashMap, FxHashSet}; +use errors::Applicability; use std::slice; use syntax::ptr::P; @@ -44,7 +45,7 @@ struct UnusedMutCx<'a, 'tcx: 'a> { impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { fn check_unused_mut_pat(&self, pats: &[P]) { let tcx = self.bccx.tcx; - let mut mutables = FxHashMap(); + let mut mutables: FxHashMap<_, Vec<_>> = FxHashMap(); for p in pats { p.each_binding(|_, hir_id, span, ident| { // Skip anything that looks like `_foo` @@ -60,7 +61,7 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { _ => return, } - mutables.entry(ident.name).or_insert(Vec::new()).push((hir_id, span)); + mutables.entry(ident.name).or_default().push((hir_id, span)); } else { tcx.sess.delay_span_bug(span, "missing binding mode"); } @@ -75,7 +76,7 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { } let (hir_id, span) = ids[0]; - let mut_span = tcx.sess.codemap().span_until_non_whitespace(span); + let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); // Ok, every name wasn't used mutably, so issue a warning that this // didn't need to be mutable. @@ -83,7 +84,11 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { hir_id, span, "variable does not need to be mutable") - .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()) + .span_suggestion_short_with_applicability( + mut_span, + "remove this `mut`", + String::new(), + Applicability::MachineApplicable) .emit(); } } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc_borrowck/dataflow.rs similarity index 96% rename from src/librustc/middle/dataflow.rs rename to src/librustc_borrowck/dataflow.rs index b949fd0212..832b69cb2a 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc_borrowck/dataflow.rs @@ -14,9 +14,9 @@ //! and thus uses bitvectors. Your job is simply to specify the so-called //! GEN and KILL bits for each expression. -use cfg; -use cfg::CFGIndex; -use ty::TyCtxt; +use rustc::cfg; +use rustc::cfg::CFGIndex; +use rustc::ty::TyCtxt; use std::io; use std::mem; use std::usize; @@ -24,10 +24,10 @@ use syntax::print::pprust::PrintState; use rustc_data_structures::graph::implementation::OUTGOING; -use util::nodemap::FxHashMap; -use hir; -use hir::intravisit::{self, IdRange}; -use hir::print as pprust; +use rustc::util::nodemap::FxHashMap; +use rustc::hir; +use rustc::hir::intravisit::{self, IdRange}; +use rustc::hir::print as pprust; #[derive(Copy, Clone, Debug)] @@ -117,12 +117,12 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O ps: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { let id = match node { - pprust::NodeName(_) => return Ok(()), - pprust::NodeExpr(expr) => expr.hir_id.local_id, - pprust::NodeBlock(blk) => blk.hir_id.local_id, - pprust::NodeItem(_) | - pprust::NodeSubItem(_) => return Ok(()), - pprust::NodePat(pat) => pat.hir_id.local_id + pprust::AnnNode::Name(_) => return Ok(()), + pprust::AnnNode::Expr(expr) => expr.hir_id.local_id, + pprust::AnnNode::Block(blk) => blk.hir_id.local_id, + pprust::AnnNode::Item(_) | + pprust::AnnNode::SubItem(_) => return Ok(()), + pprust::AnnNode::Pat(pat) => pat.hir_id.local_id }; if !self.has_bitset_for_local_id(id) { @@ -140,21 +140,21 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O let gens_str = if gens.iter().any(|&u| u != 0) { format!(" gen: {}", bits_to_string(gens)) } else { - "".to_string() + String::new() }; let action_kills = &self.action_kills[start .. end]; let action_kills_str = if action_kills.iter().any(|&u| u != 0) { format!(" action_kill: {}", bits_to_string(action_kills)) } else { - "".to_string() + String::new() }; let scope_kills = &self.scope_kills[start .. end]; let scope_kills_str = if scope_kills.iter().any(|&u| u != 0) { format!(" scope_kill: {}", bits_to_string(scope_kills)) } else { - "".to_string() + String::new() }; ps.synth_comment( @@ -181,7 +181,7 @@ fn build_local_id_to_index(body: Option<&hir::Body>, cfg.graph.each_node(|node_idx, node| { if let cfg::CFGNodeData::AST(id) = node.data { - index.entry(id).or_insert(vec![]).push(node_idx); + index.entry(id).or_default().push(node_idx); } true }); @@ -193,7 +193,7 @@ fn build_local_id_to_index(body: Option<&hir::Body>, fn add_entries_from_fn_body(index: &mut FxHashMap>, body: &hir::Body, entry: CFGIndex) { - use hir::intravisit::Visitor; + use rustc::hir::intravisit::Visitor; struct Formals<'a> { entry: CFGIndex, @@ -209,7 +209,7 @@ fn build_local_id_to_index(body: Option<&hir::Body>, } fn visit_pat(&mut self, p: &hir::Pat) { - self.index.entry(p.hir_id.local_id).or_insert(vec![]).push(self.entry); + self.index.entry(p.hir_id.local_id).or_default().push(self.entry); intravisit::walk_pat(self, p) } } diff --git a/src/librustc_borrowck/graphviz.rs b/src/librustc_borrowck/graphviz.rs index 22867ba5b5..c177ed85c3 100644 --- a/src/librustc_borrowck/graphviz.rs +++ b/src/librustc_borrowck/graphviz.rs @@ -21,7 +21,7 @@ use borrowck; use borrowck::{BorrowckCtxt, LoanPath}; use dot; use rustc::cfg::CFGIndex; -use rustc::middle::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit}; +use dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit}; use std::rc::Rc; use dot::IntoCow; @@ -53,7 +53,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> { fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String { let id = n.1.data.id(); debug!("dataflow_for({:?}, id={:?}) {:?}", e, id, self.variants); - let mut sets = "".to_string(); + let mut sets = String::new(); let mut seen_one = false; for &variant in &self.variants { if seen_one { sets.push_str(" "); } else { seen_one = true; } diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index a5a20af0e4..16da8c8a3b 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -14,7 +14,7 @@ #![allow(non_camel_case_types)] -#![feature(from_ref)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(quote)] #![recursion_limit="256"] @@ -39,4 +39,6 @@ mod borrowck; pub mod graphviz; +mod dataflow; + pub use borrowck::provide; diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 6ddae57e33..b711502b14 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -10,39 +10,13 @@ crate-type = ["dylib"] test = false [dependencies] -bitflags = "1.0.1" cc = "1.0.1" -flate2 = "1.0" -jobserver = "0.1.5" -libc = "0.2" -log = "0.4" num_cpus = "1.0" -rustc = { path = "../librustc" } rustc-demangle = "0.1.4" -rustc_allocator = { path = "../librustc_allocator" } -rustc_apfloat = { path = "../librustc_apfloat" } -rustc_target = { path = "../librustc_target" } -rustc_data_structures = { path = "../librustc_data_structures" } -rustc_errors = { path = "../librustc_errors" } -rustc_incremental = { path = "../librustc_incremental" } rustc_llvm = { path = "../librustc_llvm" } -rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } -rustc_codegen_utils = { path = "../librustc_codegen_utils" } -rustc_mir = { path = "../librustc_mir" } -serialize = { path = "../libserialize" } -syntax = { path = "../libsyntax" } -syntax_pos = { path = "../libsyntax_pos" } -tempfile = "3.0" - -# not actually used but needed to make sure we enable the same feature set as -# winapi used in librustc -env_logger = { version = "0.5", default-features = false } +memmap = "0.6" [features] -# Used to communicate the feature to `rustc_target` in the same manner that the -# `rustc` driver script communicate this. -jemalloc = ["rustc_target/jemalloc"] - # This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm` # when this option is enabled or not. That way we can build two, cache two # artifacts, and have nice speedy rebuilds. diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index f1a6e9913d..684f2b3588 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef, AttributePlace}; +use llvm::{self, AttributePlace}; use base; use builder::{Builder, MemFlags}; use common::{ty_fn_sig, C_usize}; @@ -17,6 +17,7 @@ use mir::place::PlaceRef; use mir::operand::OperandValue; use type_::Type; use type_of::{LayoutLlvmExt, PointerKind}; +use value::Value; use rustc_target::abi::{LayoutOf, Size, TyLayout}; use rustc::ty::{self, Ty}; @@ -46,12 +47,12 @@ impl ArgAttributeExt for ArgAttribute { } pub trait ArgAttributesExt { - fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef); - fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef); + fn apply_llfn(&self, idx: AttributePlace, llfn: &Value); + fn apply_callsite(&self, idx: AttributePlace, callsite: &Value); } impl ArgAttributesExt for ArgAttributes { - fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { + fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -76,7 +77,7 @@ impl ArgAttributesExt for ArgAttributes { } } - fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { + fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -103,11 +104,11 @@ impl ArgAttributesExt for ArgAttributes { } pub trait LlvmType { - fn llvm_type(&self, cx: &CodegenCx) -> Type; + fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; } impl LlvmType for Reg { - fn llvm_type(&self, cx: &CodegenCx) -> Type { + fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { match self.kind { RegKind::Integer => Type::ix(cx, self.size.bits()), RegKind::Float => { @@ -118,14 +119,14 @@ impl LlvmType for Reg { } } RegKind::Vector => { - Type::vector(&Type::i8(cx), self.size.bytes()) + Type::vector(Type::i8(cx), self.size.bytes()) } } } } impl LlvmType for CastTarget { - fn llvm_type(&self, cx: &CodegenCx) -> Type { + fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { let rest_ll_unit = self.rest.unit.llvm_type(cx); let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 { (0, 0) @@ -142,7 +143,7 @@ impl LlvmType for CastTarget { // Simplify to array when all chunks are the same size and type if rem_bytes == 0 { - return Type::array(&rest_ll_unit, rest_count); + return Type::array(rest_ll_unit, rest_count); } } @@ -164,16 +165,16 @@ impl LlvmType for CastTarget { } } -pub trait ArgTypeExt<'a, 'tcx> { - fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; - fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>); - fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>); +pub trait ArgTypeExt<'ll, 'tcx> { + fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; + fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>); + fn store_fn_arg(&self, bx: &Builder<'_, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>); } -impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { +impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { /// Get 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<'a, 'tcx>) -> Type { + fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { self.layout.llvm_type(cx) } @@ -181,13 +182,15 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { /// 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. - fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) { + fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>) { if self.is_ignore() { return; } let cx = bx.cx; - if self.is_indirect() { - OperandValue::Ref(val, self.layout.align).store(bx, dst) + if self.is_sized_indirect() { + OperandValue::Ref(val, None, self.layout.align).store(bx, dst) + } else if self.is_unsized_indirect() { + bug!("unsized ArgType 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}. @@ -234,7 +237,7 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { } } - fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) { + fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>) { let mut next = || { let val = llvm::get_param(bx.llfn(), *idx as c_uint); *idx += 1; @@ -245,39 +248,42 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { PassMode::Pair(..) => { OperandValue::Pair(next(), next()).store(bx, dst); } - PassMode::Direct(_) | PassMode::Indirect(_) | PassMode::Cast(_) => { + PassMode::Indirect(_, Some(_)) => { + OperandValue::Ref(next(), Some(next()), self.layout.align).store(bx, dst); + } + PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => { self.store(bx, next(), dst); } } } } -pub trait FnTypeExt<'a, 'tcx> { - fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>) +pub trait FnTypeExt<'tcx> { + fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self; - fn new(cx: &CodegenCx<'a, 'tcx>, + fn new(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - fn new_vtable(cx: &CodegenCx<'a, 'tcx>, + fn new_vtable(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; fn new_internal( - cx: &CodegenCx<'a, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>], mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgType<'tcx, Ty<'tcx>>, ) -> Self; fn adjust_for_abi(&mut self, - cx: &CodegenCx<'a, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, abi: Abi); - fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; + fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_cconv(&self) -> llvm::CallConv; - fn apply_attrs_llfn(&self, llfn: ValueRef); - fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef); + fn apply_attrs_llfn(&self, llfn: &'ll Value); + fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value); } -impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { - fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>) +impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { + fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self { let fn_ty = instance.ty(cx.tcx); let sig = ty_fn_sig(cx, fn_ty); @@ -285,7 +291,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { FnType::new(cx, sig, &[]) } - fn new(cx: &CodegenCx<'a, 'tcx>, + fn new(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { FnType::new_internal(cx, sig, extra_args, |ty, _| { @@ -293,7 +299,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { }) } - fn new_vtable(cx: &CodegenCx<'a, 'tcx>, + fn new_vtable(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| { @@ -301,6 +307,10 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { // Don't pass the vtable, it's not an argument of the virtual fn. // Instead, pass just the (thin pointer) first field of `*dyn Trait`. if arg_idx == Some(0) { + if layout.is_unsized() { + unimplemented!("by-value trait object is not \ + yet implemented in #![feature(unsized_locals)]"); + } // FIXME(eddyb) `layout.field(cx, 0)` is not enough because e.g. // `Box` has a few newtype wrappers around the raw // pointer, so we'd have to "dig down" to find `*dyn Trait`. @@ -316,7 +326,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } fn new_internal( - cx: &CodegenCx<'a, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>], mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgType<'tcx, Ty<'tcx>>, @@ -354,7 +364,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { assert!(!sig.variadic && extra_args.is_empty()); match sig.inputs().last().unwrap().sty { - ty::TyTuple(ref tupled_arguments) => { + ty::Tuple(ref tupled_arguments) => { inputs = &sig.inputs()[0..sig.inputs().len() - 1]; tupled_arguments } @@ -497,7 +507,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } fn adjust_for_abi(&mut self, - cx: &CodegenCx<'a, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, abi: Abi) { if abi == Abi::Unadjusted { return } @@ -537,7 +547,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } let size = arg.layout.size; - if size > layout::Pointer.size(cx) { + if arg.layout.is_unsized() || size > layout::Pointer.size(cx) { arg.make_indirect(); } else { // We want to pass small aggregates as immediates, but using @@ -553,7 +563,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { for arg in &mut self.args { fixup(arg); } - if let PassMode::Indirect(ref mut attrs) = self.ret.mode { + if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode { attrs.set(ArgAttribute::StructRet); } return; @@ -564,13 +574,13 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } } - fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { + 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 } + if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 } ).sum(); let mut llargument_tys = Vec::with_capacity( - if let PassMode::Indirect(_) = self.ret.mode { 1 } else { 0 } + args_capacity + if let PassMode::Indirect(..) = self.ret.mode { 1 } else { 0 } + args_capacity ); let llreturn_ty = match self.ret.mode { @@ -579,7 +589,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { self.ret.layout.immediate_llvm_type(cx) } PassMode::Cast(cast) => cast.llvm_type(cx), - PassMode::Indirect(_) => { + PassMode::Indirect(..) => { llargument_tys.push(self.ret.memory_ty(cx).ptr_to()); Type::void(cx) } @@ -599,16 +609,23 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } + PassMode::Indirect(_, Some(_)) => { + let ptr_ty = cx.tcx.mk_mut_ptr(arg.layout.ty); + let ptr_layout = cx.layout_of(ptr_ty); + llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true)); + llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 1, true)); + continue; + } PassMode::Cast(cast) => cast.llvm_type(cx), - PassMode::Indirect(_) => arg.memory_ty(cx).ptr_to(), + PassMode::Indirect(_, None) => arg.memory_ty(cx).ptr_to(), }; llargument_tys.push(llarg_ty); } if self.variadic { - Type::variadic_func(&llargument_tys, &llreturn_ty) + Type::variadic_func(&llargument_tys, llreturn_ty) } else { - Type::func(&llargument_tys, &llreturn_ty) + Type::func(&llargument_tys, llreturn_ty) } } @@ -629,7 +646,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } } - fn apply_attrs_llfn(&self, llfn: ValueRef) { + fn apply_attrs_llfn(&self, llfn: &'ll Value) { let mut i = 0; let mut apply = |attrs: &ArgAttributes| { attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn); @@ -639,7 +656,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { PassMode::Direct(ref attrs) => { attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn); } - PassMode::Indirect(ref attrs) => apply(attrs), + PassMode::Indirect(ref attrs, _) => apply(attrs), _ => {} } for arg in &self.args { @@ -649,7 +666,11 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { match arg.mode { PassMode::Ignore => {} PassMode::Direct(ref attrs) | - PassMode::Indirect(ref attrs) => apply(attrs), + PassMode::Indirect(ref attrs, None) => apply(attrs), + PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { + apply(attrs); + apply(extra_attrs); + } PassMode::Pair(ref a, ref b) => { apply(a); apply(b); @@ -659,7 +680,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } } - fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) { + fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value) { let mut i = 0; let mut apply = |attrs: &ArgAttributes| { attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite); @@ -669,7 +690,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { PassMode::Direct(ref attrs) => { attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite); } - PassMode::Indirect(ref attrs) => apply(attrs), + PassMode::Indirect(ref attrs, _) => apply(attrs), _ => {} } if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi { @@ -693,7 +714,11 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { match arg.mode { PassMode::Ignore => {} PassMode::Direct(ref attrs) | - PassMode::Indirect(ref attrs) => apply(attrs), + PassMode::Indirect(ref attrs, None) => apply(attrs), + PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { + apply(attrs); + apply(extra_attrs); + } PassMode::Pair(ref a, ref b) => { apply(a); apply(b); diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index eeb02e948f..0beb8a8844 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::ffi::CString; -use std::ptr; use attributes; use libc::c_uint; @@ -21,8 +20,8 @@ use ModuleLlvm; use llvm::{self, False, True}; pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) { - let llcx = mods.llcx; - let llmod = mods.llmod; + let llcx = &*mods.llcx; + let llmod = mods.llmod(); let usize = match &tcx.sess.target.target.target_pointer_width[..] { "16" => llvm::LLVMInt16TypeInContext(llcx), "32" => llvm::LLVMInt32TypeInContext(llcx), @@ -68,14 +67,15 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind if tcx.sess.target.target.options.default_hidden_visibility { llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); } - if tcx.sess.target.target.options.requires_uwtable { - attributes::emit_uwtable(llfn, true); - } + if tcx.sess.target.target.options.requires_uwtable { + attributes::emit_uwtable(llfn, true); + } let callee = CString::new(kind.fn_name(method.name)).unwrap(); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr(), ty); + llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, @@ -90,7 +90,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind callee, args.as_ptr(), args.len() as c_uint, - ptr::null_mut(), + None, "\0".as_ptr() as *const _); llvm::LLVMSetTailCall(ret, True); if output.is_some() { diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index 82f068106f..5d27f8eab3 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef}; +use llvm; use common::*; use type_::Type; use type_of::LayoutLlvmExt; use builder::Builder; +use value::Value; use rustc::hir; @@ -24,11 +25,11 @@ use syntax::ast::AsmDialect; use libc::{c_uint, c_char}; // Take an inline assembly expression and splat it out via LLVM -pub fn codegen_inline_asm<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, +pub fn codegen_inline_asm( + bx: &Builder<'a, 'll, 'tcx>, ia: &hir::InlineAsm, - outputs: Vec>, - mut inputs: Vec + outputs: Vec>, + mut inputs: Vec<&'ll Value> ) { let mut ext_constraints = vec![]; let mut output_types = vec![]; @@ -111,7 +112,7 @@ pub fn codegen_inline_asm<'a, 'tcx>( let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx, key.as_ptr() as *const c_char, key.len() as c_uint); - let val: llvm::ValueRef = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32); + let val: &'ll Value = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32); llvm::LLVMSetMetadata(r, kind, llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1)); diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 3b5f927d52..51380db5b2 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -9,33 +9,40 @@ // except according to those terms. //! Set and unset common attributes on LLVM values. -use std::ffi::{CStr, CString}; +use std::ffi::CString; -use rustc::hir::CodegenFnAttrFlags; +use rustc::hir::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::Session; use rustc::session::config::Sanitizer; use rustc::ty::TyCtxt; +use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; use rustc_data_structures::sync::Lrc; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::PanicStrategy; use attributes; -use llvm::{self, Attribute, ValueRef}; +use llvm::{self, Attribute}; use llvm::AttributePlace::Function; use llvm_util; pub use syntax::attr::{self, InlineAttr}; + use context::CodegenCx; +use value::Value; /// Mark LLVM function to use provided inline heuristic. #[inline] -pub fn inline(val: ValueRef, inline: InlineAttr) { +pub fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { use self::InlineAttr::*; match inline { Hint => Attribute::InlineHint.apply_llfn(Function, val), Always => Attribute::AlwaysInline.apply_llfn(Function, val), - Never => Attribute::NoInline.apply_llfn(Function, val), + Never => { + if cx.tcx().sess.target.target.arch != "amdgpu" { + Attribute::NoInline.apply_llfn(Function, val); + } + }, None => { Attribute::InlineHint.unapply_llfn(Function, val); Attribute::AlwaysInline.unapply_llfn(Function, val); @@ -46,38 +53,38 @@ pub fn inline(val: ValueRef, inline: InlineAttr) { /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function. #[inline] -pub fn emit_uwtable(val: ValueRef, emit: bool) { +pub fn emit_uwtable(val: &'ll Value, emit: bool) { Attribute::UWTable.toggle_llfn(Function, val, emit); } /// Tell LLVM whether the function can or cannot unwind. #[inline] -pub fn unwind(val: ValueRef, can_unwind: bool) { +pub fn unwind(val: &'ll Value, can_unwind: bool) { Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind); } /// Tell LLVM whether it should optimize function for size. #[inline] #[allow(dead_code)] // possibly useful function -pub fn set_optimize_for_size(val: ValueRef, optimize: bool) { +pub fn set_optimize_for_size(val: &'ll Value, optimize: bool) { Attribute::OptimizeForSize.toggle_llfn(Function, val, optimize); } /// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue. #[inline] -pub fn naked(val: ValueRef, is_naked: bool) { +pub fn naked(val: &'ll Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); } -pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) { +pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if cx.sess().must_not_eliminate_frame_pointers() { llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, - cstr("no-frame-pointer-elim\0"), cstr("true\0")); + const_cstr!("no-frame-pointer-elim"), const_cstr!("true")); } } -pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) { +pub 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 { @@ -106,7 +113,7 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) { // This is defined in the `compiler-builtins` crate for each architecture. llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, - cstr("probe-stack\0"), cstr("__rust_probestack\0")); + const_cstr!("probe-stack"), const_cstr!("__rust_probestack")); } pub fn llvm_target_features(sess: &Session) -> impl Iterator { @@ -121,12 +128,48 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator { .filter(|l| !l.is_empty()) } +pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + let cpu = llvm_util::target_cpu(cx.tcx.sess); + let target_cpu = CString::new(cpu).unwrap(); + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + const_cstr!("target-cpu"), + target_cpu.as_c_str()); +} + /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. -pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { - let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(id); - - inline(llfn, codegen_fn_attrs.inline); +pub fn from_fn_attrs( + cx: &CodegenCx<'ll, '_>, + llfn: &'ll Value, + id: Option, +) { + let codegen_fn_attrs = id.map(|id| cx.tcx.codegen_fn_attrs(id)) + .unwrap_or(CodegenFnAttrs::new()); + + inline(cx, llfn, codegen_fn_attrs.inline); + + // The `uwtable` attribute according to LLVM is: + // + // This attribute indicates that the ABI being targeted requires that an + // unwind table entry be produced for this function even if we can show + // that no exceptions passes by it. This is normally the case for the + // ELF x86-64 abi, but it can be disabled for some compilation units. + // + // Typically when we're compiling with `-C panic=abort` (which implies this + // `no_landing_pads` check) we don't need `uwtable` because we can't + // generate any exceptions! On Windows, however, exceptions include other + // events such as illegal instructions, segfaults, etc. This means that on + // Windows we end up still needing the `uwtable` attribute even if the `-C + // panic=abort` flag is passed. + // + // You can also find more info on why Windows is whitelisted here in: + // https://bugzilla.mozilla.org/show_bug.cgi?id=1302078 + if !cx.sess().no_landing_pads() || + cx.sess().target.target.options.requires_uwtable { + attributes::emit_uwtable(llfn, true); + } set_frame_pointer_elimination(cx, llfn); set_probestack(cx, llfn); @@ -151,7 +194,7 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { // *in Rust code* may unwind. Foreign items like `extern "C" { // fn foo(); }` are assumed not to unwind **unless** they have // a `#[unwind]` attribute. - } else if !cx.tcx.is_foreign_item(id) { + } else if id.map(|id| !cx.tcx.is_foreign_item(id)).unwrap_or(false) { Some(true) } else { None @@ -165,6 +208,15 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { Some(true) | None => {} } + // Always annotate functions with the target-cpu they are compiled for. + // Without this, ThinLTO won't inline Rust functions into Clang generated + // functions (because Clang annotates functions this way too). + // NOTE: For now we just apply this if -Zcross-lang-lto is specified, since + // it introduce a little overhead and isn't really necessary otherwise. + if cx.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() { + apply_target_cpu_attr(cx, llfn); + } + let features = llvm_target_features(cx.tcx.sess) .map(|s| s.to_string()) .chain( @@ -182,28 +234,26 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { let val = CString::new(features).unwrap(); llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, - cstr("target-features\0"), &val); + const_cstr!("target-features"), &val); } // 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 cx.tcx.sess.target.target.arch == "wasm32" { - if let Some(module) = wasm_import_module(cx.tcx, id) { - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - cstr("wasm-import-module\0"), - &module, - ); + 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, + ); + } } } } -fn cstr(s: &'static str) -> &CStr { - CStr::from_bytes_with_nul(s.as_bytes()).expect("null-terminated string") -} - pub fn provide(providers: &mut Providers) { providers.target_features_whitelist = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index b99835cb5c..af9efc6d7c 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -226,10 +226,13 @@ impl<'a> ArchiveBuilder<'a> { } fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> { - let mut archives = Vec::new(); + let removals = mem::replace(&mut self.removals, Vec::new()); + let mut additions = mem::replace(&mut self.additions, Vec::new()); let mut strings = Vec::new(); let mut members = Vec::new(); - let removals = mem::replace(&mut self.removals, Vec::new()); + + let dst = CString::new(self.config.dst.to_str().unwrap())?; + let should_update_symbols = self.should_update_symbols; unsafe { if let Some(archive) = self.src_archive() { @@ -246,22 +249,22 @@ impl<'a> ArchiveBuilder<'a> { let name = CString::new(child_name)?; members.push(llvm::LLVMRustArchiveMemberNew(ptr::null(), name.as_ptr(), - child.raw())); + Some(child.raw))); strings.push(name); } } - for addition in mem::replace(&mut self.additions, Vec::new()) { + for addition in &mut additions { match addition { Addition::File { path, name_in_archive } => { let path = CString::new(path.to_str().unwrap())?; - let name = CString::new(name_in_archive)?; + let name = CString::new(name_in_archive.clone())?; members.push(llvm::LLVMRustArchiveMemberNew(path.as_ptr(), name.as_ptr(), - ptr::null_mut())); + None)); strings.push(path); strings.push(name); } - Addition::Archive { archive, mut skip } => { + Addition::Archive { archive, skip } => { for child in archive.iter() { let child = child.map_err(string_to_io_error)?; if !is_relevant_child(&child) { @@ -284,21 +287,18 @@ impl<'a> ArchiveBuilder<'a> { let name = CString::new(child_name)?; let m = llvm::LLVMRustArchiveMemberNew(ptr::null(), name.as_ptr(), - child.raw()); + Some(child.raw)); members.push(m); strings.push(name); } - archives.push(archive); } } } - let dst = self.config.dst.to_str().unwrap().as_bytes(); - let dst = CString::new(dst)?; let r = llvm::LLVMRustWriteArchive(dst.as_ptr(), members.len() as libc::size_t, - members.as_ptr(), - self.should_update_symbols, + members.as_ptr() as *const &_, + should_update_symbols, kind); let ret = if r.into_result().is_err() { let err = llvm::LLVMRustGetLastError(); diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 845a66c6e4..8248385c12 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -17,7 +17,7 @@ use super::command::Command; use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; -use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, PrintRequest}; +use rustc::session::config::{self, DebugInfo, OutputFilenames, OutputType, PrintRequest}; use rustc::session::config::{RUST_CGU_EXT, Lto}; use rustc::session::filesearch; use rustc::session::search_paths::PathKind; @@ -26,7 +26,7 @@ use rustc::middle::cstore::{NativeLibrary, LibSource, NativeLibraryKind}; use rustc::middle::dependency_format::Linkage; use {CodegenResults, CrateInfo}; use rustc::util::common::time; -use rustc::util::fs::fix_windows_verbatim_for_gcc; +use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc::hir::def_id::CrateNum; use tempfile::{Builder as TempFileBuilder, TempDir}; use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor}; @@ -46,21 +46,15 @@ use std::process::{Output, Stdio}; use std::str; use syntax::attr; -/// The LLVM module name containing crate-metadata. This includes a `.` on -/// purpose, so it cannot clash with the name of a user-defined module. -pub const METADATA_MODULE_NAME: &'static str = "crate.metadata"; - -// same as for metadata above, but for allocator shim -pub const ALLOCATOR_MODULE_NAME: &'static str = "crate.allocator"; - pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target, - invalid_output_for_target, build_link_meta, out_filename, - check_file_is_writeable}; + invalid_output_for_target, out_filename, check_file_is_writeable}; // The third parameter is for env vars, used on windows to set up the // path for MSVC to find its DLLs, and gcc to find its bundled // toolchain -pub fn get_linker(sess: &Session) -> (PathBuf, Command) { +pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathBuf, Command) { + let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); + // If our linker looks like a batch script on Windows then to execute this // we'll need to spawn `cmd` explicitly. This is primarily done to handle // emscripten where the linker is `emcc.bat` and needs to be spawned as @@ -69,36 +63,19 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command) { // This worked historically but is needed manually since #42436 (regression // was tagged as #42791) and some more info can be found on #44443 for // emscripten itself. - let cmd = |linker: &Path| { - if let Some(linker) = linker.to_str() { - if cfg!(windows) && linker.ends_with(".bat") { - return Command::bat_script(linker) - } - } - match sess.linker_flavor() { + let mut cmd = match linker.to_str() { + Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker), + _ => match flavor { LinkerFlavor::Lld(f) => Command::lld(linker, f), + LinkerFlavor::Msvc + if sess.opts.cg.linker.is_none() && sess.target.target.options.linker.is_none() => + { + Command::new(msvc_tool.as_ref().map(|t| t.path()).unwrap_or(linker)) + }, _ => Command::new(linker), - } }; - let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); - - let linker_path = sess.opts.cg.linker.as_ref().map(|s| &**s) - .or(sess.target.target.options.linker.as_ref().map(|s| s.as_ref())) - .unwrap_or(match sess.linker_flavor() { - LinkerFlavor::Msvc => { - msvc_tool.as_ref().map(|t| t.path()).unwrap_or("link.exe".as_ref()) - } - LinkerFlavor::Em if cfg!(windows) => "emcc.bat".as_ref(), - LinkerFlavor::Em => "emcc".as_ref(), - LinkerFlavor::Gcc => "cc".as_ref(), - LinkerFlavor::Ld => "ld".as_ref(), - LinkerFlavor::Lld(_) => "lld".as_ref(), - }); - - let mut cmd = cmd(linker_path); - // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. let mut new_path = sess.host_filesearch(PathKind::All) @@ -125,7 +102,7 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command) { } cmd.env("PATH", env::join_paths(new_path).unwrap()); - (linker_path.to_path_buf(), cmd) + (linker.to_path_buf(), cmd) } pub fn remove(sess: &Session, path: &Path) { @@ -151,7 +128,7 @@ pub(crate) fn link_binary(sess: &Session, let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen()) && !output_metadata && - crate_type == config::CrateTypeExecutable { + crate_type == config::CrateType::Executable { continue; } @@ -200,7 +177,7 @@ pub(crate) fn link_binary(sess: &Session, /// split-dwarf like schemes. fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { // If the objects don't have debuginfo there's nothing to preserve. - if sess.opts.debuginfo == NoDebugInfo { + if sess.opts.debuginfo == DebugInfo::None { return false } @@ -208,7 +185,7 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { // the objects as they're losslessly contained inside the archives. let output_linked = sess.crate_types.borrow() .iter() - .any(|x| *x != config::CrateTypeRlib && *x != config::CrateTypeStaticlib); + .any(|x| *x != config::CrateType::Rlib && *x != config::CrateType::Staticlib); if !output_linked { return false } @@ -255,10 +232,10 @@ pub(crate) fn each_linked_rlib(sess: &Session, f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> { let crates = info.used_crates_static.iter(); let fmts = sess.dependency_formats.borrow(); - let fmts = fmts.get(&config::CrateTypeExecutable) - .or_else(|| fmts.get(&config::CrateTypeStaticlib)) - .or_else(|| fmts.get(&config::CrateTypeCdylib)) - .or_else(|| fmts.get(&config::CrateTypeProcMacro)); + let fmts = fmts.get(&config::CrateType::Executable) + .or_else(|| fmts.get(&config::CrateType::Staticlib)) + .or_else(|| fmts.get(&config::CrateType::Cdylib)) + .or_else(|| fmts.get(&config::CrateType::ProcMacro)); let fmts = match fmts { Some(f) => f, None => return Err("could not find formats for rlibs".to_string()) @@ -344,14 +321,14 @@ fn link_binary_output(sess: &Session, if outputs.outputs.should_codegen() { let out_filename = out_filename(sess, crate_type, outputs, crate_name); match crate_type { - config::CrateTypeRlib => { + config::CrateType::Rlib => { link_rlib(sess, codegen_results, RlibFlavor::Normal, &out_filename, &tmpdir).build(); } - config::CrateTypeStaticlib => { + config::CrateType::Staticlib => { link_staticlib(sess, codegen_results, &out_filename, &tmpdir); } _ => { @@ -563,7 +540,7 @@ fn link_staticlib(sess: &Session, }); ab.add_rlib(path, &name.as_str(), - is_full_lto_enabled(sess) && + are_upstream_rust_objects_already_included(sess) && !ignored_for_lto(sess, &codegen_results.crate_info, cnum), skip_object_files).unwrap(); @@ -615,6 +592,69 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) { } } +pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { + fn infer_from( + sess: &Session, + linker: Option, + flavor: Option, + ) -> Option<(PathBuf, LinkerFlavor)> { + match (linker, flavor) { + (Some(linker), Some(flavor)) => Some((linker, flavor)), + // only the linker flavor is known; use the default linker for the selected flavor + (None, Some(flavor)) => Some((PathBuf::from(match flavor { + LinkerFlavor::Em => if cfg!(windows) { "emcc.bat" } else { "emcc" }, + LinkerFlavor::Gcc => "cc", + LinkerFlavor::Ld => "ld", + LinkerFlavor::Msvc => "link.exe", + LinkerFlavor::Lld(_) => "lld", + }), flavor)), + (Some(linker), None) => { + let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| { + sess.fatal("couldn't extract file stem from specified linker"); + }).to_owned(); + + let flavor = if stem == "emcc" { + LinkerFlavor::Em + } else if stem == "gcc" || stem.ends_with("-gcc") { + LinkerFlavor::Gcc + } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") { + LinkerFlavor::Ld + } else if stem == "link" || stem == "lld-link" { + LinkerFlavor::Msvc + } else if stem == "lld" || stem == "rust-lld" { + LinkerFlavor::Lld(sess.target.target.options.lld_flavor) + } else { + // fall back to the value in the target spec + sess.target.target.linker_flavor + }; + + Some((linker, flavor)) + }, + (None, None) => None, + } + } + + // linker and linker flavor specified via command line have precedence over what the target + // specification specifies + if let Some(ret) = infer_from( + sess, + sess.opts.cg.linker.clone(), + sess.opts.debugging_opts.linker_flavor, + ) { + return ret; + } + + if let Some(ret) = infer_from( + sess, + sess.target.target.options.linker.clone().map(PathBuf::from), + Some(sess.target.target.linker_flavor), + ) { + return ret; + } + + bug!("Not enough information provided to determine how to invoke the linker"); +} + // Create a dynamic library or executable // // This will invoke the system linker/cc to create the resulting file. This @@ -625,10 +665,10 @@ fn link_natively(sess: &Session, codegen_results: &CodegenResults, tmpdir: &Path) { info!("preparing {:?} to {:?}", crate_type, out_filename); - let flavor = sess.linker_flavor(); + let (linker, flavor) = linker_and_flavor(sess); // The invocations of cc share some flags across platforms - let (pname, mut cmd) = get_linker(sess); + let (pname, mut cmd) = get_linker(sess, &linker, flavor); let root = sess.target_filesearch(PathKind::Native).get_lib_path(); if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) { @@ -644,7 +684,7 @@ fn link_natively(sess: &Session, } cmd.args(&sess.opts.debugging_opts.pre_link_arg); - let pre_link_objects = if crate_type == config::CrateTypeExecutable { + let pre_link_objects = if crate_type == config::CrateType::Executable { &sess.target.target.options.pre_link_objects_exe } else { &sess.target.target.options.pre_link_objects_dll @@ -653,7 +693,7 @@ fn link_natively(sess: &Session, cmd.arg(root.join(obj)); } - if crate_type == config::CrateTypeExecutable && sess.crt_static() { + if crate_type == config::CrateType::Executable && sess.crt_static() { for obj in &sess.target.target.options.pre_link_objects_exe_crt { cmd.arg(root.join(obj)); } @@ -669,8 +709,8 @@ fn link_natively(sess: &Session, } { - let mut linker = codegen_results.linker_info.to_linker(cmd, &sess); - link_args(&mut *linker, sess, crate_type, tmpdir, + let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor); + link_args(&mut *linker, flavor, sess, crate_type, tmpdir, out_filename, codegen_results); cmd = linker.finalize(); } @@ -742,7 +782,7 @@ fn link_natively(sess: &Session, // linking executables as pie. Different versions of gcc seem to use // different quotes in the error message so don't check for them. if sess.target.target.options.linker_is_gnu && - sess.linker_flavor() != LinkerFlavor::Ld && + flavor != LinkerFlavor::Ld && (out.contains("unrecognized command line option") || out.contains("unknown argument")) && out.contains("-no-pie") && @@ -834,7 +874,7 @@ fn link_natively(sess: &Session, // the symbols. Note, though, that if the object files are being preserved // for their debug information there's no need for us to run dsymutil. if sess.target.target.options.is_like_osx && - sess.opts.debuginfo != NoDebugInfo && + sess.opts.debuginfo != DebugInfo::None && !preserve_objects_for_their_debuginfo(sess) { match Command::new("dsymutil").arg(out_filename).output() { @@ -991,6 +1031,7 @@ fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: & } fn link_args(cmd: &mut dyn Linker, + flavor: LinkerFlavor, sess: &Session, crate_type: config::CrateType, tmpdir: &Path, @@ -1013,7 +1054,7 @@ fn link_args(cmd: &mut dyn Linker, } cmd.output_filename(out_filename); - if crate_type == config::CrateTypeExecutable && + if crate_type == config::CrateType::Executable && sess.target.target.options.is_like_windows { if let Some(ref s) = codegen_results.windows_subsystem { cmd.subsystem(s); @@ -1022,7 +1063,7 @@ fn link_args(cmd: &mut dyn Linker, // If we're building a dynamic library then some platforms need to make sure // that all symbols are exported correctly from the dynamic library. - if crate_type != config::CrateTypeExecutable || + if crate_type != config::CrateType::Executable || sess.target.target.options.is_like_emscripten { cmd.export_symbols(tmpdir, crate_type); } @@ -1030,8 +1071,8 @@ fn link_args(cmd: &mut dyn Linker, // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main // object file, so we link that in here. - if crate_type == config::CrateTypeDylib || - crate_type == config::CrateTypeProcMacro { + if crate_type == config::CrateType::Dylib || + crate_type == config::CrateType::ProcMacro { if let Some(obj) = codegen_results.metadata_module.object.as_ref() { cmd.add_object(obj); } @@ -1047,13 +1088,13 @@ fn link_args(cmd: &mut dyn Linker, // Try to strip as much out of the generated object by removing unused // sections if possible. See more comments in linker.rs if !sess.opts.cg.link_dead_code { - let keep_metadata = crate_type == config::CrateTypeDylib; + let keep_metadata = crate_type == config::CrateType::Dylib; cmd.gc_sections(keep_metadata); } let used_link_args = &codegen_results.crate_info.link_args; - if crate_type == config::CrateTypeExecutable { + if crate_type == config::CrateType::Executable { let mut position_independent_executable = false; if t.options.position_independent_executables { @@ -1075,7 +1116,7 @@ fn link_args(cmd: &mut dyn Linker, // independent executables by default. We have to pass -no-pie to // explicitly turn that off. Not applicable to ld. if sess.target.target.options.linker_is_gnu - && sess.linker_flavor() != LinkerFlavor::Ld { + && flavor != LinkerFlavor::Ld { cmd.no_position_independent_executable(); } } @@ -1145,10 +1186,10 @@ fn link_args(cmd: &mut dyn Linker, add_upstream_native_libraries(cmd, sess, codegen_results, crate_type); // Tell the linker what we're doing. - if crate_type != config::CrateTypeExecutable { + if crate_type != config::CrateType::Executable { cmd.build_dylib(out_filename); } - if crate_type == config::CrateTypeExecutable && sess.crt_static() { + if crate_type == config::CrateType::Executable && sess.crt_static() { cmd.build_static_executable(); } @@ -1446,9 +1487,9 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker, lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib) }); - if (!is_full_lto_enabled(sess) || + if (!are_upstream_rust_objects_already_included(sess) || ignored_for_lto(sess, &codegen_results.crate_info, cnum)) && - crate_type != config::CrateTypeDylib && + crate_type != config::CrateType::Dylib && !skip_native { cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath)); return @@ -1500,7 +1541,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker, // file, then we don't need the object file as it's part of the // LTO module. Note that `#![no_builtins]` is excluded from LTO, // though, so we let that object file slide. - let skip_because_lto = is_full_lto_enabled(sess) && + let skip_because_lto = are_upstream_rust_objects_already_included(sess) && is_rust_object && (sess.target.target.options.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum)); @@ -1524,7 +1565,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker, // Note, though, that we don't want to include the whole of a // compiler-builtins crate (e.g. compiler-rt) because it'll get // repeatedly linked anyway. - if crate_type == config::CrateTypeDylib && + if crate_type == config::CrateType::Dylib && codegen_results.crate_info.compiler_builtins != Some(cnum) { cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst)); } else { @@ -1537,7 +1578,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker, fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) { // If we're performing LTO, then it should have been previously required // that all upstream rust dependencies were available in an rlib format. - assert!(!is_full_lto_enabled(sess)); + assert!(!are_upstream_rust_objects_already_included(sess)); // Just need to tell the linker about where the library lives and // what its name is @@ -1623,11 +1664,14 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { } } -fn is_full_lto_enabled(sess: &Session) -> bool { +fn are_upstream_rust_objects_already_included(sess: &Session) -> bool { match sess.lto() { - Lto::Yes | - Lto::Thin | Lto::Fat => true, + Lto::Thin => { + // If we defer LTO to the linker, we haven't run LTO ourselves, so + // any upstream object files have not been copied yet. + !sess.opts.debugging_opts.cross_lang_lto.enabled() + } Lto::No | Lto::ThinLocal => false, } diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index 5f2f3733ec..95be2d8212 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashMap; +use rustc_data_structures::fx::FxHashMap; use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io::prelude::*; @@ -21,16 +21,17 @@ use back::symbol_export; use rustc::hir::def_id::{LOCAL_CRATE, CrateNum}; use rustc::middle::dependency_format::Linkage; use rustc::session::Session; -use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel, +use rustc::session::config::{self, CrateType, OptLevel, DebugInfo, CrossLangLto}; use rustc::ty::TyCtxt; use rustc_target::spec::{LinkerFlavor, LldFlavor}; use serialize::{json, Encoder}; +use llvm_util; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. pub struct LinkerInfo { - exports: HashMap>, + exports: FxHashMap>, } impl LinkerInfo { @@ -44,8 +45,9 @@ impl LinkerInfo { pub fn to_linker<'a>(&'a self, cmd: Command, - sess: &'a Session) -> Box { - match sess.linker_flavor() { + sess: &'a Session, + flavor: LinkerFlavor) -> Box { + match flavor { LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { Box::new(MsvcLinker { @@ -201,15 +203,14 @@ impl<'a> GccLinker<'a> { }; self.linker_arg(&format!("-plugin-opt={}", opt_level)); - self.linker_arg(&format!("-plugin-opt=mcpu={}", self.sess.target_cpu())); + self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess))); - match self.sess.opts.cg.lto { + match self.sess.lto() { config::Lto::Thin | config::Lto::ThinLocal => { self.linker_arg("-plugin-opt=thin"); } config::Lto::Fat | - config::Lto::Yes | config::Lto::No => { // default to regular LTO } @@ -338,7 +339,7 @@ impl<'a> Linker for GccLinker<'a> { fn debuginfo(&mut self) { match self.sess.opts.debuginfo { - DebugInfoLevel::NoDebugInfo => { + DebugInfo::None => { // If we are building without debuginfo enabled and we were called with // `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo // found when linking to get rid of symbols from libstd. @@ -387,8 +388,8 @@ impl<'a> Linker for GccLinker<'a> { // exported symbols to ensure we don't expose any more. The object files // have far more public symbols than we actually want to export, so we // hide them all here. - if crate_type == CrateType::CrateTypeDylib || - crate_type == CrateType::CrateTypeProcMacro { + if crate_type == CrateType::Dylib || + crate_type == CrateType::ProcMacro { return } @@ -826,9 +827,9 @@ impl<'a> Linker for EmLinker<'a> { fn debuginfo(&mut self) { // Preserve names or generate source maps depending on debug info self.cmd.arg(match self.sess.opts.debuginfo { - DebugInfoLevel::NoDebugInfo => "-g0", - DebugInfoLevel::LimitedDebugInfo => "-g3", - DebugInfoLevel::FullDebugInfo => "-g4" + DebugInfo::None => "-g0", + DebugInfo::Limited => "-g3", + DebugInfo::Full => "-g4" }); } @@ -1067,6 +1068,9 @@ impl<'a> Linker for WasmLd<'a> { // For now we just never have an entry symbol self.cmd.arg("--no-entry"); + // Make the default table accessible + self.cmd.arg("--export-table"); + let mut cmd = Command::new(""); ::std::mem::swap(&mut cmd, &mut self.cmd); cmd diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 93cb9eb976..364b469738 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -11,34 +11,38 @@ use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION}; use back::symbol_export; use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; -use back::write; +use back::write::{self, DiagnosticHandlers, pre_lto_bitcode_filename}; use errors::{FatalError, Handler}; use llvm::archive_ro::ArchiveRO; -use llvm::{ModuleRef, TargetMachineRef, True, False}; +use llvm::{True, False}; use llvm; +use memmap; +use rustc::dep_graph::WorkProduct; 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 time_graph::Timeline; -use {ModuleCodegen, ModuleLlvm, ModuleKind, ModuleSource}; +use {ModuleCodegen, ModuleLlvm, ModuleKind}; use libc; -use std::ffi::CString; +use std::ffi::{CStr, CString}; +use std::fs; use std::ptr; use std::slice; use std::sync::Arc; pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { match crate_type { - config::CrateTypeExecutable | - config::CrateTypeStaticlib | - config::CrateTypeCdylib => true, + config::CrateType::Executable | + config::CrateType::Staticlib | + config::CrateType::Cdylib => true, - config::CrateTypeDylib | - config::CrateTypeRlib | - config::CrateTypeProcMacro => false, + config::CrateType::Dylib | + config::CrateType::Rlib | + config::CrateType::ProcMacro => false, } } @@ -73,11 +77,13 @@ impl LtoModuleCodegen { match *self { LtoModuleCodegen::Fat { ref mut module, .. } => { let module = module.take().unwrap(); - let config = cgcx.config(module.kind); - let llmod = module.llvm().unwrap().llmod; - let tm = module.llvm().unwrap().tm; - run_pass_manager(cgcx, tm, llmod, config, false); - timeline.record("fat-done"); + { + let config = cgcx.config(module.kind); + let llmod = module.module_llvm.llmod(); + let tm = &*module.module_llvm.tm; + run_pass_manager(cgcx, tm, llmod, config, false); + timeline.record("fat-done"); + } Ok(module) } LtoModuleCodegen::Thin(ref mut thin) => thin.optimize(cgcx, timeline), @@ -95,10 +101,16 @@ impl LtoModuleCodegen { } } +/// Performs LTO, which in the case of full LTO means merging all modules into +/// a single one and returning it for further optimizing. For ThinLTO, it will +/// do the global analysis necessary and return two lists, one of the modules +/// the need optimization and another for modules that can simply be copied over +/// from the incr. comp. cache. pub(crate) fn run(cgcx: &CodegenContext, modules: Vec, + cached_modules: Vec<(SerializedModule, WorkProduct)>, timeline: &mut Timeline) - -> Result, FatalError> + -> Result<(Vec, Vec), FatalError> { let diag_handler = cgcx.create_diag_handler(); let export_threshold = match cgcx.lto { @@ -106,7 +118,7 @@ pub(crate) fn run(cgcx: &CodegenContext, Lto::ThinLocal => SymbolExportLevel::Rust, // We're doing LTO for the entire crate graph - Lto::Yes | Lto::Fat | Lto::Thin => { + Lto::Fat | Lto::Thin => { symbol_export::crates_export_threshold(&cgcx.crate_types) } @@ -185,15 +197,33 @@ pub(crate) fn run(cgcx: &CodegenContext, } } - let arr = symbol_white_list.iter().map(|c| c.as_ptr()).collect::>(); + let symbol_white_list = symbol_white_list.iter() + .map(|c| c.as_ptr()) + .collect::>(); match cgcx.lto { - Lto::Yes | // `-C lto` == fat LTO by default Lto::Fat => { - fat_lto(cgcx, &diag_handler, modules, upstream_modules, &arr, timeline) + assert!(cached_modules.is_empty()); + let opt_jobs = fat_lto(cgcx, + &diag_handler, + modules, + upstream_modules, + &symbol_white_list, + timeline); + opt_jobs.map(|opt_jobs| (opt_jobs, vec![])) } Lto::Thin | Lto::ThinLocal => { - thin_lto(&diag_handler, modules, upstream_modules, &arr, timeline) + if cgcx.opts.debugging_opts.cross_lang_lto.enabled() { + unreachable!("We should never reach this case if the LTO step \ + is deferred to the linker"); + } + thin_lto(cgcx, + &diag_handler, + modules, + upstream_modules, + cached_modules, + &symbol_white_list, + timeline) } Lto::No => unreachable!(), } @@ -223,66 +253,75 @@ fn fat_lto(cgcx: &CodegenContext, .filter(|&(_, module)| module.kind == ModuleKind::Regular) .map(|(i, module)| { let cost = unsafe { - llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod) + llvm::LLVMRustModuleCost(module.module_llvm.llmod()) }; (cost, i) }) .max() .expect("must be codegen'ing at least one module"); let module = modules.remove(costliest_module); - let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod; - info!("using {:?} as a base module", module.llmod_id); - - // For all other modules we codegened we'll need to link them into our own - // bitcode. All modules were codegened in their own LLVM context, however, - // and we want to move everything to the same LLVM context. Currently the - // way we know of to do that is to serialize them to a string and them parse - // them later. Not great but hey, that's why it's "fat" LTO, right? - for module in modules { - let llvm = module.llvm().expect("can't lto pre-codegened modules"); - let buffer = ModuleBuffer::new(llvm.llmod); - let llmod_id = CString::new(&module.llmod_id[..]).unwrap(); - serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); - } - - // For all serialized bitcode files we parse them and link them in as we did - // above, this is all mostly handled in C++. Like above, though, we don't - // know much about the memory management here so we err on the side of being - // save and persist everything with the original module. let mut serialized_bitcode = Vec::new(); - let mut linker = Linker::new(llmod); - for (bc_decoded, name) in serialized_modules { - info!("linking {:?}", name); - time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { - let data = bc_decoded.data(); - linker.add(&data).map_err(|()| { - let msg = format!("failed to load bc of {:?}", name); - write::llvm_err(&diag_handler, msg) - }) - })?; - timeline.record(&format!("link {:?}", name)); - serialized_bitcode.push(bc_decoded); - } - drop(linker); - cgcx.save_temp_bitcode(&module, "lto.input"); + { + let (llcx, llmod) = { + let llvm = &module.module_llvm; + (&llvm.llcx, llvm.llmod()) + }; + info!("using {:?} as a base module", module.name); + + // The linking steps below may produce errors and diagnostics within LLVM + // which we'd like to handle and print, so set up our diagnostic handlers + // (which get unregistered when they go out of scope below). + let _handler = DiagnosticHandlers::new(cgcx, diag_handler, llcx); + + // For all other modules we codegened we'll need to link them into our own + // bitcode. All modules were codegened in their own LLVM context, however, + // and we want to move everything to the same LLVM context. Currently the + // way we know of to do that is to serialize them to a string and them parse + // them later. Not great but hey, that's why it's "fat" LTO, right? + for module in modules { + let buffer = ModuleBuffer::new(module.module_llvm.llmod()); + let llmod_id = CString::new(&module.name[..]).unwrap(); + serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); + } - // Internalize everything that *isn't* in our whitelist to help strip out - // more modules and such - unsafe { - let ptr = symbol_white_list.as_ptr(); - llvm::LLVMRustRunRestrictionPass(llmod, - ptr as *const *const libc::c_char, - symbol_white_list.len() as libc::size_t); - cgcx.save_temp_bitcode(&module, "lto.after-restriction"); - } + // For all serialized bitcode files we parse them and link them in as we did + // above, this is all mostly handled in C++. Like above, though, we don't + // know much about the memory management here so we err on the side of being + // save and persist everything with the original module. + let mut linker = Linker::new(llmod); + for (bc_decoded, name) in serialized_modules { + info!("linking {:?}", name); + time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { + let data = bc_decoded.data(); + linker.add(&data).map_err(|()| { + let msg = format!("failed to load bc of {:?}", name); + write::llvm_err(&diag_handler, msg) + }) + })?; + timeline.record(&format!("link {:?}", name)); + serialized_bitcode.push(bc_decoded); + } + drop(linker); + cgcx.save_temp_bitcode(&module, "lto.input"); - if cgcx.no_landing_pads { + // Internalize everything that *isn't* in our whitelist to help strip out + // more modules and such unsafe { - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + let ptr = symbol_white_list.as_ptr(); + llvm::LLVMRustRunRestrictionPass(llmod, + ptr as *const *const libc::c_char, + symbol_white_list.len() as libc::size_t); + cgcx.save_temp_bitcode(&module, "lto.after-restriction"); + } + + if cgcx.no_landing_pads { + unsafe { + llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + } + cgcx.save_temp_bitcode(&module, "lto.after-nounwind"); } - cgcx.save_temp_bitcode(&module, "lto.after-nounwind"); + timeline.record("passes"); } - timeline.record("passes"); Ok(vec![LtoModuleCodegen::Fat { module: Some(module), @@ -290,10 +329,10 @@ fn fat_lto(cgcx: &CodegenContext, }]) } -struct Linker(llvm::LinkerRef); +struct Linker<'a>(&'a mut llvm::Linker<'a>); -impl Linker { - fn new(llmod: ModuleRef) -> Linker { +impl Linker<'a> { + fn new(llmod: &'a llvm::Module) -> Self { unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) } } @@ -310,9 +349,9 @@ impl Linker { } } -impl Drop for Linker { +impl Drop for Linker<'a> { fn drop(&mut self) { - unsafe { llvm::LLVMRustLinkerFree(self.0); } + unsafe { llvm::LLVMRustLinkerFree(&mut *(self.0 as *mut _)); } } } @@ -346,16 +385,23 @@ impl Drop for Linker { /// calculating the *index* for ThinLTO. This index will then be shared amongst /// all of the `LtoModuleCodegen` units returned below and destroyed once /// they all go out of scope. -fn thin_lto(diag_handler: &Handler, +fn thin_lto(cgcx: &CodegenContext, + diag_handler: &Handler, modules: Vec, serialized_modules: Vec<(SerializedModule, CString)>, + cached_modules: Vec<(SerializedModule, WorkProduct)>, symbol_white_list: &[*const libc::c_char], timeline: &mut Timeline) - -> Result, FatalError> + -> Result<(Vec, Vec), FatalError> { unsafe { info!("going for that thin, thin LTO"); + let green_modules: FxHashMap<_, _> = cached_modules + .iter() + .map(|&(_, ref wp)| (wp.cgu_name.clone(), wp.clone())) + .collect(); + let mut thin_buffers = Vec::new(); let mut module_names = Vec::new(); let mut thin_modules = Vec::new(); @@ -368,10 +414,25 @@ fn thin_lto(diag_handler: &Handler, // the most expensive portion of this small bit of global // analysis! for (i, module) in modules.iter().enumerate() { - info!("local module: {} - {}", i, module.llmod_id); - let llvm = module.llvm().expect("can't lto precodegened module"); - let name = CString::new(module.llmod_id.clone()).unwrap(); - let buffer = ThinBuffer::new(llvm.llmod); + info!("local module: {} - {}", i, module.name); + let name = CString::new(module.name.clone()).unwrap(); + let buffer = ThinBuffer::new(module.module_llvm.llmod()); + + // We emit the module after having serialized it into a ThinBuffer + // because only then it will contain the ThinLTO module summary. + if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir { + if cgcx.config(module.kind).emit_pre_thin_lto_bc { + let path = incr_comp_session_dir + .join(pre_lto_bitcode_filename(&module.name)); + + fs::write(&path, buffer.data()).unwrap_or_else(|e| { + panic!("Error writing pre-lto-bitcode file `{}`: {}", + path.display(), + e); + }); + } + } + thin_modules.push(llvm::ThinLTOModule { identifier: name.as_ptr(), data: buffer.data().as_ptr(), @@ -379,7 +440,7 @@ fn thin_lto(diag_handler: &Handler, }); thin_buffers.push(buffer); module_names.push(name); - timeline.record(&module.llmod_id); + timeline.record(&module.name); } // FIXME: All upstream crates are deserialized internally in the @@ -399,8 +460,13 @@ fn thin_lto(diag_handler: &Handler, // looking at upstream modules entirely sometimes (the contents, // we must always unconditionally look at the index). let mut serialized = Vec::new(); - for (module, name) in serialized_modules { - info!("foreign module {:?}", name); + + let cached_modules = cached_modules.into_iter().map(|(sm, wp)| { + (sm, CString::new(wp.cgu_name).unwrap()) + }); + + for (module, name) in serialized_modules.into_iter().chain(cached_modules) { + info!("upstream or cached module {:?}", name); thin_modules.push(llvm::ThinLTOModule { identifier: name.as_ptr(), data: module.data().as_ptr(), @@ -410,6 +476,9 @@ fn thin_lto(diag_handler: &Handler, module_names.push(name); } + // Sanity check + assert_eq!(thin_modules.len(), module_names.len()); + // Delegate to the C++ bindings to create some data here. Once this is a // tried-and-true interface we may wish to try to upstream some of this // to LLVM itself, right now we reimplement a lot of what they do @@ -419,15 +488,26 @@ fn thin_lto(diag_handler: &Handler, thin_modules.len() as u32, symbol_white_list.as_ptr(), symbol_white_list.len() as u32, - ); - if data.is_null() { - let msg = "failed to prepare thin LTO context".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - let data = ThinData(data); + ).ok_or_else(|| { + write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string()) + })?; + info!("thin LTO data created"); timeline.record("data"); + let import_map = if cgcx.incr_comp_session_dir.is_some() { + ThinLTOImports::from_thin_lto_data(data) + } else { + // If we don't compile incrementally, we don't need to load the + // import data from LLVM. + assert!(green_modules.is_empty()); + ThinLTOImports::new() + }; + info!("thin LTO import map loaded"); + timeline.record("import-map-loaded"); + + let data = ThinData(data); + // Throw our data in an `Arc` as we'll be sharing it across threads. We // also put all memory referenced by the C++ data (buffers, ids, etc) // into the arc as well. After this we'll create a thin module @@ -438,18 +518,44 @@ fn thin_lto(diag_handler: &Handler, serialized_modules: serialized, module_names, }); - Ok((0..shared.module_names.len()).map(|i| { - LtoModuleCodegen::Thin(ThinModule { + + let mut copy_jobs = vec![]; + let mut opt_jobs = vec![]; + + info!("checking which modules can be-reused and which have to be re-optimized."); + for (module_index, module_name) in shared.module_names.iter().enumerate() { + let module_name = module_name_to_str(module_name); + + // If the module hasn't changed and none of the modules it imports + // from has changed, we can re-use the post-ThinLTO version of the + // module. + if green_modules.contains_key(module_name) { + let imports_all_green = import_map.modules_imported_by(module_name) + .iter() + .all(|imported_module| green_modules.contains_key(imported_module)); + + if imports_all_green { + let work_product = green_modules[module_name].clone(); + copy_jobs.push(work_product); + info!(" - {}: re-used", module_name); + continue + } + } + + info!(" - {}: re-compiled", module_name); + opt_jobs.push(LtoModuleCodegen::Thin(ThinModule { shared: shared.clone(), - idx: i, - }) - }).collect()) + idx: module_index, + })); + } + + Ok((opt_jobs, copy_jobs)) } } fn run_pass_manager(cgcx: &CodegenContext, - tm: TargetMachineRef, - llmod: ModuleRef, + tm: &llvm::TargetMachine, + llmod: &llvm::Module, config: &ModuleConfig, thin: bool) { // Now we have one massive module inside of llmod. Time to run the @@ -464,8 +570,7 @@ fn run_pass_manager(cgcx: &CodegenContext, if config.verify_llvm_ir { let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); - assert!(!pass.is_null()); - llvm::LLVMRustAddPass(pm, pass); + llvm::LLVMRustAddPass(pm, pass.unwrap()); } // When optimizing for LTO we don't actually pass in `-O0`, but we force @@ -499,8 +604,7 @@ fn run_pass_manager(cgcx: &CodegenContext, if config.verify_llvm_ir { let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); - assert!(!pass.is_null()); - llvm::LLVMRustAddPass(pm, pass); + llvm::LLVMRustAddPass(pm, pass.unwrap()); } time_ext(cgcx.time_passes, None, "LTO passes", || @@ -514,6 +618,7 @@ fn run_pass_manager(cgcx: &CodegenContext, pub enum SerializedModule { Local(ModuleBuffer), FromRlib(Vec), + FromUncompressedFile(memmap::Mmap), } impl SerializedModule { @@ -521,17 +626,18 @@ impl SerializedModule { match *self { SerializedModule::Local(ref m) => m.data(), SerializedModule::FromRlib(ref m) => m, + SerializedModule::FromUncompressedFile(ref m) => m, } } } -pub struct ModuleBuffer(*mut llvm::ModuleBuffer); +pub struct ModuleBuffer(&'static mut llvm::ModuleBuffer); unsafe impl Send for ModuleBuffer {} unsafe impl Sync for ModuleBuffer {} impl ModuleBuffer { - pub fn new(m: ModuleRef) -> ModuleBuffer { + pub fn new(m: &llvm::Module) -> ModuleBuffer { ModuleBuffer(unsafe { llvm::LLVMRustModuleBufferCreate(m) }) @@ -548,7 +654,7 @@ impl ModuleBuffer { impl Drop for ModuleBuffer { fn drop(&mut self) { - unsafe { llvm::LLVMRustModuleBufferFree(self.0); } + unsafe { llvm::LLVMRustModuleBufferFree(&mut *(self.0 as *mut _)); } } } @@ -564,7 +670,7 @@ struct ThinShared { module_names: Vec, } -struct ThinData(*mut llvm::ThinLTOData); +struct ThinData(&'static mut llvm::ThinLTOData); unsafe impl Send for ThinData {} unsafe impl Sync for ThinData {} @@ -572,18 +678,18 @@ unsafe impl Sync for ThinData {} impl Drop for ThinData { fn drop(&mut self) { unsafe { - llvm::LLVMRustFreeThinLTOData(self.0); + llvm::LLVMRustFreeThinLTOData(&mut *(self.0 as *mut _)); } } } -pub struct ThinBuffer(*mut llvm::ThinLTOBuffer); +pub struct ThinBuffer(&'static mut llvm::ThinLTOBuffer); unsafe impl Send for ThinBuffer {} unsafe impl Sync for ThinBuffer {} impl ThinBuffer { - pub fn new(m: ModuleRef) -> ThinBuffer { + pub fn new(m: &llvm::Module) -> ThinBuffer { unsafe { let buffer = llvm::LLVMRustThinLTOBufferCreate(m); ThinBuffer(buffer) @@ -602,7 +708,7 @@ impl ThinBuffer { impl Drop for ThinBuffer { fn drop(&mut self) { unsafe { - llvm::LLVMRustThinLTOBufferFree(self.0); + llvm::LLVMRustThinLTOBufferFree(&mut *(self.0 as *mut _)); } } } @@ -640,125 +746,184 @@ impl ThinModule { // crates but for locally codegened modules we may be able to reuse // that LLVM Context and Module. let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); - let llmod = llvm::LLVMRustParseBitcodeForThinLTO( + let llmod_raw = llvm::LLVMRustParseBitcodeForThinLTO( llcx, self.data().as_ptr(), self.data().len(), self.shared.module_names[self.idx].as_ptr(), - ); - if llmod.is_null() { + ).ok_or_else(|| { let msg = "failed to parse bitcode for thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)); - } + write::llvm_err(&diag_handler, msg) + })? as *const _; let module = ModuleCodegen { - source: ModuleSource::Codegened(ModuleLlvm { - llmod, + module_llvm: ModuleLlvm { + llmod_raw, llcx, tm, - }), - llmod_id: self.name().to_string(), + }, name: self.name().to_string(), kind: ModuleKind::Regular, }; - cgcx.save_temp_bitcode(&module, "thin-lto-input"); - - // Before we do much else find the "main" `DICompileUnit` that we'll be - // using below. If we find more than one though then rustc has changed - // in a way we're not ready for, so generate an ICE by returning - // an error. - let mut cu1 = ptr::null_mut(); - let mut cu2 = ptr::null_mut(); - llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); - if !cu2.is_null() { - let msg = "multiple source DICompileUnits found".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } + { + let llmod = module.module_llvm.llmod(); + cgcx.save_temp_bitcode(&module, "thin-lto-input"); + + // Before we do much else find the "main" `DICompileUnit` that we'll be + // using below. If we find more than one though then rustc has changed + // in a way we're not ready for, so generate an ICE by returning + // an error. + let mut cu1 = ptr::null_mut(); + let mut cu2 = ptr::null_mut(); + llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); + if !cu2.is_null() { + let msg = "multiple source DICompileUnits found".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } - // Like with "fat" LTO, get some better optimizations if landing pads - // are disabled by removing all landing pads. - if cgcx.no_landing_pads { - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); - cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind"); - timeline.record("nounwind"); - } + // Like with "fat" LTO, get some better optimizations if landing pads + // are disabled by removing all landing pads. + if cgcx.no_landing_pads { + llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind"); + timeline.record("nounwind"); + } - // Up next comes the per-module local analyses that we do for Thin LTO. - // Each of these functions is basically copied from the LLVM - // implementation and then tailored to suit this implementation. Ideally - // each of these would be supported by upstream LLVM but that's perhaps - // a patch for another day! - // - // You can find some more comments about these functions in the LLVM - // bindings we've got (currently `PassWrapper.cpp`) - if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - cgcx.save_temp_bitcode(&module, "thin-lto-after-rename"); - timeline.record("rename"); - if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve"); - timeline.record("resolve"); - if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) + // Up next comes the per-module local analyses that we do for Thin LTO. + // Each of these functions is basically copied from the LLVM + // implementation and then tailored to suit this implementation. Ideally + // each of these would be supported by upstream LLVM but that's perhaps + // a patch for another day! + // + // You can find some more comments about these functions in the LLVM + // bindings we've got (currently `PassWrapper.cpp`) + if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-rename"); + timeline.record("rename"); + if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve"); + timeline.record("resolve"); + if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize"); + timeline.record("internalize"); + if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-import"); + timeline.record("import"); + + // Ok now this is a bit unfortunate. This is also something you won't + // find upstream in LLVM's ThinLTO passes! This is a hack for now to + // work around bugs in LLVM. + // + // First discovered in #45511 it was found that as part of ThinLTO + // importing passes LLVM will import `DICompileUnit` metadata + // information across modules. This means that we'll be working with one + // LLVM module that has multiple `DICompileUnit` instances in it (a + // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of + // bugs in LLVM's backend which generates invalid DWARF in a situation + // like this: + // + // https://bugs.llvm.org/show_bug.cgi?id=35212 + // https://bugs.llvm.org/show_bug.cgi?id=35562 + // + // While the first bug there is fixed the second ended up causing #46346 + // which was basically a resurgence of #45511 after LLVM's bug 35212 was + // fixed. + // + // This function below is a huge hack around this problem. The function + // below is defined in `PassWrapper.cpp` and will basically "merge" + // all `DICompileUnit` instances in a module. Basically it'll take all + // the objects, rewrite all pointers of `DISubprogram` to point to the + // first `DICompileUnit`, and then delete all the other units. + // + // This is probably mangling to the debug info slightly (but hopefully + // not too much) but for now at least gets LLVM to emit valid DWARF (or + // so it appears). Hopefully we can remove this once upstream bugs are + // fixed in LLVM. + llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); + cgcx.save_temp_bitcode(&module, "thin-lto-after-patch"); + timeline.record("patch"); + + // Alright now that we've done everything related to the ThinLTO + // analysis it's time to run some optimizations! Here we use the same + // `run_pass_manager` as the "fat" LTO above except that we tell it to + // populate a thin-specific pass manager, which presumably LLVM treats a + // little differently. + info!("running thin lto passes over {}", module.name); + let config = cgcx.config(module.kind); + run_pass_manager(cgcx, module.module_llvm.tm, llmod, config, true); + cgcx.save_temp_bitcode(&module, "thin-lto-after-pm"); + timeline.record("thin-done"); } - cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize"); - timeline.record("internalize"); - if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) + + Ok(module) + } +} + +#[derive(Debug)] +pub struct ThinLTOImports { + // key = llvm name of importing module, value = list of modules it imports from + imports: FxHashMap>, +} + +impl ThinLTOImports { + fn new() -> ThinLTOImports { + ThinLTOImports { + imports: FxHashMap(), } - cgcx.save_temp_bitcode(&module, "thin-lto-after-import"); - timeline.record("import"); + } - // Ok now this is a bit unfortunate. This is also something you won't - // find upstream in LLVM's ThinLTO passes! This is a hack for now to - // work around bugs in LLVM. - // - // First discovered in #45511 it was found that as part of ThinLTO - // importing passes LLVM will import `DICompileUnit` metadata - // information across modules. This means that we'll be working with one - // LLVM module that has multiple `DICompileUnit` instances in it (a - // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of - // bugs in LLVM's backend which generates invalid DWARF in a situation - // like this: - // - // https://bugs.llvm.org/show_bug.cgi?id=35212 - // https://bugs.llvm.org/show_bug.cgi?id=35562 - // - // While the first bug there is fixed the second ended up causing #46346 - // which was basically a resurgence of #45511 after LLVM's bug 35212 was - // fixed. - // - // This function below is a huge hack around this problem. The function - // below is defined in `PassWrapper.cpp` and will basically "merge" - // all `DICompileUnit` instances in a module. Basically it'll take all - // the objects, rewrite all pointers of `DISubprogram` to point to the - // first `DICompileUnit`, and then delete all the other units. - // - // This is probably mangling to the debug info slightly (but hopefully - // not too much) but for now at least gets LLVM to emit valid DWARF (or - // so it appears). Hopefully we can remove this once upstream bugs are - // fixed in LLVM. - llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); - cgcx.save_temp_bitcode(&module, "thin-lto-after-patch"); - timeline.record("patch"); - - // Alright now that we've done everything related to the ThinLTO - // analysis it's time to run some optimizations! Here we use the same - // `run_pass_manager` as the "fat" LTO above except that we tell it to - // populate a thin-specific pass manager, which presumably LLVM treats a - // little differently. - info!("running thin lto passes over {}", module.name); - let config = cgcx.config(module.kind); - run_pass_manager(cgcx, tm, llmod, config, true); - cgcx.save_temp_bitcode(&module, "thin-lto-after-pm"); - timeline.record("thin-done"); + fn modules_imported_by(&self, llvm_module_name: &str) -> &[String] { + self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[]) + } - Ok(module) + /// Load the ThinLTO import map from ThinLTOData. + unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports { + unsafe extern "C" fn imported_module_callback(payload: *mut libc::c_void, + importing_module_name: *const libc::c_char, + imported_module_name: *const libc::c_char) { + let map = &mut* (payload as *mut ThinLTOImports); + let importing_module_name = CStr::from_ptr(importing_module_name); + let importing_module_name = module_name_to_str(&importing_module_name); + let imported_module_name = CStr::from_ptr(imported_module_name); + let imported_module_name = module_name_to_str(&imported_module_name); + + if !map.imports.contains_key(importing_module_name) { + map.imports.insert(importing_module_name.to_owned(), vec![]); + } + + map.imports + .get_mut(importing_module_name) + .unwrap() + .push(imported_module_name.to_owned()); + } + let mut map = ThinLTOImports { + imports: FxHashMap(), + }; + llvm::LLVMRustGetThinLTOModuleImports(data, + imported_module_callback, + &mut map as *mut _ as *mut libc::c_void); + map + } +} + +fn module_name_to_str(c_str: &CStr) -> &str { + match c_str.to_str() { + Ok(s) => s, + Err(e) => { + bug!("Encountered non-utf8 LLVM module name `{}`: {}", + c_str.to_string_lossy(), + e) + } } } diff --git a/src/librustc_codegen_llvm/back/rpath.rs b/src/librustc_codegen_llvm/back/rpath.rs index 2c3a143646..aa4f7688b0 100644 --- a/src/librustc_codegen_llvm/back/rpath.rs +++ b/src/librustc_codegen_llvm/back/rpath.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashSet; +use rustc_data_structures::fx::FxHashSet; use std::env; use std::path::{Path, PathBuf}; use std::fs; @@ -172,7 +172,7 @@ fn get_install_prefix_rpath(config: &mut RPathConfig) -> String { } fn minimize_rpaths(rpaths: &[String]) -> Vec { - let mut set = HashSet::new(); + let mut set = FxHashSet::default(); let mut minimized = Vec::new(); for rpath in rpaths { if set.insert(rpath) { diff --git a/src/librustc_codegen_llvm/back/symbol_export.rs b/src/librustc_codegen_llvm/back/symbol_export.rs index 48de2f3bee..6b1b0b94fd 100644 --- a/src/librustc_codegen_llvm/back/symbol_export.rs +++ b/src/librustc_codegen_llvm/back/symbol_export.rs @@ -13,9 +13,10 @@ use std::sync::Arc; use monomorphize::Instance; use rustc::hir; +use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; -use rustc::ich::Fingerprint; +use rustc_data_structures::fingerprint::Fingerprint; use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name}; use rustc::session::config; use rustc::ty::{TyCtxt, SymbolName}; @@ -37,12 +38,12 @@ pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel { fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel { match crate_type { - config::CrateTypeExecutable | - config::CrateTypeStaticlib | - config::CrateTypeProcMacro | - config::CrateTypeCdylib => SymbolExportLevel::C, - config::CrateTypeRlib | - config::CrateTypeDylib => SymbolExportLevel::Rust, + config::CrateType::Executable | + config::CrateType::Staticlib | + config::CrateType::ProcMacro | + config::CrateType::Cdylib => SymbolExportLevel::C, + config::CrateType::Rlib | + config::CrateType::Dylib => SymbolExportLevel::Rust, } } @@ -94,7 +95,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // As a result, if this id is an FFI item (foreign item) then we only // let it through if it's included statically. match tcx.hir.get(node_id) { - hir::map::NodeForeignItem(..) => { + Node::ForeignItem(..) => { let def_id = tcx.hir.local_def_id(node_id); if tcx.is_statically_included_foreign_item(def_id) { Some(def_id) @@ -104,14 +105,14 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // Only consider nodes that actually have exported symbols. - hir::map::NodeItem(&hir::Item { + Node::Item(&hir::Item { node: hir::ItemKind::Static(..), .. }) | - hir::map::NodeItem(&hir::Item { + Node::Item(&hir::Item { node: hir::ItemKind::Fn(..), .. }) | - hir::map::NodeImplItem(&hir::ImplItem { + Node::ImplItem(&hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => { @@ -235,14 +236,14 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { + if tcx.sess.crate_types.borrow().contains(&config::CrateType::Dylib) { let symbol_name = metadata_symbol_name(tcx); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); symbols.push((exported_symbol, SymbolExportLevel::Rust)); } - if tcx.share_generics() && tcx.local_crate_exports_generics() { + if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() { use rustc::mir::mono::{Linkage, Visibility, MonoItem}; use rustc::ty::InstanceDef; @@ -299,7 +300,7 @@ fn upstream_monomorphizations_provider<'a, 'tcx>( let cnums = tcx.all_crate_nums(LOCAL_CRATE); - let mut instances = DefIdMap(); + let mut instances: DefIdMap> = DefIdMap(); let cnum_stable_ids: IndexVec = { let mut cnum_stable_ids = IndexVec::from_elem_n(Fingerprint::ZERO, @@ -318,8 +319,7 @@ fn upstream_monomorphizations_provider<'a, 'tcx>( for &cnum in cnums.iter() { for &(ref exported_symbol, _) in tcx.exported_symbols(cnum).iter() { if let &ExportedSymbol::Generic(def_id, substs) = exported_symbol { - let substs_map = instances.entry(def_id) - .or_insert_with(|| FxHashMap()); + let substs_map = instances.entry(def_id).or_default(); match substs_map.entry(substs) { Occupied(mut e) => { diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index d36142af56..7b78d4fb4f 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -10,31 +10,33 @@ use attributes; use back::bytecode::{self, RLIB_BYTECODE_EXTENSION}; -use back::lto::{self, ModuleBuffer, ThinBuffer}; +use back::lto::{self, ModuleBuffer, ThinBuffer, SerializedModule}; use back::link::{self, get_linker, remove}; use back::command::Command; use back::linker::LinkerInfo; use back::symbol_export::ExportedSymbols; use base; use consts; -use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir}; +use memmap; +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::middle::cstore::{LinkMeta, EncodedMetadata}; -use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePasses, - AllPasses, Sanitizer, Lto}; +use rustc::middle::cstore::EncodedMetadata; +use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto}; use rustc::session::Session; use rustc::util::nodemap::FxHashMap; use time_graph::{self, TimeGraph, Timeline}; -use llvm; -use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; -use llvm::{SMDiagnosticRef, ContextRef}; -use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind}; +use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic}; +use llvm_util; +use {CodegenResults, ModuleCodegen, CompiledModule, ModuleKind, // ModuleLlvm, + CachedModuleCodegen}; use CrateInfo; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::ty::TyCtxt; use rustc::util::common::{time_ext, time_depth, set_time_depth, print_time_passes_entry}; -use rustc::util::common::path2cstr; -use rustc::util::fs::{link_or_copy}; +use rustc_fs_util::{path2cstr, link_or_copy}; +use rustc_data_structures::small_c_str::SmallCStr; +use rustc_data_structures::svh::Svh; use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId}; use errors::emitter::{Emitter}; use syntax::attr; @@ -85,6 +87,8 @@ pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [ ("local-exec", llvm::ThreadLocalMode::LocalExec), ]; +const PRE_THIN_LTO_BC_EXT: &str = "pre-thin-lto.bc"; + pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError { match llvm::last_error() { Some(err) => handler.fatal(&format!("{}: {}", msg, err)), @@ -94,9 +98,9 @@ pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError { pub fn write_output_file( handler: &errors::Handler, - target: llvm::TargetMachineRef, - pm: llvm::PassManagerRef, - m: ModuleRef, + target: &'ll llvm::TargetMachine, + pm: &llvm::PassManager<'ll>, + m: &'ll llvm::Module, output: &Path, file_type: llvm::FileType) -> Result<(), FatalError> { unsafe { @@ -130,7 +134,10 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize { } } -pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachineRef { +pub fn create_target_machine( + sess: &Session, + find_features: bool, +) -> &'static mut llvm::TargetMachine { target_machine_factory(sess, find_features)().unwrap_or_else(|err| { llvm_err(sess.diagnostic(), err).raise() }) @@ -140,7 +147,7 @@ pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachi // that `is_pie_binary` is false. When we discover LLVM target features // `sess.crate_types` is uninitialized so we cannot access it. pub fn target_machine_factory(sess: &Session, find_features: bool) - -> Arc Result + Send + Sync> + -> Arc Result<&'static mut llvm::TargetMachine, String> + Send + Sync> { let reloc_model = get_reloc_model(sess); @@ -169,20 +176,28 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) None => llvm::CodeModel::None, }; - let singlethread = sess.target.target.options.singlethread; + let features = attributes::llvm_target_features(sess).collect::>(); + let mut singlethread = sess.target.target.options.singlethread; - let triple = &sess.target.target.llvm_target; + // On the wasm target once the `atomics` feature is enabled that means that + // we're no longer single-threaded, or otherwise we don't want LLVM to + // lower atomic operations to single-threaded operations. + if singlethread && + sess.target.target.llvm_target.contains("wasm32") && + features.iter().any(|s| *s == "+atomics") + { + singlethread = false; + } - let triple = CString::new(triple.as_bytes()).unwrap(); - let cpu = sess.target_cpu(); - let cpu = CString::new(cpu.as_bytes()).unwrap(); - let features = attributes::llvm_target_features(sess) - .collect::>() - .join(","); + let triple = SmallCStr::new(&sess.target.target.llvm_target); + let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); + let features = features.join(","); let features = CString::new(features).unwrap(); let is_pie_binary = !find_features && is_pie_binary(sess); let trap_unreachable = sess.target.target.options.trap_unreachable; + let asm_comments = sess.asm_comments(); + Arc::new(move || { let tm = unsafe { llvm::LLVMRustCreateTargetMachine( @@ -196,15 +211,14 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) fdata_sections, trap_unreachable, singlethread, + asm_comments, ) }; - if tm.is_null() { - Err(format!("Could not create LLVM TargetMachine for triple: {}", - triple.to_str().unwrap())) - } else { - Ok(tm) - } + tm.ok_or_else(|| { + format!("Could not create LLVM TargetMachine for triple: {}", + triple.to_str().unwrap()) + }) }) } @@ -223,6 +237,7 @@ pub struct ModuleConfig { pgo_use: String, // Flags indicating which outputs to produce. + pub emit_pre_thin_lto_bc: bool, emit_no_opt_bc: bool, emit_bc: bool, emit_bc_compressed: bool, @@ -260,6 +275,7 @@ impl ModuleConfig { pgo_use: String::new(), emit_no_opt_bc: false, + emit_pre_thin_lto_bc: false, emit_bc: false, emit_bc_compressed: false, emit_lto_bc: false, @@ -329,7 +345,7 @@ struct AssemblerCommand { /// Additional resources used by optimize_and_codegen (not module specific) #[derive(Clone)] pub struct CodegenContext { - // Resouces needed when running LTO + // Resources needed when running LTO pub time_passes: bool, pub lto: Lto, pub no_landing_pads: bool, @@ -343,10 +359,10 @@ pub struct CodegenContext { regular_module_config: Arc, metadata_module_config: Arc, allocator_module_config: Arc, - pub tm_factory: Arc Result + Send + Sync>, + pub tm_factory: Arc Result<&'static mut llvm::TargetMachine, String> + Send + Sync>, pub msvc_imps_needed: bool, pub target_pointer_width: String, - debuginfo: config::DebugInfoLevel, + debuginfo: config::DebugInfo, // Number of cgus excluding the allocator/metadata modules pub total_cgus: usize, @@ -392,21 +408,21 @@ impl CodegenContext { let cgu = Some(&module.name[..]); let path = self.output_filenames.temp_path_ext(&ext, cgu); let cstr = path2cstr(&path); - let llmod = module.llvm().unwrap().llmod; + let llmod = module.module_llvm.llmod(); llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr()); } } } -struct DiagnosticHandlers<'a> { +pub struct DiagnosticHandlers<'a> { data: *mut (&'a CodegenContext, &'a Handler), - llcx: ContextRef, + llcx: &'a llvm::Context, } impl<'a> DiagnosticHandlers<'a> { - fn new(cgcx: &'a CodegenContext, - handler: &'a Handler, - llcx: ContextRef) -> DiagnosticHandlers<'a> { + pub fn new(cgcx: &'a CodegenContext, + handler: &'a Handler, + llcx: &'a llvm::Context) -> Self { let data = Box::into_raw(Box::new((cgcx, handler))); unsafe { llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _); @@ -433,7 +449,7 @@ unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext, cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_string()); } -unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef, +unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) { if user.is_null() { @@ -447,7 +463,7 @@ unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef, report_inline_asm(cgcx, &msg, cookie); } -unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) { +unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { if user.is_null() { return } @@ -462,8 +478,8 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo llvm::diagnostic::Optimization(opt) => { let enabled = match cgcx.remark { - AllPasses => true, - SomePasses(ref v) => v.iter().any(|s| *s == opt.pass_name), + Passes::All => true, + Passes::Some(ref v) => v.iter().any(|s| *s == opt.pass_name), }; if enabled { @@ -476,10 +492,11 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo opt.message)); } } - llvm::diagnostic::PGO(diagnostic_ref) => { + llvm::diagnostic::PGO(diagnostic_ref) | + llvm::diagnostic::Linker(diagnostic_ref) => { let msg = llvm::build_string(|s| { llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s) - }).expect("non-UTF8 PGO diagnostic"); + }).expect("non-UTF8 diagnostic"); diag_handler.warn(&msg); } llvm::diagnostic::UnknownDiagnostic(..) => {}, @@ -494,13 +511,9 @@ unsafe fn optimize(cgcx: &CodegenContext, timeline: &mut Timeline) -> Result<(), FatalError> { - let (llmod, llcx, tm) = match module.source { - ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm), - ModuleSource::Preexisting(_) => { - bug!("optimize_and_codegen: called with ModuleSource::Preexisting") - } - }; - + let llmod = module.module_llvm.llmod(); + let llcx = &*module.module_llvm.llcx; + let tm = &*module.module_llvm.tm; let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); let module_name = module.name.clone(); @@ -520,50 +533,84 @@ unsafe fn optimize(cgcx: &CodegenContext, let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod); let mpm = llvm::LLVMCreatePassManager(); - // If we're verifying or linting, add them to the function pass - // manager. - let addpass = |pass_name: &str| { - let pass_name = CString::new(pass_name).unwrap(); - let pass = llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()); - if pass.is_null() { - return false; - } - let pass_manager = match llvm::LLVMRustPassKind(pass) { - llvm::PassKind::Function => fpm, - llvm::PassKind::Module => mpm, - llvm::PassKind::Other => { - diag_handler.err("Encountered LLVM pass kind we can't handle"); - return true - }, + { + // If we're verifying or linting, add them to the function pass + // manager. + let addpass = |pass_name: &str| { + let pass_name = SmallCStr::new(pass_name); + let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) { + Some(pass) => pass, + None => return false, + }; + let pass_manager = match llvm::LLVMRustPassKind(pass) { + llvm::PassKind::Function => &*fpm, + llvm::PassKind::Module => &*mpm, + llvm::PassKind::Other => { + diag_handler.err("Encountered LLVM pass kind we can't handle"); + return true + }, + }; + llvm::LLVMRustAddPass(pass_manager, pass); + true }; - llvm::LLVMRustAddPass(pass_manager, pass); - true - }; - if config.verify_llvm_ir { assert!(addpass("verify")); } - if !config.no_prepopulate_passes { - llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); - llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); - let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); - let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal; - with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| { - llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); - llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); - }) - } + if config.verify_llvm_ir { assert!(addpass("verify")); } + + // 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 = llvm::LLVMRustThinLTOAvailable() && (config.emit_bc + || config.obj_is_bitcode || config.emit_bc_compressed || config.embed_bitcode); + let mut have_name_anon_globals_pass = false; + if !config.no_prepopulate_passes { + llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); + llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); + let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); + let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal || + (cgcx.lto != Lto::Fat && cgcx.opts.debugging_opts.cross_lang_lto.enabled()); + have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto; + if using_thin_buffers && !prepare_for_thin_lto { + assert!(addpass("name-anon-globals")); + have_name_anon_globals_pass = true; + } + with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| { + llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); + llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); + }) + } + + for pass in &config.passes { + if !addpass(pass) { + diag_handler.warn(&format!("unknown pass `{}`, ignoring", + pass)); + } + if pass == "name-anon-globals" { + have_name_anon_globals_pass = true; + } + } - for pass in &config.passes { - if !addpass(pass) { - diag_handler.warn(&format!("unknown pass `{}`, ignoring", - pass)); + for pass in &cgcx.plugin_passes { + if !addpass(pass) { + diag_handler.err(&format!("a plugin asked for LLVM pass \ + `{}` but LLVM does not \ + recognize it", pass)); + } + if pass == "name-anon-globals" { + have_name_anon_globals_pass = true; + } } - } - for pass in &cgcx.plugin_passes { - if !addpass(pass) { - diag_handler.err(&format!("a plugin asked for LLVM pass \ - `{}` but LLVM does not \ - recognize it", pass)); + if using_thin_buffers && !have_name_anon_globals_pass { + // As described above, this will probably cause an error in LLVM + if config.no_prepopulate_passes { + diag_handler.err("The current compilation is going to use thin LTO buffers \ + without running LLVM's NameAnonGlobals pass. \ + This will likely cause errors in LLVM. Consider adding \ + -C passes=name-anon-globals to the compiler command line."); + } else { + bug!("We are using thin LTO buffers without running the NameAnonGlobals pass. \ + This will likely cause errors in LLVM and should never happen."); + } } } @@ -592,7 +639,8 @@ unsafe fn optimize(cgcx: &CodegenContext, } fn generate_lto_work(cgcx: &CodegenContext, - modules: Vec) + modules: Vec, + import_only_modules: Vec<(SerializedModule, WorkProduct)>) -> Vec<(WorkItem, u64)> { let mut timeline = cgcx.time_graph.as_ref().map(|tg| { @@ -600,13 +648,22 @@ fn generate_lto_work(cgcx: &CodegenContext, CODEGEN_WORK_PACKAGE_KIND, "generate lto") }).unwrap_or(Timeline::noop()); - let lto_modules = lto::run(cgcx, modules, &mut timeline) + let (lto_modules, copy_jobs) = lto::run(cgcx, modules, import_only_modules, &mut timeline) .unwrap_or_else(|e| e.raise()); - lto_modules.into_iter().map(|module| { + let lto_modules = lto_modules.into_iter().map(|module| { let cost = module.cost(); (WorkItem::LTO(module), cost) - }).collect() + }); + + let copy_jobs = copy_jobs.into_iter().map(|wp| { + (WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen { + name: wp.cgu_name.clone(), + source: wp, + }), 0) + }); + + lto_modules.chain(copy_jobs).collect() } unsafe fn codegen(cgcx: &CodegenContext, @@ -617,192 +674,188 @@ unsafe fn codegen(cgcx: &CodegenContext, -> Result { timeline.record("codegen"); - let (llmod, llcx, tm) = match module.source { - ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm), - ModuleSource::Preexisting(_) => { - bug!("codegen: called with ModuleSource::Preexisting") - } - }; - let module_name = module.name.clone(); - let module_name = Some(&module_name[..]); - let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); - - if cgcx.msvc_imps_needed { - create_msvc_imps(cgcx, llcx, llmod); - } - - // A codegen-specific pass manager is used to generate object - // files for an LLVM module. - // - // Apparently each of these pass managers is a one-shot kind of - // thing, so we create a new one for each type of output. The - // pass manager passed to the closure should be ensured to not - // escape the closure itself, and the manager should only be - // used once. - unsafe fn with_codegen(tm: TargetMachineRef, - llmod: ModuleRef, - no_builtins: bool, - f: F) -> R - where F: FnOnce(PassManagerRef) -> R, { - let cpm = llvm::LLVMCreatePassManager(); - llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); - llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); - f(cpm) - } + let llmod = module.module_llvm.llmod(); + let llcx = &*module.module_llvm.llcx; + let tm = &*module.module_llvm.tm; + let module_name = module.name.clone(); + let module_name = Some(&module_name[..]); + let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); - // If we don't have the integrated assembler, then we need to emit asm - // from LLVM and use `gcc` to create the object file. - let asm_to_obj = config.emit_obj && config.no_integrated_as; - - // Change what we write and cleanup based on whether obj files are - // just llvm bitcode. In that case write bitcode, and possibly - // delete the bitcode if it wasn't requested. Don't generate the - // machine code, instead copy the .o file from the .bc - let write_bc = config.emit_bc || config.obj_is_bitcode; - let rm_bc = !config.emit_bc && config.obj_is_bitcode; - let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj; - let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; - - let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); - - - if write_bc || config.emit_bc_compressed || config.embed_bitcode { - let thin; - let old; - let data = if llvm::LLVMRustThinLTOAvailable() { - thin = ThinBuffer::new(llmod); - thin.data() - } else { - old = ModuleBuffer::new(llmod); - old.data() - }; - timeline.record("make-bc"); + if cgcx.msvc_imps_needed { + create_msvc_imps(cgcx, llcx, llmod); + } + + // A codegen-specific pass manager is used to generate object + // files for an LLVM module. + // + // Apparently each of these pass managers is a one-shot kind of + // thing, so we create a new one for each type of output. The + // pass manager passed to the closure should be ensured to not + // escape the closure itself, and the manager should only be + // used once. + unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine, + llmod: &'ll llvm::Module, + no_builtins: bool, + f: F) -> R + where F: FnOnce(&'ll mut PassManager<'ll>) -> R, + { + let cpm = llvm::LLVMCreatePassManager(); + llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); + llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); + f(cpm) + } + + // If we don't have the integrated assembler, then we need to emit asm + // from LLVM and use `gcc` to create the object file. + let asm_to_obj = config.emit_obj && config.no_integrated_as; + + // Change what we write and cleanup based on whether obj files are + // just llvm bitcode. In that case write bitcode, and possibly + // delete the bitcode if it wasn't requested. Don't generate the + // machine code, instead copy the .o file from the .bc + let write_bc = config.emit_bc || config.obj_is_bitcode; + let rm_bc = !config.emit_bc && config.obj_is_bitcode; + let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj; + let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; + + let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); + let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + + + if write_bc || config.emit_bc_compressed || config.embed_bitcode { + let thin; + let old; + let data = if llvm::LLVMRustThinLTOAvailable() { + thin = ThinBuffer::new(llmod); + thin.data() + } else { + old = ModuleBuffer::new(llmod); + old.data() + }; + timeline.record("make-bc"); - if write_bc { - if let Err(e) = fs::write(&bc_out, data) { - diag_handler.err(&format!("failed to write bytecode: {}", e)); + if write_bc { + if let Err(e) = fs::write(&bc_out, data) { + diag_handler.err(&format!("failed to write bytecode: {}", e)); + } + timeline.record("write-bc"); } - timeline.record("write-bc"); - } - if config.embed_bitcode { - embed_bitcode(cgcx, llcx, llmod, Some(data)); - timeline.record("embed-bc"); - } + if config.embed_bitcode { + embed_bitcode(cgcx, llcx, llmod, Some(data)); + timeline.record("embed-bc"); + } - if config.emit_bc_compressed { - let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); - let data = bytecode::encode(&module.llmod_id, data); - if let Err(e) = fs::write(&dst, data) { - diag_handler.err(&format!("failed to write bytecode: {}", e)); + if config.emit_bc_compressed { + let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); + let data = bytecode::encode(&module.name, data); + if let Err(e) = fs::write(&dst, data) { + diag_handler.err(&format!("failed to write bytecode: {}", e)); + } + timeline.record("compress-bc"); } - timeline.record("compress-bc"); - } - } else if config.embed_bitcode_marker { - embed_bitcode(cgcx, llcx, llmod, None); - } + } else if config.embed_bitcode_marker { + embed_bitcode(cgcx, llcx, llmod, None); + } + + time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), + || -> Result<(), FatalError> { + if config.emit_ir { + let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out = path2cstr(&out); + + extern "C" fn demangle_callback(input_ptr: *const c_char, + input_len: size_t, + output_ptr: *mut c_char, + output_len: size_t) -> size_t { + let input = unsafe { + slice::from_raw_parts(input_ptr as *const u8, input_len as usize) + }; - time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), - || -> Result<(), FatalError> { - if config.emit_ir { - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); - let out = path2cstr(&out); - - extern "C" fn demangle_callback(input_ptr: *const c_char, - input_len: size_t, - output_ptr: *mut c_char, - output_len: size_t) -> size_t { - let input = unsafe { - slice::from_raw_parts(input_ptr as *const u8, input_len as usize) - }; + let input = match str::from_utf8(input) { + Ok(s) => s, + Err(_) => return 0, + }; - let input = match str::from_utf8(input) { - Ok(s) => s, - Err(_) => return 0, - }; + let output = unsafe { + slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) + }; + let mut cursor = io::Cursor::new(output); - let output = unsafe { - slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) - }; - let mut cursor = io::Cursor::new(output); + let demangled = match rustc_demangle::try_demangle(input) { + Ok(d) => d, + Err(_) => return 0, + }; - let demangled = match rustc_demangle::try_demangle(input) { - Ok(d) => d, - Err(_) => return 0, - }; + if let Err(_) = write!(cursor, "{:#}", demangled) { + // Possible only if provided buffer is not big enough + return 0; + } - if let Err(_) = write!(cursor, "{:#}", demangled) { - // Possible only if provided buffer is not big enough - return 0; + cursor.position() as size_t } - cursor.position() as size_t + with_codegen(tm, llmod, config.no_builtins, |cpm| { + llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); + llvm::LLVMDisposePassManager(cpm); + }); + timeline.record("ir"); } - with_codegen(tm, llmod, config.no_builtins, |cpm| { - llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); - llvm::LLVMDisposePassManager(cpm); - }); - timeline.record("ir"); - } - - if config.emit_asm || asm_to_obj { - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + if config.emit_asm || asm_to_obj { + let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - // We can't use the same module for asm and binary output, because that triggers - // various errors like invalid IR or broken binaries, so we might have to clone the - // module to produce the asm output - let llmod = if config.emit_obj { - llvm::LLVMCloneModule(llmod) - } else { - llmod - }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(diag_handler, tm, cpm, llmod, &path, - llvm::FileType::AssemblyFile) - })?; - if config.emit_obj { - llvm::LLVMDisposeModule(llmod); + // We can't use the same module for asm and binary output, because that triggers + // various errors like invalid IR or broken binaries, so we might have to clone the + // module to produce the asm output + let llmod = if config.emit_obj { + llvm::LLVMCloneModule(llmod) + } else { + llmod + }; + with_codegen(tm, llmod, config.no_builtins, |cpm| { + write_output_file(diag_handler, tm, cpm, llmod, &path, + llvm::FileType::AssemblyFile) + })?; + timeline.record("asm"); } - timeline.record("asm"); - } - if write_obj { - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(diag_handler, tm, cpm, llmod, &obj_out, - llvm::FileType::ObjectFile) - })?; - timeline.record("obj"); - } else if asm_to_obj { - let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - run_assembler(cgcx, diag_handler, &assembly, &obj_out); - timeline.record("asm_to_obj"); - - if !config.emit_asm && !cgcx.save_temps { - drop(fs::remove_file(&assembly)); + if write_obj { + with_codegen(tm, llmod, config.no_builtins, |cpm| { + write_output_file(diag_handler, tm, cpm, llmod, &obj_out, + llvm::FileType::ObjectFile) + })?; + timeline.record("obj"); + } else if asm_to_obj { + let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + run_assembler(cgcx, diag_handler, &assembly, &obj_out); + timeline.record("asm_to_obj"); + + if !config.emit_asm && !cgcx.save_temps { + drop(fs::remove_file(&assembly)); + } } - } - Ok(()) - })?; + Ok(()) + })?; - if copy_bc_to_obj { - debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); - if let Err(e) = link_or_copy(&bc_out, &obj_out) { - diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + if copy_bc_to_obj { + debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); + if let Err(e) = link_or_copy(&bc_out, &obj_out) { + diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + } } - } - if rm_bc { - debug!("removing_bitcode {:?}", bc_out); - if let Err(e) = fs::remove_file(&bc_out) { - diag_handler.err(&format!("failed to remove bitcode: {}", e)); + if rm_bc { + debug!("removing_bitcode {:?}", bc_out); + if let Err(e) = fs::remove_file(&bc_out) { + diag_handler.err(&format!("failed to remove bitcode: {}", e)); + } } - } - drop(handlers); + drop(handlers); + } Ok(module.into_compiled_module(config.emit_obj, config.emit_bc, config.emit_bc_compressed, @@ -828,13 +881,13 @@ unsafe fn codegen(cgcx: &CodegenContext, /// Basically all of this is us attempting to follow in the footsteps of clang /// on iOS. See #35968 for lots more info. unsafe fn embed_bitcode(cgcx: &CodegenContext, - llcx: ContextRef, - llmod: ModuleRef, + llcx: &llvm::Context, + llmod: &llvm::Module, bitcode: Option<&[u8]>) { let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[])); let llglobal = llvm::LLVMAddGlobal( llmod, - val_ty(llconst).to_ref(), + val_ty(llconst), "rustc.embedded.module\0".as_ptr() as *const _, ); llvm::LLVMSetInitializer(llglobal, llconst); @@ -854,7 +907,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, let llconst = C_bytes_in_context(llcx, &[]); let llglobal = llvm::LLVMAddGlobal( llmod, - val_ty(llconst).to_ref(), + val_ty(llconst), "rustc.embedded.cmdline\0".as_ptr() as *const _, ); llvm::LLVMSetInitializer(llglobal, llconst); @@ -874,19 +927,32 @@ pub(crate) struct CompiledModules { } fn need_crate_bitcode_for_rlib(sess: &Session) -> bool { - sess.crate_types.borrow().contains(&config::CrateTypeRlib) && + sess.crate_types.borrow().contains(&config::CrateType::Rlib) && sess.opts.output_types.contains_key(&OutputType::Exe) } +fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool { + if sess.opts.incremental.is_none() { + return false + } + + match sess.lto() { + Lto::Fat | + Lto::No => false, + Lto::Thin | + Lto::ThinLocal => true, + } +} + pub fn start_async_codegen(tcx: TyCtxt, time_graph: Option, - link: LinkMeta, metadata: EncodedMetadata, coordinator_receive: Receiver>, total_cgus: usize) -> OngoingCodegen { let sess = tcx.sess; let crate_name = tcx.crate_name(LOCAL_CRATE); + let crate_hash = tcx.crate_hash(LOCAL_CRATE); let no_builtins = attr::contains_name(&tcx.hir.krate().attrs, "no_builtins"); let subsystem = attr::first_attr_value_str_by_name(&tcx.hir.krate().attrs, "windows_subsystem"); @@ -936,6 +1002,7 @@ pub fn start_async_codegen(tcx: TyCtxt, // Save all versions of the bytecode if we're saving our temporaries. if sess.opts.cg.save_temps { modules_config.emit_no_opt_bc = true; + modules_config.emit_pre_thin_lto_bc = true; modules_config.emit_bc = true; modules_config.emit_lto_bc = true; metadata_config.emit_bc = true; @@ -950,6 +1017,9 @@ pub fn start_async_codegen(tcx: TyCtxt, allocator_config.emit_bc_compressed = true; } + modules_config.emit_pre_thin_lto_bc = + need_pre_thin_lto_bitcode_for_incr_comp(sess); + modules_config.no_integrated_as = tcx.sess.opts.cg.no_integrated_as || tcx.sess.target.target.options.no_integrated_as; @@ -1005,7 +1075,7 @@ pub fn start_async_codegen(tcx: TyCtxt, OngoingCodegen { crate_name, - link, + crate_hash, metadata, windows_subsystem, linker_info, @@ -1022,7 +1092,7 @@ pub fn start_async_codegen(tcx: TyCtxt, fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( sess: &Session, - compiled_modules: &CompiledModules + compiled_modules: &CompiledModules, ) -> FxHashMap { let mut work_products = FxHashMap::default(); @@ -1030,7 +1100,7 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( return work_products; } - for module in compiled_modules.modules.iter() { + for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { let mut files = vec![]; if let Some(ref path) = module.object { @@ -1202,21 +1272,30 @@ fn produce_final_output_artifacts(sess: &Session, // These are used in linking steps and will be cleaned up afterward. } -pub(crate) fn dump_incremental_data(codegen_results: &CodegenResults) { - println!("[incremental] Re-using {} out of {} modules", - codegen_results.modules.iter().filter(|m| m.pre_existing).count(), - codegen_results.modules.len()); +pub(crate) fn dump_incremental_data(_codegen_results: &CodegenResults) { + // FIXME(mw): This does not work at the moment because the situation has + // become more complicated due to incremental LTO. Now a CGU + // can have more than two caching states. + // println!("[incremental] Re-using {} out of {} modules", + // codegen_results.modules.iter().filter(|m| m.pre_existing).count(), + // codegen_results.modules.len()); } enum WorkItem { + /// Optimize a newly codegened, totally unoptimized module. Optimize(ModuleCodegen), + /// Copy the post-LTO artifacts from the incremental cache to the output + /// directory. + CopyPostLtoArtifacts(CachedModuleCodegen), + /// Perform (Thin)LTO on the given module. LTO(lto::LtoModuleCodegen), } impl WorkItem { - fn kind(&self) -> ModuleKind { + fn module_kind(&self) -> ModuleKind { match *self { WorkItem::Optimize(ref m) => m.kind, + WorkItem::CopyPostLtoArtifacts(_) | WorkItem::LTO(_) => ModuleKind::Regular, } } @@ -1224,6 +1303,7 @@ impl WorkItem { fn name(&self) -> String { match *self { WorkItem::Optimize(ref m) => format!("optimize: {}", m.name), + WorkItem::CopyPostLtoArtifacts(ref m) => format!("copy post LTO artifacts: {}", m.name), WorkItem::LTO(ref m) => format!("lto: {}", m.name()), } } @@ -1239,140 +1319,168 @@ fn execute_work_item(cgcx: &CodegenContext, timeline: &mut Timeline) -> Result { - let diag_handler = cgcx.create_diag_handler(); - let config = cgcx.config(work_item.kind()); - let module = match work_item { - WorkItem::Optimize(module) => module, - WorkItem::LTO(mut lto) => { - unsafe { - let module = lto.optimize(cgcx, timeline)?; - let module = codegen(cgcx, &diag_handler, module, config, timeline)?; - return Ok(WorkItemResult::Compiled(module)) - } + let module_config = cgcx.config(work_item.module_kind()); + + match work_item { + WorkItem::Optimize(module) => { + execute_optimize_work_item(cgcx, module, module_config, timeline) } - }; - let module_name = module.name.clone(); + WorkItem::CopyPostLtoArtifacts(module) => { + execute_copy_from_cache_work_item(cgcx, module, module_config, timeline) + } + WorkItem::LTO(module) => { + execute_lto_work_item(cgcx, module, module_config, timeline) + } + } +} - let pre_existing = match module.source { - ModuleSource::Codegened(_) => None, - ModuleSource::Preexisting(ref wp) => Some(wp.clone()), - }; +fn execute_optimize_work_item(cgcx: &CodegenContext, + module: ModuleCodegen, + module_config: &ModuleConfig, + timeline: &mut Timeline) + -> Result +{ + let diag_handler = cgcx.create_diag_handler(); - if let Some(wp) = pre_existing { - let incr_comp_session_dir = cgcx.incr_comp_session_dir - .as_ref() - .unwrap(); - let name = &module.name; - let mut object = None; - let mut bytecode = None; - let mut bytecode_compressed = None; - for (kind, saved_file) in wp.saved_files { - let obj_out = match kind { - WorkProductFileKind::Object => { - let path = cgcx.output_filenames.temp_path(OutputType::Object, Some(name)); - object = Some(path.clone()); - path - } - WorkProductFileKind::Bytecode => { - let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(name)); - bytecode = Some(path.clone()); - path - } - WorkProductFileKind::BytecodeCompressed => { - let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(name)) - .with_extension(RLIB_BYTECODE_EXTENSION); - bytecode_compressed = Some(path.clone()); - path - } - }; - let source_file = in_incr_comp_dir(&incr_comp_session_dir, - &saved_file); - debug!("copying pre-existing module `{}` from {:?} to {}", - module.name, - source_file, - obj_out.display()); - match link_or_copy(&source_file, &obj_out) { - Ok(_) => { } - Err(err) => { - diag_handler.err(&format!("unable to copy {} to {}: {}", - source_file.display(), - obj_out.display(), - err)); - } - } - } - assert_eq!(object.is_some(), config.emit_obj); - assert_eq!(bytecode.is_some(), config.emit_bc); - assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed); - - Ok(WorkItemResult::Compiled(CompiledModule { - llmod_id: module.llmod_id.clone(), - name: module_name, - kind: ModuleKind::Regular, - pre_existing: true, - object, - bytecode, - bytecode_compressed, - })) - } else { - debug!("llvm-optimizing {:?}", module_name); + unsafe { + optimize(cgcx, &diag_handler, &module, module_config, timeline)?; + } - unsafe { - optimize(cgcx, &diag_handler, &module, config, timeline)?; - - // After we've done the initial round of optimizations we need to - // decide whether to synchronously codegen this module or ship it - // back to the coordinator thread for further LTO processing (which - // has to wait for all the initial modules to be optimized). - // - // Here we dispatch based on the `cgcx.lto` and kind of module we're - // codegenning... - let needs_lto = match cgcx.lto { - Lto::No => false, - - // Here we've got a full crate graph LTO requested. We ignore - // this, however, if the crate type is only an rlib as there's - // no full crate graph to process, that'll happen later. - // - // This use case currently comes up primarily for targets that - // require LTO so the request for LTO is always unconditionally - // passed down to the backend, but we don't actually want to do - // anything about it yet until we've got a final product. - Lto::Yes | Lto::Fat | Lto::Thin => { - cgcx.crate_types.len() != 1 || - cgcx.crate_types[0] != config::CrateTypeRlib - } + let linker_does_lto = cgcx.opts.debugging_opts.cross_lang_lto.enabled(); - // When we're automatically doing ThinLTO for multi-codegen-unit - // builds we don't actually want to LTO the allocator modules if - // it shows up. This is due to various linker shenanigans that - // we'll encounter later. - // - // Additionally here's where we also factor in the current LLVM - // version. If it doesn't support ThinLTO we skip this. - Lto::ThinLocal => { - module.kind != ModuleKind::Allocator && - llvm::LLVMRustThinLTOAvailable() - } - }; + // After we've done the initial round of optimizations we need to + // decide whether to synchronously codegen this module or ship it + // back to the coordinator thread for further LTO processing (which + // has to wait for all the initial modules to be optimized). + // + // Here we dispatch based on the `cgcx.lto` and kind of module we're + // codegenning... + let needs_lto = match cgcx.lto { + Lto::No => false, + + // If the linker does LTO, we don't have to do it. Note that we + // keep doing full LTO, if it is requested, as not to break the + // assumption that the output will be a single module. + Lto::Thin | Lto::ThinLocal if linker_does_lto => false, + + // Here we've got a full crate graph LTO requested. We ignore + // this, however, if the crate type is only an rlib as there's + // no full crate graph to process, that'll happen later. + // + // This use case currently comes up primarily for targets that + // require LTO so the request for LTO is always unconditionally + // passed down to the backend, but we don't actually want to do + // anything about it yet until we've got a final product. + Lto::Fat | Lto::Thin => { + cgcx.crate_types.len() != 1 || + cgcx.crate_types[0] != config::CrateType::Rlib + } + + // When we're automatically doing ThinLTO for multi-codegen-unit + // builds we don't actually want to LTO the allocator modules if + // it shows up. This is due to various linker shenanigans that + // we'll encounter later. + // + // Additionally here's where we also factor in the current LLVM + // version. If it doesn't support ThinLTO we skip this. + Lto::ThinLocal => { + module.kind != ModuleKind::Allocator && + unsafe { llvm::LLVMRustThinLTOAvailable() } + } + }; - // Metadata modules never participate in LTO regardless of the lto - // settings. - let needs_lto = needs_lto && module.kind != ModuleKind::Metadata; + // Metadata modules never participate in LTO regardless of the lto + // settings. + let needs_lto = needs_lto && module.kind != ModuleKind::Metadata; - // Don't run LTO passes when cross-lang LTO is enabled. The linker - // will do that for us in this case. - let needs_lto = needs_lto && - !cgcx.opts.debugging_opts.cross_lang_lto.enabled(); + if needs_lto { + Ok(WorkItemResult::NeedsLTO(module)) + } else { + let module = unsafe { + codegen(cgcx, &diag_handler, module, module_config, timeline)? + }; + Ok(WorkItemResult::Compiled(module)) + } +} - if needs_lto { - Ok(WorkItemResult::NeedsLTO(module)) - } else { - let module = codegen(cgcx, &diag_handler, module, config, timeline)?; - Ok(WorkItemResult::Compiled(module)) +fn execute_copy_from_cache_work_item(cgcx: &CodegenContext, + module: CachedModuleCodegen, + module_config: &ModuleConfig, + _: &mut Timeline) + -> Result +{ + let incr_comp_session_dir = cgcx.incr_comp_session_dir + .as_ref() + .unwrap(); + let mut object = None; + let mut bytecode = None; + let mut bytecode_compressed = None; + for (kind, saved_file) in &module.source.saved_files { + let obj_out = match kind { + WorkProductFileKind::Object => { + let path = cgcx.output_filenames.temp_path(OutputType::Object, + Some(&module.name)); + object = Some(path.clone()); + path + } + WorkProductFileKind::Bytecode => { + let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, + Some(&module.name)); + bytecode = Some(path.clone()); + path + } + WorkProductFileKind::BytecodeCompressed => { + let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, + Some(&module.name)) + .with_extension(RLIB_BYTECODE_EXTENSION); + bytecode_compressed = Some(path.clone()); + path + } + }; + let source_file = in_incr_comp_dir(&incr_comp_session_dir, + &saved_file); + debug!("copying pre-existing module `{}` from {:?} to {}", + module.name, + source_file, + obj_out.display()); + match link_or_copy(&source_file, &obj_out) { + Ok(_) => { } + Err(err) => { + let diag_handler = cgcx.create_diag_handler(); + diag_handler.err(&format!("unable to copy {} to {}: {}", + source_file.display(), + obj_out.display(), + err)); } } } + + assert_eq!(object.is_some(), module_config.emit_obj); + assert_eq!(bytecode.is_some(), module_config.emit_bc); + assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed); + + Ok(WorkItemResult::Compiled(CompiledModule { + name: module.name, + kind: ModuleKind::Regular, + object, + bytecode, + bytecode_compressed, + })) +} + +fn execute_lto_work_item(cgcx: &CodegenContext, + mut module: lto::LtoModuleCodegen, + module_config: &ModuleConfig, + timeline: &mut Timeline) + -> Result +{ + let diag_handler = cgcx.create_diag_handler(); + + unsafe { + let module = module.optimize(cgcx, timeline)?; + let module = codegen(cgcx, &diag_handler, module, module_config, timeline)?; + Ok(WorkItemResult::Compiled(module)) + } } enum Message { @@ -1389,6 +1497,10 @@ enum Message { llvm_work_item: WorkItem, cost: u64, }, + AddImportOnlyModule { + module_data: SerializedModule, + work_product: WorkProduct, + }, CodegenComplete, CodegenItem, } @@ -1439,7 +1551,7 @@ fn start_executing_work(tcx: TyCtxt, exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); Some(Arc::new(exported_symbols)) } - Lto::Yes | Lto::Fat | Lto::Thin => { + Lto::Fat | Lto::Thin => { exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); for &cnum in tcx.crates().iter() { exported_symbols.insert(cnum, copy_symbols(cnum)); @@ -1469,7 +1581,9 @@ fn start_executing_work(tcx: TyCtxt, let assembler_cmd = if modules_config.no_integrated_as { // HACK: currently we use linker (gcc) as our assembler - let (name, mut cmd) = get_linker(sess); + let (linker, flavor) = link::linker_and_flavor(sess); + + let (name, mut cmd) = get_linker(sess, &linker, flavor); cmd.args(&sess.target.target.options.asm_args); Some(Arc::new(AssemblerCommand { name, @@ -1666,6 +1780,7 @@ fn start_executing_work(tcx: TyCtxt, let mut compiled_metadata_module = None; let mut compiled_allocator_module = None; let mut needs_lto = Vec::new(); + let mut lto_import_only_modules = Vec::new(); let mut started_lto = false; // This flag tracks whether all items have gone through codegens @@ -1689,6 +1804,7 @@ fn start_executing_work(tcx: TyCtxt, work_items.len() > 0 || running > 0 || needs_lto.len() > 0 || + lto_import_only_modules.len() > 0 || main_thread_worker_state != MainThreadWorkerState::Idle { // While there are still CGUs to be codegened, the coordinator has @@ -1712,7 +1828,7 @@ fn start_executing_work(tcx: TyCtxt, worker: get_worker_id(&mut free_worker_ids), .. cgcx.clone() }; - maybe_start_llvm_timer(cgcx.config(item.kind()), + maybe_start_llvm_timer(cgcx.config(item.module_kind()), &mut llvm_start_time); main_thread_worker_state = MainThreadWorkerState::LLVMing; spawn_work(cgcx, item); @@ -1728,10 +1844,12 @@ fn start_executing_work(tcx: TyCtxt, running == 0 && main_thread_worker_state == MainThreadWorkerState::Idle { assert!(!started_lto); - assert!(needs_lto.len() > 0); + assert!(needs_lto.len() + lto_import_only_modules.len() > 0); started_lto = true; let modules = mem::replace(&mut needs_lto, Vec::new()); - for (work, cost) in generate_lto_work(&cgcx, modules) { + let import_only_modules = + mem::replace(&mut lto_import_only_modules, Vec::new()); + for (work, cost) in generate_lto_work(&cgcx, modules, import_only_modules) { let insertion_index = work_items .binary_search_by_key(&cost, |&(_, cost)| cost) .unwrap_or_else(|e| e); @@ -1752,7 +1870,7 @@ fn start_executing_work(tcx: TyCtxt, worker: get_worker_id(&mut free_worker_ids), .. cgcx.clone() }; - maybe_start_llvm_timer(cgcx.config(item.kind()), + maybe_start_llvm_timer(cgcx.config(item.module_kind()), &mut llvm_start_time); main_thread_worker_state = MainThreadWorkerState::LLVMing; spawn_work(cgcx, item); @@ -1783,7 +1901,7 @@ fn start_executing_work(tcx: TyCtxt, while work_items.len() > 0 && running < tokens.len() { let (item, _) = work_items.pop().unwrap(); - maybe_start_llvm_timer(cgcx.config(item.kind()), + maybe_start_llvm_timer(cgcx.config(item.module_kind()), &mut llvm_start_time); let cgcx = CodegenContext { @@ -1895,10 +2013,17 @@ fn start_executing_work(tcx: TyCtxt, } else { running -= 1; } - free_worker_ids.push(worker_id); needs_lto.push(result); } + Message::AddImportOnlyModule { module_data, work_product } => { + assert!(!started_lto); + assert!(!codegen_done); + assert_eq!(main_thread_worker_state, + MainThreadWorkerState::Codegenning); + lto_import_only_modules.push((module_data, work_product)); + main_thread_worker_state = MainThreadWorkerState::Idle; + } Message::Done { result: Err(()), worker_id: _ } => { shared_emitter.fatal("aborting due to worker thread failure"); // Exit the coordinator thread @@ -2050,11 +2175,11 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path, } } -pub unsafe fn with_llvm_pmb(llmod: ModuleRef, +pub unsafe fn with_llvm_pmb(llmod: &llvm::Module, config: &ModuleConfig, opt_level: llvm::CodeGenOptLevel, prepare_for_thin_lto: bool, - f: &mut dyn FnMut(llvm::PassManagerBuilderRef)) { + f: &mut dyn FnMut(&llvm::PassManagerBuilder)) { use std::ptr; // Create the PassManagerBuilder for LLVM. We configure it with @@ -2235,7 +2360,7 @@ impl SharedEmitterMain { pub struct OngoingCodegen { crate_name: Symbol, - link: LinkMeta, + crate_hash: Svh, metadata: EncodedMetadata, windows_subsystem: Option, linker_info: LinkerInfo, @@ -2271,9 +2396,9 @@ impl OngoingCodegen { time_graph.dump(&format!("{}-timings", self.crate_name)); } - let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, - &compiled_modules); - + let work_products = + copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, + &compiled_modules); produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames); @@ -2286,7 +2411,7 @@ impl OngoingCodegen { (CodegenResults { crate_name: self.crate_name, - link: self.link, + crate_hash: self.crate_hash, metadata: self.metadata, windows_subsystem: self.windows_subsystem, linker_info: self.linker_info, @@ -2334,8 +2459,8 @@ impl OngoingCodegen { } pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt, - module: ModuleCodegen, - cost: u64) { + module: ModuleCodegen, + cost: u64) { let llvm_work_item = WorkItem::Optimize(module); drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone { llvm_work_item, @@ -2343,9 +2468,53 @@ pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt, }))); } +pub(crate) fn submit_post_lto_module_to_llvm(tcx: TyCtxt, + module: CachedModuleCodegen) { + let llvm_work_item = WorkItem::CopyPostLtoArtifacts(module); + drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone { + llvm_work_item, + cost: 0, + }))); +} + +pub(crate) fn submit_pre_lto_module_to_llvm(tcx: TyCtxt, + module: CachedModuleCodegen) { + let filename = pre_lto_bitcode_filename(&module.name); + let bc_path = in_incr_comp_dir_sess(tcx.sess, &filename); + let file = fs::File::open(&bc_path).unwrap_or_else(|e| { + panic!("failed to open bitcode file `{}`: {}", bc_path.display(), e) + }); + + let mmap = unsafe { + memmap::Mmap::map(&file).unwrap_or_else(|e| { + panic!("failed to mmap bitcode file `{}`: {}", bc_path.display(), e) + }) + }; + + // Schedule the module to be loaded + drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::AddImportOnlyModule { + module_data: SerializedModule::FromUncompressedFile(mmap), + work_product: module.source, + }))); +} + +pub(super) fn pre_lto_bitcode_filename(module_name: &str) -> String { + format!("{}.{}", module_name, PRE_THIN_LTO_BC_EXT) +} + fn msvc_imps_needed(tcx: TyCtxt) -> bool { + // This should never be true (because it's not supported). If it is true, + // something is wrong with commandline arg validation. + assert!(!(tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() && + tcx.sess.target.target.options.is_like_msvc && + tcx.sess.opts.cg.prefer_dynamic)); + tcx.sess.target.target.options.is_like_msvc && - tcx.sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) + tcx.sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateType::Rlib) && + // ThinLTO can't handle this workaround in all cases, so we don't + // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing + // dynamic linking when cross-language LTO is enabled. + !tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() } // Create a `__imp_ = &symbol` global for every public static `symbol`. @@ -2353,7 +2522,7 @@ fn msvc_imps_needed(tcx: TyCtxt) -> bool { // when using MSVC linker. We do this only for data, as linker can fix up // code references on its own. // See #26591, #27438 -fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) { +fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) { if !cgcx.msvc_imps_needed { return } @@ -2383,7 +2552,7 @@ fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) { .collect::>(); for (imp_name, val) in globals { let imp = llvm::LLVMAddGlobal(llmod, - i8p_ty.to_ref(), + i8p_ty, imp_name.as_ptr() as *const _); llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty)); llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 223c04f420..c1f6006e68 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -17,36 +17,34 @@ //! //! Hopefully useful general knowledge about codegen: //! -//! * There's no way to find out the Ty type of a ValueRef. 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 TypeRef by calling val_ty, -//! but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int, -//! int) and rec(x=int, y=int, z=int) will have the same TypeRef. +//! 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 super::ModuleLlvm; -use super::ModuleSource; use super::ModuleCodegen; use super::ModuleKind; +use super::CachedModuleCodegen; use abi; -use back::link; -use back::write::{self, OngoingCodegen, create_target_machine}; -use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param}; -use llvm; +use back::write::{self, OngoingCodegen}; +use llvm::{self, TypeKind, get_param}; use metadata; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::weak_lang_items; -use rustc::mir::mono::{Linkage, Visibility, Stats}; +use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder}; use rustc::middle::cstore::{EncodedMetadata}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf}; use rustc::ty::query::Providers; -use rustc::dep_graph::{DepNode, DepConstructor}; -use rustc::middle::cstore::{self, LinkMeta, LinkagePreference}; +use rustc::middle::cstore::{self, LinkagePreference}; use rustc::middle::exported_symbols; use rustc::util::common::{time, print_time_passes_entry}; -use rustc::session::config::{self, NoDebugInfo}; +use rustc::util::profiling::ProfileCategory; +use rustc::session::config::{self, DebugInfo, EntryFnType, Lto}; use rustc::session::Session; use rustc_incremental; use allocator; @@ -59,7 +57,7 @@ use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode}; use rustc_mir::monomorphize::item::DefPathBasedNames; use common::{self, C_struct_in_context, C_array, val_ty}; use consts; -use context::{self, CodegenCx}; +use context::CodegenCx; use debuginfo; use declare; use meth; @@ -73,11 +71,11 @@ use type_::Type; use type_of::LayoutLlvmExt; use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet}; use CrateInfo; +use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::sync::Lrc; use std::any::Any; use std::ffi::CString; -use std::str; use std::sync::Arc; use std::time::{Instant, Duration}; use std::i32; @@ -88,18 +86,20 @@ use syntax_pos::symbol::InternedString; use syntax::attr; use rustc::hir::{self, CodegenFnAttrs}; +use value::Value; + use mir::operand::OperandValue; use rustc_codegen_utils::check_for_rustc_errors_attr; -pub struct StatRecorder<'a, 'tcx: 'a> { - cx: &'a CodegenCx<'a, 'tcx>, +pub struct StatRecorder<'a, 'll: 'a, 'tcx: 'll> { + cx: &'a CodegenCx<'ll, 'tcx>, name: Option, istart: usize, } -impl<'a, 'tcx> StatRecorder<'a, 'tcx> { - pub fn new(cx: &'a CodegenCx<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> { +impl StatRecorder<'a, 'll, 'tcx> { + pub fn new(cx: &'a CodegenCx<'ll, 'tcx>, name: String) -> Self { let istart = cx.stats.borrow().n_llvm_insns; StatRecorder { cx, @@ -109,7 +109,7 @@ impl<'a, 'tcx> StatRecorder<'a, 'tcx> { } } -impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> { +impl Drop for StatRecorder<'a, 'll, 'tcx> { fn drop(&mut self) { if self.cx.sess().codegen_stats() { let mut stats = self.cx.stats.borrow_mut(); @@ -156,21 +156,21 @@ pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate { } } -pub fn compare_simd_types<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - lhs: ValueRef, - rhs: ValueRef, +pub fn compare_simd_types( + bx: &Builder<'a, 'll, 'tcx>, + lhs: &'ll Value, + rhs: &'ll Value, t: Ty<'tcx>, - ret_ty: Type, + ret_ty: &'ll Type, op: hir::BinOpKind -) -> ValueRef { +) -> &'ll Value { let signed = match t.sty { - ty::TyFloat(_) => { + ty::Float(_) => { let cmp = bin_op_to_fcmp_predicate(op); return bx.sext(bx.fcmp(cmp, lhs, rhs), ret_ty); }, - ty::TyUint(_) => false, - ty::TyInt(_) => true, + ty::Uint(_) => false, + ty::Int(_) => true, _ => bug!("compare_simd_types: invalid SIMD type"), }; @@ -188,23 +188,24 @@ pub fn compare_simd_types<'a, 'tcx>( /// 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. -pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>, - source: Ty<'tcx>, - target: Ty<'tcx>, - old_info: Option) - -> ValueRef { +pub fn unsized_info( + cx: &CodegenCx<'ll, 'tcx>, + source: Ty<'tcx>, + target: Ty<'tcx>, + old_info: Option<&'ll Value>, +) -> &'ll Value { let (source, target) = cx.tcx.struct_lockstep_tails(source, target); match (&source.sty, &target.sty) { - (&ty::TyArray(_, len), &ty::TySlice(_)) => { + (&ty::Array(_, len), &ty::Slice(_)) => { C_usize(cx, len.unwrap_usize(cx.tcx)) } - (&ty::TyDynamic(..), &ty::TyDynamic(..)) => { + (&ty::Dynamic(..), &ty::Dynamic(..)) => { // For now, upcasts are limited to changes in marker // traits, and hence never actually require an actual // change to the vtable. old_info.expect("unsized_info: missing old info for trait upcast") } - (_, &ty::TyDynamic(ref data, ..)) => { + (_, &ty::Dynamic(ref data, ..)) => { let vtable_ptr = cx.layout_of(cx.tcx.mk_mut_ptr(target)) .field(cx, abi::FAT_PTR_EXTRA); consts::ptrcast(meth::get_vtable(cx, source, data.principal()), @@ -217,31 +218,31 @@ pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>, } /// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer. -pub fn unsize_thin_ptr<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - src: ValueRef, +pub fn unsize_thin_ptr( + bx: &Builder<'a, 'll, 'tcx>, + src: &'ll Value, src_ty: Ty<'tcx>, dst_ty: Ty<'tcx> -) -> (ValueRef, ValueRef) { +) -> (&'ll Value, &'ll Value) { debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty); match (&src_ty.sty, &dst_ty.sty) { - (&ty::TyRef(_, a, _), - &ty::TyRef(_, b, _)) | - (&ty::TyRef(_, a, _), - &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) | - (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }), - &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => { + (&ty::Ref(_, a, _), + &ty::Ref(_, b, _)) | + (&ty::Ref(_, a, _), + &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) | + (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), + &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { assert!(bx.cx.type_is_sized(a)); let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to(); (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None)) } - (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => { + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty()); assert!(bx.cx.type_is_sized(a)); let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to(); (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None)) } - (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => { + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); let src_layout = bx.cx.layout_of(src_ty); @@ -272,9 +273,11 @@ pub fn unsize_thin_ptr<'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` -pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - src: PlaceRef<'tcx>, - dst: PlaceRef<'tcx>) { +pub fn coerce_unsized_into( + bx: &Builder<'a, 'll, 'tcx>, + src: PlaceRef<'ll, 'tcx>, + dst: PlaceRef<'ll, 'tcx> +) { let src_ty = src.layout.ty; let dst_ty = dst.layout.ty; let coerce_ptr = || { @@ -295,16 +298,16 @@ pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>, OperandValue::Pair(base, info).store(bx, dst); }; match (&src_ty.sty, &dst_ty.sty) { - (&ty::TyRef(..), &ty::TyRef(..)) | - (&ty::TyRef(..), &ty::TyRawPtr(..)) | - (&ty::TyRawPtr(..), &ty::TyRawPtr(..)) => { + (&ty::Ref(..), &ty::Ref(..)) | + (&ty::Ref(..), &ty::RawPtr(..)) | + (&ty::RawPtr(..), &ty::RawPtr(..)) => { coerce_ptr() } - (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => { + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { coerce_ptr() } - (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => { + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); for i in 0..def_a.variants[0].fields.len() { @@ -330,28 +333,28 @@ pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>, } pub fn cast_shift_expr_rhs( - cx: &Builder, op: hir::BinOpKind, lhs: ValueRef, rhs: ValueRef -) -> ValueRef { + cx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value +) -> &'ll Value { cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b)) } -fn cast_shift_rhs(op: hir::BinOpKind, - lhs: ValueRef, - rhs: ValueRef, +fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind, + lhs: &'ll Value, + rhs: &'ll Value, trunc: F, zext: G) - -> ValueRef - where F: FnOnce(ValueRef, Type) -> ValueRef, - G: FnOnce(ValueRef, Type) -> ValueRef + -> &'ll Value + where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value, + G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value { // Shifts may have any size int on the rhs if op.is_shift() { let mut rhs_llty = val_ty(rhs); let mut lhs_llty = val_ty(lhs); - if rhs_llty.kind() == Vector { + if rhs_llty.kind() == TypeKind::Vector { rhs_llty = rhs_llty.element_type() } - if lhs_llty.kind() == Vector { + if lhs_llty.kind() == TypeKind::Vector { lhs_llty = lhs_llty.element_type() } let rhs_sz = rhs_llty.int_width(); @@ -379,12 +382,12 @@ pub fn wants_msvc_seh(sess: &Session) -> bool { sess.target.target.options.is_like_msvc } -pub fn call_assume<'a, 'tcx>(bx: &Builder<'a, 'tcx>, val: ValueRef) { +pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) { let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume"); bx.call(assume_intrinsic, &[val], None); } -pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef { +pub fn from_immediate(bx: &Builder<'_, 'll, '_>, val: &'ll Value) -> &'ll Value { if val_ty(val) == Type::i1(bx.cx) { bx.zext(val, Type::i8(bx.cx)) } else { @@ -392,26 +395,36 @@ pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef { } } -pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef { +pub fn to_immediate( + bx: &Builder<'_, 'll, '_>, + val: &'ll Value, + layout: layout::TyLayout, +) -> &'ll Value { if let layout::Abi::Scalar(ref scalar) = layout.abi { return to_immediate_scalar(bx, val, scalar); } val } -pub fn to_immediate_scalar(bx: &Builder, val: ValueRef, scalar: &layout::Scalar) -> ValueRef { +pub fn to_immediate_scalar( + bx: &Builder<'_, 'll, '_>, + val: &'ll Value, + scalar: &layout::Scalar, +) -> &'ll Value { if scalar.is_bool() { return bx.trunc(val, Type::i1(bx.cx)); } val } -pub fn call_memcpy(bx: &Builder, - dst: ValueRef, - src: ValueRef, - n_bytes: ValueRef, - align: Align, - flags: MemFlags) { +pub fn call_memcpy( + bx: &Builder<'_, 'll, '_>, + dst: &'ll Value, + src: &'ll Value, + n_bytes: &'ll Value, + align: Align, + flags: MemFlags, +) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. let val = bx.load(src, align); @@ -431,10 +444,10 @@ pub fn call_memcpy(bx: &Builder, bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None); } -pub fn memcpy_ty<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - dst: ValueRef, - src: ValueRef, +pub fn memcpy_ty( + bx: &Builder<'_, 'll, 'tcx>, + dst: &'ll Value, + src: &'ll Value, layout: TyLayout<'tcx>, align: Align, flags: MemFlags, @@ -447,12 +460,14 @@ pub fn memcpy_ty<'a, 'tcx>( call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags); } -pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - ptr: ValueRef, - fill_byte: ValueRef, - size: ValueRef, - align: ValueRef, - volatile: bool) -> ValueRef { +pub fn call_memset( + bx: &Builder<'_, 'll, '_>, + ptr: &'ll Value, + fill_byte: &'ll Value, + size: &'ll Value, + align: &'ll Value, + volatile: bool, +) -> &'ll Value { let ptr_width = &bx.cx.sess().target.target.target_pointer_width; let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width); let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key); @@ -486,38 +501,17 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<' cx.stats.borrow_mut().n_closures += 1; - // The `uwtable` attribute according to LLVM is: - // - // This attribute indicates that the ABI being targeted requires that an - // unwind table entry be produced for this function even if we can show - // that no exceptions passes by it. This is normally the case for the - // ELF x86-64 abi, but it can be disabled for some compilation units. - // - // Typically when we're compiling with `-C panic=abort` (which implies this - // `no_landing_pads` check) we don't need `uwtable` because we can't - // generate any exceptions! On Windows, however, exceptions include other - // events such as illegal instructions, segfaults, etc. This means that on - // Windows we end up still needing the `uwtable` attribute even if the `-C - // panic=abort` flag is passed. - // - // You can also find more info on why Windows is whitelisted here in: - // https://bugzilla.mozilla.org/show_bug.cgi?id=1302078 - if !cx.sess().no_landing_pads() || - cx.sess().target.target.options.requires_uwtable { - attributes::emit_uwtable(lldecl, true); - } - let mir = cx.tcx.instance_mir(instance.def); mir::codegen_mir(cx, lldecl, &mir, instance, sig); } -pub fn set_link_section(llval: ValueRef, attrs: &CodegenFnAttrs) { +pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { let sect = match attrs.link_section { Some(name) => name, None => return, }; unsafe { - let buf = CString::new(sect.as_str().as_bytes()).unwrap(); + let buf = SmallCStr::new(§.as_str()); llvm::LLVMSetSection(llval, buf.as_ptr()); } } @@ -544,17 +538,19 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { let et = cx.sess().entry_fn.get().map(|e| e.2); match et { - Some(config::EntryMain) => create_entry_fn(cx, span, main_llfn, main_def_id, true), - Some(config::EntryStart) => create_entry_fn(cx, span, main_llfn, main_def_id, false), + Some(EntryFnType::Main) => create_entry_fn(cx, span, main_llfn, main_def_id, true), + Some(EntryFnType::Start) => create_entry_fn(cx, span, main_llfn, main_def_id, false), None => {} // Do nothing. } - fn create_entry_fn<'cx>(cx: &'cx CodegenCx, - sp: Span, - rust_main: ValueRef, - rust_main_def_id: DefId, - use_start_lang_item: bool) { - let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], &Type::c_int(cx)); + fn create_entry_fn( + cx: &CodegenCx<'ll, '_>, + sp: Span, + rust_main: &'ll Value, + rust_main_def_id: DefId, + use_start_lang_item: bool, + ) { + let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx)); let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output(); // Given that `main()` has no arguments, @@ -578,6 +574,7 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { // `main` should respect same config for frame pointer elimination as rest of code attributes::set_frame_pointer_elimination(cx, llfn); + attributes::apply_target_cpu_attr(cx, llfn); let bx = Builder::new_block(cx, llfn, "top"); @@ -609,16 +606,13 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { } fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, - llmod_id: &str, - link_meta: &LinkMeta) - -> (ContextRef, ModuleRef, EncodedMetadata) { + llvm_module: &ModuleLlvm) + -> EncodedMetadata { use std::io::Write; use flate2::Compression; use flate2::write::DeflateEncoder; - let (metadata_llcx, metadata_llmod) = unsafe { - context::create_context_and_module(tcx.sess, llmod_id) - }; + let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); #[derive(PartialEq, Eq, PartialOrd, Ord)] enum MetadataKind { @@ -629,26 +623,24 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, let kind = tcx.sess.crate_types.borrow().iter().map(|ty| { match *ty { - config::CrateTypeExecutable | - config::CrateTypeStaticlib | - config::CrateTypeCdylib => MetadataKind::None, + config::CrateType::Executable | + config::CrateType::Staticlib | + config::CrateType::Cdylib => MetadataKind::None, - config::CrateTypeRlib => MetadataKind::Uncompressed, + config::CrateType::Rlib => MetadataKind::Uncompressed, - config::CrateTypeDylib | - config::CrateTypeProcMacro => MetadataKind::Compressed, + config::CrateType::Dylib | + config::CrateType::ProcMacro => MetadataKind::Compressed, } }).max().unwrap_or(MetadataKind::None); if kind == MetadataKind::None { - return (metadata_llcx, - metadata_llmod, - EncodedMetadata::new()); + return EncodedMetadata::new(); } - let metadata = tcx.encode_metadata(link_meta); + let metadata = tcx.encode_metadata(); if kind == MetadataKind::Uncompressed { - return (metadata_llcx, metadata_llmod, metadata); + return metadata; } assert!(kind == MetadataKind::Compressed); @@ -661,12 +653,12 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, let name = exported_symbols::metadata_symbol_name(tcx); let buf = CString::new(name).unwrap(); let llglobal = unsafe { - llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr()) + llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr()) }; unsafe { llvm::LLVMSetInitializer(llglobal, llconst); let section_name = metadata::metadata_section_name(&tcx.sess.target.target); - let name = CString::new(section_name).unwrap(); + let name = SmallCStr::new(section_name); llvm::LLVMSetSection(llglobal, name.as_ptr()); // Also generate a .section directive to force no @@ -676,29 +668,27 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, let directive = CString::new(directive).unwrap(); llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr()) } - return (metadata_llcx, metadata_llmod, metadata); + return metadata; } -pub struct ValueIter { - cur: ValueRef, - step: unsafe extern "C" fn(ValueRef) -> ValueRef, +pub struct ValueIter<'ll> { + cur: Option<&'ll Value>, + step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>, } -impl Iterator for ValueIter { - type Item = ValueRef; +impl Iterator for ValueIter<'ll> { + type Item = &'ll Value; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option<&'ll Value> { let old = self.cur; - if !old.is_null() { + if let Some(old) = old { self.cur = unsafe { (self.step)(old) }; - Some(old) - } else { - None } + old } } -pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter { +pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), @@ -707,6 +697,50 @@ pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter { } } +#[derive(Debug)] +enum CguReUsable { + PreLto, + PostLto, + No +} + +fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + cgu: &CodegenUnit<'tcx>) + -> CguReUsable { + if !tcx.dep_graph.is_fully_enabled() { + return CguReUsable::No + } + + let work_product_id = &cgu.work_product_id(); + if tcx.dep_graph.previous_work_product(work_product_id).is_none() { + // We don't have anything cached for this CGU. This can happen + // if the CGU did not exist in the previous session. + return CguReUsable::No + } + + // Try to mark the CGU as green. If it we can do so, it means that nothing + // affecting the LLVM module has changed and we can re-use a cached version. + // If we compile with any kind of LTO, this means we can re-use the bitcode + // of the Pre-LTO stage (possibly also the Post-LTO version but we'll only + // know that later). If we are not doing LTO, there is only one optimized + // version of each module, so we re-use that. + let dep_node = cgu.codegen_dep_node(tcx); + assert!(!tcx.dep_graph.dep_node_exists(&dep_node), + "CompileCodegenUnit dep-node for CGU `{}` already exists before marking.", + cgu.name()); + + if tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() { + // We can re-use either the pre- or the post-thinlto state + if tcx.sess.lto() != Lto::No { + CguReUsable::PreLto + } else { + CguReUsable::PostLto + } + } else { + CguReUsable::No + } +} + pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, rx: mpsc::Receiver>) -> OngoingCodegen { @@ -726,24 +760,24 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.sess.fatal("this compiler's LLVM does not support PGO"); } - let crate_hash = tcx.crate_hash(LOCAL_CRATE); - let link_meta = link::build_link_meta(crate_hash); + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); // Codegen the metadata. - let llmod_id = "metadata"; - let (metadata_llcx, metadata_llmod, metadata) = - time(tcx.sess, "write metadata", || { - write_metadata(tcx, llmod_id, &link_meta) - }); + tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen)); + + let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, + &["crate"], + Some("metadata")).as_str() + .to_string(); + let metadata_llvm_module = ModuleLlvm::new(tcx.sess, &metadata_cgu_name); + let metadata = time(tcx.sess, "write metadata", || { + write_metadata(tcx, &metadata_llvm_module) + }); + tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen)); let metadata_module = ModuleCodegen { - name: link::METADATA_MODULE_NAME.to_string(), - llmod_id: llmod_id.to_string(), - source: ModuleSource::Codegened(ModuleLlvm { - llcx: metadata_llcx, - llmod: metadata_llmod, - tm: create_target_machine(tcx.sess, false), - }), + name: metadata_cgu_name, + module_llvm: metadata_llvm_module, kind: ModuleKind::Metadata, }; @@ -759,7 +793,6 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ongoing_codegen = write::start_async_codegen( tcx, time_graph.clone(), - link_meta, metadata, rx, 1); @@ -794,33 +827,48 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ongoing_codegen = write::start_async_codegen( tcx, time_graph.clone(), - link_meta, metadata, rx, codegen_units.len()); - // Codegen an allocator shim, if any - let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() { - unsafe { - let llmod_id = "allocator"; - let (llcx, llmod) = - context::create_context_and_module(tcx.sess, llmod_id); - let modules = ModuleLlvm { - llmod, - llcx, - tm: create_target_machine(tcx.sess, false), - }; - time(tcx.sess, "write allocator module", || { + // Codegen an allocator shim, if necessary. + // + // If the crate doesn't have an `allocator_kind` set then there's definitely + // no shim to generate. Otherwise we also check our dependency graph for all + // our output crate types. If anything there looks like its a `Dynamic` + // linkage, then it's already got an allocator shim and we'll be using that + // one instead. If nothing exists then it's our job to generate the + // allocator! + let any_dynamic_crate = tcx.sess.dependency_formats.borrow() + .iter() + .any(|(_, list)| { + use rustc::middle::dependency_format::Linkage; + list.iter().any(|linkage| { + match linkage { + Linkage::Dynamic => true, + _ => false, + } + }) + }); + let allocator_module = if any_dynamic_crate { + None + } else if let Some(kind) = *tcx.sess.allocator_kind.get() { + let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, + &["crate"], + Some("allocator")).as_str() + .to_string(); + let modules = ModuleLlvm::new(tcx.sess, &llmod_id); + time(tcx.sess, "write allocator module", || { + unsafe { allocator::codegen(tcx, &modules, kind) - }); + } + }); - Some(ModuleCodegen { - name: link::ALLOCATOR_MODULE_NAME.to_string(), - llmod_id: llmod_id.to_string(), - source: ModuleSource::Codegened(modules), - kind: ModuleKind::Allocator, - }) - } + Some(ModuleCodegen { + name: llmod_id, + module_llvm: modules, + kind: ModuleKind::Allocator, + }) } else { None }; @@ -846,59 +894,40 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ongoing_codegen.wait_for_signal_to_codegen_item(); ongoing_codegen.check_for_errors(tcx.sess); - // First, if incremental compilation is enabled, we try to re-use the - // codegen unit from the cache. - if tcx.dep_graph.is_fully_enabled() { - let cgu_id = cgu.work_product_id(); - - // Check whether there is a previous work-product we can - // re-use. Not only must the file exist, and the inputs not - // be dirty, but the hash of the symbols we will generate must - // be the same. - if let Some(buf) = tcx.dep_graph.previous_work_product(&cgu_id) { - let dep_node = &DepNode::new(tcx, - DepConstructor::CompileCodegenUnit(cgu.name().clone())); - - // We try to mark the DepNode::CompileCodegenUnit green. If we - // succeed it means that none of the dependencies has changed - // and we can safely re-use. - if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, dep_node) { - // Append ".rs" to LLVM module identifier. - // - // LLVM code generator emits a ".file filename" directive - // for ELF backends. Value of the "filename" is set as the - // LLVM module identifier. Due to a LLVM MC bug[1], LLVM - // crashes if the module identifier is same as other symbols - // such as a function name in the module. - // 1. http://llvm.org/bugs/show_bug.cgi?id=11479 - let llmod_id = format!("{}.rs", cgu.name()); - - let module = ModuleCodegen { - name: cgu.name().to_string(), - source: ModuleSource::Preexisting(buf), - kind: ModuleKind::Regular, - llmod_id, - }; - tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true); - write::submit_codegened_module_to_llvm(tcx, module, 0); - // Continue to next cgu, this one is done. - continue - } - } else { - // This can happen if files were deleted from the cache - // directory for some reason. We just re-compile then. + let loaded_from_cache = match determine_cgu_reuse(tcx, &cgu) { + CguReUsable::No => { + let _timing_guard = time_graph.as_ref().map(|time_graph| { + time_graph.start(write::CODEGEN_WORKER_TIMELINE, + write::CODEGEN_WORK_PACKAGE_KIND, + &format!("codegen {}", cgu.name())) + }); + let start_time = Instant::now(); + let stats = compile_codegen_unit(tcx, *cgu.name()); + all_stats.extend(stats); + total_codegen_time += start_time.elapsed(); + false } - } + CguReUsable::PreLto => { + write::submit_pre_lto_module_to_llvm(tcx, CachedModuleCodegen { + name: cgu.name().to_string(), + source: cgu.work_product(tcx), + }); + true + } + CguReUsable::PostLto => { + write::submit_post_lto_module_to_llvm(tcx, CachedModuleCodegen { + name: cgu.name().to_string(), + source: cgu.work_product(tcx), + }); + true + } + }; - let _timing_guard = time_graph.as_ref().map(|time_graph| { - time_graph.start(write::CODEGEN_WORKER_TIMELINE, - write::CODEGEN_WORK_PACKAGE_KIND, - &format!("codegen {}", cgu.name())) - }); - let start_time = Instant::now(); - all_stats.extend(tcx.compile_codegen_unit(*cgu.name())); - total_codegen_time += start_time.elapsed(); - ongoing_codegen.check_for_errors(tcx.sess); + if tcx.dep_graph.is_fully_enabled() { + let dep_node = cgu.codegen_dep_node(tcx); + let dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node); + tcx.dep_graph.mark_loaded_from_cache(dep_node_index, loaded_from_cache); + } } ongoing_codegen.codegen_finished(tcx); @@ -1020,12 +1049,12 @@ fn collect_and_partition_mono_items<'a, 'tcx>( }).collect(); if tcx.sess.opts.debugging_opts.print_mono_items.is_some() { - let mut item_to_cgus = FxHashMap(); + let mut item_to_cgus: FxHashMap<_, Vec<_>> = FxHashMap(); for cgu in &codegen_units { for (&mono_item, &linkage) in cgu.items() { item_to_cgus.entry(mono_item) - .or_insert(Vec::new()) + .or_default() .push((cgu.name().clone(), linkage)); } } @@ -1098,7 +1127,7 @@ impl CrateInfo { let load_wasm_items = tcx.sess.crate_types.borrow() .iter() - .any(|c| *c != config::CrateTypeRlib) && + .any(|c| *c != config::CrateType::Rlib) && tcx.sess.opts.target_triple.triple() == "wasm32-unknown-unknown"; if load_wasm_items { @@ -1162,11 +1191,15 @@ fn is_codegened_item(tcx: TyCtxt, id: DefId) -> bool { } fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - cgu: InternedString) -> Stats { - let cgu = tcx.codegen_unit(cgu); - + cgu_name: InternedString) + -> Stats { let start_time = Instant::now(); - let (stats, module) = module_codegen(tcx, cgu); + + let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); + let ((stats, module), _) = tcx.dep_graph.with_task(dep_node, + tcx, + cgu_name, + module_codegen); let time_to_codegen = start_time.elapsed(); // We assume that the cost to run LLVM on a CGU is proportional to @@ -1175,35 +1208,23 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time_to_codegen.subsec_nanos() as u64; write::submit_codegened_module_to_llvm(tcx, - module, - cost); + module, + cost); return stats; fn module_codegen<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - cgu: Arc>) + cgu_name: InternedString) -> (Stats, ModuleCodegen) { - let cgu_name = cgu.name().to_string(); - - // Append ".rs" to LLVM module identifier. - // - // LLVM code generator emits a ".file filename" directive - // for ELF backends. Value of the "filename" is set as the - // LLVM module identifier. Due to a LLVM MC bug[1], LLVM - // crashes if the module identifier is same as other symbols - // such as a function name in the module. - // 1. http://llvm.org/bugs/show_bug.cgi?id=11479 - let llmod_id = format!("{}-{}.rs", - cgu.name(), - tcx.crate_disambiguator(LOCAL_CRATE) - .to_fingerprint().to_hex()); + let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let cx = CodegenCx::new(tcx, cgu, &llmod_id); - let module = { + let llvm_module = ModuleLlvm::new(tcx.sess, &cgu_name.as_str()); + let stats = { + let cx = CodegenCx::new(tcx, cgu, &llvm_module); let mono_items = cx.codegen_unit - .items_in_deterministic_order(cx.tcx); + .items_in_deterministic_order(cx.tcx); for &(mono_item, (linkage, visibility)) in &mono_items { mono_item.predefine(&cx, linkage, visibility); } @@ -1220,7 +1241,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Run replace-all-uses-with for statics that need it for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() { unsafe { - let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g)); + let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g)); llvm::LLVMReplaceAllUsesWith(old_g, bitcast); llvm::LLVMDeleteGlobal(old_g); } @@ -1229,13 +1250,13 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Create the llvm.used variable // This variable has type [N x i8*] and is stored in the llvm.metadata section if !cx.used_statics.borrow().is_empty() { - let name = CString::new("llvm.used").unwrap(); - let section = CString::new("llvm.metadata").unwrap(); + let name = const_cstr!("llvm.used"); + let section = const_cstr!("llvm.metadata"); let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow()); unsafe { let g = llvm::LLVMAddGlobal(cx.llmod, - val_ty(array).to_ref(), + val_ty(array), name.as_ptr()); llvm::LLVMSetInitializer(g, array); llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage); @@ -1244,25 +1265,18 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // Finalize debuginfo - if cx.sess().opts.debuginfo != NoDebugInfo { + if cx.sess().opts.debuginfo != DebugInfo::None { debuginfo::finalize(&cx); } - let llvm_module = ModuleLlvm { - llcx: cx.llcx, - llmod: cx.llmod, - tm: create_target_machine(cx.sess(), false), - }; - - ModuleCodegen { - name: cgu_name, - source: ModuleSource::Codegened(llvm_module), - kind: ModuleKind::Regular, - llmod_id, - } + cx.stats.into_inner() }; - (cx.into_stats(), module) + (stats, ModuleCodegen { + name: cgu_name.to_string(), + module_llvm: llvm_module, + kind: ModuleKind::Regular, + }) } } @@ -1279,7 +1293,6 @@ pub fn provide(providers: &mut Providers) { .cloned() .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name)) }; - providers.compile_codegen_unit = compile_codegen_unit; provide_extern(providers); } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index b34d0f1cd9..e3526a5a2e 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -8,12 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] // FFI wrappers - -use llvm; use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect}; -use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef}; -use llvm::{ValueRef, BasicBlockRef, BuilderRef}; +use llvm::{IntPredicate, RealPredicate, False, OperandBundleDef}; +use llvm::{self, BasicBlock}; use common::*; use type_::Type; use value::Value; @@ -21,24 +18,23 @@ use libc::{c_uint, c_char}; use rustc::ty::TyCtxt; use rustc::ty::layout::{Align, Size}; use rustc::session::{config, Session}; +use rustc_data_structures::small_c_str::SmallCStr; use std::borrow::Cow; -use std::ffi::CString; use std::ops::Range; use std::ptr; -use syntax_pos::Span; // All Builders must have an llfn associated with them #[must_use] -pub struct Builder<'a, 'tcx: 'a> { - pub llbuilder: BuilderRef, - pub cx: &'a CodegenCx<'a, 'tcx>, +pub struct Builder<'a, 'll: 'a, 'tcx: 'll> { + pub llbuilder: &'ll mut llvm::Builder<'ll>, + pub cx: &'a CodegenCx<'ll, 'tcx>, } -impl<'a, 'tcx> Drop for Builder<'a, 'tcx> { +impl Drop for Builder<'a, 'll, 'tcx> { fn drop(&mut self) { unsafe { - llvm::LLVMDisposeBuilder(self.llbuilder); + llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _)); } } } @@ -58,11 +54,11 @@ bitflags! { } } -impl<'a, 'tcx> Builder<'a, 'tcx> { - pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self { +impl Builder<'a, 'll, 'tcx> { + pub fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self { let bx = Builder::with_cx(cx); let llbb = unsafe { - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(name); llvm::LLVMAppendBasicBlockInContext( cx.llcx, llfn, @@ -73,7 +69,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bx } - pub fn with_cx(cx: &'a CodegenCx<'a, 'tcx>) -> Self { + pub fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { // Create a fresh builder from the crate context. let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) @@ -84,7 +80,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'tcx> { + pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'll, 'tcx> { Builder::new_block(self.cx, self.llfn(), name) } @@ -96,13 +92,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cx.tcx } - pub fn llfn(&self) -> ValueRef { + pub fn llfn(&self) -> &'ll Value { unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) } } - pub fn llbb(&self) -> BasicBlockRef { + pub fn llbb(&self) -> &'ll BasicBlock { unsafe { llvm::LLVMGetInsertBlock(self.llbuilder) } @@ -121,26 +117,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn set_value_name(&self, value: ValueRef, name: &str) { - let cname = CString::new(name.as_bytes()).unwrap(); + pub fn set_value_name(&self, value: &'ll Value, name: &str) { + let cname = SmallCStr::new(name); unsafe { llvm::LLVMSetValueName(value, cname.as_ptr()); } } - pub fn position_before(&self, insn: ValueRef) { - unsafe { - llvm::LLVMPositionBuilderBefore(self.llbuilder, insn); - } - } - - pub fn position_at_end(&self, llbb: BasicBlockRef) { + pub fn position_at_end(&self, llbb: &'ll BasicBlock) { unsafe { llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb); } } - pub fn position_at_start(&self, llbb: BasicBlockRef) { + pub fn position_at_start(&self, llbb: &'ll BasicBlock) { unsafe { llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb); } @@ -153,65 +143,57 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn ret(&self, v: ValueRef) { + pub fn ret(&self, v: &'ll Value) { self.count_insn("ret"); unsafe { llvm::LLVMBuildRet(self.llbuilder, v); } } - pub fn aggregate_ret(&self, ret_vals: &[ValueRef]) { - unsafe { - llvm::LLVMBuildAggregateRet(self.llbuilder, - ret_vals.as_ptr(), - ret_vals.len() as c_uint); - } - } - - pub fn br(&self, dest: BasicBlockRef) { + pub fn br(&self, dest: &'ll BasicBlock) { self.count_insn("br"); unsafe { llvm::LLVMBuildBr(self.llbuilder, dest); } } - pub fn cond_br(&self, cond: ValueRef, then_llbb: BasicBlockRef, else_llbb: BasicBlockRef) { + pub fn cond_br( + &self, + cond: &'ll Value, + then_llbb: &'ll BasicBlock, + else_llbb: &'ll BasicBlock, + ) { self.count_insn("condbr"); unsafe { llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb); } } - pub fn switch(&self, v: ValueRef, else_llbb: BasicBlockRef, num_cases: usize) -> ValueRef { + pub fn switch( + &self, + v: &'ll Value, + else_llbb: &'ll BasicBlock, + num_cases: usize, + ) -> &'ll Value { unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint) } } - pub fn indirect_br(&self, addr: ValueRef, num_dests: usize) { - self.count_insn("indirectbr"); - unsafe { - llvm::LLVMBuildIndirectBr(self.llbuilder, addr, num_dests as c_uint); - } - } - pub fn invoke(&self, - llfn: ValueRef, - args: &[ValueRef], - then: BasicBlockRef, - catch: BasicBlockRef, - bundle: Option<&OperandBundleDef>) -> ValueRef { + llfn: &'ll Value, + args: &[&'ll Value], + then: &'ll BasicBlock, + catch: &'ll BasicBlock, + bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value { self.count_insn("invoke"); - debug!("Invoke {:?} with args ({})", - Value(llfn), - args.iter() - .map(|&v| format!("{:?}", Value(v))) - .collect::>() - .join(", ")); + debug!("Invoke {:?} with args ({:?})", + llfn, + args); let args = self.check_call("invoke", llfn, args); - let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut()); + let bundle = bundle.map(|b| &*b.raw); unsafe { llvm::LLVMRustBuildInvoke(self.llbuilder, @@ -233,35 +215,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } /* Arithmetic */ - pub fn add(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn add(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("add"); unsafe { llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname()) } } - pub fn nswadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nswadd"); - unsafe { - llvm::LLVMBuildNSWAdd(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn nuwadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nuwadd"); - unsafe { - llvm::LLVMBuildNUWAdd(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn fadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fadd(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fadd"); unsafe { llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname()) } } - pub fn fadd_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fadd_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fadd"); unsafe { let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname()); @@ -270,35 +238,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn sub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn sub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("sub"); unsafe { llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname()) } } - pub fn nswsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nswsub"); - unsafe { - llvm::LLVMBuildNSWSub(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn nuwsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nuwsub"); - unsafe { - llvm::LLVMBuildNUWSub(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn fsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fsub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fsub"); unsafe { llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()) } } - pub fn fsub_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fsub_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fsub"); unsafe { let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()); @@ -307,35 +261,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn mul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn mul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("mul"); unsafe { llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname()) } } - pub fn nswmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nswmul"); - unsafe { - llvm::LLVMBuildNSWMul(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn nuwmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nuwmul"); - unsafe { - llvm::LLVMBuildNUWMul(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn fmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fmul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fmul"); unsafe { llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname()) } } - pub fn fmul_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fmul_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fmul"); unsafe { let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname()); @@ -345,42 +285,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } - pub fn udiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn udiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("udiv"); unsafe { llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn exactudiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn exactudiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("exactudiv"); unsafe { llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn sdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn sdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("sdiv"); unsafe { llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn exactsdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn exactsdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("exactsdiv"); unsafe { llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn fdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fdiv"); unsafe { llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn fdiv_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fdiv_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fdiv"); unsafe { let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname()); @@ -389,28 +329,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn urem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn urem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("urem"); unsafe { llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname()) } } - pub fn srem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn srem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("srem"); unsafe { llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname()) } } - pub fn frem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn frem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("frem"); unsafe { llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname()) } } - pub fn frem_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn frem_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("frem"); unsafe { let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname()); @@ -419,91 +359,70 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn shl(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn shl(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("shl"); unsafe { llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname()) } } - pub fn lshr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn lshr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("lshr"); unsafe { llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname()) } } - pub fn ashr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn ashr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("ashr"); unsafe { llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname()) } } - pub fn and(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn and(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("and"); unsafe { llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname()) } } - pub fn or(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn or(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("or"); unsafe { llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname()) } } - pub fn xor(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn xor(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("xor"); unsafe { llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname()) } } - pub fn binop(&self, op: Opcode, lhs: ValueRef, rhs: ValueRef) - -> ValueRef { - self.count_insn("binop"); - unsafe { - llvm::LLVMBuildBinOp(self.llbuilder, op, lhs, rhs, noname()) - } - } - - pub fn neg(&self, v: ValueRef) -> ValueRef { + pub fn neg(&self, v: &'ll Value) -> &'ll Value { self.count_insn("neg"); unsafe { llvm::LLVMBuildNeg(self.llbuilder, v, noname()) } } - pub fn nswneg(&self, v: ValueRef) -> ValueRef { - self.count_insn("nswneg"); - unsafe { - llvm::LLVMBuildNSWNeg(self.llbuilder, v, noname()) - } - } - - pub fn nuwneg(&self, v: ValueRef) -> ValueRef { - self.count_insn("nuwneg"); - unsafe { - llvm::LLVMBuildNUWNeg(self.llbuilder, v, noname()) - } - } - pub fn fneg(&self, v: ValueRef) -> ValueRef { + pub fn fneg(&self, v: &'ll Value) -> &'ll Value { self.count_insn("fneg"); unsafe { llvm::LLVMBuildFNeg(self.llbuilder, v, noname()) } } - pub fn not(&self, v: ValueRef) -> ValueRef { + pub fn not(&self, v: &'ll Value) -> &'ll Value { self.count_insn("not"); unsafe { llvm::LLVMBuildNot(self.llbuilder, v, noname()) } } - pub fn alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef { + pub fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { let bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) @@ -511,14 +430,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bx.dynamic_alloca(ty, name, align) } - pub fn dynamic_alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef { + pub fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { - llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname()) + llvm::LLVMBuildAlloca(self.llbuilder, ty, noname()) } else { - let name = CString::new(name).unwrap(); - llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), + let name = SmallCStr::new(name); + llvm::LLVMBuildAlloca(self.llbuilder, ty, name.as_ptr()) }; llvm::LLVMSetAlignment(alloca, align.abi() as c_uint); @@ -526,14 +445,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn free(&self, ptr: ValueRef) { - self.count_insn("free"); + pub fn array_alloca(&self, + ty: &'ll Type, + len: &'ll Value, + name: &str, + align: Align) -> &'ll Value { + self.count_insn("alloca"); unsafe { - llvm::LLVMBuildFree(self.llbuilder, ptr); + let alloca = if name.is_empty() { + llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname()) + } else { + let name = SmallCStr::new(name); + llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, + name.as_ptr()) + }; + llvm::LLVMSetAlignment(alloca, align.abi() as c_uint); + alloca } } - pub fn load(&self, ptr: ValueRef, align: Align) -> ValueRef { + pub fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value { self.count_insn("load"); unsafe { let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); @@ -542,7 +473,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn volatile_load(&self, ptr: ValueRef) -> ValueRef { + pub fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value { self.count_insn("load.volatile"); unsafe { let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); @@ -551,7 +482,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn atomic_load(&self, ptr: ValueRef, order: AtomicOrdering, align: Align) -> ValueRef { + pub fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, align: Align) -> &'ll Value { self.count_insn("load.atomic"); unsafe { let load = llvm::LLVMRustBuildAtomicLoad(self.llbuilder, ptr, noname(), order); @@ -564,7 +495,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } - pub fn range_metadata(&self, load: ValueRef, range: Range) { + pub fn range_metadata(&self, load: &'ll Value, range: Range) { + if self.sess().target.target.arch == "amdgpu" { + // amdgpu/LLVM does something weird and thinks a i64 value is + // split into a v2i32, halving the bitwidth LLVM expects, + // tripping an assertion. So, for now, just disable this + // optimization. + return; + } + unsafe { let llty = val_ty(load); let v = [ @@ -579,26 +518,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn nonnull_metadata(&self, load: ValueRef) { + pub fn nonnull_metadata(&self, load: &'ll Value) { unsafe { llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint, llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0)); } } - pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Align) -> ValueRef { + pub fn store(&self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value { self.store_with_flags(val, ptr, align, MemFlags::empty()) } pub fn store_with_flags( &self, - val: ValueRef, - ptr: ValueRef, + val: &'ll Value, + ptr: &'ll Value, align: Align, flags: MemFlags, - ) -> ValueRef { - debug!("Store {:?} -> {:?} ({:?})", Value(val), Value(ptr), flags); - assert!(!self.llbuilder.is_null()); + ) -> &'ll Value { + debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags); self.count_insn("store"); let ptr = self.check_store(val, ptr); unsafe { @@ -625,9 +563,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, + pub fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value, order: AtomicOrdering, align: Align) { - debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); + debug!("Store {:?} -> {:?}", val, ptr); self.count_insn("store.atomic"); let ptr = self.check_store(val, ptr); unsafe { @@ -638,7 +576,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef { + pub fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { self.count_insn("gep"); unsafe { llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(), @@ -646,7 +584,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn inbounds_gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef { + pub fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { self.count_insn("inboundsgep"); unsafe { llvm::LLVMBuildInBoundsGEP( @@ -654,7 +592,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn struct_gep(&self, ptr: ValueRef, idx: u64) -> ValueRef { + pub fn struct_gep(&self, ptr: &'ll Value, idx: u64) -> &'ll Value { self.count_insn("structgep"); assert_eq!(idx as c_uint as u64, idx); unsafe { @@ -662,164 +600,114 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn global_string(&self, _str: *const c_char) -> ValueRef { - self.count_insn("globalstring"); - unsafe { - llvm::LLVMBuildGlobalString(self.llbuilder, _str, noname()) - } - } - - pub fn global_string_ptr(&self, _str: *const c_char) -> ValueRef { - self.count_insn("globalstringptr"); - unsafe { - llvm::LLVMBuildGlobalStringPtr(self.llbuilder, _str, noname()) - } - } - /* Casts */ - pub fn trunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("trunc"); unsafe { - llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname()) } } - pub fn zext(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("zext"); unsafe { - llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname()) } } - pub fn sext(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("sext"); unsafe { - llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptoui(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptoui"); unsafe { - llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptosi(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptosi"); unsafe { - llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty.to_ref(),noname()) + llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname()) } } - pub fn uitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("uitofp"); unsafe { - llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname()) } } - pub fn sitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("sitofp"); unsafe { - llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptrunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptrunc"); unsafe { - llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname()) } } - pub fn fpext(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fpext"); unsafe { - llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname()) } } - pub fn ptrtoint(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("ptrtoint"); unsafe { - llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname()) } } - pub fn inttoptr(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("inttoptr"); unsafe { - llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname()) } } - pub fn bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("bitcast"); unsafe { - llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname()) } } - pub fn zext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("zextorbitcast"); - unsafe { - llvm::LLVMBuildZExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname()) - } - } - - pub fn sext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("sextorbitcast"); - unsafe { - llvm::LLVMBuildSExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname()) - } - } - - pub fn trunc_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("truncorbitcast"); - unsafe { - llvm::LLVMBuildTruncOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname()) - } - } - - pub fn cast(&self, op: Opcode, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("cast"); - unsafe { - llvm::LLVMBuildCast(self.llbuilder, op, val, dest_ty.to_ref(), noname()) - } - } - - pub fn pointercast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("pointercast"); unsafe { - llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname()) } } - pub fn intcast(&self, val: ValueRef, dest_ty: Type, is_signed: bool) -> ValueRef { + pub fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { self.count_insn("intcast"); unsafe { - llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty.to_ref(), is_signed) - } - } - - pub fn fpcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("fpcast"); - unsafe { - llvm::LLVMBuildFPCast(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) } } - /* Comparisons */ - pub fn icmp(&self, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("icmp"); unsafe { llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname()) } } - pub fn fcmp(&self, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fcmp"); unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname()) @@ -827,14 +715,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } /* Miscellaneous instructions */ - pub fn empty_phi(&self, ty: Type) -> ValueRef { + pub fn empty_phi(&self, ty: &'ll Type) -> &'ll Value { self.count_insn("emptyphi"); unsafe { - llvm::LLVMBuildPhi(self.llbuilder, ty.to_ref(), noname()) + llvm::LLVMBuildPhi(self.llbuilder, ty, noname()) } } - pub fn phi(&self, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef { + pub fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value { assert_eq!(vals.len(), bbs.len()); let phi = self.empty_phi(ty); self.count_insn("addincoming"); @@ -846,36 +734,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn add_span_comment(&self, sp: Span, text: &str) { - if self.cx.sess().asm_comments() { - let s = format!("{} ({})", - text, - self.cx.sess().codemap().span_to_string(sp)); - debug!("{}", s); - self.add_comment(&s); - } - } - - pub fn add_comment(&self, text: &str) { - if self.cx.sess().asm_comments() { - let sanitized = text.replace("$", ""); - let comment_text = format!("{} {}", "#", - sanitized.replace("\n", "\n\t# ")); - self.count_insn("inlineasm"); - let comment_text = CString::new(comment_text).unwrap(); - let asm = unsafe { - llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.cx)).to_ref(), - comment_text.as_ptr(), noname(), False, - False) - }; - self.call(asm, &[], None); - } - } - pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, - inputs: &[ValueRef], output: Type, + inputs: &[&'ll Value], output: &'ll Type, volatile: bool, alignstack: bool, - dia: AsmDialect) -> ValueRef { + dia: AsmDialect) -> &'ll Value { self.count_insn("inlineasm"); let volatile = if volatile { llvm::True } @@ -884,32 +746,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { else { llvm::False }; let argtys = inputs.iter().map(|v| { - debug!("Asm Input Type: {:?}", Value(*v)); + debug!("Asm Input Type: {:?}", *v); val_ty(*v) }).collect::>(); debug!("Asm Output Type: {:?}", output); - let fty = Type::func(&argtys[..], &output); + let fty = Type::func(&argtys[..], output); unsafe { let v = llvm::LLVMRustInlineAsm( - fty.to_ref(), asm, cons, volatile, alignstack, dia); + fty, asm, cons, volatile, alignstack, dia); self.call(v, inputs, None) } } - pub fn call(&self, llfn: ValueRef, args: &[ValueRef], - bundle: Option<&OperandBundleDef>) -> ValueRef { + pub fn call(&self, llfn: &'ll Value, args: &[&'ll Value], + bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value { self.count_insn("call"); - debug!("Call {:?} with args ({})", - Value(llfn), - args.iter() - .map(|&v| format!("{:?}", Value(v))) - .collect::>() - .join(", ")); + debug!("Call {:?} with args ({:?})", + llfn, + args); let args = self.check_call("call", llfn, args); - let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut()); + let bundle = bundle.map(|b| &*b.raw); unsafe { llvm::LLVMRustBuildCall(self.llbuilder, llfn, args.as_ptr(), @@ -917,214 +776,182 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn minnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("minnum"); unsafe { let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs); - if instr.is_null() { - bug!("LLVMRustBuildMinNum is not available in LLVM version < 6.0"); - } - instr + instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0") } } - pub fn maxnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("maxnum"); unsafe { let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs); - if instr.is_null() { - bug!("LLVMRustBuildMaxNum is not available in LLVM version < 6.0"); - } - instr + instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0") } } - pub fn select(&self, cond: ValueRef, then_val: ValueRef, else_val: ValueRef) -> ValueRef { + pub fn select( + &self, cond: &'ll Value, + then_val: &'ll Value, + else_val: &'ll Value, + ) -> &'ll Value { self.count_insn("select"); unsafe { llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname()) } } - pub fn va_arg(&self, list: ValueRef, ty: Type) -> ValueRef { + #[allow(dead_code)] + pub fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { self.count_insn("vaarg"); unsafe { - llvm::LLVMBuildVAArg(self.llbuilder, list, ty.to_ref(), noname()) + llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname()) } } - pub fn extract_element(&self, vec: ValueRef, idx: ValueRef) -> ValueRef { + pub fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value { self.count_insn("extractelement"); unsafe { llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname()) } } - pub fn insert_element(&self, vec: ValueRef, elt: ValueRef, idx: ValueRef) -> ValueRef { + pub fn insert_element( + &self, vec: &'ll Value, + elt: &'ll Value, + idx: &'ll Value, + ) -> &'ll Value { self.count_insn("insertelement"); unsafe { llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname()) } } - pub fn shuffle_vector(&self, v1: ValueRef, v2: ValueRef, mask: ValueRef) -> ValueRef { + pub fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value { self.count_insn("shufflevector"); unsafe { llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname()) } } - pub fn vector_splat(&self, num_elts: usize, elt: ValueRef) -> ValueRef { + pub fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value { unsafe { let elt_ty = val_ty(elt); - let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref()); + let undef = llvm::LLVMGetUndef(Type::vector(elt_ty, num_elts as u64)); let vec = self.insert_element(undef, elt, C_i32(self.cx, 0)); - let vec_i32_ty = Type::vector(&Type::i32(self.cx), num_elts as u64); + let vec_i32_ty = Type::vector(Type::i32(self.cx), num_elts as u64); self.shuffle_vector(vec, undef, C_null(vec_i32_ty)) } } - pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fadd_fast"); unsafe { // FIXME: add a non-fast math version once // https://bugs.llvm.org/show_bug.cgi?id=36732 // is fixed. - let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0"); - } + let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src) + .expect("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0"); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } } - pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmul_fast"); unsafe { // FIXME: add a non-fast math version once // https://bugs.llvm.org/show_bug.cgi?id=36732 // is fixed. - let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0"); - } + let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src) + .expect("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0"); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } } - pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.add"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0") } } - pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.mul"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0") } } - pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.and"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0") } } - pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.or"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0") } } - pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.xor"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0") } } - pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmin"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0") } } - pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmax"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0") } } - pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmin_fast"); unsafe { - let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); - } + let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true) + .expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } } - pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmax_fast"); unsafe { - let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); - } + let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true) + .expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } } - pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef { + pub fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value { self.count_insn("vector.reduce.min"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0") } } - pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef { + pub fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value { self.count_insn("vector.reduce.max"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0") } } - pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef { + pub fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value { self.count_insn("extractvalue"); assert_eq!(idx as c_uint as u64, idx); unsafe { @@ -1132,8 +959,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef, - idx: u64) -> ValueRef { + pub fn insert_value(&self, agg_val: &'ll Value, elt: &'ll Value, + idx: u64) -> &'ll Value { self.count_insn("insertvalue"); assert_eq!(idx as c_uint as u64, idx); unsafe { @@ -1142,50 +969,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn is_null(&self, val: ValueRef) -> ValueRef { - self.count_insn("isnull"); - unsafe { - llvm::LLVMBuildIsNull(self.llbuilder, val, noname()) - } - } - - pub fn is_not_null(&self, val: ValueRef) -> ValueRef { - self.count_insn("isnotnull"); - unsafe { - llvm::LLVMBuildIsNotNull(self.llbuilder, val, noname()) - } - } - - pub fn ptrdiff(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("ptrdiff"); - unsafe { - llvm::LLVMBuildPtrDiff(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef, - num_clauses: usize) -> ValueRef { + pub fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value, + num_clauses: usize) -> &'ll Value { self.count_insn("landingpad"); unsafe { - llvm::LLVMBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn, + llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn, num_clauses as c_uint, noname()) } } - pub fn add_clause(&self, landing_pad: ValueRef, clause: ValueRef) { + pub fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value) { unsafe { llvm::LLVMAddClause(landing_pad, clause); } } - pub fn set_cleanup(&self, landing_pad: ValueRef) { + pub fn set_cleanup(&self, landing_pad: &'ll Value) { self.count_insn("setcleanup"); unsafe { llvm::LLVMSetCleanup(landing_pad, llvm::True); } } - pub fn resume(&self, exn: ValueRef) -> ValueRef { + pub fn resume(&self, exn: &'ll Value) -> &'ll Value { self.count_insn("resume"); unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) @@ -1193,11 +999,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } pub fn cleanup_pad(&self, - parent: Option, - args: &[ValueRef]) -> ValueRef { + parent: Option<&'ll Value>, + args: &[&'ll Value]) -> &'ll Value { self.count_insn("cleanuppad"); - let parent = parent.unwrap_or(ptr::null_mut()); - let name = CString::new("cleanuppad").unwrap(); + let name = const_cstr!("cleanuppad"); let ret = unsafe { llvm::LLVMRustBuildCleanupPad(self.llbuilder, parent, @@ -1205,87 +1010,91 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { args.as_ptr(), name.as_ptr()) }; - assert!(!ret.is_null(), "LLVM does not have support for cleanuppad"); - return ret + ret.expect("LLVM does not have support for cleanuppad") } - pub fn cleanup_ret(&self, cleanup: ValueRef, - unwind: Option) -> ValueRef { + pub fn cleanup_ret( + &self, cleanup: &'ll Value, + unwind: Option<&'ll BasicBlock>, + ) -> &'ll Value { self.count_insn("cleanupret"); - let unwind = unwind.unwrap_or(ptr::null_mut()); let ret = unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind) }; - assert!(!ret.is_null(), "LLVM does not have support for cleanupret"); - return ret + ret.expect("LLVM does not have support for cleanupret") } pub fn catch_pad(&self, - parent: ValueRef, - args: &[ValueRef]) -> ValueRef { + parent: &'ll Value, + args: &[&'ll Value]) -> &'ll Value { self.count_insn("catchpad"); - let name = CString::new("catchpad").unwrap(); + let name = const_cstr!("catchpad"); let ret = unsafe { llvm::LLVMRustBuildCatchPad(self.llbuilder, parent, args.len() as c_uint, args.as_ptr(), name.as_ptr()) }; - assert!(!ret.is_null(), "LLVM does not have support for catchpad"); - return ret + ret.expect("LLVM does not have support for catchpad") } - pub fn catch_ret(&self, pad: ValueRef, unwind: BasicBlockRef) -> ValueRef { + pub fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value { self.count_insn("catchret"); let ret = unsafe { llvm::LLVMRustBuildCatchRet(self.llbuilder, pad, unwind) }; - assert!(!ret.is_null(), "LLVM does not have support for catchret"); - return ret + ret.expect("LLVM does not have support for catchret") } - pub fn catch_switch(&self, - parent: Option, - unwind: Option, - num_handlers: usize) -> ValueRef { + pub fn catch_switch( + &self, + parent: Option<&'ll Value>, + unwind: Option<&'ll BasicBlock>, + num_handlers: usize, + ) -> &'ll Value { self.count_insn("catchswitch"); - let parent = parent.unwrap_or(ptr::null_mut()); - let unwind = unwind.unwrap_or(ptr::null_mut()); - let name = CString::new("catchswitch").unwrap(); + let name = const_cstr!("catchswitch"); let ret = unsafe { llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind, num_handlers as c_uint, name.as_ptr()) }; - assert!(!ret.is_null(), "LLVM does not have support for catchswitch"); - return ret + ret.expect("LLVM does not have support for catchswitch") } - pub fn add_handler(&self, catch_switch: ValueRef, handler: BasicBlockRef) { + pub fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock) { unsafe { llvm::LLVMRustAddHandler(catch_switch, handler); } } - pub fn set_personality_fn(&self, personality: ValueRef) { + pub fn set_personality_fn(&self, personality: &'ll Value) { unsafe { llvm::LLVMSetPersonalityFn(self.llfn(), personality); } } // Atomic Operations - pub fn atomic_cmpxchg(&self, dst: ValueRef, - cmp: ValueRef, src: ValueRef, - order: AtomicOrdering, - failure_order: AtomicOrdering, - weak: llvm::Bool) -> ValueRef { + pub fn atomic_cmpxchg( + &self, + dst: &'ll Value, + cmp: &'ll Value, + src: &'ll Value, + order: AtomicOrdering, + failure_order: AtomicOrdering, + weak: llvm::Bool, + ) -> &'ll Value { unsafe { llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src, order, failure_order, weak) } } - pub fn atomic_rmw(&self, op: AtomicRmwBinOp, - dst: ValueRef, src: ValueRef, - order: AtomicOrdering) -> ValueRef { + pub fn atomic_rmw( + &self, + op: AtomicRmwBinOp, + dst: &'ll Value, + src: &'ll Value, + order: AtomicOrdering, + ) -> &'ll Value { unsafe { llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order, False) } @@ -1297,20 +1106,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn add_case(&self, s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) { + pub fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) { unsafe { llvm::LLVMAddCase(s, on_val, dest) } } - pub fn add_incoming_to_phi(&self, phi: ValueRef, val: ValueRef, bb: BasicBlockRef) { + pub fn add_incoming_to_phi(&self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) { self.count_insn("addincoming"); unsafe { llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint); } } - pub fn set_invariant_load(&self, load: ValueRef) { + pub fn set_invariant_load(&self, load: &'ll Value) { unsafe { llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint, llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0)); @@ -1319,8 +1128,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns the ptr value that should be used for storing `val`. fn check_store<'b>(&self, - val: ValueRef, - ptr: ValueRef) -> ValueRef { + val: &'ll Value, + ptr: &'ll Value) -> &'ll Value { let dest_ptr_ty = val_ty(ptr); let stored_ty = val_ty(val); let stored_ptr_ty = stored_ty.ptr_to(); @@ -1340,8 +1149,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns the args that should be used for a call to `llfn`. fn check_call<'b>(&self, typ: &str, - llfn: ValueRef, - args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> { + llfn: &'ll Value, + args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> { let mut fn_ty = val_ty(llfn); // Strip off pointers while fn_ty.kind() == llvm::TypeKind::Pointer { @@ -1369,8 +1178,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if expected_ty != actual_ty { debug!("Type mismatch in function call of {:?}. \ Expected {:?} for param {}, got {:?}; injecting bitcast", - Value(llfn), - expected_ty, i, actual_ty); + llfn, expected_ty, i, actual_ty); self.bitcast(actual_val, expected_ty) } else { actual_val @@ -1381,11 +1189,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { return Cow::Owned(casted_args); } - pub fn lifetime_start(&self, ptr: ValueRef, size: Size) { + pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) { self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size); } - pub fn lifetime_end(&self, ptr: ValueRef, size: Size) { + pub fn lifetime_end(&self, ptr: &'ll Value, size: Size) { self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size); } @@ -1397,7 +1205,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// /// If LLVM lifetime intrinsic support is disabled (i.e. optimizations /// off) or `ptr` is zero-sized, then no-op (does not call `emit`). - fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: ValueRef, size: Size) { + fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) { if self.cx.sess().opts.optimize == config::OptLevel::No { return; } diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 2c01bd42cc..4b4ccb3b60 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -18,9 +18,10 @@ use attributes; use common::{self, CodegenCx}; use consts; use declare; -use llvm::{self, ValueRef}; +use llvm; use monomorphize::Instance; use type_of::LayoutLlvmExt; +use value::Value; use rustc::hir::def_id::DefId; use rustc::ty::{self, TypeFoldable}; @@ -34,10 +35,10 @@ use rustc::ty::subst::Substs; /// /// - `cx`: the crate context /// - `instance`: the instance to be instantiated -pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - instance: Instance<'tcx>) - -> ValueRef -{ +pub fn get_fn( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, +) -> &'ll Value { let tcx = cx.tcx; debug!("get_fn(instance={:?})", instance); @@ -95,9 +96,9 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, debug!("get_fn: not casting pointer!"); if instance.def.is_inline(tcx) { - attributes::inline(llfn, attributes::InlineAttr::Hint); + attributes::inline(cx, llfn, attributes::InlineAttr::Hint); } - attributes::from_fn_attrs(cx, llfn, instance.def.def_id()); + attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id())); let instance_def_id = instance.def_id(); @@ -132,7 +133,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // This is a monomorphization. Its expected visibility depends // on whether we are in share-generics mode. - if cx.tcx.share_generics() { + if cx.tcx.sess.opts.share_generics() { // We are in share_generics mode. if instance_def_id.is_local() { @@ -204,11 +205,11 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, llfn } -pub fn resolve_and_get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - def_id: DefId, - substs: &'tcx Substs<'tcx>) - -> ValueRef -{ +pub fn resolve_and_get_fn( + cx: &CodegenCx<'ll, 'tcx>, + def_id: DefId, + substs: &'tcx Substs<'tcx>, +) -> &'ll Value { get_fn( cx, ty::Instance::resolve( diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 60bba635a7..53bb02ddd9 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -12,8 +12,7 @@ //! Code that is useful in various codegen modules. -use llvm; -use llvm::{ValueRef, ContextRef, TypeKind}; +use llvm::{self, TypeKind}; use llvm::{True, False, Bool, OperandBundleDef}; use rustc::hir::def_id::DefId; use rustc::middle::lang_items::LangItem; @@ -25,6 +24,7 @@ use declare; use type_::Type; use type_of::LayoutLlvmExt; use value::Value; + use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::hir; @@ -90,83 +90,83 @@ pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bo /// When inside of a landing pad, each function call in LLVM IR needs to be /// annotated with which landing pad it's a part of. This is accomplished via /// the `OperandBundleDef` value created for MSVC landing pads. -pub struct Funclet { - cleanuppad: ValueRef, - operand: OperandBundleDef, +pub struct Funclet<'ll> { + cleanuppad: &'ll Value, + operand: OperandBundleDef<'ll>, } -impl Funclet { - pub fn new(cleanuppad: ValueRef) -> Funclet { +impl Funclet<'ll> { + pub fn new(cleanuppad: &'ll Value) -> Self { Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]), } } - pub fn cleanuppad(&self) -> ValueRef { + pub fn cleanuppad(&self) -> &'ll Value { self.cleanuppad } - pub fn bundle(&self) -> &OperandBundleDef { + pub fn bundle(&self) -> &OperandBundleDef<'ll> { &self.operand } } -pub fn val_ty(v: ValueRef) -> Type { +pub fn val_ty(v: &'ll Value) -> &'ll Type { unsafe { - Type::from_ref(llvm::LLVMTypeOf(v)) + llvm::LLVMTypeOf(v) } } // LLVM constant constructors. -pub fn C_null(t: Type) -> ValueRef { +pub fn C_null(t: &'ll Type) -> &'ll Value { unsafe { - llvm::LLVMConstNull(t.to_ref()) + llvm::LLVMConstNull(t) } } -pub fn C_undef(t: Type) -> ValueRef { +pub fn C_undef(t: &'ll Type) -> &'ll Value { unsafe { - llvm::LLVMGetUndef(t.to_ref()) + llvm::LLVMGetUndef(t) } } -pub fn C_int(t: Type, i: i64) -> ValueRef { +pub fn C_int(t: &'ll Type, i: i64) -> &'ll Value { unsafe { - llvm::LLVMConstInt(t.to_ref(), i as u64, True) + llvm::LLVMConstInt(t, i as u64, True) } } -pub fn C_uint(t: Type, i: u64) -> ValueRef { +pub fn C_uint(t: &'ll Type, i: u64) -> &'ll Value { unsafe { - llvm::LLVMConstInt(t.to_ref(), i, False) + llvm::LLVMConstInt(t, i, False) } } -pub fn C_uint_big(t: Type, u: u128) -> ValueRef { +pub fn C_uint_big(t: &'ll Type, u: u128) -> &'ll Value { unsafe { let words = [u as u64, (u >> 64) as u64]; - llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, words.as_ptr()) + llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr()) } } -pub fn C_bool(cx: &CodegenCx, val: bool) -> ValueRef { +pub fn C_bool(cx: &CodegenCx<'ll, '_>, val: bool) -> &'ll Value { C_uint(Type::i1(cx), val as u64) } -pub fn C_i32(cx: &CodegenCx, i: i32) -> ValueRef { +pub fn C_i32(cx: &CodegenCx<'ll, '_>, i: i32) -> &'ll Value { C_int(Type::i32(cx), i as i64) } -pub fn C_u32(cx: &CodegenCx, i: u32) -> ValueRef { +pub fn C_u32(cx: &CodegenCx<'ll, '_>, i: u32) -> &'ll Value { C_uint(Type::i32(cx), i as u64) } -pub fn C_u64(cx: &CodegenCx, i: u64) -> ValueRef { +pub fn C_u64(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value { C_uint(Type::i64(cx), i) } -pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef { +pub fn C_usize(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value { let bit_size = cx.data_layout().pointer_size.bits(); if bit_size < 64 { // make sure it doesn't overflow @@ -176,14 +176,18 @@ pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef { C_uint(cx.isize_ty, i) } -pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef { +pub fn C_u8(cx: &CodegenCx<'ll, '_>, i: u8) -> &'ll Value { C_uint(Type::i8(cx), i as u64) } // This is a 'c-like' raw string, which differs from // our boxed-and-length-annotated strings. -pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> ValueRef { +pub fn C_cstr( + cx: &CodegenCx<'ll, '_>, + s: LocalInternedString, + null_terminated: bool, +) -> &'ll Value { unsafe { if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) { return llval; @@ -208,24 +212,28 @@ pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> // NB: Do not use `do_spill_noroot` to make this into a constant string, or // you will be kicked off fast isel. See issue #4352 for an example of this. -pub fn C_str_slice(cx: &CodegenCx, s: LocalInternedString) -> ValueRef { +pub fn C_str_slice(cx: &CodegenCx<'ll, '_>, s: LocalInternedString) -> &'ll Value { let len = s.len(); let cs = consts::ptrcast(C_cstr(cx, s, false), cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to()); C_fat_ptr(cx, cs, C_usize(cx, len as u64)) } -pub fn C_fat_ptr(cx: &CodegenCx, ptr: ValueRef, meta: ValueRef) -> ValueRef { +pub fn C_fat_ptr(cx: &CodegenCx<'ll, '_>, ptr: &'ll Value, meta: &'ll Value) -> &'ll Value { assert_eq!(abi::FAT_PTR_ADDR, 0); assert_eq!(abi::FAT_PTR_EXTRA, 1); C_struct(cx, &[ptr, meta], false) } -pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef { +pub fn C_struct(cx: &CodegenCx<'ll, '_>, elts: &[&'ll Value], packed: bool) -> &'ll Value { C_struct_in_context(cx.llcx, elts, packed) } -pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef { +pub fn C_struct_in_context( + llcx: &'ll llvm::Context, + elts: &[&'ll Value], + packed: bool, +) -> &'ll Value { unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), elts.len() as c_uint, @@ -233,47 +241,47 @@ pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> } } -pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef { +pub fn C_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { unsafe { - return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint); + return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint); } } -pub fn C_vector(elts: &[ValueRef]) -> ValueRef { +pub fn C_vector(elts: &[&'ll Value]) -> &'ll Value { unsafe { return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint); } } -pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef { +pub fn C_bytes(cx: &CodegenCx<'ll, '_>, bytes: &[u8]) -> &'ll Value { C_bytes_in_context(cx.llcx, bytes) } -pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef { +pub fn C_bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True); } } -pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef { +pub fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value { unsafe { assert_eq!(idx as c_uint as u64, idx); let us = &[idx as c_uint]; let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint); debug!("const_get_elt(v={:?}, idx={}, r={:?})", - Value(v), idx, Value(r)); + v, idx, r); r } } -pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> { +pub fn const_get_real(v: &'ll Value) -> Option<(f64, bool)> { unsafe { if is_const_real(v) { let mut loses_info: llvm::Bool = ::std::mem::uninitialized(); - let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool); + let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info); let loses_info = if loses_info == 1 { true } else { false }; Some((r, loses_info)) } else { @@ -282,21 +290,21 @@ pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> { } } -pub fn const_to_uint(v: ValueRef) -> u64 { +pub fn const_to_uint(v: &'ll Value) -> u64 { unsafe { llvm::LLVMConstIntGetZExtValue(v) } } -pub fn is_const_integral(v: ValueRef) -> bool { +pub fn is_const_integral(v: &'ll Value) -> bool { unsafe { - !llvm::LLVMIsAConstantInt(v).is_null() + llvm::LLVMIsAConstantInt(v).is_some() } } -pub fn is_const_real(v: ValueRef) -> bool { +pub fn is_const_real(v: &'ll Value) -> bool { unsafe { - !llvm::LLVMIsAConstantFP(v).is_null() + llvm::LLVMIsAConstantFP(v).is_some() } } @@ -306,12 +314,12 @@ fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) } -pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option { +pub fn const_to_opt_u128(v: &'ll Value, sign_ext: bool) -> Option { unsafe { if is_const_integral(v) { let (mut lo, mut hi) = (0u64, 0u64); let success = llvm::LLVMRustConstInt128Get(v, sign_ext, - &mut hi as *mut u64, &mut lo as *mut u64); + &mut hi, &mut lo); if success { Some(hi_lo_to_u128(lo, hi)) } else { @@ -345,20 +353,20 @@ pub fn langcall(tcx: TyCtxt, // all shifts). For 32- and 64-bit types, this matches the semantics // of Java. (See related discussion on #1877 and #10183.) -pub fn build_unchecked_lshift<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - lhs: ValueRef, - rhs: ValueRef -) -> ValueRef { +pub fn build_unchecked_lshift( + bx: &Builder<'a, 'll, 'tcx>, + lhs: &'ll Value, + rhs: &'ll Value +) -> &'ll Value { let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs); // #1877, #10183: Ensure that input is always valid let rhs = shift_mask_rhs(bx, rhs); bx.shl(lhs, rhs) } -pub fn build_unchecked_rshift<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef -) -> ValueRef { +pub fn build_unchecked_rshift( + bx: &Builder<'a, 'll, 'tcx>, lhs_t: Ty<'tcx>, lhs: &'ll Value, rhs: &'ll Value +) -> &'ll Value { let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs); // #1877, #10183: Ensure that input is always valid let rhs = shift_mask_rhs(bx, rhs); @@ -370,17 +378,17 @@ pub fn build_unchecked_rshift<'a, 'tcx>( } } -fn shift_mask_rhs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, rhs: ValueRef) -> ValueRef { +fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value { let rhs_llty = val_ty(rhs); bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false)) } -pub fn shift_mask_val<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - llty: Type, - mask_llty: Type, +pub fn shift_mask_val( + bx: &Builder<'a, 'll, 'tcx>, + llty: &'ll Type, + mask_llty: &'ll Type, invert: bool -) -> ValueRef { +) -> &'ll Value { let kind = llty.kind(); match kind { TypeKind::Integer => { @@ -405,10 +413,10 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, -> ty::PolyFnSig<'tcx> { match ty.sty { - ty::TyFnDef(..) | - // Shims currently have type TyFnPtr. Not sure this should remain. - ty::TyFnPtr(_) => ty.fn_sig(cx.tcx), - ty::TyClosure(def_id, substs) => { + ty::FnDef(..) | + // Shims currently have type FnPtr. Not sure this should remain. + ty::FnPtr(_) => ty.fn_sig(cx.tcx), + ty::Closure(def_id, substs) => { let tcx = cx.tcx; let sig = substs.closure_sig(def_id, tcx); @@ -421,7 +429,7 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, sig.abi )) } - ty::TyGenerator(def_id, substs, _) => { + ty::Generator(def_id, substs, _) => { let tcx = cx.tcx; let sig = substs.poly_sig(def_id, cx.tcx); diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index f0b5f4b887..522de2f15e 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -9,11 +9,9 @@ // except according to those terms. use libc::c_uint; -use llvm; -use llvm::{SetUnnamedAddr}; -use llvm::{ValueRef, True}; +use llvm::{self, SetUnnamedAddr, True}; use rustc::hir::def_id::DefId; -use rustc::hir::map as hir_map; +use rustc::hir::Node; use debuginfo; use base; use monomorphize::MonoItem; @@ -24,27 +22,29 @@ use syntax_pos::Span; use syntax_pos::symbol::LocalInternedString; use type_::Type; use type_of::LayoutLlvmExt; +use value::Value; use rustc::ty::{self, Ty}; + use rustc::ty::layout::{Align, LayoutOf}; use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; use std::ffi::{CStr, CString}; -pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef { +pub fn ptrcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { - llvm::LLVMConstPointerCast(val, ty.to_ref()) + llvm::LLVMConstPointerCast(val, ty) } } -pub fn bitcast(val: ValueRef, ty: Type) -> ValueRef { +pub fn bitcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { - llvm::LLVMConstBitCast(val, ty.to_ref()) + llvm::LLVMConstBitCast(val, ty) } } -fn set_global_alignment(cx: &CodegenCx, - gv: ValueRef, +fn set_global_alignment(cx: &CodegenCx<'ll, '_>, + gv: &'ll Value, mut align: Align) { // The target may require greater alignment for globals than the type does. // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, @@ -62,29 +62,37 @@ fn set_global_alignment(cx: &CodegenCx, } } -pub fn addr_of_mut(cx: &CodegenCx, - cv: ValueRef, - align: Align, - kind: &str) - -> ValueRef { +pub fn addr_of_mut( + cx: &CodegenCx<'ll, '_>, + cv: &'ll Value, + align: Align, + kind: Option<&str>, +) -> &'ll Value { unsafe { - let name = cx.generate_local_symbol_name(kind); - let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{ - bug!("symbol `{}` is already defined", name); - }); + let gv = match kind { + Some(kind) if !cx.tcx.sess.fewer_names() => { + let name = cx.generate_local_symbol_name(kind); + let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{ + bug!("symbol `{}` is already defined", name); + }); + llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage); + gv + }, + _ => declare::define_private_global(cx, val_ty(cv)), + }; llvm::LLVMSetInitializer(gv, cv); set_global_alignment(cx, gv, align); - llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage); SetUnnamedAddr(gv, true); gv } } -pub fn addr_of(cx: &CodegenCx, - cv: ValueRef, - align: Align, - kind: &str) - -> ValueRef { +pub fn addr_of( + cx: &CodegenCx<'ll, '_>, + cv: &'ll Value, + align: Align, + kind: Option<&str>, +) -> &'ll Value { if let Some(&gv) = cx.const_globals.borrow().get(&cv) { unsafe { // Upgrade the alignment in cases where the same constant is used with different @@ -104,7 +112,7 @@ pub fn addr_of(cx: &CodegenCx, gv } -pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { +pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value { let instance = Instance::mono(cx.tcx, def_id); if let Some(&g) = cx.instances.borrow().get(&instance) { return g; @@ -127,7 +135,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { let llty = cx.layout_of(ty).llvm_type(cx); let (g, attrs) = match cx.tcx.hir.get(id) { - hir_map::NodeItem(&hir::Item { + Node::Item(&hir::Item { ref attrs, span, node: hir::ItemKind::Static(..), .. }) => { if declare::get_declared_value(cx, &sym[..]).is_some() { @@ -145,7 +153,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { (g, attrs) } - hir_map::NodeForeignItem(&hir::ForeignItem { + Node::ForeignItem(&hir::ForeignItem { ref attrs, span, node: hir::ForeignItemKind::Static(..), .. }) => { let fn_attrs = cx.tcx.codegen_fn_attrs(def_id); @@ -181,7 +189,20 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { llvm::set_thread_local_mode(g, cx.tls_model); } - if cx.use_dll_storage_attrs && !cx.tcx.is_foreign_item(def_id) { + let needs_dll_storage_attr = + cx.use_dll_storage_attrs && !cx.tcx.is_foreign_item(def_id) && + // ThinLTO can't handle this workaround in all cases, so we don't + // emit the attrs. Instead we make them unnecessary by disallowing + // dynamic linking when cross-language LTO is enabled. + !cx.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled(); + + // If this assertion triggers, there's something wrong with commandline + // argument validation. + debug_assert!(!(cx.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() && + cx.tcx.sess.target.target.options.is_like_msvc && + cx.tcx.sess.opts.cg.prefer_dynamic)); + + if needs_dll_storage_attr { // This item is external but not foreign, i.e. it originates from an external Rust // crate. Since we don't know whether this crate will be linked dynamically or // statically in the final application, we always mark such symbols as 'dllimport'. @@ -209,17 +230,16 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { } cx.instances.borrow_mut().insert(instance, g); - cx.statics.borrow_mut().insert(g, def_id); g } -fn check_and_apply_linkage<'tcx>( - cx: &CodegenCx<'_, 'tcx>, +fn check_and_apply_linkage( + cx: &CodegenCx<'ll, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: LocalInternedString, span: Option -) -> ValueRef { +) -> &'ll Value { let llty = cx.layout_of(ty).llvm_type(cx); if let Some(linkage) = attrs.linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); @@ -230,7 +250,7 @@ fn check_and_apply_linkage<'tcx>( // static and call it a day. Some linkages (like weak) will make it such // that the static actually has a null value. let llty2 = match ty.sty { - ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx), + ty::RawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx), _ => { if span.is_some() { cx.sess().span_fatal(span.unwrap(), "must have type `*const T` or `*mut T`") @@ -294,7 +314,7 @@ pub fn codegen_static<'a, 'tcx>( let mut val_llty = val_ty(v); let v = if val_llty == Type::i1(cx) { val_llty = Type::i8(cx); - llvm::LLVMConstZExt(v, val_llty.to_ref()) + llvm::LLVMConstZExt(v, val_llty) } else { v }; @@ -307,7 +327,7 @@ pub fn codegen_static<'a, 'tcx>( } else { // If we created the global with the wrong type, // correct the type. - let empty_string = CString::new("").unwrap(); + 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()); @@ -316,7 +336,7 @@ pub fn codegen_static<'a, 'tcx>( let visibility = llvm::LLVMRustGetVisibility(g); let new_g = llvm::LLVMRustGetOrInsertGlobal( - cx.llmod, name_string.as_ptr(), val_llty.to_ref()); + cx.llmod, name_string.as_ptr(), val_llty); llvm::LLVMRustSetLinkage(new_g, linkage); llvm::LLVMRustSetVisibility(new_g, visibility); @@ -411,7 +431,7 @@ pub fn codegen_static<'a, 'tcx>( if attrs.flags.contains(CodegenFnAttrFlags::USED) { // This static will be stored in the llvm.used variable which is an array of i8* - let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref()); + let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx)); cx.used_statics.borrow_mut().push(cast); } } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index b774d7c5de..9547f4a190 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -8,34 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use attributes; use common; use llvm; -use llvm::{ContextRef, ModuleRef, ValueRef}; use rustc::dep_graph::DepGraphSafe; use rustc::hir; -use rustc::hir::def_id::DefId; use debuginfo; use callee; use base; use declare; use monomorphize::Instance; +use value::Value; use monomorphize::partitioning::CodegenUnit; use type_::Type; use type_of::PointeeInfo; use rustc_data_structures::base_n; +use rustc_data_structures::small_c_str::SmallCStr; use rustc::mir::mono::Stats; -use rustc::session::config::{self, NoDebugInfo}; +use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; -use std::ffi::{CStr, CString}; +use std::ffi::CStr; use std::cell::{Cell, RefCell}; -use std::ptr; use std::iter; use std::str; use std::sync::Arc; @@ -43,65 +43,62 @@ use syntax::symbol::LocalInternedString; use abi::Abi; /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM -/// `ContextRef` so that several compilation units may be optimized in parallel. -/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`. +/// `llvm::Context` so that several compilation units may be optimized in parallel. +/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`. pub struct CodegenCx<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub check_overflow: bool, pub use_dll_storage_attrs: bool, pub tls_model: llvm::ThreadLocalMode, - pub llmod: ModuleRef, - pub llcx: ContextRef, + pub llmod: &'a llvm::Module, + pub llcx: &'a llvm::Context, pub stats: RefCell, pub codegen_unit: Arc>, /// Cache instances of monomorphic and polymorphic items - pub instances: RefCell, ValueRef>>, + pub instances: RefCell, &'a Value>>, /// Cache generated vtables pub vtables: RefCell, - Option>), ValueRef>>, + Option>), &'a Value>>, /// Cache of constant strings, - pub const_cstr_cache: RefCell>, + pub const_cstr_cache: RefCell>, /// Reverse-direction for const ptrs cast from globals. - /// Key is a ValueRef holding a *T, - /// Val is a ValueRef holding a *[T]. + /// Key is a Value holding a *T, + /// Val is a Value holding a *[T]. /// /// Needed because LLVM loses pointer->pointee association /// when we ptrcast, and we have to ptrcast during codegen /// of a [T] const because we form a slice, a (*T,usize) pair, not /// a pointer to an LLVM array type. Similar for trait objects. - pub const_unsized: RefCell>, + pub const_unsized: RefCell>, /// Cache of emitted const globals (value -> global) - pub const_globals: RefCell>, - - /// Mapping from static definitions to their DefId's. - pub statics: RefCell>, + pub const_globals: RefCell>, /// List of globals for static variables which need to be passed to the /// LLVM function ReplaceAllUsesWith (RAUW) when codegen is complete. - /// (We have to make sure we don't invalidate any ValueRefs referring + /// (We have to make sure we don't invalidate any Values referring /// to constants.) - pub statics_to_rauw: RefCell>, + pub statics_to_rauw: RefCell>, /// Statics that will be placed in the llvm.used variable /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details - pub used_statics: RefCell>, + pub used_statics: RefCell>, - pub lltypes: RefCell, Option), Type>>, - pub scalar_lltypes: RefCell, Type>>, + pub lltypes: RefCell, Option), &'a Type>>, + pub scalar_lltypes: RefCell, &'a Type>>, pub pointee_infos: RefCell, Size), Option>>, - pub isize_ty: Type, + pub isize_ty: &'a Type, - pub dbg_cx: Option>, + pub dbg_cx: Option>, - eh_personality: Cell>, - eh_unwind_resume: Cell>, - pub rust_try_fn: Cell>, + eh_personality: Cell>, + eh_unwind_resume: Cell>, + pub rust_try_fn: Cell>, - intrinsics: RefCell>, + intrinsics: RefCell>, /// A counter that is used for generating local symbol names local_gen_sym_counter: Cell, @@ -148,7 +145,7 @@ fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode { fn is_any_library(sess: &Session) -> bool { sess.crate_types.borrow().iter().any(|ty| { - *ty != config::CrateTypeExecutable + *ty != config::CrateType::Executable }) } @@ -156,9 +153,12 @@ pub fn is_pie_binary(sess: &Session) -> bool { !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC } -pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) { - let llcx = llvm::LLVMRustContextCreate(sess.fewer_names()); - let mod_name = CString::new(mod_name).unwrap(); +pub unsafe fn create_module( + sess: &Session, + llcx: &'ll llvm::Context, + mod_name: &str, +) -> &'ll llvm::Module { + let mod_name = SmallCStr::new(mod_name); let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); // Ensure the data-layout values hardcoded remain the defaults. @@ -198,24 +198,23 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont } } - let data_layout = CString::new(&sess.target.target.data_layout[..]).unwrap(); + let data_layout = SmallCStr::new(&sess.target.target.data_layout); llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); - let llvm_target = sess.target.target.llvm_target.as_bytes(); - let llvm_target = CString::new(llvm_target).unwrap(); + let llvm_target = SmallCStr::new(&sess.target.target.llvm_target); llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); if is_pie_binary(sess) { llvm::LLVMRustSetModulePIELevel(llmod); } - (llcx, llmod) + llmod } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, codegen_unit: Arc>, - llmod_id: &str) + llvm_module: &'a ::ModuleLlvm) -> CodegenCx<'a, 'tcx> { // An interesting part of Windows which MSVC forces our hand on (and // apparently MinGW didn't) is the usage of `dllimport` and `dllexport` @@ -266,55 +265,47 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { let tls_model = get_tls_model(&tcx.sess); - unsafe { - let (llcx, llmod) = create_context_and_module(&tcx.sess, - &llmod_id[..]); - - let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo { - let dctx = debuginfo::CrateDebugContext::new(llmod); - debuginfo::metadata::compile_unit_metadata(tcx, - &codegen_unit.name().as_str(), - &dctx); - Some(dctx) - } else { - None - }; - - let mut cx = CodegenCx { - tcx, - check_overflow, - use_dll_storage_attrs, - tls_model, - llmod, - llcx, - stats: RefCell::new(Stats::default()), - codegen_unit, - instances: RefCell::new(FxHashMap()), - vtables: RefCell::new(FxHashMap()), - const_cstr_cache: RefCell::new(FxHashMap()), - const_unsized: RefCell::new(FxHashMap()), - const_globals: RefCell::new(FxHashMap()), - statics: RefCell::new(FxHashMap()), - statics_to_rauw: RefCell::new(Vec::new()), - used_statics: RefCell::new(Vec::new()), - lltypes: RefCell::new(FxHashMap()), - scalar_lltypes: RefCell::new(FxHashMap()), - pointee_infos: RefCell::new(FxHashMap()), - isize_ty: Type::from_ref(ptr::null_mut()), - dbg_cx, - eh_personality: Cell::new(None), - eh_unwind_resume: Cell::new(None), - rust_try_fn: Cell::new(None), - intrinsics: RefCell::new(FxHashMap()), - local_gen_sym_counter: Cell::new(0), - }; - cx.isize_ty = Type::isize(&cx); - cx - } - } + let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - pub fn into_stats(self) -> Stats { - self.stats.into_inner() + let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None { + let dctx = debuginfo::CrateDebugContext::new(llmod); + debuginfo::metadata::compile_unit_metadata(tcx, + &codegen_unit.name().as_str(), + &dctx); + Some(dctx) + } else { + None + }; + + let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits()); + + CodegenCx { + tcx, + check_overflow, + use_dll_storage_attrs, + tls_model, + llmod, + llcx, + stats: RefCell::new(Stats::default()), + codegen_unit, + instances: RefCell::new(FxHashMap()), + vtables: RefCell::new(FxHashMap()), + const_cstr_cache: RefCell::new(FxHashMap()), + const_unsized: RefCell::new(FxHashMap()), + const_globals: RefCell::new(FxHashMap()), + statics_to_rauw: RefCell::new(Vec::new()), + used_statics: RefCell::new(Vec::new()), + lltypes: RefCell::new(FxHashMap()), + scalar_lltypes: RefCell::new(FxHashMap()), + pointee_infos: RefCell::new(FxHashMap()), + isize_ty, + dbg_cx, + eh_personality: Cell::new(None), + eh_unwind_resume: Cell::new(None), + rust_try_fn: Cell::new(None), + intrinsics: RefCell::new(FxHashMap()), + local_gen_sym_counter: Cell::new(0), + } } } @@ -323,7 +314,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { &self.tcx.sess } - pub fn get_intrinsic(&self, key: &str) -> ValueRef { + pub fn get_intrinsic(&self, key: &str) -> &'b Value { if let Some(v) = self.intrinsics.borrow().get(key).cloned() { return v; } @@ -347,7 +338,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { name } - pub fn eh_personality(&self) -> ValueRef { + pub fn eh_personality(&self) -> &'b Value { // The exception handling personality function. // // If our compilation unit has the `eh_personality` lang item somewhere @@ -382,17 +373,18 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { } else { "rust_eh_personality" }; - let fty = Type::variadic_func(&[], &Type::i32(self)); + let fty = Type::variadic_func(&[], Type::i32(self)); declare::declare_cfn(self, name, fty) } }; + attributes::apply_target_cpu_attr(self, llfn); self.eh_personality.set(Some(llfn)); llfn } - // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined, + // Returns a Value of the "eh_unwind_resume" lang item if one is defined, // otherwise declares it as an external function. - pub fn eh_unwind_resume(&self) -> ValueRef { + pub fn eh_unwind_resume(&self) -> &'b Value { use attributes; let unwresume = &self.eh_unwind_resume; if let Some(llfn) = unwresume.get() { @@ -417,6 +409,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty); attributes::unwind(llfn, true); + attributes::apply_target_cpu_attr(self, llfn); unwresume.set(Some(llfn)); llfn } @@ -441,32 +434,32 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { let tail = self.tcx.struct_tail(ty); match tail.sty { - ty::TyForeign(..) => false, - ty::TyStr | ty::TySlice(..) | ty::TyDynamic(..) => true, + ty::Foreign(..) => false, + ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, _ => bug!("unexpected unsized tail: {:?}", tail.sty), } } } -impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CodegenCx<'a, 'tcx> { +impl ty::layout::HasDataLayout for &'a CodegenCx<'ll, 'tcx> { fn data_layout(&self) -> &ty::layout::TargetDataLayout { &self.tcx.data_layout } } -impl<'a, 'tcx> HasTargetSpec for &'a CodegenCx<'a, 'tcx> { +impl HasTargetSpec for &'a CodegenCx<'ll, 'tcx> { fn target_spec(&self) -> &Target { &self.tcx.sess.target.target } } -impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'a, 'tcx> { +impl ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'ll, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx } } -impl<'a, 'tcx> LayoutOf for &'a CodegenCx<'a, 'tcx> { +impl LayoutOf for &'a CodegenCx<'ll, 'tcx> { type Ty = Ty<'tcx>; type TyLayout = TyLayout<'tcx>; @@ -480,11 +473,11 @@ impl<'a, 'tcx> LayoutOf for &'a CodegenCx<'a, 'tcx> { } /// Declare any llvm intrinsics that you might need -fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { +fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> { macro_rules! ifn { ($name:expr, fn() -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::func(&[], &$ret)); + let f = declare::declare_cfn(cx, $name, Type::func(&[], $ret)); llvm::SetUnnamedAddr(f, false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -492,7 +485,7 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { ); ($name:expr, fn(...) -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], &$ret)); + let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], $ret)); llvm::SetUnnamedAddr(f, false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -500,7 +493,7 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { ); ($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], &$ret)); + let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], $ret)); llvm::SetUnnamedAddr(f, false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -522,14 +515,14 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { let t_f32 = Type::f32(cx); let t_f64 = Type::f64(cx); - let t_v2f32 = Type::vector(&t_f32, 2); - let t_v4f32 = Type::vector(&t_f32, 4); - let t_v8f32 = Type::vector(&t_f32, 8); - let t_v16f32 = Type::vector(&t_f32, 16); + let t_v2f32 = Type::vector(t_f32, 2); + let t_v4f32 = Type::vector(t_f32, 4); + let t_v8f32 = Type::vector(t_f32, 8); + let t_v16f32 = Type::vector(t_f32, 16); - let t_v2f64 = Type::vector(&t_f64, 2); - let t_v4f64 = Type::vector(&t_f64, 4); - let t_v8f64 = Type::vector(&t_f64, 8); + let t_v2f64 = Type::vector(t_f64, 2); + let t_v4f64 = Type::vector(t_f64, 4); + let t_v8f64 = Type::vector(t_f64, 8); ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void); ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void); @@ -775,7 +768,7 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { ifn!("llvm.assume", fn(i1) -> void); ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void); - if cx.sess().opts.debuginfo != NoDebugInfo { + if cx.sess().opts.debuginfo != DebugInfo::None { ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void); ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void); } diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index fcde7f9bbc..a76f1d50fa 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs @@ -18,36 +18,38 @@ use common::CodegenCx; use rustc::mir::{Mir, SourceScope}; use libc::c_uint; -use std::ptr; use syntax_pos::Pos; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use syntax_pos::BytePos; #[derive(Clone, Copy, Debug)] -pub struct MirDebugScope { - pub scope_metadata: DIScope, +pub struct MirDebugScope<'ll> { + pub scope_metadata: Option<&'ll DIScope>, // Start and end offsets of the file to which this DIScope belongs. // These are used to quickly determine whether some span refers to the same file. pub file_start_pos: BytePos, pub file_end_pos: BytePos, } -impl MirDebugScope { +impl MirDebugScope<'ll> { pub fn is_valid(&self) -> bool { - !self.scope_metadata.is_null() + !self.scope_metadata.is_none() } } /// Produce DIScope DIEs for each MIR Scope which has variables defined in it. /// If debuginfo is disabled, the returned vector is empty. -pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebugContext) - -> IndexVec { +pub fn create_mir_scopes( + cx: &CodegenCx<'ll, '_>, + mir: &Mir, + debug_context: &FunctionDebugContext<'ll>, +) -> IndexVec> { let null_scope = MirDebugScope { - scope_metadata: ptr::null_mut(), + scope_metadata: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0) }; @@ -62,7 +64,7 @@ pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebu }; // Find all the scopes with variables defined in them. - let mut has_variables = BitVector::new(mir.source_scopes.len()); + let mut has_variables = BitArray::new(mir.source_scopes.len()); for var in mir.vars_iter() { let decl = &mir.local_decls[var]; has_variables.insert(decl.visibility_scope); @@ -77,12 +79,12 @@ pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebu scopes } -fn make_mir_scope(cx: &CodegenCx, +fn make_mir_scope(cx: &CodegenCx<'ll, '_>, mir: &Mir, - has_variables: &BitVector, - debug_context: &FunctionDebugContextData, + has_variables: &BitArray, + debug_context: &FunctionDebugContextData<'ll>, scope: SourceScope, - scopes: &mut IndexVec) { + scopes: &mut IndexVec>) { if scopes[scope].is_valid() { return; } @@ -95,7 +97,7 @@ fn make_mir_scope(cx: &CodegenCx, // The root is the function itself. let loc = span_start(cx, mir.span); scopes[scope] = MirDebugScope { - scope_metadata: debug_context.fn_metadata, + scope_metadata: Some(debug_context.fn_metadata), file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_pos, }; @@ -109,7 +111,7 @@ fn make_mir_scope(cx: &CodegenCx, // However, we don't skip creating a nested scope if // our parent is the root, because we might want to // put arguments in the root and not have shadowing. - if parent_scope.scope_metadata != debug_context.fn_metadata { + if parent_scope.scope_metadata.unwrap() != debug_context.fn_metadata { scopes[scope] = parent_scope; return; } @@ -121,12 +123,12 @@ fn make_mir_scope(cx: &CodegenCx, debug_context.defining_crate); let scope_metadata = unsafe { - llvm::LLVMRustDIBuilderCreateLexicalBlock( + Some(llvm::LLVMRustDIBuilderCreateLexicalBlock( DIB(cx), - parent_scope.scope_metadata, + parent_scope.scope_metadata.unwrap(), file_metadata, loc.line as c_uint, - loc.col.to_usize() as c_uint) + loc.col.to_usize() as c_uint)) }; scopes[scope] = MirDebugScope { scope_metadata, diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 0b4858c7ab..f6faddb894 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -15,10 +15,10 @@ use llvm; use common::{C_bytes, CodegenCx, C_i32}; use builder::Builder; use declare; +use rustc::session::config::DebugInfo; use type_::Type; -use rustc::session::config::NoDebugInfo; +use value::Value; -use std::ptr; use syntax::attr; @@ -40,8 +40,8 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &Builder) { /// Allocates the global variable responsible for the .debug_gdb_scripts binary /// section. -pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx) - -> llvm::ValueRef { +pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) + -> &'ll Value { let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0"; let section_var_name = &c_section_var_name[..c_section_var_name.len()-1]; @@ -50,12 +50,12 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx) c_section_var_name.as_ptr() as *const _) }; - if section_var == ptr::null_mut() { + section_var.unwrap_or_else(|| { let section_name = b".debug_gdb_scripts\0"; let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0"; unsafe { - let llvm_type = Type::array(&Type::i8(cx), + let llvm_type = Type::array(Type::i8(cx), section_contents.len() as u64); let section_var = declare::define_global(cx, section_var_name, @@ -72,9 +72,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx) llvm::LLVMSetAlignment(section_var, 1); section_var } - } else { - section_var - } + }) } pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool { @@ -83,6 +81,6 @@ pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool { "omit_gdb_pretty_printer_section"); !omit_gdb_pretty_printer_section && - cx.sess().opts.debuginfo != NoDebugInfo && + cx.sess().opts.debuginfo != DebugInfo::None && cx.sess().target.target.options.emit_debug_gdb_scripts } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 2f4dd5a7ce..0221cfd9b2 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -18,8 +18,9 @@ use super::namespace::mangled_name_of_instance; use super::type_names::compute_debuginfo_type_name; use super::{CrateDebugContext}; use abi; +use value::Value; -use llvm::{self, ValueRef}; +use llvm; use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DILexicalBlock, DIFlags}; @@ -27,18 +28,21 @@ 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::{Fingerprint, NodeIdHashingMode}; +use rustc::ich::NodeIdHashingMode; +use rustc_data_structures::fingerprint::Fingerprint; use rustc::ty::Instance; use common::CodegenCx; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, LayoutOf, PrimitiveExt, Size, TyLayout}; use rustc::session::config; use rustc::util::nodemap::FxHashMap; -use rustc::util::common::path2cstr; +use rustc_fs_util::path2cstr; +use rustc_data_structures::small_c_str::SmallCStr; use libc::{c_uint, c_longlong}; use std::ffi::CString; -use std::fmt::Write; +use std::fmt::{self, Write}; +use std::hash::{Hash, Hasher}; use std::iter; use std::ptr; use std::path::{Path, PathBuf}; @@ -46,6 +50,25 @@ use syntax::ast; use syntax::symbol::{Interner, InternedString, Symbol}; use syntax_pos::{self, Span, FileName}; +impl PartialEq for llvm::Metadata { + fn eq(&self, other: &Self) -> bool { + self as *const _ == other as *const _ + } +} + +impl Eq for llvm::Metadata {} + +impl Hash for llvm::Metadata { + fn hash(&self, hasher: &mut H) { + (self as *const Self).hash(hasher); + } +} + +impl fmt::Debug for llvm::Metadata { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (self as *const Self).fmt(f) + } +} // From DWARF 5. // See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1 @@ -64,8 +87,7 @@ const DW_ATE_unsigned_char: c_uint = 0x08; pub const UNKNOWN_LINE_NUMBER: c_uint = 0; pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0; -// ptr::null() doesn't work :( -pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope); +pub const NO_SCOPE_METADATA: Option<&DIScope> = None; #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] pub struct UniqueTypeId(ast::Name); @@ -74,19 +96,19 @@ pub struct UniqueTypeId(ast::Name); // created so far. The metadata nodes are indexed by UniqueTypeId, and, for // faster lookup, also by Ty. The TypeMap is responsible for creating // UniqueTypeIds. -pub struct TypeMap<'tcx> { +pub struct TypeMap<'ll, 'tcx> { // The UniqueTypeIds created so far unique_id_interner: Interner, // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping. - unique_id_to_metadata: FxHashMap, + unique_id_to_metadata: FxHashMap, // A map from types to debuginfo metadata. This is a N:1 mapping. - type_to_metadata: FxHashMap, DIType>, + type_to_metadata: FxHashMap, &'ll DIType>, // A map from types to UniqueTypeId. This is a N:1 mapping. type_to_unique_id: FxHashMap, UniqueTypeId> } -impl<'tcx> TypeMap<'tcx> { - pub fn new() -> TypeMap<'tcx> { +impl TypeMap<'ll, 'tcx> { + pub fn new() -> Self { TypeMap { unique_id_interner: Interner::new(), type_to_metadata: FxHashMap(), @@ -97,9 +119,11 @@ impl<'tcx> TypeMap<'tcx> { // Adds a Ty to metadata mapping to the TypeMap. The method will fail if // the mapping already exists. - fn register_type_with_metadata<'a>(&mut self, - type_: Ty<'tcx>, - metadata: DIType) { + 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_); } @@ -107,20 +131,22 @@ impl<'tcx> TypeMap<'tcx> { // 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: DIType) { + 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!", self.get_unique_type_id_as_string(unique_type_id)); } } - fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option { + fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> { self.type_to_metadata.get(&type_).cloned() } - fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option { + fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> { self.unique_id_to_metadata.get(&unique_type_id).cloned() } @@ -182,23 +208,23 @@ impl<'tcx> TypeMap<'tcx> { // 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<'tcx> { +enum RecursiveTypeDescription<'ll, 'tcx> { UnfinishedMetadata { unfinished_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - metadata_stub: DICompositeType, - member_description_factory: MemberDescriptionFactory<'tcx>, + metadata_stub: &'ll DICompositeType, + member_description_factory: MemberDescriptionFactory<'ll, 'tcx>, }, - FinalMetadata(DICompositeType) + FinalMetadata(&'ll DICompositeType) } -fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>( - cx: &CodegenCx<'a, 'tcx>, +fn create_and_register_recursive_type_forward_declaration( + cx: &CodegenCx<'ll, 'tcx>, unfinished_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - metadata_stub: DICompositeType, - member_description_factory: MemberDescriptionFactory<'tcx>) - -> RecursiveTypeDescription<'tcx> { + metadata_stub: &'ll DICompositeType, + member_description_factory: MemberDescriptionFactory<'ll, 'tcx>, +) -> RecursiveTypeDescription<'ll, 'tcx> { // Insert the stub into the TypeMap in order to allow for recursive references let mut type_map = debug_context(cx).type_map.borrow_mut(); @@ -213,11 +239,11 @@ fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>( } } -impl<'tcx> RecursiveTypeDescription<'tcx> { +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. - fn finalize<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> MetadataCreationResult { + fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> { match *self { FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false), UnfinishedMetadata { @@ -249,7 +275,7 @@ impl<'tcx> RecursiveTypeDescription<'tcx> { // ... and attach them to the stub to complete it. set_members_of_composite_type(cx, metadata_stub, - &member_descriptions[..]); + member_descriptions); return MetadataCreationResult::new(metadata_stub, true); } } @@ -269,12 +295,13 @@ macro_rules! return_if_metadata_created_in_meantime { ) } -fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - unique_type_id: UniqueTypeId, - array_or_slice_type: Ty<'tcx>, - element_type: Ty<'tcx>, - span: Span) - -> MetadataCreationResult { +fn fixed_vec_metadata( + cx: &CodegenCx<'ll, 'tcx>, + unique_type_id: UniqueTypeId, + array_or_slice_type: Ty<'tcx>, + element_type: Ty<'tcx>, + span: Span, +) -> MetadataCreationResult<'ll> { let element_type_metadata = type_metadata(cx, element_type, span); return_if_metadata_created_in_meantime!(cx, unique_type_id); @@ -282,14 +309,14 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let (size, align) = cx.size_and_align_of(array_or_slice_type); let upper_bound = match array_or_slice_type.sty { - ty::TyArray(_, len) => { + ty::Array(_, len) => { len.unwrap_usize(cx.tcx) as c_longlong } _ => -1 }; let subrange = unsafe { - llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound) + Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) }; let subscripts = create_DIArray(DIB(cx), &[subrange]); @@ -305,12 +332,13 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return MetadataCreationResult::new(metadata, false); } -fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - slice_ptr_type: Ty<'tcx>, - element_type: Ty<'tcx>, - unique_type_id: UniqueTypeId, - span: Span) - -> MetadataCreationResult { +fn vec_slice_metadata( + cx: &CodegenCx<'ll, 'tcx>, + slice_ptr_type: Ty<'tcx>, + element_type: Ty<'tcx>, + unique_type_id: UniqueTypeId, + span: Span, +) -> MetadataCreationResult<'ll> { let data_ptr_type = cx.tcx.mk_imm_ptr(element_type); let data_ptr_metadata = type_metadata(cx, data_ptr_type, span); @@ -322,7 +350,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let (pointer_size, pointer_align) = cx.size_and_align_of(data_ptr_type); let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize); - let member_descriptions = [ + let member_descriptions = vec![ MemberDescription { name: "data_ptr".to_string(), type_metadata: data_ptr_metadata, @@ -347,33 +375,35 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, slice_ptr_type, &slice_type_name[..], unique_type_id, - &member_descriptions, + member_descriptions, NO_SCOPE_METADATA, file_metadata, span); MetadataCreationResult::new(metadata, false) } -fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - unique_type_id: UniqueTypeId, - signature: ty::PolyFnSig<'tcx>, - span: Span) - -> MetadataCreationResult -{ +fn subroutine_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + unique_type_id: UniqueTypeId, + signature: ty::PolyFnSig<'tcx>, + span: Span, +) -> MetadataCreationResult<'ll> { let signature = cx.tcx.normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), &signature, ); - let signature_metadata: Vec = iter::once( + let signature_metadata: Vec<_> = iter::once( // return type match signature.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), - _ => type_metadata(cx, signature.output(), span) + ty::Tuple(ref tys) if tys.is_empty() => None, + _ => Some(type_metadata(cx, signature.output(), span)) } ).chain( // regular arguments - signature.inputs().iter().map(|argument_type| type_metadata(cx, argument_type, span)) + signature.inputs().iter().map(|argument_type| { + Some(type_metadata(cx, argument_type, span)) + }) ).collect(); return_if_metadata_created_in_meantime!(cx, unique_type_id); @@ -394,19 +424,20 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // trait_type should be the actual trait (e.g., Trait). Where the trait is part // of a DST struct, there is no trait_object_type and the results of this // function will be a little bit weird. -fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - trait_type: Ty<'tcx>, - trait_object_type: Option>, - unique_type_id: UniqueTypeId) - -> DIType { +fn trait_pointer_metadata( + cx: &CodegenCx<'ll, 'tcx>, + trait_type: Ty<'tcx>, + trait_object_type: Option>, + unique_type_id: UniqueTypeId, +) -> &'ll DIType { // The implementation provided here is a stub. It makes sure that the trait // type is assigned the correct name, size, namespace, and source location. // But it does not describe the trait's methods. let containing_scope = match trait_type.sty { - ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() { + ty::Dynamic(ref data, ..) => if let Some(principal) = data.principal() { let def_id = principal.def_id(); - get_namespace_for_item(cx, def_id) + Some(get_namespace_for_item(cx, def_id)) } else { NO_SCOPE_METADATA }, @@ -430,7 +461,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let data_ptr_field = layout.field(cx, 0); let vtable_field = layout.field(cx, 1); - let member_descriptions = [ + let member_descriptions = vec![ MemberDescription { name: "pointer".to_string(), type_metadata: type_metadata(cx, @@ -455,16 +486,17 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, trait_object_type, &trait_type_name[..], unique_type_id, - &member_descriptions, + member_descriptions, containing_scope, file_metadata, syntax_pos::DUMMY_SP) } -pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - t: Ty<'tcx>, - usage_site_span: Span) - -> DIType { +pub fn type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, + usage_site_span: Span, +) -> &'ll DIType { // Get the unique type id of this type. let unique_type_id = { let mut type_map = debug_context(cx).type_map.borrow_mut(); @@ -502,13 +534,13 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let ptr_metadata = |ty: Ty<'tcx>| { match ty.sty { - ty::TySlice(typ) => { + ty::Slice(typ) => { Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)) } - ty::TyStr => { + ty::Str => { Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span)) } - ty::TyDynamic(..) => { + ty::Dynamic(..) => { Ok(MetadataCreationResult::new( trait_pointer_metadata(cx, ty, Some(t), unique_type_id), false)) @@ -530,48 +562,48 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, }; let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty { - ty::TyNever | - ty::TyBool | - ty::TyChar | - ty::TyInt(_) | - ty::TyUint(_) | - ty::TyFloat(_) => { + ty::Never | + ty::Bool | + ty::Char | + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } - ty::TyTuple(ref elements) if elements.is_empty() => { + ty::Tuple(ref elements) if elements.is_empty() => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } - ty::TyArray(typ, _) | - ty::TySlice(typ) => { + ty::Array(typ, _) | + ty::Slice(typ) => { fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span) } - ty::TyStr => { + ty::Str => { fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span) } - ty::TyDynamic(..) => { + ty::Dynamic(..) => { MetadataCreationResult::new( trait_pointer_metadata(cx, t, None, unique_type_id), false) } - ty::TyForeign(..) => { + ty::Foreign(..) => { MetadataCreationResult::new( foreign_type_metadata(cx, t, unique_type_id), false) } - ty::TyRawPtr(ty::TypeAndMut{ty, ..}) | - ty::TyRef(_, ty, _) => { + ty::RawPtr(ty::TypeAndMut{ty, ..}) | + ty::Ref(_, ty, _) => { match ptr_metadata(ty) { Ok(res) => res, Err(metadata) => return metadata, } } - ty::TyAdt(def, _) if def.is_box() => { + ty::Adt(def, _) if def.is_box() => { match ptr_metadata(t.boxed_ty()) { Ok(res) => res, Err(metadata) => return metadata, } } - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { let fn_metadata = subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx), @@ -587,7 +619,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false) } - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect(); prepare_tuple_metadata(cx, t, @@ -595,7 +627,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, unique_type_id, usage_site_span).finalize(cx) } - ty::TyGenerator(def_id, substs, _) => { + ty::Generator(def_id, substs, _) => { let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx).map(|t| { cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t) }).collect(); @@ -605,7 +637,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, unique_type_id, usage_site_span).finalize(cx) } - ty::TyAdt(def, ..) => match def.adt_kind() { + ty::Adt(def, ..) => match def.adt_kind() { AdtKind::Struct => { prepare_struct_metadata(cx, t, @@ -626,7 +658,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, usage_site_span).finalize(cx) } }, - ty::TyTuple(ref elements) => { + ty::Tuple(ref elements) => { prepare_tuple_metadata(cx, t, &elements[..], @@ -681,9 +713,9 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, metadata } -pub fn file_metadata(cx: &CodegenCx, +pub fn file_metadata(cx: &CodegenCx<'ll, '_>, file_name: &FileName, - defining_crate: CrateNum) -> DIFile { + defining_crate: CrateNum) -> &'ll DIFile { debug!("file_metadata: file_name: {}, defining_crate: {}", file_name, defining_crate); @@ -699,14 +731,14 @@ pub fn file_metadata(cx: &CodegenCx, file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy()) } -pub fn unknown_file_metadata(cx: &CodegenCx) -> DIFile { +pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { file_metadata_raw(cx, "", "") } -fn file_metadata_raw(cx: &CodegenCx, +fn file_metadata_raw(cx: &CodegenCx<'ll, '_>, file_name: &str, directory: &str) - -> DIFile { + -> &'ll DIFile { let key = (Symbol::intern(file_name), Symbol::intern(directory)); if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(&key) { @@ -715,8 +747,8 @@ fn file_metadata_raw(cx: &CodegenCx, debug!("file_metadata: file_name: {}, directory: {}", file_name, directory); - let file_name = CString::new(file_name).unwrap(); - let directory = CString::new(directory).unwrap(); + let file_name = SmallCStr::new(file_name); + let directory = SmallCStr::new(directory); let file_metadata = unsafe { llvm::LLVMRustDIBuilderCreateFile(DIB(cx), @@ -729,31 +761,29 @@ fn file_metadata_raw(cx: &CodegenCx, file_metadata } -fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - t: Ty<'tcx>) -> DIType { - +fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { debug!("basic_type_metadata: {:?}", t); let (name, encoding) = match t.sty { - ty::TyNever => ("!", DW_ATE_unsigned), - ty::TyTuple(ref elements) if elements.is_empty() => + ty::Never => ("!", DW_ATE_unsigned), + ty::Tuple(ref elements) if elements.is_empty() => ("()", DW_ATE_unsigned), - ty::TyBool => ("bool", DW_ATE_boolean), - ty::TyChar => ("char", DW_ATE_unsigned_char), - ty::TyInt(int_ty) => { + 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) }, - ty::TyUint(uint_ty) => { + ty::Uint(uint_ty) => { (uint_ty.ty_to_string(), DW_ATE_unsigned) }, - ty::TyFloat(float_ty) => { + ty::Float(float_ty) => { (float_ty.ty_to_string(), DW_ATE_float) }, _ => bug!("debuginfo::basic_type_metadata - t is invalid type") }; let (size, align) = cx.size_and_align_of(t); - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(name); let ty_metadata = unsafe { llvm::LLVMRustDIBuilderCreateBasicType( DIB(cx), @@ -766,22 +796,25 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return ty_metadata; } -fn foreign_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - t: Ty<'tcx>, - unique_type_id: UniqueTypeId) -> DIType { +fn foreign_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, + unique_type_id: UniqueTypeId, +) -> &'ll DIType { debug!("foreign_type_metadata: {:?}", t); let name = compute_debuginfo_type_name(cx, t, false); create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA) } -fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - pointer_type: Ty<'tcx>, - pointee_type_metadata: DIType) - -> DIType { +fn pointer_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + pointer_type: Ty<'tcx>, + pointee_type_metadata: &'ll DIType, +) -> &'ll DIType { let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type); let name = compute_debuginfo_type_name(cx, pointer_type, false); - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(&name); unsafe { llvm::LLVMRustDIBuilderCreatePointerType( DIB(cx), @@ -794,8 +827,8 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, pub fn compile_unit_metadata(tcx: TyCtxt, codegen_unit_name: &str, - debug_context: &CrateDebugContext) - -> DIDescriptor { + debug_context: &CrateDebugContext<'ll, '_>) + -> &'ll DIDescriptor { let mut name_in_debuginfo = match tcx.sess.local_crate_source_file { Some(ref path) => path.clone(), None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()), @@ -815,9 +848,9 @@ pub fn compile_unit_metadata(tcx: TyCtxt, let producer = format!("clang LLVM (rustc version {})", (option_env!("CFG_VERSION")).expect("CFG_VERSION")); - let name_in_debuginfo = name_in_debuginfo.to_string_lossy().into_owned(); - let name_in_debuginfo = CString::new(name_in_debuginfo).unwrap(); - let work_dir = CString::new(&tcx.sess.working_dir.0.to_string_lossy()[..]).unwrap(); + let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); + let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo); + let work_dir = SmallCStr::new(&tcx.sess.working_dir.0.to_string_lossy()); let producer = CString::new(producer).unwrap(); let flags = "\0"; let split_name = "\0"; @@ -851,7 +884,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt, gcov_cu_info.as_ptr(), gcov_cu_info.len() as c_uint); - let llvm_gcov_ident = CString::new("llvm.gcov").unwrap(); + let llvm_gcov_ident = const_cstr!("llvm.gcov"); llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), gcov_metadata); @@ -860,7 +893,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt, return unit_metadata; }; - fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef { + fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { let path_str = path2cstr(path); unsafe { llvm::LLVMMDStringInContext(llcx, @@ -870,13 +903,13 @@ pub fn compile_unit_metadata(tcx: TyCtxt, } } -struct MetadataCreationResult { - metadata: DIType, +struct MetadataCreationResult<'ll> { + metadata: &'ll DIType, already_stored_in_typemap: bool } -impl MetadataCreationResult { - fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult { +impl MetadataCreationResult<'ll> { + fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self { MetadataCreationResult { metadata, already_stored_in_typemap, @@ -887,9 +920,9 @@ impl MetadataCreationResult { // 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 { +struct MemberDescription<'ll> { name: String, - type_metadata: DIType, + type_metadata: &'ll DIType, offset: Size, size: Size, align: Align, @@ -900,17 +933,17 @@ struct MemberDescription { // 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. -enum MemberDescriptionFactory<'tcx> { +enum MemberDescriptionFactory<'ll, 'tcx> { StructMDF(StructMemberDescriptionFactory<'tcx>), TupleMDF(TupleMemberDescriptionFactory<'tcx>), - EnumMDF(EnumMemberDescriptionFactory<'tcx>), + EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>), UnionMDF(UnionMemberDescriptionFactory<'tcx>), - VariantMDF(VariantMemberDescriptionFactory<'tcx>) + VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>) } -impl<'tcx> MemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { +impl MemberDescriptionFactory<'ll, 'tcx> { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { match *self { StructMDF(ref this) => { this.create_member_descriptions(cx) @@ -943,8 +976,8 @@ struct StructMemberDescriptionFactory<'tcx> { } impl<'tcx> StructMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { let layout = cx.layout_of(self.ty); self.variant.fields.iter().enumerate().map(|(i, f)| { let name = if self.variant.ctor_kind == CtorKind::Fn { @@ -967,15 +1000,16 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { } -fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - struct_type: Ty<'tcx>, - unique_type_id: UniqueTypeId, - span: Span) - -> RecursiveTypeDescription<'tcx> { +fn prepare_struct_metadata( + cx: &CodegenCx<'ll, 'tcx>, + struct_type: Ty<'tcx>, + unique_type_id: UniqueTypeId, + span: Span, +) -> RecursiveTypeDescription<'ll, 'tcx> { let struct_name = compute_debuginfo_type_name(cx, struct_type, false); let (struct_def_id, variant) = match struct_type.sty { - ty::TyAdt(def, _) => (def.did, def.non_enum_variant()), + ty::Adt(def, _) => (def.did, def.non_enum_variant()), _ => bug!("prepare_struct_metadata on a non-ADT") }; @@ -985,7 +1019,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, struct_type, &struct_name, unique_type_id, - containing_scope); + Some(containing_scope)); create_and_register_recursive_type_forward_declaration( cx, @@ -1012,8 +1046,8 @@ struct TupleMemberDescriptionFactory<'tcx> { } impl<'tcx> TupleMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { let layout = cx.layout_of(self.ty); self.component_types.iter().enumerate().map(|(i, &component_type)| { let (size, align) = cx.size_and_align_of(component_type); @@ -1029,12 +1063,13 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> { } } -fn prepare_tuple_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - tuple_type: Ty<'tcx>, - component_types: &[Ty<'tcx>], - unique_type_id: UniqueTypeId, - span: Span) - -> RecursiveTypeDescription<'tcx> { +fn prepare_tuple_metadata( + cx: &CodegenCx<'ll, 'tcx>, + tuple_type: Ty<'tcx>, + component_types: &[Ty<'tcx>], + unique_type_id: UniqueTypeId, + span: Span, +) -> RecursiveTypeDescription<'ll, 'tcx> { let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false); create_and_register_recursive_type_forward_declaration( @@ -1065,8 +1100,8 @@ struct UnionMemberDescriptionFactory<'tcx> { } impl<'tcx> UnionMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { self.variant.fields.iter().enumerate().map(|(i, f)| { let field = self.layout.field(cx, i); let (size, align) = field.size_and_align(); @@ -1082,15 +1117,16 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { } } -fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - union_type: Ty<'tcx>, - unique_type_id: UniqueTypeId, - span: Span) - -> RecursiveTypeDescription<'tcx> { +fn prepare_union_metadata( + cx: &CodegenCx<'ll, 'tcx>, + union_type: Ty<'tcx>, + unique_type_id: UniqueTypeId, + span: Span, +) -> RecursiveTypeDescription<'ll, 'tcx> { let union_name = compute_debuginfo_type_name(cx, union_type, false); let (union_def_id, variant) = match union_type.sty { - ty::TyAdt(def, _) => (def.did, def.non_enum_variant()), + ty::Adt(def, _) => (def.did, def.non_enum_variant()), _ => bug!("prepare_union_metadata on a non-ADT") }; @@ -1124,17 +1160,17 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // 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<'tcx> { +struct EnumMemberDescriptionFactory<'ll, 'tcx> { enum_type: Ty<'tcx>, layout: TyLayout<'tcx>, - discriminant_type_metadata: Option, - containing_scope: DIScope, + discriminant_type_metadata: Option<&'ll DIType>, + containing_scope: &'ll DIScope, span: Span, } -impl<'tcx> EnumMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { +impl EnumMemberDescriptionFactory<'ll, 'tcx> { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { let adt = &self.enum_type.ty_adt_def().unwrap(); match self.layout.variants { layout::Variants::Single { .. } if adt.variants.is_empty() => vec![], @@ -1152,10 +1188,10 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { set_members_of_composite_type(cx, variant_type_metadata, - &member_descriptions[..]); + member_descriptions); vec![ MemberDescription { - name: "".to_string(), + name: String::new(), type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, @@ -1182,9 +1218,9 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { set_members_of_composite_type(cx, variant_type_metadata, - &member_descriptions); + member_descriptions); MemberDescription { - name: "".to_string(), + name: String::new(), type_metadata: variant_type_metadata, offset: Size::ZERO, size: variant.size, @@ -1209,7 +1245,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { set_members_of_composite_type(cx, variant_type_metadata, - &variant_member_descriptions[..]); + variant_member_descriptions); // Encode the information about the null variant in the union // member's name. @@ -1259,17 +1295,17 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { } // Creates MemberDescriptions for the fields of a single enum variant. -struct VariantMemberDescriptionFactory<'tcx> { +struct VariantMemberDescriptionFactory<'ll, 'tcx> { // Cloned from the layout::Struct describing the variant. offsets: Vec, args: Vec<(String, Ty<'tcx>)>, - discriminant_type_metadata: Option, + discriminant_type_metadata: Option<&'ll DIType>, span: Span, } -impl<'tcx> VariantMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { +impl VariantMemberDescriptionFactory<'ll, 'tcx> { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { self.args.iter().enumerate().map(|(i, &(ref name, ty))| { let (size, align) = cx.size_and_align_of(ty); MemberDescription { @@ -1288,8 +1324,8 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> { } #[derive(Copy, Clone)] -enum EnumDiscriminantInfo { - RegularDiscriminant(DIType), +enum EnumDiscriminantInfo<'ll> { + RegularDiscriminant(&'ll DIType), OptimizedDiscriminant, NoDiscriminant } @@ -1298,13 +1334,14 @@ enum EnumDiscriminantInfo { // of the variant, and (3) 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<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - layout: layout::TyLayout<'tcx>, - variant: &'tcx ty::VariantDef, - discriminant_info: EnumDiscriminantInfo, - containing_scope: DIScope, - span: Span) - -> (DICompositeType, MemberDescriptionFactory<'tcx>) { +fn describe_enum_variant( + cx: &CodegenCx<'ll, 'tcx>, + layout: layout::TyLayout<'tcx>, + variant: &'tcx ty::VariantDef, + discriminant_info: EnumDiscriminantInfo<'ll>, + containing_scope: &'ll DIScope, + span: Span, +) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { let variant_name = variant.name.as_str(); let unique_type_id = debug_context(cx).type_map .borrow_mut() @@ -1317,11 +1354,12 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout.ty, &variant_name, unique_type_id, - containing_scope); + Some(containing_scope)); // If this is not a univariant enum, there is also the discriminant field. let (discr_offset, discr_arg) = match discriminant_info { RegularDiscriminant(_) => { + // We have the layout of an enum variant, we need the layout of the outer enum let enum_layout = cx.layout_of(layout.ty); (Some(enum_layout.fields.offset(0)), Some(("RUST$ENUM$DISR".to_string(), enum_layout.field(cx, 0).ty))) @@ -1358,12 +1396,13 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, (metadata_stub, member_description_factory) } -fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - enum_type: Ty<'tcx>, - enum_def_id: DefId, - unique_type_id: UniqueTypeId, - span: Span) - -> RecursiveTypeDescription<'tcx> { +fn prepare_enum_metadata( + cx: &CodegenCx<'ll, 'tcx>, + enum_type: Ty<'tcx>, + enum_def_id: DefId, + unique_type_id: UniqueTypeId, + span: Span, +) -> RecursiveTypeDescription<'ll, 'tcx> { let enum_name = compute_debuginfo_type_name(cx, enum_type, false); let containing_scope = get_namespace_for_item(cx, enum_def_id); @@ -1376,17 +1415,16 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let file_metadata = unknown_file_metadata(cx); let def = enum_type.ty_adt_def().unwrap(); - let enumerators_metadata: Vec = def.discriminants(cx.tcx) + let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx) .zip(&def.variants) .map(|(discr, v)| { - let token = v.name.as_str(); - let name = CString::new(token.as_bytes()).unwrap(); + let name = SmallCStr::new(&v.name.as_str()); unsafe { - llvm::LLVMRustDIBuilderCreateEnumerator( + Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), name.as_ptr(), // FIXME: what if enumeration has i128 discriminant? - discr.val as u64) + discr.val as u64)) } }) .collect(); @@ -1405,7 +1443,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP); let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str(); - let name = CString::new(discriminant_name.as_bytes()).unwrap(); + let name = SmallCStr::new(&discriminant_name); let discriminant_type_metadata = unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), @@ -1445,10 +1483,10 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let (enum_type_size, enum_type_align) = layout.size_and_align(); - let enum_name = CString::new(enum_name).unwrap(); - let unique_type_id_str = CString::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() - ).unwrap(); + let enum_name = SmallCStr::new(&enum_name); + let unique_type_id_str = SmallCStr::new( + debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id) + ); let enum_metadata = unsafe { llvm::LLVMRustDIBuilderCreateUnionType( DIB(cx), @@ -1459,7 +1497,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, enum_type_size.bits(), enum_type_align.abi_bits() as u32, DIFlags::FlagZero, - ptr::null_mut(), + None, 0, // RuntimeLang unique_type_id_str.as_ptr()) }; @@ -1489,18 +1527,19 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// results in a LLVM struct. /// /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. -fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - composite_type: Ty<'tcx>, - composite_type_name: &str, - composite_type_unique_id: UniqueTypeId, - member_descriptions: &[MemberDescription], - containing_scope: DIScope, - - // Ignore source location information as long as it - // can't be reconstructed for non-local crates. - _file_metadata: DIFile, - _definition_span: Span) - -> DICompositeType { +fn composite_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + composite_type: Ty<'tcx>, + composite_type_name: &str, + composite_type_unique_id: UniqueTypeId, + member_descriptions: Vec>, + containing_scope: Option<&'ll DIScope>, + + // Ignore source location information as long as it + // can't be reconstructed for non-local crates. + _file_metadata: &'ll DIFile, + _definition_span: Span, +) -> &'ll DICompositeType { // Create the (empty) struct metadata node ... let composite_type_metadata = create_struct_stub(cx, composite_type, @@ -1515,9 +1554,9 @@ fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return composite_type_metadata; } -fn set_members_of_composite_type(cx: &CodegenCx, - composite_type_metadata: DICompositeType, - member_descriptions: &[MemberDescription]) { +fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, + composite_type_metadata: &'ll DICompositeType, + member_descriptions: Vec>) { // In some rare cases LLVM metadata uniquing would lead to an existing type // description being used instead of a new one created in // create_struct_stub. This would cause a hard to trace assertion in @@ -1535,13 +1574,12 @@ fn set_members_of_composite_type(cx: &CodegenCx, } } - let member_metadata: Vec = member_descriptions - .iter() + let member_metadata: Vec<_> = member_descriptions + .into_iter() .map(|member_description| { - let member_name = member_description.name.as_bytes(); - let member_name = CString::new(member_name).unwrap(); + let member_name = CString::new(member_description.name).unwrap(); unsafe { - llvm::LLVMRustDIBuilderCreateMemberType( + Some(llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), composite_type_metadata, member_name.as_ptr(), @@ -1551,7 +1589,7 @@ fn set_members_of_composite_type(cx: &CodegenCx, member_description.align.abi_bits() as u32, member_description.offset.bits(), member_description.flags, - member_description.type_metadata) + member_description.type_metadata)) } }) .collect(); @@ -1566,18 +1604,19 @@ fn set_members_of_composite_type(cx: &CodegenCx, // 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<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - struct_type: Ty<'tcx>, - struct_type_name: &str, - unique_type_id: UniqueTypeId, - containing_scope: DIScope) - -> DICompositeType { +fn create_struct_stub( + cx: &CodegenCx<'ll, 'tcx>, + struct_type: Ty<'tcx>, + struct_type_name: &str, + unique_type_id: UniqueTypeId, + containing_scope: Option<&'ll DIScope>, +) -> &'ll DICompositeType { let (struct_size, struct_align) = cx.size_and_align_of(struct_type); - let name = CString::new(struct_type_name).unwrap(); - let unique_type_id = CString::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() - ).unwrap(); + let name = SmallCStr::new(struct_type_name); + let unique_type_id = SmallCStr::new( + 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 // pointer will lead to hard to trace and debug LLVM assertions @@ -1593,28 +1632,29 @@ fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, struct_size.bits(), struct_align.abi_bits() as u32, DIFlags::FlagZero, - ptr::null_mut(), + None, empty_array, 0, - ptr::null_mut(), + None, unique_type_id.as_ptr()) }; return metadata_stub; } -fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - union_type: Ty<'tcx>, - union_type_name: &str, - unique_type_id: UniqueTypeId, - containing_scope: DIScope) - -> DICompositeType { +fn create_union_stub( + cx: &CodegenCx<'ll, 'tcx>, + union_type: Ty<'tcx>, + union_type_name: &str, + unique_type_id: UniqueTypeId, + containing_scope: &'ll DIScope, +) -> &'ll DICompositeType { let (union_size, union_align) = cx.size_and_align_of(union_type); - let name = CString::new(union_type_name).unwrap(); - let unique_type_id = CString::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() - ).unwrap(); + let name = SmallCStr::new(union_type_name); + let unique_type_id = SmallCStr::new( + 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 // pointer will lead to hard to trace and debug LLVM assertions @@ -1630,7 +1670,7 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, union_size.bits(), union_align.abi_bits() as u32, DIFlags::FlagZero, - empty_array, + Some(empty_array), 0, // RuntimeLang unique_type_id.as_ptr()) }; @@ -1641,9 +1681,11 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// Creates debug information for the given global variable. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_global_var_metadata(cx: &CodegenCx, - def_id: DefId, - global: ValueRef) { +pub fn create_global_var_metadata( + cx: &CodegenCx<'ll, '_>, + def_id: DefId, + global: &'ll Value, +) { if cx.dbg_cx.is_none() { return; } @@ -1671,20 +1713,19 @@ pub fn create_global_var_metadata(cx: &CodegenCx, let is_local_to_unit = is_node_local_to_unit(cx, def_id); let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx); let type_metadata = type_metadata(cx, variable_type, span); - let var_name = tcx.item_name(def_id).to_string(); - let var_name = CString::new(var_name).unwrap(); + let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str()); let linkage_name = if no_mangle { None } else { let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)); - Some(CString::new(linkage_name.to_string()).unwrap()) + Some(SmallCStr::new(&linkage_name.as_str())) }; let global_align = cx.align_of(variable_type); unsafe { llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx), - var_scope, + Some(var_scope), var_name.as_ptr(), // If null, linkage_name field is omitted, // which is what we want for no_mangle statics @@ -1695,18 +1736,19 @@ pub fn create_global_var_metadata(cx: &CodegenCx, type_metadata, is_local_to_unit, global, - ptr::null_mut(), + None, global_align.abi() as u32, ); } } // Creates an "extension" of an existing DIScope into another file. -pub fn extend_scope_to_file(cx: &CodegenCx, - scope_metadata: DIScope, - file: &syntax_pos::FileMap, - defining_crate: CrateNum) - -> DILexicalBlock { +pub fn extend_scope_to_file( + cx: &CodegenCx<'ll, '_>, + scope_metadata: &'ll DIScope, + file: &syntax_pos::SourceFile, + defining_crate: CrateNum, +) -> &'ll DILexicalBlock { let file_metadata = file_metadata(cx, &file.name, defining_crate); unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile( @@ -1720,9 +1762,11 @@ pub fn extend_scope_to_file(cx: &CodegenCx, /// given type. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - ty: ty::Ty<'tcx>, - vtable: ValueRef) { +pub fn create_vtable_metadata( + cx: &CodegenCx<'ll, 'tcx>, + ty: ty::Ty<'tcx>, + vtable: &'ll Value, +) { if cx.dbg_cx.is_none() { return; } @@ -1735,7 +1779,7 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // later on in llvm/lib/IR/Value.cpp. let empty_array = create_DIArray(DIB(cx), &[]); - let name = CString::new("vtable").unwrap(); + let name = const_cstr!("vtable"); // Create a new one each time. We don't want metadata caching // here, because each vtable will refer to a unique containing @@ -1749,10 +1793,10 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, Size::ZERO.bits(), cx.tcx.data_layout.pointer_align.abi_bits() as u32, DIFlags::FlagArtificial, - ptr::null_mut(), + None, empty_array, 0, - type_metadata, + Some(type_metadata), name.as_ptr() ); @@ -1771,7 +1815,7 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, vtable_type, true, vtable, - ptr::null_mut(), + None, 0); } } diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 9671db75ba..99919a940b 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -21,8 +21,7 @@ use self::metadata::{type_metadata, file_metadata, TypeMap}; use self::source_loc::InternalDebugLocation::{self, UnknownLocation}; use llvm; -use llvm::{ModuleRef, ContextRef, ValueRef}; -use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags}; +use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags}; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, CrateNum}; use rustc::ty::subst::{Substs, UnpackedKind}; @@ -33,13 +32,14 @@ use builder::Builder; use monomorphize::Instance; use rustc::ty::{self, ParamEnv, Ty, InstanceDef}; use rustc::mir; -use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; +use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; +use rustc_data_structures::small_c_str::SmallCStr; +use value::Value; use libc::c_uint; use std::cell::{Cell, RefCell}; use std::ffi::CString; -use std::ptr; use syntax_pos::{self, Span, Pos}; use syntax::ast; @@ -67,23 +67,31 @@ const DW_TAG_auto_variable: c_uint = 0x100; const DW_TAG_arg_variable: c_uint = 0x101; /// A context object for maintaining all state needed by the debuginfo module. -pub struct CrateDebugContext<'tcx> { - llcontext: ContextRef, - llmod: ModuleRef, - builder: DIBuilderRef, - created_files: RefCell>, - created_enum_disr_types: RefCell>, +pub struct CrateDebugContext<'a, 'tcx> { + llcontext: &'a llvm::Context, + llmod: &'a llvm::Module, + builder: &'a mut DIBuilder<'a>, + created_files: RefCell>, + created_enum_disr_types: RefCell>, - type_map: RefCell>, - namespace_map: RefCell>, + type_map: RefCell>, + namespace_map: RefCell>, // This collection is used to assert that composite types (structs, enums, // ...) have their members only set once: - composite_types_completed: RefCell>, + composite_types_completed: RefCell>, } -impl<'tcx> CrateDebugContext<'tcx> { - pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> { +impl Drop for CrateDebugContext<'a, 'tcx> { + fn drop(&mut self) { + unsafe { + llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _)); + } + } +} + +impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> { + pub fn new(llmod: &'a llvm::Module) -> Self { debug!("CrateDebugContext::new"); let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; // DIBuilder inherits context from the module, so we'd better use the same one @@ -101,14 +109,14 @@ impl<'tcx> CrateDebugContext<'tcx> { } } -pub enum FunctionDebugContext { - RegularContext(FunctionDebugContextData), +pub enum FunctionDebugContext<'ll> { + RegularContext(FunctionDebugContextData<'ll>), DebugInfoDisabled, FunctionWithoutDebugInfo, } -impl FunctionDebugContext { - pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData { +impl FunctionDebugContext<'ll> { + pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData<'ll> { match *self { FunctionDebugContext::RegularContext(ref data) => data, FunctionDebugContext::DebugInfoDisabled => { @@ -130,18 +138,18 @@ impl FunctionDebugContext { } } -pub struct FunctionDebugContextData { - fn_metadata: DISubprogram, +pub struct FunctionDebugContextData<'ll> { + fn_metadata: &'ll DISubprogram, source_locations_enabled: Cell, pub defining_crate: CrateNum, } -pub enum VariableAccess<'a> { +pub enum VariableAccess<'a, 'll> { // The llptr given is an alloca containing the variable's value - DirectVariable { alloca: ValueRef }, + DirectVariable { alloca: &'ll Value }, // The llptr given is an alloca containing the start of some pointer chain // leading to the variable's content. - IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] } + IndirectVariable { alloca: &'ll Value, address_operations: &'a [i64] } } pub enum VariableKind { @@ -167,7 +175,6 @@ pub fn finalize(cx: &CodegenCx) { unsafe { llvm::LLVMRustDIBuilderFinalize(DIB(cx)); - llvm::LLVMRustDIBuilderDispose(DIB(cx)); // Debuginfo generation in LLVM by default uses a higher // version of dwarf than macOS currently understands. We can // instruct LLVM to emit an older version of dwarf, however, @@ -201,12 +208,14 @@ pub fn finalize(cx: &CodegenCx) { /// for debug info creation. The function may also return another variant of the /// FunctionDebugContext enum which indicates why no debuginfo should be created /// for the function. -pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, - llfn: ValueRef, - mir: &mir::Mir) -> FunctionDebugContext { - if cx.sess().opts.debuginfo == NoDebugInfo { +pub fn create_function_debug_context( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, + sig: ty::FnSig<'tcx>, + llfn: &'ll Value, + mir: &mir::Mir, +) -> FunctionDebugContext<'ll> { + if cx.sess().opts.debuginfo == DebugInfo::None { return FunctionDebugContext::DebugInfoDisabled; } @@ -257,7 +266,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let is_local_to_unit = is_node_local_to_unit(cx, def_id); let function_name = CString::new(name).unwrap(); - let linkage_name = CString::new(linkage_name.to_string()).unwrap(); + let linkage_name = SmallCStr::new(&linkage_name.as_str()); let mut flags = DIFlags::FlagPrototyped; @@ -290,7 +299,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, cx.sess().opts.optimize != config::OptLevel::No, llfn, template_parameters, - ptr::null_mut()) + None) }; // Initialize fn debug context (including scope map and namespace map) @@ -302,9 +311,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return FunctionDebugContext::RegularContext(fn_debug_context); - fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - sig: ty::FnSig<'tcx>) -> DIArray { - if cx.sess().opts.debuginfo == LimitedDebugInfo { + fn get_function_signature( + cx: &CodegenCx<'ll, 'tcx>, + sig: ty::FnSig<'tcx>, + ) -> &'ll DIArray { + if cx.sess().opts.debuginfo == DebugInfo::Limited { return create_DIArray(DIB(cx), &[]); } @@ -312,8 +323,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // Return type -- llvm::DIBuilder wants this at index 0 signature.push(match sig.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), - _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP) + 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 { @@ -336,25 +347,26 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // already inaccurate due to ABI adjustments (see #42800). signature.extend(inputs.iter().map(|&t| { let t = match t.sty { - ty::TyArray(ct, _) + ty::Array(ct, _) if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => { cx.tcx.mk_imm_ptr(ct) } _ => t }; - type_metadata(cx, t, syntax_pos::DUMMY_SP) + Some(type_metadata(cx, t, syntax_pos::DUMMY_SP)) })); } else { signature.extend(inputs.iter().map(|t| { - type_metadata(cx, t, syntax_pos::DUMMY_SP) + Some(type_metadata(cx, t, syntax_pos::DUMMY_SP)) })); } if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { - if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty { + if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].sty { signature.extend( - args.iter().map(|argument_type| - type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)) + args.iter().map(|argument_type| { + Some(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)) + }) ); } } @@ -362,13 +374,13 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return create_DIArray(DIB(cx), &signature[..]); } - fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - generics: &ty::Generics, - substs: &Substs<'tcx>, - file_metadata: DIFile, - name_to_append_suffix_to: &mut String) - -> DIArray - { + fn get_template_parameters( + cx: &CodegenCx<'ll, 'tcx>, + generics: &ty::Generics, + substs: &Substs<'tcx>, + file_metadata: &'ll DIFile, + name_to_append_suffix_to: &mut String, + ) -> &'ll DIArray { if substs.types().next().is_none() { return create_DIArray(DIB(cx), &[]); } @@ -389,23 +401,24 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name_to_append_suffix_to.push('>'); // Again, only create type information if full debuginfo is enabled - let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { + let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { let names = get_parameter_names(cx, generics); substs.iter().zip(names).filter_map(|(kind, name)| { if let UnpackedKind::Type(ty) = kind.unpack() { let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); - let name = CString::new(name.as_str().as_bytes()).unwrap(); + let name = SmallCStr::new(&name.as_str()); Some(unsafe { - llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( + Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), - ptr::null_mut(), + None, name.as_ptr(), actual_type_metadata, file_metadata, 0, - 0) + 0, + )) }) } else { None @@ -428,9 +441,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, names } - fn get_containing_scope<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>, - instance: Instance<'tcx>) - -> DIScope { + fn get_containing_scope( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, + ) -> &'ll DIScope { // First, let's see if this is a method within an inherent impl. Because // if yes, we want to make the result subroutine DIE a child of the // subroutine's self-type. @@ -446,7 +460,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // Only "class" methods are generally understood by LLVM, // so avoid methods on other types (e.g. `<*mut T>::null`). match impl_self_ty.sty { - ty::TyAdt(def, ..) if !def.is_box() => { + ty::Adt(def, ..) if !def.is_box() => { Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP)) } _ => None @@ -470,14 +484,16 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } } -pub fn declare_local<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - dbg_context: &FunctionDebugContext, - variable_name: ast::Name, - variable_type: Ty<'tcx>, - scope_metadata: DIScope, - variable_access: VariableAccess, - variable_kind: VariableKind, - span: Span) { +pub fn declare_local( + bx: &Builder<'a, 'll, 'tcx>, + dbg_context: &FunctionDebugContext<'ll>, + variable_name: ast::Name, + variable_type: Ty<'tcx>, + scope_metadata: &'ll DIScope, + variable_access: VariableAccess<'_, 'll>, + variable_kind: VariableKind, + span: Span, +) { assert!(!dbg_context.get_ref(span).source_locations_enabled.get()); let cx = bx.cx; @@ -495,7 +511,7 @@ pub fn declare_local<'a, 'tcx>(bx: &Builder<'a, 'tcx>, }; let align = cx.align_of(variable_type); - let name = CString::new(variable_name.as_str().as_bytes()).unwrap(); + let name = SmallCStr::new(&variable_name.as_str()); match (variable_access, &[][..]) { (DirectVariable { alloca }, address_operations) | (IndirectVariable {alloca, address_operations}, _) => { diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs index 51c45de9dc..06f8a4b131 100644 --- a/src/librustc_codegen_llvm/debuginfo/namespace.rs +++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs @@ -21,8 +21,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; use common::CodegenCx; -use std::ffi::CString; -use std::ptr; +use rustc_data_structures::small_c_str::SmallCStr; pub fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, @@ -32,13 +31,13 @@ pub fn mangled_name_of_instance<'a, 'tcx>( tcx.symbol_name(instance) } -pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope { +pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) { return scope; } let def_key = cx.tcx.def_key(def_id); - let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| { + let parent_scope = def_key.parent.map(|parent| { item_namespace(cx, DefId { krate: def_id.krate, index: parent @@ -50,7 +49,7 @@ pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope { data => data.as_interned_str().as_str() }; - let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); + let namespace_name = SmallCStr::new(&namespace_name); 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 958d09413e..c59b5e2b8f 100644 --- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs +++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs @@ -19,14 +19,16 @@ use llvm::debuginfo::DIScope; use builder::Builder; use libc::c_uint; -use std::ptr; use syntax_pos::{Span, Pos}; /// Sets the current debug location at the beginning of the span. /// /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). pub fn set_source_location( - debug_context: &FunctionDebugContext, bx: &Builder, scope: DIScope, span: Span + debug_context: &FunctionDebugContext<'ll>, + bx: &Builder<'_, 'll, '_>, + scope: Option<&'ll DIScope>, + span: Span, ) { let function_debug_context = match *debug_context { FunctionDebugContext::DebugInfoDisabled => return, @@ -38,9 +40,9 @@ pub fn set_source_location( }; let dbg_loc = if function_debug_context.source_locations_enabled.get() { - debug!("set_source_location: {}", bx.sess().codemap().span_to_string(span)); + debug!("set_source_location: {}", bx.sess().source_map().span_to_string(span)); let loc = span_start(bx.cx, span); - InternalDebugLocation::new(scope, loc.line, loc.col.to_usize()) + InternalDebugLocation::new(scope.unwrap(), loc.line, loc.col.to_usize()) } else { UnknownLocation }; @@ -53,7 +55,7 @@ pub fn set_source_location( /// they are disabled when beginning to codegen a new function. This functions /// switches source location emitting on and must therefore be called before the /// first real statement/expression of the function is codegened. -pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) { +pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext<'ll>) { match *dbg_context { FunctionDebugContext::RegularContext(ref data) => { data.source_locations_enabled.set(true) @@ -64,13 +66,13 @@ pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) { #[derive(Copy, Clone, PartialEq)] -pub enum InternalDebugLocation { - KnownLocation { scope: DIScope, line: usize, col: usize }, +pub enum InternalDebugLocation<'ll> { + KnownLocation { scope: &'ll DIScope, line: usize, col: usize }, UnknownLocation } -impl InternalDebugLocation { - pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation { +impl InternalDebugLocation<'ll> { + pub fn new(scope: &'ll DIScope, line: usize, col: usize) -> Self { KnownLocation { scope, line, @@ -79,7 +81,7 @@ impl InternalDebugLocation { } } -pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) { +pub fn set_debug_location(bx: &Builder<'_, 'll, '_>, debug_location: InternalDebugLocation<'ll>) { let metadata_node = match debug_location { KnownLocation { scope, line, col } => { // For MSVC, set the column number to zero. @@ -93,17 +95,17 @@ pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) { debug!("setting debug location to {} {}", line, col); unsafe { - llvm::LLVMRustDIBuilderCreateDebugLocation( + Some(llvm::LLVMRustDIBuilderCreateDebugLocation( debug_context(bx.cx).llcontext, line as c_uint, col_used, scope, - ptr::null_mut()) + None)) } } UnknownLocation => { debug!("clearing debug location "); - ptr::null_mut() + None } }; diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index 05a74db3a6..f9eb80a198 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -41,19 +41,19 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let cpp_like_names = cx.sess().target.target.options.is_like_msvc; match t.sty { - ty::TyBool => output.push_str("bool"), - ty::TyChar => output.push_str("char"), - ty::TyStr => output.push_str("str"), - ty::TyNever => output.push_str("!"), - ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()), - ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()), - ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()), - ty::TyForeign(def_id) => push_item_name(cx, def_id, qualified, output), - ty::TyAdt(def, substs) => { + ty::Bool => output.push_str("bool"), + 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::Foreign(def_id) => push_item_name(cx, def_id, qualified, output), + ty::Adt(def, substs) => { push_item_name(cx, def.did, qualified, output); push_type_params(cx, substs, output); }, - ty::TyTuple(component_types) => { + ty::Tuple(component_types) => { output.push('('); for &component_type in component_types { push_debuginfo_type_name(cx, component_type, true, output); @@ -65,7 +65,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } output.push(')'); }, - ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { + ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { if !cpp_like_names { output.push('*'); } @@ -80,7 +80,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, output.push('*'); } }, - ty::TyRef(_, inner_type, mutbl) => { + ty::Ref(_, inner_type, mutbl) => { if !cpp_like_names { output.push('&'); } @@ -94,13 +94,13 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, output.push('*'); } }, - ty::TyArray(inner_type, len) => { + ty::Array(inner_type, len) => { output.push('['); push_debuginfo_type_name(cx, inner_type, true, output); output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx))); output.push(']'); }, - ty::TySlice(inner_type) => { + ty::Slice(inner_type) => { if cpp_like_names { output.push_str("slice<"); } else { @@ -115,7 +115,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, output.push(']'); } }, - ty::TyDynamic(ref trait_data, ..) => { + ty::Dynamic(ref trait_data, ..) => { if let Some(principal) = trait_data.principal() { let principal = cx.tcx.normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), @@ -125,7 +125,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, push_type_params(cx, principal.substs, output); } }, - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { let sig = t.fn_sig(cx.tcx); if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); @@ -160,23 +160,23 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, output.push(')'); - if !sig.output().is_nil() { + if !sig.output().is_unit() { output.push_str(" -> "); push_debuginfo_type_name(cx, sig.output(), true, output); } }, - ty::TyClosure(..) => { + ty::Closure(..) => { output.push_str("closure"); } - ty::TyGenerator(..) => { + ty::Generator(..) => { output.push_str("generator"); } - ty::TyError | - ty::TyInfer(_) | - ty::TyProjection(..) | - ty::TyAnon(..) | - ty::TyGeneratorWitness(..) | - ty::TyParam(_) => { + ty::Error | + ty::Infer(_) | + ty::Projection(..) | + ty::Opaque(..) | + ty::GeneratorWitness(..) | + ty::Param(_) => { bug!("debuginfo: Trying to create type name for \ unexpected type: {:?}", t); } diff --git a/src/librustc_codegen_llvm/debuginfo/utils.rs b/src/librustc_codegen_llvm/debuginfo/utils.rs index 9d37f99cb2..19bc4ac39d 100644 --- a/src/librustc_codegen_llvm/debuginfo/utils.rs +++ b/src/librustc_codegen_llvm/debuginfo/utils.rs @@ -17,7 +17,7 @@ use rustc::hir::def_id::DefId; use rustc::ty::DefIdTree; use llvm; -use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray}; +use llvm::debuginfo::{DIScope, DIBuilder, DIDescriptor, DIArray}; use common::{CodegenCx}; use syntax_pos::{self, Span}; @@ -36,7 +36,10 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool } #[allow(non_snake_case)] -pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { +pub fn create_DIArray( + builder: &DIBuilder<'ll>, + arr: &[Option<&'ll DIDescriptor>], +) -> &'ll DIArray { return unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) }; @@ -44,22 +47,21 @@ pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { /// Return syntax_pos::Loc corresponding to the beginning of the span pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc { - cx.sess().codemap().lookup_char_pos(span.lo()) + cx.sess().source_map().lookup_char_pos(span.lo()) } #[inline] -pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>) - -> &'a CrateDebugContext<'tcx> { +pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> { cx.dbg_cx.as_ref().unwrap() } #[inline] #[allow(non_snake_case)] -pub fn DIB(cx: &CodegenCx) -> DIBuilderRef { +pub fn DIB(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { cx.dbg_cx.as_ref().unwrap().builder } -pub fn get_namespace_for_item(cx: &CodegenCx, def_id: DefId) -> DIScope { +pub fn get_namespace_for_item(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { item_namespace(cx, cx.tcx.parent(def_id) .expect("get_namespace_for_item: missing parent?")) } diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index fdc84f914f..5e743ac51b 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -16,15 +16,16 @@ //! Some useful guidelines: //! //! * Use declare_* family of methods if you are declaring, but are not -//! interested in defining the ValueRef they return. -//! * Use define_* family of methods when you might be defining the ValueRef. +//! interested in defining the Value they return. +//! * Use define_* family of methods when you might be defining the Value. //! * When in doubt, define. -use llvm::{self, ValueRef}; +use llvm; use llvm::AttributePlace::Function; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, LayoutOf}; use rustc::session::config::Sanitizer; +use rustc_data_structures::small_c_str::SmallCStr; use rustc_target::spec::PanicStrategy; use abi::{Abi, FnType, FnTypeExt}; use attributes; @@ -33,20 +34,16 @@ use common; use type_::Type; use value::Value; -use std::ffi::CString; - /// Declare a global value. /// /// If there’s a value with the same name already declared, the function will -/// return its ValueRef instead. -pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef { +/// return its Value instead. +pub fn declare_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> &'ll Value { debug!("declare_global(name={:?})", name); - let namebuf = CString::new(name).unwrap_or_else(|_|{ - bug!("name {:?} contains an interior null byte", name) - }); + let namebuf = SmallCStr::new(name); unsafe { - llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty.to_ref()) + llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty) } } @@ -54,14 +51,17 @@ pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef { /// Declare a function. /// /// If there’s a value with the same name already declared, the function will -/// update the declaration and return existing ValueRef instead. -fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef { +/// update the declaration and return existing Value instead. +fn declare_raw_fn( + cx: &CodegenCx<'ll, '_>, + name: &str, + callconv: llvm::CallConv, + ty: &'ll Type, +) -> &'ll Value { debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); - let namebuf = CString::new(name).unwrap_or_else(|_|{ - bug!("name {:?} contains an interior null byte", name) - }); + let namebuf = SmallCStr::new(name); let llfn = unsafe { - llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty.to_ref()) + llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty) }; llvm::SetFunctionCallConv(llfn, callconv); @@ -114,8 +114,8 @@ fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type /// `declare_fn` instead. /// /// If there’s a value with the same name already declared, the function will -/// update the declaration and return existing ValueRef instead. -pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef { +/// update the declaration and return existing Value instead. +pub fn declare_cfn(cx: &CodegenCx<'ll, '_>, name: &str, fn_type: &'ll Type) -> &'ll Value { declare_raw_fn(cx, name, llvm::CCallConv, fn_type) } @@ -123,9 +123,12 @@ pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef { /// Declare a Rust function. /// /// If there’s a value with the same name already declared, the function will -/// update the declaration and return existing ValueRef instead. -pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str, - fn_type: Ty<'tcx>) -> ValueRef { +/// update the declaration and return existing Value instead. +pub fn declare_fn( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + fn_type: Ty<'tcx>, +) -> &'ll Value { debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type); let sig = common::ty_fn_sig(cx, fn_type); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); @@ -154,7 +157,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str, /// return None if the name already has a definition associated with it. In that /// case an error should be reported to the user, because it usually happens due /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). -pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option { +pub fn define_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> Option<&'ll Value> { if get_defined_value(cx, name).is_some() { None } else { @@ -162,14 +165,25 @@ pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option { } } +/// Declare a private global +/// +/// Use this function when you intend to define a global without a name. +pub fn define_private_global(cx: &CodegenCx<'ll, '_>, ty: &'ll Type) -> &'ll Value { + unsafe { + llvm::LLVMRustInsertPrivateGlobal(cx.llmod, ty) + } +} + /// 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. -pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - name: &str, - fn_type: Ty<'tcx>) -> ValueRef { +pub fn define_fn( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + fn_type: Ty<'tcx>, +) -> &'ll Value { if get_defined_value(cx, name).is_some() { cx.sess().fatal(&format!("symbol `{}` already defined", name)) } else { @@ -182,9 +196,11 @@ pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// 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. -pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - name: &str, - fn_type: Ty<'tcx>) -> ValueRef { +pub fn define_internal_fn( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + fn_type: Ty<'tcx>, +) -> &'ll Value { let llfn = define_fn(cx, name, fn_type); unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; llfn @@ -192,24 +208,15 @@ pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// Get declared value by name. -pub fn get_declared_value(cx: &CodegenCx, name: &str) -> Option { +pub fn get_declared_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> { debug!("get_declared_value(name={:?})", name); - let namebuf = CString::new(name).unwrap_or_else(|_|{ - bug!("name {:?} contains an interior null byte", name) - }); - let val = unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) }; - if val.is_null() { - debug!("get_declared_value: {:?} value is null", name); - None - } else { - debug!("get_declared_value: {:?} => {:?}", name, Value(val)); - Some(val) - } + let namebuf = SmallCStr::new(name); + unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) } } /// Get defined or externally defined (AvailableExternally linkage) value by /// name. -pub fn get_defined_value(cx: &CodegenCx, name: &str) -> Option { +pub fn get_defined_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> { get_declared_value(cx, name).and_then(|val|{ let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 diff --git a/src/librustc_codegen_llvm/glue.rs b/src/librustc_codegen_llvm/glue.rs index c7275d0940..ff33cec043 100644 --- a/src/librustc_codegen_llvm/glue.rs +++ b/src/librustc_codegen_llvm/glue.rs @@ -16,37 +16,36 @@ use std; use builder::Builder; use common::*; -use llvm::{ValueRef}; use llvm; use meth; use rustc::ty::layout::LayoutOf; use rustc::ty::{self, Ty}; use value::Value; -pub fn size_and_align_of_dst<'a, 'tcx>(bx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef) - -> (ValueRef, ValueRef) { +pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Option<&'ll Value>) + -> (&'ll Value, &'ll Value) { debug!("calculate size of DST: {}; with lost info: {:?}", - t, Value(info)); + t, info); if bx.cx.type_is_sized(t) { let (size, align) = bx.cx.size_and_align_of(t); debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}", - t, Value(info), size, align); + t, info, size, align); let size = C_usize(bx.cx, size.bytes()); let align = C_usize(bx.cx, align.abi()); return (size, align); } - assert!(!info.is_null()); match t.sty { - ty::TyDynamic(..) => { + ty::Dynamic(..) => { // load size/align from vtable - (meth::SIZE.get_usize(bx, info), meth::ALIGN.get_usize(bx, info)) + let vtable = info.unwrap(); + (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable)) } - ty::TySlice(_) | ty::TyStr => { + ty::Slice(_) | ty::Str => { let unit = t.sequence_element_type(bx.tcx()); // The info in this case is the length of the str, so the size is that // times the unit size. let (size, align) = bx.cx.size_and_align_of(unit); - (bx.mul(info, C_usize(bx.cx, size.bytes())), + (bx.mul(info.unwrap(), C_usize(bx.cx, size.bytes())), C_usize(bx.cx, align.abi())) } _ => { @@ -82,7 +81,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info let size = bx.add(sized_size, unsized_size); // Packed types ignore the alignment of their fields. - if let ty::TyAdt(def, _) = t.sty { + if let ty::Adt(def, _) = t.sty { if def.repr.packed() { unsized_align = sized_align; } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 9c5c0f730c..5ec934ebd0 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -10,9 +10,9 @@ #![allow(non_upper_case_globals)] +use attributes; use intrinsics::{self, Intrinsic}; -use llvm; -use llvm::{ValueRef}; +use llvm::{self, TypeKind}; use abi::{Abi, FnType, LlvmType, PassMode}; use mir::place::PlaceRef; use mir::operand::{OperandRef, OperandValue}; @@ -28,6 +28,7 @@ use rustc::hir; use syntax::ast; use syntax::symbol::Symbol; use builder::Builder; +use value::Value; use rustc::session::Session; use syntax_pos::Span; @@ -35,7 +36,7 @@ use syntax_pos::Span; use std::cmp::Ordering; use std::iter; -fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option { +fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> { let llvm_name = match name { "sqrtf32" => "llvm.sqrt.f32", "sqrtf64" => "llvm.sqrt.f64", @@ -85,17 +86,19 @@ fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option { /// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs, /// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics, /// add them to librustc_codegen_llvm/context.rs -pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - callee_ty: Ty<'tcx>, - fn_ty: &FnType<'tcx, Ty<'tcx>>, - args: &[OperandRef<'tcx>], - llresult: ValueRef, - span: Span) { +pub fn codegen_intrinsic_call( + bx: &Builder<'a, 'll, 'tcx>, + callee_ty: Ty<'tcx>, + fn_ty: &FnType<'tcx, Ty<'tcx>>, + args: &[OperandRef<'ll, 'tcx>], + llresult: &'ll Value, + span: Span, +) { let cx = bx.cx; let tcx = cx.tcx; let (def_id, substs) = match callee_ty.sty { - ty::TyFnDef(def_id, substs) => (def_id, substs), + ty::FnDef(def_id, substs) => (def_id, substs), _ => bug!("expected fn item type, found {}", callee_ty) }; @@ -146,7 +149,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, let tp_ty = substs.type_at(0); if let OperandValue::Pair(_, meta) = args[0].val { let (llsize, _) = - glue::size_and_align_of_dst(bx, tp_ty, meta); + glue::size_and_align_of_dst(bx, tp_ty, Some(meta)); llsize } else { C_usize(cx, cx.size_of(tp_ty).bytes()) @@ -160,7 +163,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, let tp_ty = substs.type_at(0); if let OperandValue::Pair(_, meta) = args[0].val { let (_, llalign) = - glue::size_and_align_of_dst(bx, tp_ty, meta); + glue::size_and_align_of_dst(bx, tp_ty, Some(meta)); llalign } else { C_usize(cx, cx.align_of(tp_ty).abi()) @@ -545,7 +548,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, assert_eq!(x.len(), 1); x.into_iter().next().unwrap() } - fn ty_to_type(cx: &CodegenCx, t: &intrinsics::Type) -> Vec { + fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> { use intrinsics::Type::*; match *t { Void => vec![Type::void(cx)], @@ -567,7 +570,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, Vector(ref t, ref llvm_elem, length) => { let t = llvm_elem.as_ref().unwrap_or(t); let elem = one(ty_to_type(cx, t)); - vec![Type::vector(&elem, length as u64)] + vec![Type::vector(elem, length as u64)] } Aggregate(false, ref contents) => { let elems = contents.iter() @@ -587,11 +590,11 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // qux` to be converted into `foo, bar, baz, qux`, integer // arguments to be truncated as needed and pointers to be // cast. - fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - t: &intrinsics::Type, - arg: &OperandRef<'tcx>) - -> Vec - { + fn modify_as_needed( + bx: &Builder<'a, 'll, 'tcx>, + t: &intrinsics::Type, + arg: &OperandRef<'ll, 'tcx>, + ) -> Vec<&'ll Value> { match *t { intrinsics::Type::Aggregate(true, ref contents) => { // We found a tuple that needs squishing! So @@ -602,7 +605,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // etc. assert!(!bx.cx.type_needs_drop(arg.layout.ty)); let (ptr, align) = match arg.val { - OperandValue::Ref(ptr, align) => (ptr, align), + OperandValue::Ref(ptr, None, align) => (ptr, align), _ => bug!() }; let arg = PlaceRef::new_sized(ptr, arg.layout, align); @@ -616,7 +619,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, } intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => { let llvm_elem = one(ty_to_type(bx.cx, llvm_elem)); - vec![bx.bitcast(arg.immediate(), Type::vector(&llvm_elem, length as u64))] + vec![bx.bitcast(arg.immediate(), Type::vector(llvm_elem, length as u64))] } intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => { // the LLVM intrinsic uses a smaller integer @@ -644,7 +647,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, intrinsics::IntrinsicDef::Named(name) => { let f = declare::declare_cfn(cx, name, - Type::func(&inputs, &outputs)); + Type::func(&inputs, outputs)); bx.call(f, &llargs, None) } }; @@ -677,14 +680,15 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, } } -fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - allow_overlap: bool, - volatile: bool, - ty: Ty<'tcx>, - dst: ValueRef, - src: ValueRef, - count: ValueRef) - -> ValueRef { +fn copy_intrinsic( + bx: &Builder<'a, 'll, 'tcx>, + allow_overlap: bool, + volatile: bool, + ty: Ty<'tcx>, + dst: &'ll Value, + src: &'ll Value, + count: &'ll Value, +) -> &'ll Value { let cx = bx.cx; let (size, align) = cx.size_and_align_of(ty); let size = C_usize(cx, size.bytes()); @@ -712,14 +716,14 @@ fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>, None) } -fn memset_intrinsic<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, +fn memset_intrinsic( + bx: &Builder<'a, 'll, 'tcx>, volatile: bool, ty: Ty<'tcx>, - dst: ValueRef, - val: ValueRef, - count: ValueRef -) -> ValueRef { + dst: &'ll Value, + val: &'ll Value, + count: &'ll Value +) -> &'ll Value { let cx = bx.cx; let (size, align) = cx.size_and_align_of(ty); let size = C_usize(cx, size.bytes()); @@ -728,13 +732,13 @@ fn memset_intrinsic<'a, 'tcx>( call_memset(bx, dst, val, bx.mul(size, count), align, volatile) } -fn try_intrinsic<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - cx: &CodegenCx, - func: ValueRef, - data: ValueRef, - local_ptr: ValueRef, - dest: ValueRef, +fn try_intrinsic( + bx: &Builder<'a, 'll, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, + func: &'ll Value, + data: &'ll Value, + local_ptr: &'ll Value, + dest: &'ll Value, ) { if bx.sess().no_landing_pads() { bx.call(func, &[data], None); @@ -754,12 +758,14 @@ fn try_intrinsic<'a, 'tcx>( // instructions are meant to work for all targets, as of the time of this // writing, however, LLVM does not recommend the usage of these new instructions // as the old ones are still more optimized. -fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - cx: &CodegenCx, - func: ValueRef, - data: ValueRef, - local_ptr: ValueRef, - dest: ValueRef) { +fn codegen_msvc_try( + bx: &Builder<'a, 'll, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, + func: &'ll Value, + data: &'ll Value, + local_ptr: &'ll Value, + dest: &'ll Value, +) { let llfn = get_rust_try_fn(cx, &mut |bx| { let cx = bx.cx; @@ -862,12 +868,14 @@ fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // function calling it, and that function may already have other personality // functions in play. By calling a shim we're guaranteed that our shim will have // the right personality function. -fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - cx: &CodegenCx, - func: ValueRef, - data: ValueRef, - local_ptr: ValueRef, - dest: ValueRef) { +fn codegen_gnu_try( + bx: &Builder<'a, 'll, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, + func: &'ll Value, + data: &'ll Value, + local_ptr: &'ll Value, + dest: &'ll Value, +) { let llfn = get_rust_try_fn(cx, &mut |bx| { let cx = bx.cx; @@ -922,12 +930,13 @@ fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // Helper function to give a Block to a closure to codegen a shim function. // This is currently primarily used for the `try` intrinsic functions above. -fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - name: &str, - inputs: Vec>, - output: Ty<'tcx>, - codegen: &mut dyn for<'b> FnMut(Builder<'b, 'tcx>)) - -> ValueRef { +fn gen_fn<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + inputs: Vec>, + output: Ty<'tcx>, + codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), +) -> &'ll Value { let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig( inputs.into_iter(), output, @@ -936,6 +945,7 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, Abi::Rust ))); let llfn = declare::define_internal_fn(cx, name, rust_fn_ty); + attributes::from_fn_attrs(cx, llfn, None); let bx = Builder::new_block(cx, llfn, "entry-block"); codegen(bx); llfn @@ -945,9 +955,10 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // catch exceptions. // // This function is only generated once and is then cached. -fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - codegen: &mut dyn for<'b> FnMut(Builder<'b, 'tcx>)) - -> ValueRef { +fn get_rust_try_fn<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), +) -> &'ll Value { if let Some(llfn) = cx.rust_try_fn.get() { return llfn; } @@ -957,7 +968,7 @@ fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let i8p = tcx.mk_mut_ptr(tcx.types.i8); let fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( iter::once(i8p), - tcx.mk_nil(), + tcx.mk_unit(), false, hir::Unsafety::Unsafe, Abi::Rust @@ -972,15 +983,15 @@ fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { span_err!(a, b, E0511, "{}", c); } -fn generic_simd_intrinsic<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, +fn generic_simd_intrinsic( + bx: &Builder<'a, 'll, 'tcx>, name: &str, callee_ty: Ty<'tcx>, - args: &[OperandRef<'tcx>], + args: &[OperandRef<'ll, 'tcx>], ret_ty: Ty<'tcx>, - llret_ty: Type, + llret_ty: &'ll Type, span: Span -) -> Result { +) -> Result<&'ll Value, ()> { // macros for error handling: macro_rules! emit_error { ($msg: tt) => { @@ -1050,7 +1061,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( found `{}` with length {}", in_len, in_ty, ret_ty, out_len); - require!(llret_ty.element_type().kind() == llvm::Integer, + require!(llret_ty.element_type().kind() == TypeKind::Integer, "expected return type with integer elements, found `{}` with non-integer `{}`", ret_ty, ret_ty.simd_type(tcx)); @@ -1138,26 +1149,27 @@ fn generic_simd_intrinsic<'a, 'tcx>( m_len, v_len ); match m_elem_ty.sty { - ty::TyInt(_) => {}, + ty::Int(_) => {}, _ => { return_error!("mask element type is `{}`, expected `i_`", m_elem_ty); } } // truncate the mask to a vector of i1s let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, m_len as u64); + let i1xn = Type::vector(i1, m_len as u64); let m_i1s = bx.trunc(args[0].immediate(), i1xn); return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } - fn simd_simple_float_intrinsic<'a, 'tcx>(name: &str, - in_elem: &::rustc::ty::TyS, - in_ty: &::rustc::ty::TyS, - in_len: usize, - bx: &Builder<'a, 'tcx>, - span: Span, - args: &[OperandRef<'tcx>]) - -> Result { + fn simd_simple_float_intrinsic( + name: &str, + in_elem: &::rustc::ty::TyS, + in_ty: &::rustc::ty::TyS, + in_len: usize, + bx: &Builder<'a, 'll, 'tcx>, + span: Span, + args: &[OperandRef<'ll, 'tcx>], + ) -> Result<&'ll Value, ()> { macro_rules! emit_error { ($msg: tt) => { emit_error!($msg, ) @@ -1179,7 +1191,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( } } let ety = match in_elem.sty { - ty::TyFloat(f) if f.bit_width() == 32 => { + ty::Float(f) if f.bit_width() == 32 => { if in_len < 2 || in_len > 16 { return_error!( "unsupported floating-point vector `{}` with length `{}` \ @@ -1188,7 +1200,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( } "f32" }, - ty::TyFloat(f) if f.bit_width() == 64 => { + ty::Float(f) if f.bit_width() == 64 => { if in_len < 2 || in_len > 8 { return_error!("unsupported floating-point vector `{}` with length `{}` \ out-of-range [2, 8]", @@ -1196,7 +1208,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( } "f64" }, - ty::TyFloat(f) => { + ty::Float(f) => { return_error!("unsupported element type `{}` of floating-point vector `{}`", f, in_ty); }, @@ -1276,27 +1288,27 @@ fn generic_simd_intrinsic<'a, 'tcx>( fn llvm_vector_str(elem_ty: ty::Ty, vec_len: usize, no_pointers: usize) -> String { let p0s: String = "p0".repeat(no_pointers); match elem_ty.sty { - ty::TyInt(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), - ty::TyUint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), - ty::TyFloat(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()), + ty::Int(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), + ty::Uint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), + ty::Float(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()), _ => unreachable!(), } } - fn llvm_vector_ty(cx: &CodegenCx, elem_ty: ty::Ty, vec_len: usize, - mut no_pointers: usize) -> Type { + fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize, + mut no_pointers: usize) -> &'ll Type { // FIXME: use cx.layout_of(ty).llvm_type() ? let mut elem_ty = match elem_ty.sty { - ty::TyInt(v) => Type::int_from_ty(cx, v), - ty::TyUint(v) => Type::uint_from_ty(cx, v), - ty::TyFloat(v) => Type::float_from_ty(cx, v), + ty::Int(v) => Type::int_from_ty(cx, v), + ty::Uint(v) => Type::uint_from_ty(cx, v), + ty::Float(v) => Type::float_from_ty(cx, v), _ => unreachable!(), }; while no_pointers > 0 { elem_ty = elem_ty.ptr_to(); no_pointers -= 1; } - Type::vector(&elem_ty, vec_len as u64) + Type::vector(elem_ty, vec_len as u64) } @@ -1331,7 +1343,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // This counts how many pointers fn ptr_count(t: ty::Ty) -> usize { match t.sty { - ty::TyRawPtr(p) => 1 + ptr_count(p.ty), + ty::RawPtr(p) => 1 + ptr_count(p.ty), _ => 0, } } @@ -1339,7 +1351,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // Non-ptr type fn non_ptr(t: ty::Ty) -> ty::Ty { match t.sty { - ty::TyRawPtr(p) => non_ptr(p.ty), + ty::RawPtr(p) => non_ptr(p.ty), _ => t, } } @@ -1347,7 +1359,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // 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).sty { - ty::TyRawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)), + ty::RawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx))), _ => { require!(false, "expected element type `{}` of second argument `{}` \ @@ -1364,7 +1376,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // The element type of the third argument must be a signed integer type of any width: match arg_tys[2].simd_type(tcx).sty { - ty::TyInt(_) => (), + ty::Int(_) => (), _ => { require!(false, "expected element type `{}` of third argument `{}` \ to be a signed integer type", @@ -1379,7 +1391,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, in_len as u64); + let i1xn = Type::vector(i1, in_len as u64); (bx.trunc(args[2].immediate(), i1xn), i1xn) }; @@ -1395,7 +1407,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( llvm_elem_vec_str, llvm_pointer_vec_str); let f = declare::declare_cfn(bx.cx, &llvm_intrinsic, Type::func(&[llvm_pointer_vec_ty, alignment_ty, mask_ty, - llvm_elem_vec_ty], &llvm_elem_vec_ty)); + llvm_elem_vec_ty], llvm_elem_vec_ty)); llvm::SetUnnamedAddr(f, false); let v = bx.call(f, &[args[1].immediate(), alignment, mask, args[0].immediate()], None); @@ -1427,7 +1439,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // This counts how many pointers fn ptr_count(t: ty::Ty) -> usize { match t.sty { - ty::TyRawPtr(p) => 1 + ptr_count(p.ty), + ty::RawPtr(p) => 1 + ptr_count(p.ty), _ => 0, } } @@ -1435,7 +1447,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // Non-ptr type fn non_ptr(t: ty::Ty) -> ty::Ty { match t.sty { - ty::TyRawPtr(p) => non_ptr(p.ty), + ty::RawPtr(p) => non_ptr(p.ty), _ => t, } } @@ -1443,7 +1455,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // 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).sty { - ty::TyRawPtr(p) if p.ty == in_elem && p.mutbl == hir::MutMutable + ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::MutMutable => (ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx))), _ => { @@ -1461,7 +1473,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // The element type of the third argument must be a signed integer type of any width: match arg_tys[2].simd_type(tcx).sty { - ty::TyInt(_) => (), + ty::Int(_) => (), _ => { require!(false, "expected element type `{}` of third argument `{}` \ to be a signed integer type", @@ -1476,7 +1488,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, in_len as u64); + let i1xn = Type::vector(i1, in_len as u64); (bx.trunc(args[2].immediate(), i1xn), i1xn) }; @@ -1496,7 +1508,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( Type::func(&[llvm_elem_vec_ty, llvm_pointer_vec_ty, alignment_ty, - mask_ty], &ret_t)); + mask_ty], ret_t)); llvm::SetUnnamedAddr(f, false); let v = bx.call(f, &[args[0].immediate(), args[1].immediate(), alignment, mask], None); @@ -1510,7 +1522,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( "expected return type `{}` (element of input `{}`), found `{}`", in_elem, in_ty, ret_ty); return match in_elem.sty { - ty::TyInt(_) | ty::TyUint(_) => { + ty::Int(_) | ty::Uint(_) => { let r = bx.$integer_reduce(args[0].immediate()); if $ordered { // if overflow occurs, the result is the @@ -1524,7 +1536,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( Ok(bx.$integer_reduce(args[0].immediate())) } }, - ty::TyFloat(f) => { + ty::Float(f) => { // ordered arithmetic reductions take an accumulator let acc = if $ordered { let acc = args[1].immediate(); @@ -1585,13 +1597,13 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, "expected return type `{}` (element of input `{}`), found `{}`", in_elem, in_ty, ret_ty); return match in_elem.sty { - ty::TyInt(_i) => { + ty::Int(_i) => { Ok(bx.$int_red(args[0].immediate(), true)) }, - ty::TyUint(_u) => { + ty::Uint(_u) => { Ok(bx.$int_red(args[0].immediate(), false)) }, - ty::TyFloat(_f) => { + ty::Float(_f) => { Ok(bx.$float_red(args[0].immediate())) } _ => { @@ -1620,7 +1632,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, args[0].immediate() } else { match in_elem.sty { - ty::TyInt(_) | ty::TyUint(_) => {}, + ty::Int(_) | ty::Uint(_) => {}, _ => { return_error!("unsupported {} from `{}` with element `{}` to `{}`", $name, in_ty, in_elem, ret_ty) @@ -1629,11 +1641,11 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, // boolean reductions operate on vectors of i1s: let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, in_len as u64); + let i1xn = Type::vector(i1, in_len as u64); bx.trunc(args[0].immediate(), i1xn) }; return match in_elem.sty { - ty::TyInt(_) | ty::TyUint(_) => { + ty::Int(_) | ty::Uint(_) => { let r = bx.$red(input); Ok( if !$boolean { @@ -1676,15 +1688,15 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let (in_style, in_width) = match in_elem.sty { // vectors of pointer-sized integers should've been // disallowed before here, so this unwrap is safe. - ty::TyInt(i) => (Style::Int(true), i.bit_width().unwrap()), - ty::TyUint(u) => (Style::Int(false), u.bit_width().unwrap()), - ty::TyFloat(f) => (Style::Float, f.bit_width()), + ty::Int(i) => (Style::Int(true), i.bit_width().unwrap()), + ty::Uint(u) => (Style::Int(false), u.bit_width().unwrap()), + ty::Float(f) => (Style::Float, f.bit_width()), _ => (Style::Unsupported, 0) }; let (out_style, out_width) = match out_elem.sty { - ty::TyInt(i) => (Style::Int(true), i.bit_width().unwrap()), - ty::TyUint(u) => (Style::Int(false), u.bit_width().unwrap()), - ty::TyFloat(f) => (Style::Float, f.bit_width()), + ty::Int(i) => (Style::Int(true), i.bit_width().unwrap()), + ty::Uint(u) => (Style::Int(false), u.bit_width().unwrap()), + ty::Float(f) => (Style::Float, f.bit_width()), _ => (Style::Unsupported, 0) }; @@ -1745,18 +1757,18 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, } } arith! { - simd_add: TyUint, TyInt => add, TyFloat => fadd; - simd_sub: TyUint, TyInt => sub, TyFloat => fsub; - simd_mul: TyUint, TyInt => mul, TyFloat => fmul; - simd_div: TyUint => udiv, TyInt => sdiv, TyFloat => fdiv; - simd_rem: TyUint => urem, TyInt => srem, TyFloat => frem; - simd_shl: TyUint, TyInt => shl; - simd_shr: TyUint => lshr, TyInt => ashr; - simd_and: TyUint, TyInt => and; - simd_or: TyUint, TyInt => or; - simd_xor: TyUint, TyInt => xor; - simd_fmax: TyFloat => maxnum; - simd_fmin: TyFloat => minnum; + simd_add: Uint, Int => add, Float => fadd; + simd_sub: Uint, Int => sub, Float => fsub; + simd_mul: Uint, Int => mul, Float => fmul; + simd_div: Uint => udiv, Int => sdiv, Float => fdiv; + simd_rem: Uint => urem, Int => srem, Float => frem; + simd_shl: Uint, Int => shl; + simd_shr: Uint => lshr, Int => ashr; + simd_and: Uint, Int => and; + simd_or: Uint, Int => or; + simd_xor: Uint, Int => xor; + simd_fmax: Float => maxnum; + simd_fmin: Float => minnum; } span_bug!(span, "unknown SIMD intrinsic"); } @@ -1767,30 +1779,16 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, // stuffs. fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> { match ty.sty { - ty::TyInt(t) => Some((match t { - ast::IntTy::Isize => { - match &cx.tcx.sess.target.target.target_pointer_width[..] { - "16" => 16, - "32" => 32, - "64" => 64, - tws => bug!("Unsupported target word size for isize: {}", tws), - } - }, + ty::Int(t) => Some((match t { + ast::IntTy::Isize => cx.tcx.sess.target.isize_ty.bit_width().unwrap() as u64, ast::IntTy::I8 => 8, ast::IntTy::I16 => 16, ast::IntTy::I32 => 32, ast::IntTy::I64 => 64, ast::IntTy::I128 => 128, }, true)), - ty::TyUint(t) => Some((match t { - ast::UintTy::Usize => { - match &cx.tcx.sess.target.target.target_pointer_width[..] { - "16" => 16, - "32" => 32, - "64" => 64, - tws => bug!("Unsupported target word size for usize: {}", tws), - } - }, + ty::Uint(t) => Some((match t { + ast::UintTy::Usize => cx.tcx.sess.target.usize_ty.bit_width().unwrap() as u64, ast::UintTy::U8 => 8, ast::UintTy::U16 => 16, ast::UintTy::U32 => 32, @@ -1803,14 +1801,9 @@ fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> { // Returns the width of a float TypeVariant // Returns None if the type is not a float -fn float_type_width<'tcx>(sty: &ty::TypeVariants<'tcx>) - -> Option { - use rustc::ty::TyFloat; +fn float_type_width<'tcx>(sty: &ty::TyKind<'tcx>) -> Option { match *sty { - TyFloat(t) => Some(match t { - ast::FloatTy::F32 => 32, - ast::FloatTy::F64 => 64, - }), + ty::Float(t) => Some(t.bit_width() as u64), _ => None, } } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 90f96c9687..9cb233122c 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -20,16 +20,23 @@ #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(crate_visibility_modifier)] #![feature(custom_attribute)] -#![feature(fs_read_write)] +#![feature(extern_types)] +#![feature(in_band_lifetimes)] #![allow(unused_attributes)] #![feature(libc)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(quote)] #![feature(range_contains)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] #![feature(optin_builtin_traits)] +#![feature(concat_idents)] +#![feature(link_args)] +#![feature(static_nobundle)] +use back::write::create_target_machine; use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; @@ -46,9 +53,10 @@ extern crate rustc_target; #[macro_use] extern crate rustc_data_structures; extern crate rustc_demangle; extern crate rustc_incremental; -extern crate rustc_llvm as llvm; +extern crate rustc_llvm; extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_codegen_utils; +extern crate rustc_fs_util; #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -57,13 +65,13 @@ extern crate rustc_errors as errors; extern crate serialize; extern crate cc; // Used to locate MSVC extern crate tempfile; +extern crate memmap; use back::bytecode::RLIB_BYTECODE_EXTENSION; pub use llvm_util::target_features; - use std::any::Any; -use std::path::PathBuf; +use std::path::{PathBuf}; use std::sync::mpsc; use rustc_data_structures::sync::Lrc; @@ -77,8 +85,10 @@ use rustc::session::config::{OutputFilenames, OutputType, PrintRequest}; use rustc::ty::{self, TyCtxt}; use rustc::util::time_graph; use rustc::util::nodemap::{FxHashSet, FxHashMap}; +use rustc::util::profiling::ProfileCategory; use rustc_mir::monomorphize; use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_data_structures::svh::Svh; mod diagnostics; @@ -89,7 +99,7 @@ mod back { mod command; pub mod linker; pub mod link; - mod lto; + pub mod lto; pub mod symbol_export; pub mod write; mod rpath; @@ -110,6 +120,7 @@ mod debuginfo; mod declare; mod glue; mod intrinsic; +pub mod llvm; mod llvm_util; mod metadata; mod meth; @@ -232,14 +243,16 @@ impl CodegenBackend for LlvmCodegenBackend { // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. + sess.profiler(|p| p.start_activity(ProfileCategory::Linking)); time(sess, "linking", || { back::link::link_binary(sess, &ongoing_codegen, outputs, &ongoing_codegen.crate_name.as_str()); }); + sess.profiler(|p| p.end_activity(ProfileCategory::Linking)); // Now that we won't touch anything in the incremental compilation directory // any more, we can finalize it (which involves renaming it) - rustc_incremental::finalize_session_directory(sess, ongoing_codegen.link.crate_hash); + rustc_incremental::finalize_session_directory(sess, ongoing_codegen.crate_hash); Ok(()) } @@ -257,12 +270,17 @@ struct ModuleCodegen { /// unique amongst **all** crates. Therefore, it should contain /// something unique to this crate (e.g., a module path) as well /// as the crate name and disambiguator. + /// We currently generate these names via CodegenUnit::build_cgu_name(). name: String, - llmod_id: String, - source: ModuleSource, + module_llvm: ModuleLlvm, kind: ModuleKind, } +struct CachedModuleCodegen { + name: String, + source: WorkProduct, +} + #[derive(Copy, Clone, Debug, PartialEq)] enum ModuleKind { Regular, @@ -271,22 +289,11 @@ enum ModuleKind { } impl ModuleCodegen { - fn llvm(&self) -> Option<&ModuleLlvm> { - match self.source { - ModuleSource::Codegened(ref llvm) => Some(llvm), - ModuleSource::Preexisting(_) => None, - } - } - fn into_compiled_module(self, - emit_obj: bool, - emit_bc: bool, - emit_bc_compressed: bool, - outputs: &OutputFilenames) -> CompiledModule { - let pre_existing = match self.source { - ModuleSource::Preexisting(_) => true, - ModuleSource::Codegened(_) => false, - }; + emit_obj: bool, + 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 { @@ -305,10 +312,8 @@ impl ModuleCodegen { }; CompiledModule { - llmod_id: self.llmod_id, name: self.name.clone(), kind: self.kind, - pre_existing, object, bytecode, bytecode_compressed, @@ -319,38 +324,47 @@ impl ModuleCodegen { #[derive(Debug)] struct CompiledModule { name: String, - llmod_id: String, kind: ModuleKind, - pre_existing: bool, object: Option, bytecode: Option, bytecode_compressed: Option, } -enum ModuleSource { - /// Copy the `.o` files or whatever from the incr. comp. directory. - Preexisting(WorkProduct), - - /// Rebuild from this LLVM module. - Codegened(ModuleLlvm), -} - -#[derive(Debug)] struct ModuleLlvm { - llcx: llvm::ContextRef, - llmod: llvm::ModuleRef, - tm: llvm::TargetMachineRef, + llcx: &'static mut llvm::Context, + llmod_raw: *const llvm::Module, + tm: &'static mut llvm::TargetMachine, } unsafe impl Send for ModuleLlvm { } unsafe impl Sync for ModuleLlvm { } +impl ModuleLlvm { + fn new(sess: &Session, mod_name: &str) -> Self { + unsafe { + let llcx = llvm::LLVMRustContextCreate(sess.fewer_names()); + let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _; + + ModuleLlvm { + llmod_raw, + llcx, + tm: create_target_machine(sess, false), + } + } + } + + fn llmod(&self) -> &llvm::Module { + unsafe { + &*self.llmod_raw + } + } +} + impl Drop for ModuleLlvm { fn drop(&mut self) { unsafe { - llvm::LLVMDisposeModule(self.llmod); - llvm::LLVMContextDispose(self.llcx); - llvm::LLVMRustDisposeTargetMachine(self.tm); + llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); + llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _)); } } } @@ -360,7 +374,7 @@ struct CodegenResults { modules: Vec, allocator_module: Option, metadata_module: CompiledModule, - link: rustc::middle::cstore::LinkMeta, + crate_hash: Svh, metadata: rustc::middle::cstore::EncodedMetadata, windows_subsystem: Option, linker_info: back::linker::LinkerInfo, diff --git a/src/librustc_codegen_llvm/llvm/archive_ro.rs b/src/librustc_codegen_llvm/llvm/archive_ro.rs new file mode 100644 index 0000000000..4cbf0d92d7 --- /dev/null +++ b/src/librustc_codegen_llvm/llvm/archive_ro.rs @@ -0,0 +1,131 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A wrapper around LLVM's archive (.a) code + +use std::ffi::CString; +use std::path::Path; +use std::slice; +use std::str; + +pub struct ArchiveRO { + pub raw: &'static mut super::Archive, +} + +unsafe impl Send for ArchiveRO {} + +pub struct Iter<'a> { + raw: &'a mut super::ArchiveIterator<'a>, +} + +pub struct Child<'a> { + pub raw: &'a mut super::ArchiveChild<'a>, +} + +impl ArchiveRO { + /// Opens a static archive for read-only purposes. This is more optimized + /// than the `open` method because it uses LLVM's internal `Archive` class + /// rather than shelling out to `ar` for everything. + /// + /// If this archive is used with a mutable method, then an error will be + /// raised. + pub fn open(dst: &Path) -> Result { + return unsafe { + let s = path2cstr(dst); + let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { + super::last_error().unwrap_or("failed to open archive".to_string()) + })?; + Ok(ArchiveRO { raw: ar }) + }; + + #[cfg(unix)] + fn path2cstr(p: &Path) -> CString { + use std::os::unix::prelude::*; + use std::ffi::OsStr; + let p: &OsStr = p.as_ref(); + CString::new(p.as_bytes()).unwrap() + } + #[cfg(windows)] + fn path2cstr(p: &Path) -> CString { + CString::new(p.to_str().unwrap()).unwrap() + } + } + + pub fn iter(&self) -> Iter { + unsafe { + Iter { + raw: super::LLVMRustArchiveIteratorNew(self.raw), + } + } + } +} + +impl Drop for ArchiveRO { + fn drop(&mut self) { + unsafe { + super::LLVMRustDestroyArchive(&mut *(self.raw as *mut _)); + } + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = Result, String>; + + fn next(&mut self) -> Option, String>> { + unsafe { + match super::LLVMRustArchiveIteratorNext(self.raw) { + Some(raw) => Some(Ok(Child { raw })), + None => super::last_error().map(Err), + } + } + } +} + +impl<'a> Drop for Iter<'a> { + fn drop(&mut self) { + unsafe { + super::LLVMRustArchiveIteratorFree(&mut *(self.raw as *mut _)); + } + } +} + +impl<'a> Child<'a> { + pub fn name(&self) -> Option<&'a str> { + unsafe { + let mut name_len = 0; + let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len); + if name_ptr.is_null() { + None + } else { + let name = slice::from_raw_parts(name_ptr as *const u8, name_len as usize); + str::from_utf8(name).ok().map(|s| s.trim()) + } + } + } + + pub fn data(&self) -> &'a [u8] { + unsafe { + let mut data_len = 0; + let data_ptr = super::LLVMRustArchiveChildData(self.raw, &mut data_len); + if data_ptr.is_null() { + panic!("failed to read data from archive child"); + } + slice::from_raw_parts(data_ptr as *const u8, data_len as usize) + } + } +} + +impl<'a> Drop for Child<'a> { + fn drop(&mut self) { + unsafe { + super::LLVMRustArchiveChildFree(&mut *(self.raw as *mut _)); + } + } +} diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_codegen_llvm/llvm/diagnostic.rs similarity index 75% rename from src/librustc_llvm/diagnostic.rs rename to src/librustc_codegen_llvm/llvm/diagnostic.rs index e73c570ed8..c41a5f74ae 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_codegen_llvm/llvm/diagnostic.rs @@ -14,9 +14,9 @@ pub use self::OptimizationDiagnosticKind::*; pub use self::Diagnostic::*; use libc::c_uint; -use std::ptr; +use value::Value; -use {DiagnosticInfoRef, TwineRef, ValueRef}; +use super::{DiagnosticInfo, Twine}; #[derive(Copy, Clone)] pub enum OptimizationDiagnosticKind { @@ -42,21 +42,22 @@ impl OptimizationDiagnosticKind { } } -pub struct OptimizationDiagnostic { +pub struct OptimizationDiagnostic<'ll> { pub kind: OptimizationDiagnosticKind, pub pass_name: String, - pub function: ValueRef, + pub function: &'ll Value, pub line: c_uint, pub column: c_uint, pub filename: String, pub message: String, } -impl OptimizationDiagnostic { - unsafe fn unpack(kind: OptimizationDiagnosticKind, - di: DiagnosticInfoRef) - -> OptimizationDiagnostic { - let mut function = ptr::null_mut(); +impl OptimizationDiagnostic<'ll> { + unsafe fn unpack( + kind: OptimizationDiagnosticKind, + di: &'ll DiagnosticInfo, + ) -> Self { + let mut function = None; let mut line = 0; let mut column = 0; @@ -72,9 +73,9 @@ impl OptimizationDiagnostic { &mut column, filename, message) - ) - ) - ); + ).ok() + ).ok() + ).ok(); let mut filename = filename.unwrap_or(String::new()); if filename.is_empty() { @@ -84,7 +85,7 @@ impl OptimizationDiagnostic { OptimizationDiagnostic { kind, pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"), - function, + function: function.unwrap(), line, column, filename, @@ -94,41 +95,45 @@ impl OptimizationDiagnostic { } #[derive(Copy, Clone)] -pub struct InlineAsmDiagnostic { +pub struct InlineAsmDiagnostic<'ll> { pub cookie: c_uint, - pub message: TwineRef, - pub instruction: ValueRef, + pub message: &'ll Twine, + pub instruction: &'ll Value, } -impl InlineAsmDiagnostic { - unsafe fn unpack(di: DiagnosticInfoRef) -> InlineAsmDiagnostic { - - let mut opt = InlineAsmDiagnostic { - cookie: 0, - message: ptr::null_mut(), - instruction: ptr::null_mut(), - }; +impl InlineAsmDiagnostic<'ll> { + unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { + let mut cookie = 0; + let mut message = None; + let mut instruction = None; - super::LLVMRustUnpackInlineAsmDiagnostic(di, - &mut opt.cookie, - &mut opt.message, - &mut opt.instruction); + super::LLVMRustUnpackInlineAsmDiagnostic( + di, + &mut cookie, + &mut message, + &mut instruction, + ); - opt + InlineAsmDiagnostic { + cookie, + message: message.unwrap(), + instruction: instruction.unwrap(), + } } } -pub enum Diagnostic { - Optimization(OptimizationDiagnostic), - InlineAsm(InlineAsmDiagnostic), - PGO(DiagnosticInfoRef), +pub enum Diagnostic<'ll> { + Optimization(OptimizationDiagnostic<'ll>), + InlineAsm(InlineAsmDiagnostic<'ll>), + PGO(&'ll DiagnosticInfo), + Linker(&'ll DiagnosticInfo), /// LLVM has other types that we do not wrap here. - UnknownDiagnostic(DiagnosticInfoRef), + UnknownDiagnostic(&'ll DiagnosticInfo), } -impl Diagnostic { - pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic { +impl Diagnostic<'ll> { + pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { use super::DiagnosticKind as Dk; let kind = super::LLVMRustGetDiagInfoKind(di); @@ -164,6 +169,9 @@ impl Diagnostic { Dk::PGOProfile => { PGO(di) } + Dk::Linker => { + Linker(di) + } _ => UnknownDiagnostic(di), } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs new file mode 100644 index 0000000000..6c2601bf1e --- /dev/null +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -0,0 +1,1651 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression' +// once support for LLVM 3.9 is dropped. +// +// This method was changed in this LLVM patch: +// https://reviews.llvm.org/D26769 + +use super::debuginfo::{ + DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType, + DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable, + DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, + DINameSpace, DIFlags, +}; + +use libc::{c_uint, c_int, size_t, c_char}; +use libc::{c_ulonglong, c_void}; + +use std::marker::PhantomData; + +use super::RustString; + +pub type Bool = c_uint; + +pub const True: Bool = 1 as Bool; +pub const False: Bool = 0 as Bool; + +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +#[allow(dead_code)] // Variants constructed by C++. +pub enum LLVMRustResult { + Success, + Failure, +} +// Consts for the LLVM CallConv type, pre-cast to usize. + +/// LLVM CallingConv::ID. Should we wrap this? +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] +pub enum CallConv { + CCallConv = 0, + FastCallConv = 8, + ColdCallConv = 9, + X86StdcallCallConv = 64, + X86FastcallCallConv = 65, + ArmAapcsCallConv = 67, + Msp430Intr = 69, + X86_ThisCall = 70, + PtxKernel = 71, + X86_64_SysV = 78, + X86_64_Win64 = 79, + X86_VectorCall = 80, + X86_Intr = 83, + AmdGpuKernel = 91, +} + +/// LLVMRustLinkage +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[repr(C)] +pub enum Linkage { + ExternalLinkage = 0, + AvailableExternallyLinkage = 1, + LinkOnceAnyLinkage = 2, + LinkOnceODRLinkage = 3, + WeakAnyLinkage = 4, + WeakODRLinkage = 5, + AppendingLinkage = 6, + InternalLinkage = 7, + PrivateLinkage = 8, + ExternalWeakLinkage = 9, + CommonLinkage = 10, +} + +// LLVMRustVisibility +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[repr(C)] +pub enum Visibility { + Default = 0, + Hidden = 1, + Protected = 2, +} + +/// LLVMDLLStorageClass +#[derive(Copy, Clone)] +#[repr(C)] +pub enum DLLStorageClass { + #[allow(dead_code)] + Default = 0, + DllImport = 1, // Function to be imported from DLL. + #[allow(dead_code)] + DllExport = 2, // Function to be accessible from DLL. +} + +/// Matches LLVMRustAttribute in rustllvm.h +/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind, +/// though it is not ABI compatible (since it's a C++ enum) +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub enum Attribute { + AlwaysInline = 0, + ByVal = 1, + Cold = 2, + InlineHint = 3, + MinSize = 4, + Naked = 5, + NoAlias = 6, + NoCapture = 7, + NoInline = 8, + NonNull = 9, + NoRedZone = 10, + NoReturn = 11, + NoUnwind = 12, + OptimizeForSize = 13, + ReadOnly = 14, + SExt = 15, + StructRet = 16, + UWTable = 17, + ZExt = 18, + InReg = 19, + SanitizeThread = 20, + SanitizeAddress = 21, + SanitizeMemory = 22, +} + +/// LLVMIntPredicate +#[derive(Copy, Clone)] +#[repr(C)] +pub enum IntPredicate { + IntEQ = 32, + IntNE = 33, + IntUGT = 34, + IntUGE = 35, + IntULT = 36, + IntULE = 37, + IntSGT = 38, + IntSGE = 39, + IntSLT = 40, + IntSLE = 41, +} + +/// LLVMRealPredicate +#[derive(Copy, Clone)] +#[repr(C)] +pub enum RealPredicate { + RealPredicateFalse = 0, + RealOEQ = 1, + RealOGT = 2, + RealOGE = 3, + RealOLT = 4, + RealOLE = 5, + RealONE = 6, + RealORD = 7, + RealUNO = 8, + RealUEQ = 9, + RealUGT = 10, + RealUGE = 11, + RealULT = 12, + RealULE = 13, + RealUNE = 14, + RealPredicateTrue = 15, +} + +/// LLVMTypeKind +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] +pub enum TypeKind { + Void = 0, + Half = 1, + Float = 2, + Double = 3, + X86_FP80 = 4, + FP128 = 5, + PPC_FP128 = 6, + Label = 7, + Integer = 8, + Function = 9, + Struct = 10, + Array = 11, + Pointer = 12, + Vector = 13, + Metadata = 14, + X86_MMX = 15, + Token = 16, +} + +/// LLVMAtomicRmwBinOp +#[derive(Copy, Clone)] +#[repr(C)] +pub enum AtomicRmwBinOp { + AtomicXchg = 0, + AtomicAdd = 1, + AtomicSub = 2, + AtomicAnd = 3, + AtomicNand = 4, + AtomicOr = 5, + AtomicXor = 6, + AtomicMax = 7, + AtomicMin = 8, + AtomicUMax = 9, + AtomicUMin = 10, +} + +/// LLVMAtomicOrdering +#[derive(Copy, Clone)] +#[repr(C)] +pub enum AtomicOrdering { + #[allow(dead_code)] + NotAtomic = 0, + Unordered = 1, + Monotonic = 2, + // Consume = 3, // Not specified yet. + Acquire = 4, + Release = 5, + AcquireRelease = 6, + SequentiallyConsistent = 7, +} + +/// LLVMRustSynchronizationScope +#[derive(Copy, Clone)] +#[repr(C)] +pub enum SynchronizationScope { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + SingleThread, + CrossThread, +} + +/// LLVMRustFileType +#[derive(Copy, Clone)] +#[repr(C)] +pub enum FileType { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + AssemblyFile, + ObjectFile, +} + +/// LLVMMetadataType +#[derive(Copy, Clone)] +#[repr(C)] +pub enum MetadataType { + MD_dbg = 0, + MD_tbaa = 1, + MD_prof = 2, + MD_fpmath = 3, + MD_range = 4, + MD_tbaa_struct = 5, + MD_invariant_load = 6, + MD_alias_scope = 7, + MD_noalias = 8, + MD_nontemporal = 9, + MD_mem_parallel_loop_access = 10, + MD_nonnull = 11, +} + +/// LLVMRustAsmDialect +#[derive(Copy, Clone)] +#[repr(C)] +pub enum AsmDialect { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + Att, + Intel, +} + +/// LLVMRustCodeGenOptLevel +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +pub enum CodeGenOptLevel { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + None, + Less, + Default, + Aggressive, +} + +/// LLVMRelocMode +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +pub enum RelocMode { + Default, + Static, + PIC, + DynamicNoPic, + ROPI, + RWPI, + ROPI_RWPI, +} + +/// LLVMRustCodeModel +#[derive(Copy, Clone)] +#[repr(C)] +pub enum CodeModel { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + Small, + Kernel, + Medium, + Large, + None, +} + +/// LLVMRustDiagnosticKind +#[derive(Copy, Clone)] +#[repr(C)] +#[allow(dead_code)] // Variants constructed by C++. +pub enum DiagnosticKind { + Other, + InlineAsm, + StackSize, + DebugMetadataVersion, + SampleProfile, + OptimizationRemark, + OptimizationRemarkMissed, + OptimizationRemarkAnalysis, + OptimizationRemarkAnalysisFPCommute, + OptimizationRemarkAnalysisAliasing, + OptimizationRemarkOther, + OptimizationFailure, + PGOProfile, + Linker, +} + +/// LLVMRustArchiveKind +#[derive(Copy, Clone)] +#[repr(C)] +pub enum ArchiveKind { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + K_GNU, + K_BSD, + K_COFF, +} + +/// LLVMRustPassKind +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] +#[allow(dead_code)] // Variants constructed by C++. +pub enum PassKind { + Other, + Function, + Module, +} + +/// LLVMRustThinLTOData +extern { pub type ThinLTOData; } + +/// LLVMRustThinLTOBuffer +extern { pub type ThinLTOBuffer; } + +// LLVMRustModuleNameCallback +pub type ThinLTOModuleNameCallback = + unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char); + +/// LLVMRustThinLTOModule +#[repr(C)] +pub struct ThinLTOModule { + pub identifier: *const c_char, + pub data: *const u8, + pub len: usize, +} + +/// LLVMThreadLocalMode +#[derive(Copy, Clone)] +#[repr(C)] +pub enum ThreadLocalMode { + NotThreadLocal, + GeneralDynamic, + LocalDynamic, + InitialExec, + LocalExec +} + +extern { type Opaque; } +#[repr(C)] +struct InvariantOpaque<'a> { + _marker: PhantomData<&'a mut &'a ()>, + _opaque: Opaque, +} + +// Opaque pointer types +extern { pub type Module; } +extern { pub type Context; } +extern { pub type Type; } +extern { pub type Value; } +extern { pub type Metadata; } +extern { pub type BasicBlock; } +#[repr(C)] +pub struct Builder<'a>(InvariantOpaque<'a>); +extern { pub type MemoryBuffer; } +#[repr(C)] +pub struct PassManager<'a>(InvariantOpaque<'a>); +extern { pub type PassManagerBuilder; } +extern { pub type ObjectFile; } +#[repr(C)] +pub struct SectionIterator<'a>(InvariantOpaque<'a>); +extern { pub type Pass; } +extern { pub type TargetMachine; } +extern { pub type Archive; } +#[repr(C)] +pub struct ArchiveIterator<'a>(InvariantOpaque<'a>); +#[repr(C)] +pub struct ArchiveChild<'a>(InvariantOpaque<'a>); +extern { pub type Twine; } +extern { pub type DiagnosticInfo; } +extern { pub type SMDiagnostic; } +#[repr(C)] +pub struct RustArchiveMember<'a>(InvariantOpaque<'a>); +#[repr(C)] +pub struct OperandBundleDef<'a>(InvariantOpaque<'a>); +#[repr(C)] +pub struct Linker<'a>(InvariantOpaque<'a>); + +pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); +pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); + + +pub mod debuginfo { + use super::{InvariantOpaque, Metadata}; + + #[repr(C)] + pub struct DIBuilder<'a>(InvariantOpaque<'a>); + + pub type DIDescriptor = Metadata; + pub type DIScope = DIDescriptor; + pub type DIFile = DIScope; + pub type DILexicalBlock = DIScope; + pub type DISubprogram = DIScope; + pub type DINameSpace = DIScope; + pub type DIType = DIDescriptor; + pub type DIBasicType = DIType; + pub type DIDerivedType = DIType; + pub type DICompositeType = DIDerivedType; + pub type DIVariable = DIDescriptor; + pub type DIGlobalVariable = DIDescriptor; + pub type DIArray = DIDescriptor; + pub type DISubrange = DIDescriptor; + pub type DIEnumerator = DIDescriptor; + pub type DITemplateTypeParameter = DIDescriptor; + + // These values **must** match with LLVMRustDIFlags!! + bitflags! { + #[repr(C)] + #[derive(Default)] + pub struct DIFlags: ::libc::uint32_t { + const FlagZero = 0; + const FlagPrivate = 1; + const FlagProtected = 2; + const FlagPublic = 3; + const FlagFwdDecl = (1 << 2); + const FlagAppleBlock = (1 << 3); + const FlagBlockByrefStruct = (1 << 4); + const FlagVirtual = (1 << 5); + const FlagArtificial = (1 << 6); + const FlagExplicit = (1 << 7); + const FlagPrototyped = (1 << 8); + const FlagObjcClassComplete = (1 << 9); + const FlagObjectPointer = (1 << 10); + const FlagVector = (1 << 11); + const FlagStaticMember = (1 << 12); + const FlagLValueReference = (1 << 13); + const FlagRValueReference = (1 << 14); + const FlagExternalTypeRef = (1 << 15); + const FlagIntroducedVirtual = (1 << 18); + const FlagBitField = (1 << 19); + const FlagNoReturn = (1 << 20); + const FlagMainSubprogram = (1 << 21); + } + } +} + +extern { pub type ModuleBuffer; } + +extern "C" { + // Create and destroy contexts. + pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context; + pub fn LLVMContextDispose(C: &'static mut Context); + pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint; + + // Create modules. + pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: &Context) -> &Module; + pub fn LLVMGetModuleContext(M: &Module) -> &Context; + pub fn LLVMCloneModule(M: &Module) -> &Module; + + /// Data layout. See Module::getDataLayout. + pub fn LLVMGetDataLayout(M: &Module) -> *const c_char; + pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char); + + /// See Module::setModuleInlineAsm. + pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char); + pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char); + + /// See llvm::LLVMTypeKind::getTypeID. + pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind; + + // Operations on integer types + pub fn LLVMInt1TypeInContext(C: &Context) -> &Type; + pub fn LLVMInt8TypeInContext(C: &Context) -> &Type; + pub fn LLVMInt16TypeInContext(C: &Context) -> &Type; + pub fn LLVMInt32TypeInContext(C: &Context) -> &Type; + pub fn LLVMInt64TypeInContext(C: &Context) -> &Type; + pub fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> &Type; + + pub fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint; + + // Operations on real types + pub fn LLVMFloatTypeInContext(C: &Context) -> &Type; + pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type; + + // Operations on function types + pub fn LLVMFunctionType(ReturnType: &'a Type, + ParamTypes: *const &'a Type, + ParamCount: c_uint, + IsVarArg: Bool) + -> &'a Type; + pub fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint; + pub fn LLVMGetParamTypes(FunctionTy: &'a Type, Dest: *mut &'a Type); + + // Operations on struct types + pub fn LLVMStructTypeInContext(C: &'a Context, + ElementTypes: *const &'a Type, + ElementCount: c_uint, + Packed: Bool) + -> &'a Type; + + // Operations on array, pointer, and vector types (sequence types) + pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type; + pub fn LLVMPointerType(ElementType: &Type, AddressSpace: c_uint) -> &Type; + pub fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type; + + pub fn LLVMGetElementType(Ty: &Type) -> &Type; + pub fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint; + + // Operations on other types + pub fn LLVMVoidTypeInContext(C: &Context) -> &Type; + pub fn LLVMX86MMXTypeInContext(C: &Context) -> &Type; + pub fn LLVMRustMetadataTypeInContext(C: &Context) -> &Type; + + // 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 LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value); + pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value); + + // Operations on constants of any type + pub fn LLVMConstNull(Ty: &Type) -> &Value; + pub fn LLVMGetUndef(Ty: &Type) -> &Value; + + // Operations on metadata + pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value; + pub fn LLVMMDNodeInContext(C: &'a Context, Vals: *const &'a Value, Count: c_uint) -> &'a Value; + pub fn LLVMAddNamedMetadataOperand(M: &'a Module, Name: *const c_char, Val: &'a Value); + + // Operations on scalar constants + pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; + pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value; + pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong; + pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool, + high: &mut u64, low: &mut u64) -> bool; + pub fn LLVMConstRealGetDouble (ConstantVal: &Value, losesInfo: &mut Bool) -> f64; + + + // Operations on composite constants + pub fn LLVMConstStringInContext(C: &Context, + Str: *const c_char, + Length: c_uint, + DontNullTerminate: Bool) + -> &Value; + pub fn LLVMConstStructInContext(C: &'a Context, + ConstantVals: *const &'a Value, + Count: c_uint, + Packed: Bool) + -> &'a Value; + + pub fn LLVMConstArray(ElementTy: &'a Type, + ConstantVals: *const &'a Value, + Length: c_uint) + -> &'a Value; + pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; + + // Constant expressions + pub fn LLVMConstInBoundsGEP( + ConstantVal: &'a Value, + ConstantIndices: *const &'a Value, + NumIndices: c_uint, + ) -> &'a Value; + pub fn LLVMConstZExt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstPtrToInt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstIntToPtr(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstBitCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstPointerCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstExtractValue(AggConstant: &Value, + IdxList: *const c_uint, + NumIdx: c_uint) + -> &Value; + + // Operations on global variables, functions, and aliases (globals) + pub fn LLVMIsDeclaration(Global: &Value) -> Bool; + pub fn LLVMRustGetLinkage(Global: &Value) -> Linkage; + pub fn LLVMRustSetLinkage(Global: &Value, RustLinkage: Linkage); + pub fn LLVMSetSection(Global: &Value, Section: *const c_char); + pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility; + pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility); + pub fn LLVMGetAlignment(Global: &Value) -> c_uint; + pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint); + pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass); + + + // Operations on global variables + 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 LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value; + pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>; + pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>; + pub fn LLVMDeleteGlobal(GlobalVar: &Value); + pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>; + pub fn LLVMSetInitializer(GlobalVar: &'a Value, ConstantVal: &'a Value); + pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool); + pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode); + pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool; + pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool); + pub fn LLVMRustGetNamedValue(M: &Module, Name: *const c_char) -> Option<&Value>; + pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool); + + // Operations on functions + pub fn LLVMRustGetOrInsertFunction(M: &'a Module, + Name: *const c_char, + FunctionTy: &'a Type) + -> &'a Value; + pub fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint); + pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32); + pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64); + pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64); + pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute); + pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value, + index: c_uint, + Name: *const c_char, + Value: *const c_char); + pub fn LLVMRustRemoveFunctionAttributes(Fn: &Value, index: c_uint, attr: Attribute); + + // Operations on parameters + pub fn LLVMCountParams(Fn: &Value) -> c_uint; + pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value; + + // Operations on basic blocks + pub fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value; + pub fn LLVMAppendBasicBlockInContext(C: &'a Context, + Fn: &'a Value, + Name: *const c_char) + -> &'a BasicBlock; + pub fn LLVMDeleteBasicBlock(BB: &BasicBlock); + + // Operations on instructions + pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock; + + // Operations on call sites + pub fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint); + pub fn LLVMRustAddCallSiteAttribute(Instr: &Value, index: c_uint, attr: Attribute); + pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: &Value, index: c_uint, bytes: u32); + pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: &Value, index: c_uint, bytes: u64); + pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value, + index: c_uint, + bytes: u64); + + // Operations on load/store instructions (only) + pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool); + + // Operations on phi nodes + pub fn LLVMAddIncoming(PhiNode: &'a Value, + IncomingValues: *const &'a Value, + IncomingBlocks: *const &'a BasicBlock, + Count: c_uint); + + // Instruction builders + pub fn LLVMCreateBuilderInContext(C: &'a Context) -> &'a mut Builder<'a>; + pub fn LLVMPositionBuilderAtEnd(Builder: &Builder<'a>, Block: &'a BasicBlock); + pub fn LLVMGetInsertBlock(Builder: &Builder<'a>) -> &'a BasicBlock; + pub fn LLVMDisposeBuilder(Builder: &'a mut Builder<'a>); + + // Metadata + pub fn LLVMSetCurrentDebugLocation(Builder: &Builder<'a>, L: Option<&'a Value>); + pub fn LLVMGetCurrentDebugLocation(Builder: &Builder<'a>) -> &'a Value; + pub fn LLVMSetInstDebugLocation(Builder: &Builder<'a>, Inst: &'a Value); + + // Terminators + pub fn LLVMBuildRetVoid(B: &Builder<'a>) -> &'a Value; + pub fn LLVMBuildRet(B: &Builder<'a>, V: &'a Value) -> &'a Value; + pub fn LLVMBuildBr(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value; + pub fn LLVMBuildCondBr(B: &Builder<'a>, + If: &'a Value, + Then: &'a BasicBlock, + Else: &'a BasicBlock) + -> &'a Value; + pub fn LLVMBuildSwitch(B: &Builder<'a>, + V: &'a Value, + Else: &'a BasicBlock, + NumCases: c_uint) + -> &'a Value; + pub fn LLVMRustBuildInvoke(B: &Builder<'a>, + Fn: &'a Value, + Args: *const &'a Value, + NumArgs: c_uint, + Then: &'a BasicBlock, + Catch: &'a BasicBlock, + Bundle: Option<&OperandBundleDef<'a>>, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildLandingPad(B: &Builder<'a>, + Ty: &'a Type, + PersFn: &'a Value, + NumClauses: c_uint, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildResume(B: &Builder<'a>, Exn: &'a Value) -> &'a Value; + pub fn LLVMBuildUnreachable(B: &Builder<'a>) -> &'a Value; + + pub fn LLVMRustBuildCleanupPad(B: &Builder<'a>, + ParentPad: Option<&'a Value>, + ArgCnt: c_uint, + Args: *const &'a Value, + Name: *const c_char) + -> Option<&'a Value>; + pub fn LLVMRustBuildCleanupRet(B: &Builder<'a>, + CleanupPad: &'a Value, + UnwindBB: Option<&'a BasicBlock>) + -> Option<&'a Value>; + pub fn LLVMRustBuildCatchPad(B: &Builder<'a>, + ParentPad: &'a Value, + ArgCnt: c_uint, + Args: *const &'a Value, + Name: *const c_char) + -> Option<&'a Value>; + pub fn LLVMRustBuildCatchRet( + B: &Builder<'a>, + Pad: &'a Value, + BB: &'a BasicBlock, + ) -> Option<&'a Value>; + pub fn LLVMRustBuildCatchSwitch(Builder: &Builder<'a>, + ParentPad: Option<&'a Value>, + BB: Option<&'a BasicBlock>, + NumHandlers: c_uint, + Name: *const c_char) + -> Option<&'a Value>; + pub fn LLVMRustAddHandler(CatchSwitch: &'a Value, Handler: &'a BasicBlock); + pub fn LLVMSetPersonalityFn(Func: &'a Value, Pers: &'a Value); + + // Add a case to the switch instruction + pub fn LLVMAddCase(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock); + + // Add a clause to the landing pad instruction + pub fn LLVMAddClause(LandingPad: &'a Value, ClauseVal: &'a Value); + + // Set the cleanup on a landing pad instruction + pub fn LLVMSetCleanup(LandingPad: &Value, Val: Bool); + + // Arithmetic + pub fn LLVMBuildAdd(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFAdd(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSub(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFSub(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildMul(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFMul(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildUDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildExactUDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildExactSDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildURem(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSRem(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFRem(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildShl(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildLShr(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildAShr(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildAnd(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildOr(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildXor(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildFNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildNot(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMRustSetHasUnsafeAlgebra(Instr: &Value); + + // Memory + pub fn LLVMBuildAlloca(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildArrayAlloca(B: &Builder<'a>, + Ty: &'a Type, + Val: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildLoad(B: &Builder<'a>, PointerVal: &'a Value, Name: *const c_char) -> &'a Value; + + pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value; + + pub fn LLVMBuildGEP(B: &Builder<'a>, + Pointer: &'a Value, + Indices: *const &'a Value, + NumIndices: c_uint, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildInBoundsGEP(B: &Builder<'a>, + Pointer: &'a Value, + Indices: *const &'a Value, + NumIndices: c_uint, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildStructGEP(B: &Builder<'a>, + Pointer: &'a Value, + Idx: c_uint, + Name: *const c_char) + -> &'a Value; + + // Casts + pub fn LLVMBuildTrunc(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildZExt(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSExt(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFPToUI(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFPToSI(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildUIToFP(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSIToFP(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFPTrunc(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFPExt(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildPtrToInt(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildIntToPtr(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildBitCast(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildPointerCast(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMRustBuildIntCast(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + IsSized: bool) + -> &'a Value; + + // Comparisons + pub fn LLVMBuildICmp(B: &Builder<'a>, + Op: c_uint, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFCmp(B: &Builder<'a>, + Op: c_uint, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + + // Miscellaneous instructions + pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMRustBuildCall(B: &Builder<'a>, + Fn: &'a Value, + Args: *const &'a Value, + NumArgs: c_uint, + Bundle: Option<&OperandBundleDef<'a>>, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSelect(B: &Builder<'a>, + If: &'a Value, + Then: &'a Value, + Else: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildVAArg(B: &Builder<'a>, + list: &'a Value, + Ty: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildExtractElement(B: &Builder<'a>, + VecVal: &'a Value, + Index: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildInsertElement(B: &Builder<'a>, + VecVal: &'a Value, + EltVal: &'a Value, + Index: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildShuffleVector(B: &Builder<'a>, + V1: &'a Value, + V2: &'a Value, + Mask: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildExtractValue(B: &Builder<'a>, + AggVal: &'a Value, + Index: c_uint, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildInsertValue(B: &Builder<'a>, + AggVal: &'a Value, + EltVal: &'a Value, + Index: c_uint, + Name: *const c_char) + -> &'a Value; + + pub fn LLVMRustBuildVectorReduceFAdd(B: &Builder<'a>, + Acc: &'a Value, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceFMul(B: &Builder<'a>, + Acc: &'a Value, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceAdd(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceMul(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceAnd(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceOr(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceXor(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceMin(B: &Builder<'a>, + Src: &'a Value, + IsSigned: bool) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceMax(B: &Builder<'a>, + Src: &'a Value, + IsSigned: bool) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceFMin(B: &Builder<'a>, + Src: &'a Value, + IsNaN: bool) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceFMax(B: &Builder<'a>, + Src: &'a Value, + IsNaN: bool) + -> Option<&'a Value>; + + pub fn LLVMRustBuildMinNum( + B: &Builder<'a>, + LHS: &'a Value, + LHS: &'a Value, + ) -> Option<&'a Value>; + pub fn LLVMRustBuildMaxNum( + B: &Builder<'a>, + LHS: &'a Value, + LHS: &'a Value, + ) -> Option<&'a Value>; + + // Atomic Operations + pub fn LLVMRustBuildAtomicLoad(B: &Builder<'a>, + PointerVal: &'a Value, + Name: *const c_char, + Order: AtomicOrdering) + -> &'a Value; + + pub fn LLVMRustBuildAtomicStore(B: &Builder<'a>, + Val: &'a Value, + Ptr: &'a Value, + Order: AtomicOrdering) + -> &'a Value; + + pub fn LLVMRustBuildAtomicCmpXchg(B: &Builder<'a>, + LHS: &'a Value, + CMP: &'a Value, + RHS: &'a Value, + Order: AtomicOrdering, + FailureOrder: AtomicOrdering, + Weak: Bool) + -> &'a Value; + + pub fn LLVMBuildAtomicRMW(B: &Builder<'a>, + Op: AtomicRmwBinOp, + LHS: &'a Value, + RHS: &'a Value, + Order: AtomicOrdering, + SingleThreaded: Bool) + -> &'a Value; + + pub fn LLVMRustBuildAtomicFence(B: &Builder, + Order: AtomicOrdering, + Scope: SynchronizationScope); + + /// Writes a module to the specified path. Returns 0 on success. + pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; + + /// Creates a pass manager. + pub fn LLVMCreatePassManager() -> &'a mut PassManager<'a>; + + /// Creates a function-by-function pass manager + pub fn LLVMCreateFunctionPassManagerForModule(M: &'a Module) -> &'a mut PassManager<'a>; + + /// Disposes a pass manager. + pub fn LLVMDisposePassManager(PM: &'a mut PassManager<'a>); + + /// Runs a pass manager on a module. + pub fn LLVMRunPassManager(PM: &PassManager<'a>, M: &'a Module) -> Bool; + + pub fn LLVMInitializePasses(); + + pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder; + pub fn LLVMPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder); + pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: &PassManagerBuilder, Value: Bool); + pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: &PassManagerBuilder, Value: Bool); + pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: &PassManagerBuilder, + threshold: c_uint); + pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: &PassManagerBuilder, + PM: &PassManager); + + pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: &PassManagerBuilder, + PM: &PassManager); + pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: &PassManagerBuilder, + PM: &PassManager, + Internalize: Bool, + RunInliner: Bool); + pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( + PMB: &PassManagerBuilder, + PM: &PassManager) -> bool; + + // Stuff that's in rustllvm/ because it's not upstream yet. + + /// Opens an object file. + pub fn LLVMCreateObjectFile( + MemBuf: &'static mut MemoryBuffer, + ) -> Option<&'static mut ObjectFile>; + /// Closes an object file. + pub fn LLVMDisposeObjectFile(ObjFile: &'static mut ObjectFile); + + /// Enumerates the sections in an object file. + pub fn LLVMGetSections(ObjFile: &'a ObjectFile) -> &'a mut SectionIterator<'a>; + /// Destroys a section iterator. + pub fn LLVMDisposeSectionIterator(SI: &'a mut SectionIterator<'a>); + /// Returns true if the section iterator is at the end of the section + /// list: + pub fn LLVMIsSectionIteratorAtEnd(ObjFile: &'a ObjectFile, SI: &SectionIterator<'a>) -> Bool; + /// Moves the section iterator to point to the next section. + pub fn LLVMMoveToNextSection(SI: &SectionIterator); + /// Returns the current section size. + pub fn LLVMGetSectionSize(SI: &SectionIterator) -> c_ulonglong; + /// Returns the current section contents as a string buffer. + pub fn LLVMGetSectionContents(SI: &SectionIterator) -> *const c_char; + + /// Reads the given file and returns it as a memory buffer. Use + /// LLVMDisposeMemoryBuffer() to get rid of it. + pub fn LLVMRustCreateMemoryBufferWithContentsOfFile( + Path: *const c_char, + ) -> Option<&'static mut MemoryBuffer>; + + pub fn LLVMStartMultithreaded() -> Bool; + + /// Returns a string describing the last error caused by an LLVMRust* call. + pub fn LLVMRustGetLastError() -> *const c_char; + + /// Print the pass timings since static dtors aren't picking them up. + pub fn LLVMRustPrintPassTimings(); + + pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type; + + pub fn LLVMStructSetBody(StructTy: &'a Type, + ElementTypes: *const &'a Type, + ElementCount: c_uint, + Packed: Bool); + + /// Prepares inline assembly. + pub fn LLVMRustInlineAsm(Ty: &Type, + AsmString: *const c_char, + Constraints: *const c_char, + SideEffects: Bool, + AlignStack: Bool, + Dialect: AsmDialect) + -> &Value; + + pub fn LLVMRustDebugMetadataVersion() -> u32; + pub fn LLVMRustVersionMajor() -> u32; + pub fn LLVMRustVersionMinor() -> u32; + + pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32); + + pub fn LLVMRustMetadataAsValue(C: &'a Context, MD: &'a Metadata) -> &'a Value; + + pub fn LLVMRustDIBuilderCreate(M: &'a Module) -> &'a mut DIBuilder<'a>; + + pub fn LLVMRustDIBuilderDispose(Builder: &'a mut DIBuilder<'a>); + + pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder); + + pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: &DIBuilder<'a>, + Lang: c_uint, + File: &'a DIFile, + Producer: *const c_char, + isOptimized: bool, + Flags: *const c_char, + RuntimeVer: c_uint, + SplitName: *const c_char) + -> &'a DIDescriptor; + + pub fn LLVMRustDIBuilderCreateFile(Builder: &DIBuilder<'a>, + Filename: *const c_char, + Directory: *const c_char) + -> &'a DIFile; + + pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: &DIBuilder<'a>, + File: &'a DIFile, + ParameterTypes: &'a DIArray) + -> &'a DICompositeType; + + pub fn LLVMRustDIBuilderCreateFunction(Builder: &DIBuilder<'a>, + Scope: &'a DIDescriptor, + Name: *const c_char, + LinkageName: *const c_char, + File: &'a DIFile, + LineNo: c_uint, + Ty: &'a DIType, + isLocalToUnit: bool, + isDefinition: bool, + ScopeLine: c_uint, + Flags: DIFlags, + isOptimized: bool, + Fn: &'a Value, + TParam: &'a DIArray, + Decl: Option<&'a DIDescriptor>) + -> &'a DISubprogram; + + pub fn LLVMRustDIBuilderCreateBasicType(Builder: &DIBuilder<'a>, + Name: *const c_char, + SizeInBits: u64, + AlignInBits: u32, + Encoding: c_uint) + -> &'a DIBasicType; + + pub fn LLVMRustDIBuilderCreatePointerType(Builder: &DIBuilder<'a>, + PointeeTy: &'a DIType, + SizeInBits: u64, + AlignInBits: u32, + Name: *const c_char) + -> &'a DIDerivedType; + + pub fn LLVMRustDIBuilderCreateStructType(Builder: &DIBuilder<'a>, + Scope: Option<&'a DIDescriptor>, + Name: *const c_char, + File: &'a DIFile, + LineNumber: c_uint, + SizeInBits: u64, + AlignInBits: u32, + Flags: DIFlags, + DerivedFrom: Option<&'a DIType>, + Elements: &'a DIArray, + RunTimeLang: c_uint, + VTableHolder: Option<&'a DIType>, + UniqueId: *const c_char) + -> &'a DICompositeType; + + pub fn LLVMRustDIBuilderCreateMemberType(Builder: &DIBuilder<'a>, + Scope: &'a DIDescriptor, + Name: *const c_char, + File: &'a DIFile, + LineNo: c_uint, + SizeInBits: u64, + AlignInBits: u32, + OffsetInBits: u64, + Flags: DIFlags, + Ty: &'a DIType) + -> &'a DIDerivedType; + + pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: &DIBuilder<'a>, + Scope: &'a DIScope, + File: &'a DIFile, + Line: c_uint, + Col: c_uint) + -> &'a DILexicalBlock; + + pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: &DIBuilder<'a>, + Scope: &'a DIScope, + File: &'a DIFile) + -> &'a DILexicalBlock; + + pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: &DIBuilder<'a>, + Context: Option<&'a DIScope>, + Name: *const c_char, + LinkageName: *const c_char, + File: &'a DIFile, + LineNo: c_uint, + Ty: &'a DIType, + isLocalToUnit: bool, + Val: &'a Value, + Decl: Option<&'a DIDescriptor>, + AlignInBits: u32) + -> &'a DIGlobalVariable; + + pub fn LLVMRustDIBuilderCreateVariable(Builder: &DIBuilder<'a>, + Tag: c_uint, + Scope: &'a DIDescriptor, + Name: *const c_char, + File: &'a DIFile, + LineNo: c_uint, + Ty: &'a DIType, + AlwaysPreserve: bool, + Flags: DIFlags, + ArgNo: c_uint, + AlignInBits: u32) + -> &'a DIVariable; + + pub fn LLVMRustDIBuilderCreateArrayType(Builder: &DIBuilder<'a>, + Size: u64, + AlignInBits: u32, + Ty: &'a DIType, + Subscripts: &'a DIArray) + -> &'a DIType; + + pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: &DIBuilder<'a>, + Lo: i64, + Count: i64) + -> &'a DISubrange; + + pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: &DIBuilder<'a>, + Ptr: *const Option<&'a DIDescriptor>, + Count: c_uint) + -> &'a DIArray; + + pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: &DIBuilder<'a>, + Val: &'a Value, + VarInfo: &'a DIVariable, + AddrOps: *const i64, + AddrOpsCount: c_uint, + DL: &'a Value, + InsertAtEnd: &'a BasicBlock) + -> &'a Value; + + pub fn LLVMRustDIBuilderCreateEnumerator(Builder: &DIBuilder<'a>, + Name: *const c_char, + Val: u64) + -> &'a DIEnumerator; + + pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: &DIBuilder<'a>, + Scope: &'a DIScope, + Name: *const c_char, + File: &'a DIFile, + LineNumber: c_uint, + SizeInBits: u64, + AlignInBits: u32, + Elements: &'a DIArray, + ClassType: &'a DIType) + -> &'a DIType; + + pub fn LLVMRustDIBuilderCreateUnionType(Builder: &DIBuilder<'a>, + Scope: &'a DIScope, + Name: *const c_char, + File: &'a DIFile, + LineNumber: c_uint, + SizeInBits: u64, + AlignInBits: u32, + Flags: DIFlags, + Elements: Option<&'a DIArray>, + RunTimeLang: c_uint, + UniqueId: *const c_char) + -> &'a DIType; + + pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool); + + pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: &DIBuilder<'a>, + Scope: Option<&'a DIScope>, + Name: *const c_char, + Ty: &'a DIType, + File: &'a DIFile, + LineNo: c_uint, + ColumnNo: c_uint) + -> &'a DITemplateTypeParameter; + + + pub fn LLVMRustDIBuilderCreateNameSpace(Builder: &DIBuilder<'a>, + Scope: Option<&'a DIScope>, + Name: *const c_char, + File: &'a DIFile, + LineNo: c_uint) + -> &'a DINameSpace; + + pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: &DIBuilder<'a>, + CompositeType: &'a DIType, + TypeArray: &'a DIArray); + + + pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context, + Line: c_uint, + Column: c_uint, + Scope: &'a DIScope, + InlinedAt: Option<&'a Metadata>) + -> &'a Value; + pub fn LLVMRustDIBuilderCreateOpDeref() -> i64; + pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64; +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); + pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); +} + +extern "C" { + pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>; + pub fn LLVMIsAConstantFP(value_ref: &Value) -> Option<&Value>; + + pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind; + pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; + pub fn LLVMRustAddPass(PM: &PassManager, Pass: &'static mut Pass); + + pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; + + pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine); + pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine); + + pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char; + pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, + CPU: *const c_char, + Features: *const c_char, + Model: CodeModel, + Reloc: RelocMode, + Level: CodeGenOptLevel, + UseSoftFP: bool, + PositionIndependentExecutable: bool, + FunctionSections: bool, + DataSections: bool, + TrapUnreachable: bool, + Singlethread: bool, + AsmComments: 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); + pub fn LLVMRustConfigurePassManagerBuilder(PMB: &PassManagerBuilder, + OptLevel: CodeGenOptLevel, + MergeFunctions: bool, + SLPVectorize: bool, + LoopVectorize: bool, + PrepareForThinLTO: bool, + PGOGenPath: *const c_char, + PGOUsePath: *const c_char); + pub fn LLVMRustAddLibraryInfo(PM: &PassManager<'a>, + M: &'a Module, + DisableSimplifyLibCalls: bool); + pub fn LLVMRustRunFunctionPassManager(PM: &PassManager<'a>, M: &'a Module); + pub fn LLVMRustWriteOutputFile(T: &'a TargetMachine, + PM: &PassManager<'a>, + M: &'a Module, + Output: *const c_char, + FileType: FileType) + -> LLVMRustResult; + pub fn LLVMRustPrintModule(PM: &PassManager<'a>, + M: &'a Module, + Output: *const c_char, + Demangle: extern fn(*const c_char, + size_t, + *mut c_char, + size_t) -> size_t); + pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); + pub fn LLVMRustPrintPasses(); + 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); + pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module); + + pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>; + pub fn LLVMRustArchiveIteratorNew(AR: &'a Archive) -> &'a mut ArchiveIterator<'a>; + pub fn LLVMRustArchiveIteratorNext( + AIR: &ArchiveIterator<'a>, + ) -> Option<&'a mut ArchiveChild<'a>>; + pub fn LLVMRustArchiveChildName(ACR: &ArchiveChild, size: &mut size_t) -> *const c_char; + pub fn LLVMRustArchiveChildData(ACR: &ArchiveChild, size: &mut size_t) -> *const c_char; + pub fn LLVMRustArchiveChildFree(ACR: &'a mut ArchiveChild<'a>); + pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>); + pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); + + pub fn LLVMRustGetSectionName(SI: &SectionIterator, data: &mut *const c_char) -> size_t; +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); +} + +extern "C" { + pub fn LLVMContextSetDiagnosticHandler(C: &Context, + Handler: DiagnosticHandler, + DiagnosticContext: *mut c_void); +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustUnpackOptimizationDiagnostic(DI: &'a DiagnosticInfo, + pass_name_out: &RustString, + function_out: &mut Option<&'a Value>, + loc_line_out: &mut c_uint, + loc_column_out: &mut c_uint, + loc_filename_out: &RustString, + message_out: &RustString); +} + +extern "C" { + pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: &'a DiagnosticInfo, + cookie_out: &mut c_uint, + message_out: &mut Option<&'a Twine>, + instruction_out: &mut Option<&'a Value>); +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString); +} + +extern "C" { + pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind; + + pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: &Context, + H: InlineAsmDiagHandler, + CX: *mut c_void); +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustWriteSMDiagnosticToString(d: &SMDiagnostic, s: &RustString); +} + +extern "C" { + pub fn LLVMRustWriteArchive(Dst: *const c_char, + NumMembers: size_t, + Members: *const &RustArchiveMember, + WriteSymbtab: bool, + Kind: ArchiveKind) + -> LLVMRustResult; + pub fn LLVMRustArchiveMemberNew(Filename: *const c_char, + Name: *const c_char, + Child: Option<&ArchiveChild<'a>>) + -> &'a mut RustArchiveMember<'a>; + pub fn LLVMRustArchiveMemberFree(Member: &'a mut RustArchiveMember<'a>); + + pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &'a Module, TM: &'a TargetMachine); + + pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char, + Inputs: *const &'a Value, + NumInputs: c_uint) + -> &'a mut OperandBundleDef<'a>; + pub fn LLVMRustFreeOperandBundleDef(Bundle: &'a mut OperandBundleDef<'a>); + + pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock); + + pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char); + pub fn LLVMRustUnsetComdat(V: &Value); + pub fn LLVMRustSetModulePIELevel(M: &Module); + pub fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer; + pub fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8; + pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize; + pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer); + pub fn LLVMRustModuleCost(M: &Module) -> u64; + + pub fn LLVMRustThinLTOAvailable() -> bool; + pub fn LLVMRustPGOAvailable() -> bool; + pub fn LLVMRustThinLTOBufferCreate(M: &Module) -> &'static mut ThinLTOBuffer; + pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer); + pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char; + pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t; + pub fn LLVMRustCreateThinLTOData( + Modules: *const ThinLTOModule, + NumModules: c_uint, + PreservedSymbols: *const *const c_char, + PreservedSymbolsLen: c_uint, + ) -> Option<&'static mut ThinLTOData>; + pub fn LLVMRustPrepareThinLTORename( + Data: &ThinLTOData, + Module: &Module, + ) -> bool; + pub fn LLVMRustPrepareThinLTOResolveWeak( + Data: &ThinLTOData, + Module: &Module, + ) -> bool; + pub fn LLVMRustPrepareThinLTOInternalize( + Data: &ThinLTOData, + Module: &Module, + ) -> bool; + pub fn LLVMRustPrepareThinLTOImport( + Data: &ThinLTOData, + Module: &Module, + ) -> bool; + pub fn LLVMRustGetThinLTOModuleImports( + Data: *const ThinLTOData, + ModuleNameCallback: ThinLTOModuleNameCallback, + CallbackPayload: *mut c_void, + ); + pub fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData); + pub fn LLVMRustParseBitcodeForThinLTO( + Context: &Context, + Data: *const u8, + len: usize, + Identifier: *const c_char, + ) -> Option<&Module>; + pub fn LLVMRustThinLTOGetDICompileUnit(M: &Module, + CU1: &mut *mut c_void, + CU2: &mut *mut c_void); + pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); + + pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>; + pub fn LLVMRustLinkerAdd(linker: &Linker, + bytecode: *const c_char, + bytecode_len: usize) -> bool; + pub fn LLVMRustLinkerFree(linker: &'a mut Linker<'a>); +} diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs new file mode 100644 index 0000000000..4343c8c184 --- /dev/null +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -0,0 +1,282 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![deny(bare_trait_objects)] + +pub use self::IntPredicate::*; +pub use self::RealPredicate::*; +pub use self::AtomicRmwBinOp::*; +pub use self::MetadataType::*; +pub use self::CodeGenOptSize::*; +pub use self::CallConv::*; +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::{self, c_uint, c_char, size_t}; +use rustc_data_structures::small_c_str::SmallCStr; + +pub mod archive_ro; +pub mod diagnostic; +mod ffi; + +pub use self::ffi::*; + +impl LLVMRustResult { + pub fn into_result(self) -> Result<(), ()> { + match self { + LLVMRustResult::Success => Ok(()), + LLVMRustResult::Failure => Err(()), + } + } +} + +pub fn AddFunctionAttrStringValue(llfn: &'a Value, + idx: AttributePlace, + attr: &CStr, + value: &CStr) { + unsafe { + LLVMRustAddFunctionAttrStringValue(llfn, + idx.as_uint(), + attr.as_ptr(), + value.as_ptr()) + } +} + +#[derive(Copy, Clone)] +pub enum AttributePlace { + ReturnValue, + Argument(u32), + Function, +} + +impl AttributePlace { + pub fn as_uint(self) -> c_uint { + match self { + AttributePlace::ReturnValue => 0, + AttributePlace::Argument(i) => 1 + i, + AttributePlace::Function => !0, + } + } +} + +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +pub enum CodeGenOptSize { + CodeGenOptSizeNone = 0, + CodeGenOptSizeDefault = 1, + CodeGenOptSizeAggressive = 2, +} + +impl FromStr for ArchiveKind { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "gnu" => Ok(ArchiveKind::K_GNU), + "bsd" => Ok(ArchiveKind::K_BSD), + "coff" => Ok(ArchiveKind::K_COFF), + _ => Err(()), + } + } +} + +#[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); + } +} +pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { + unsafe { + LLVMSetFunctionCallConv(fn_, cc as c_uint); + } +} + +// Externally visible symbols that might appear in multiple codegen units need to appear in +// their own comdat section so that the duplicates can be discarded at link time. This can for +// example happen for generics when using multiple codegen units. This function simply uses the +// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the +// function. +// 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)); + } +} + +pub fn UnsetComdat(val: &'a Value) { + unsafe { + LLVMRustUnsetComdat(val); + } +} + +pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) { + unsafe { + LLVMSetUnnamedAddr(global, unnamed as Bool); + } +} + +pub fn set_thread_local(global: &'a Value, is_thread_local: bool) { + unsafe { + LLVMSetThreadLocal(global, is_thread_local as Bool); + } +} +pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) { + unsafe { + LLVMSetThreadLocalMode(global, mode); + } +} + +impl Attribute { + pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) { + unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) } + } + + pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) { + unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) } + } + + pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) { + unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) } + } + + pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) { + if set { + self.apply_llfn(idx, llfn); + } else { + self.unapply_llfn(idx, llfn); + } + } +} + +// Memory-managed interface to object files. + +pub struct ObjectFile { + pub llof: &'static mut ffi::ObjectFile, +} + +unsafe impl Send for ObjectFile {} + +impl ObjectFile { + // This will take ownership of llmb + pub fn new(llmb: &'static mut MemoryBuffer) -> Option { + unsafe { + let llof = LLVMCreateObjectFile(llmb)?; + Some(ObjectFile { llof: llof }) + } + } +} + +impl Drop for ObjectFile { + fn drop(&mut self) { + unsafe { + LLVMDisposeObjectFile(&mut *(self.llof as *mut _)); + } + } +} + +// Memory-managed interface to section iterators. + +pub struct SectionIter<'a> { + pub llsi: &'a mut SectionIterator<'a>, +} + +impl Drop for SectionIter<'a> { + fn drop(&mut self) { + unsafe { + LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _)); + } + } +} + +pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> { + unsafe { SectionIter { llsi: LLVMGetSections(llof) } } +} + +/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun. +pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value { + unsafe { + assert!(index < LLVMCountParams(llfn), + "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn)); + LLVMGetParam(llfn, index) + } +} + +pub fn build_string(f: impl FnOnce(&RustString)) -> Result { + let sr = RustString { + bytes: RefCell::new(Vec::new()), + }; + f(&sr); + String::from_utf8(sr.bytes.into_inner()) +} + +pub fn twine_to_string(tr: &Twine) -> String { + unsafe { + build_string(|s| LLVMRustWriteTwineToString(tr, s)) + .expect("got a non-UTF8 Twine from LLVM") + } +} + +pub fn last_error() -> Option { + unsafe { + let cstr = LLVMRustGetLastError(); + if cstr.is_null() { + None + } else { + let err = CStr::from_ptr(cstr).to_bytes(); + let err = String::from_utf8_lossy(err).to_string(); + libc::free(cstr as *mut _); + Some(err) + } + } +} + +pub struct OperandBundleDef<'a> { + pub raw: &'a mut ffi::OperandBundleDef<'a>, +} + +impl OperandBundleDef<'a> { + pub fn new(name: &str, vals: &[&'a Value]) -> Self { + let name = SmallCStr::new(name); + let def = unsafe { + LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint) + }; + OperandBundleDef { raw: def } + } +} + +impl Drop for OperandBundleDef<'a> { + fn drop(&mut self) { + unsafe { + LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _)); + } + } +} diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index e941998098..9e8ff20470 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -17,6 +17,8 @@ use libc::c_int; use std::ffi::CString; use syntax::feature_gate::UnstableFeatures; +use std::str; +use std::slice; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; @@ -73,7 +75,7 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializePasses(); - llvm::initialize_available_targets(); + ::rustc_llvm::initialize_available_targets(); llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); @@ -84,10 +86,14 @@ unsafe fn configure_llvm(sess: &Session) { // array, leading to crashes. const ARM_WHITELIST: &[(&str, Option<&str>)] = &[ + ("aclass", Some("arm_target_feature")), ("mclass", Some("arm_target_feature")), ("rclass", Some("arm_target_feature")), ("dsp", Some("arm_target_feature")), ("neon", Some("arm_target_feature")), + ("v5te", Some("arm_target_feature")), + ("v6k", Some("arm_target_feature")), + ("v6t2", Some("arm_target_feature")), ("v7", Some("arm_target_feature")), ("vfp2", Some("arm_target_feature")), ("vfp3", Some("arm_target_feature")), @@ -169,6 +175,11 @@ const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[ ("msa", Some("mips_target_feature")), ]; +const WASM_WHITELIST: &[(&str, Option<&str>)] = &[ + ("simd128", Some("wasm_target_feature")), + ("atomics", Some("wasm_target_feature")), +]; + /// When rustdoc is running, provide a list of all known features so that all their respective /// primtives may be documented. /// @@ -181,6 +192,7 @@ pub fn all_known_features() -> impl Iterator(sess: &Session, s: &'a str) -> &'a str { @@ -228,6 +240,7 @@ pub fn target_feature_whitelist(sess: &Session) "hexagon" => HEXAGON_WHITELIST, "mips" | "mips64" => MIPS_WHITELIST, "powerpc" | "powerpc64" => POWERPC_WHITELIST, + "wasm32" => WASM_WHITELIST, _ => &[], } } @@ -256,3 +269,19 @@ pub(crate) fn print(req: PrintRequest, sess: &Session) { } } } + +pub fn target_cpu(sess: &Session) -> &str { + let name = match sess.opts.cg.target_cpu { + Some(ref s) => &**s, + None => &*sess.target.target.options.cpu + }; + if name != "native" { + return name + } + + unsafe { + let mut len = 0; + let ptr = llvm::LLVMRustGetHostCPUName(&mut len); + str::from_utf8(slice::from_raw_parts(ptr as *const u8, len)).unwrap() + } +} diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index 144baa65c1..a4526a5376 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::util::common; use rustc::middle::cstore::MetadataLoader; use rustc_target::spec::Target; use llvm; @@ -19,6 +18,7 @@ use rustc_data_structures::owning_ref::OwningRef; use std::path::Path; use std::ptr; use std::slice; +use rustc_fs_util::path2cstr; pub use rustc_data_structures::sync::MetadataRef; @@ -57,11 +57,9 @@ impl MetadataLoader for LlvmMetadataLoader { filename: &Path) -> Result { unsafe { - let buf = common::path2cstr(filename); - let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()); - if mb as isize == 0 { - return Err(format!("error reading library: '{}'", filename.display())); - } + let buf = path2cstr(filename); + let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()) + .ok_or_else(|| format!("error reading library: '{}'", filename.display()))?; let of = ObjectFile::new(mb) .map(|of| OwningRef::new(box of)) .ok_or_else(|| format!("provided path not an object file: '{}'", diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs index 21bbdf31dc..8a1159bc47 100644 --- a/src/librustc_codegen_llvm/meth.rs +++ b/src/librustc_codegen_llvm/meth.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::ValueRef; use abi::{FnType, FnTypeExt}; use callee; use common::*; @@ -17,6 +16,7 @@ use consts; use monomorphize; use type_::Type; use value::Value; + use rustc::ty::{self, Ty}; use rustc::ty::layout::HasDataLayout; use debuginfo; @@ -33,11 +33,11 @@ impl<'a, 'tcx> VirtualIndex { VirtualIndex(index as u64 + 3) } - pub fn get_fn(self, bx: &Builder<'a, 'tcx>, - llvtable: ValueRef, - fn_ty: &FnType<'tcx, Ty<'tcx>>) -> ValueRef { + pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>, + llvtable: &'ll Value, + fn_ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Value { // Load the data pointer from the object. - debug!("get_fn({:?}, {:?})", Value(llvtable), self); + debug!("get_fn({:?}, {:?})", llvtable, self); let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to()); let ptr_align = bx.tcx().data_layout.pointer_align; @@ -48,9 +48,9 @@ impl<'a, 'tcx> VirtualIndex { ptr } - pub fn get_usize(self, bx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef { + pub fn get_usize(self, bx: &Builder<'a, 'll, 'tcx>, llvtable: &'ll Value) -> &'ll Value { // Load the data pointer from the object. - debug!("get_int({:?}, {:?})", Value(llvtable), self); + debug!("get_int({:?}, {:?})", llvtable, self); let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx).ptr_to()); let usize_align = bx.tcx().data_layout.pointer_align; @@ -69,11 +69,11 @@ 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`. -pub fn get_vtable<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - ty: Ty<'tcx>, - trait_ref: Option>) - -> ValueRef -{ +pub fn get_vtable( + cx: &CodegenCx<'ll, 'tcx>, + ty: Ty<'tcx>, + trait_ref: Option>, +) -> &'ll Value { let tcx = cx.tcx; debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref); @@ -106,7 +106,7 @@ pub fn get_vtable<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let vtable_const = C_struct(cx, &components, false); let align = cx.data_layout().pointer_align; - let vtable = consts::addr_of(cx, vtable_const, align, "vtable"); + let vtable = consts::addr_of(cx, vtable_const, align, Some("vtable")); debuginfo::create_vtable_metadata(cx, ty, vtable); diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs index e105baba8a..0206744eb2 100644 --- a/src/librustc_codegen_llvm/mir/analyze.rs +++ b/src/librustc_codegen_llvm/mir/analyze.rs @@ -11,7 +11,7 @@ //! An analysis to determine which locals require allocas and //! which do not. -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::{self, Location, TerminatorKind}; @@ -22,7 +22,7 @@ use rustc::ty::layout::LayoutOf; use type_of::LayoutLlvmExt; use super::FunctionCx; -pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector { +pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray { let mir = fx.mir; let mut analyzer = LocalAnalyzer::new(fx); @@ -34,7 +34,7 @@ pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector(fx: &FunctionCx<'a, 'tcx>) -> BitVector { - fx: &'mir FunctionCx<'a, 'tcx>, +struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> { + fx: &'mir FunctionCx<'a, 'll, 'tcx>, dominators: Dominators, - non_ssa_locals: BitVector, + non_ssa_locals: BitArray, // The location of the first visited direct assignment to each // local, or an invalid location (out of bounds `block` index). first_assignment: IndexVec } -impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> { - fn new(fx: &'mir FunctionCx<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> { +impl LocalAnalyzer<'mir, 'a, 'll, 'tcx> { + fn new(fx: &'mir FunctionCx<'a, 'll, 'tcx>) -> Self { let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location(); let mut analyzer = LocalAnalyzer { fx, dominators: fx.mir.dominators(), - non_ssa_locals: BitVector::new(fx.mir.local_decls.len()), + non_ssa_locals: BitArray::new(fx.mir.local_decls.len()), first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls) }; @@ -102,7 +102,7 @@ impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> { } } -impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> { +impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { fn visit_assign(&mut self, block: mir::BasicBlock, place: &mir::Place<'tcx>, @@ -131,7 +131,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> { func: mir::Operand::Constant(ref c), ref args, .. } => match c.ty.sty { - ty::TyFnDef(did, _) => Some((did, args)), + ty::FnDef(did, _) => Some((did, args)), _ => None, }, _ => None, diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index dc4b9e0ae9..a534b4e478 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef, BasicBlockRef}; +use llvm::{self, BasicBlock}; use rustc::middle::lang_items; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::layout::{self, LayoutOf}; @@ -24,6 +24,7 @@ use meth; use monomorphize; use type_of::LayoutLlvmExt; use type_::Type; +use value::Value; use syntax::symbol::Symbol; use syntax_pos::Pos; @@ -33,7 +34,7 @@ use super::place::PlaceRef; use super::operand::OperandRef; use super::operand::OperandValue::{Pair, Ref, Immediate}; -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_block(&mut self, bb: mir::BasicBlock) { let mut bx = self.build_block(bb); let data = &self.mir[bb]; @@ -48,7 +49,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } fn codegen_terminator(&mut self, - mut bx: Builder<'a, 'tcx>, + mut bx: Builder<'a, 'll, 'tcx>, bb: mir::BasicBlock, terminator: &mir::Terminator<'tcx>) { @@ -97,7 +98,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } }; - let funclet_br = |this: &mut Self, bx: Builder, target: mir::BasicBlock| { + let funclet_br = |this: &mut Self, bx: Builder<'_, 'll, '_>, target: mir::BasicBlock| { let (lltarget, is_cleanupret) = lltarget(this, target); if is_cleanupret { // micro-optimization: generate a `ret` rather than a jump @@ -110,11 +111,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let do_call = | this: &mut Self, - bx: Builder<'a, 'tcx>, + bx: Builder<'a, 'll, 'tcx>, fn_ty: FnType<'tcx, Ty<'tcx>>, - fn_ptr: ValueRef, - llargs: &[ValueRef], - destination: Option<(ReturnDest<'tcx>, mir::BasicBlock)>, + fn_ptr: &'ll Value, + llargs: &[&'ll Value], + destination: Option<(ReturnDest<'ll, 'tcx>, mir::BasicBlock)>, cleanup: Option | { if let Some(cleanup) = cleanup { @@ -224,14 +225,14 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { mir::TerminatorKind::Return => { let llval = match self.fn_ty.ret.mode { - PassMode::Ignore | PassMode::Indirect(_) => { + PassMode::Ignore | PassMode::Indirect(..) => { bx.ret_void(); return; } PassMode::Direct(_) | PassMode::Pair(..) => { let op = self.codegen_consume(&bx, &mir::Place::Local(mir::RETURN_PLACE)); - if let Ref(llval, align) = op.val { + if let Ref(llval, _, align) = op.val { bx.load(llval, align) } else { op.immediate_or_packed_pair(&bx) @@ -244,10 +245,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { LocalRef::Operand(None) => bug!("use of return before def"), LocalRef::Place(cg_place) => { OperandRef { - val: Ref(cg_place.llval, cg_place.align), + val: Ref(cg_place.llval, None, cg_place.align), layout: cg_place.layout } } + LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), }; let llslot = match op.val { Immediate(_) | Pair(..) => { @@ -255,7 +257,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { op.val.store(&bx, scratch); scratch.llval } - Ref(llval, align) => { + Ref(llval, _, align) => { assert_eq!(align.abi(), op.layout.align.abi(), "return place is unaligned!"); llval @@ -285,10 +287,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } let place = self.codegen_place(&bx, location); - let mut args: &[_] = &[place.llval, place.llextra]; - args = &args[..1 + place.has_extra() as usize]; + let (args1, args2); + let mut args = if let Some(llextra) = place.llextra { + args2 = [place.llval, llextra]; + &args2[..] + } else { + args1 = [place.llval]; + &args1[..] + }; let (drop_fn, fn_ty) = match ty.sty { - ty::TyDynamic(..) => { + ty::Dynamic(..) => { let fn_ty = drop_fn.ty(bx.cx.tcx); let sig = common::ty_fn_sig(bx.cx, fn_ty); let sig = bx.tcx().normalize_erasing_late_bound_regions( @@ -296,8 +304,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { &sig, ); let fn_ty = FnType::new_vtable(bx.cx, sig, &[]); + let vtable = args[1]; args = &args[..1]; - (meth::DESTRUCTOR.get_fn(&bx, place.llextra, &fn_ty), fn_ty) + (meth::DESTRUCTOR.get_fn(&bx, vtable, &fn_ty), fn_ty) } _ => { (callee::get_fn(bx.cx, drop_fn), @@ -350,7 +359,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { self.set_debug_loc(&bx, terminator.source_info); // Get the location information. - let loc = bx.sess().codemap().lookup_char_pos(span.lo()); + let loc = bx.sess().source_map().lookup_char_pos(span.lo()); let filename = Symbol::intern(&loc.file.name.to_string()).as_str(); let filename = C_str_slice(bx.cx, filename); let line = C_u32(bx.cx, loc.line as u32); @@ -369,7 +378,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let file_line_col = consts::addr_of(bx.cx, file_line_col, align, - "panic_bounds_check_loc"); + Some("panic_bounds_check_loc")); (lang_items::PanicBoundsCheckFnLangItem, vec![file_line_col, index, len]) } @@ -383,7 +392,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let msg_file_line_col = consts::addr_of(bx.cx, msg_file_line_col, align, - "panic_loc"); + Some("panic_loc")); (lang_items::PanicFnLangItem, vec![msg_file_line_col]) } @@ -408,14 +417,14 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let callee = self.codegen_operand(&bx, func); let (instance, mut llfn) = match callee.layout.ty.sty { - ty::TyFnDef(def_id, substs) => { + ty::FnDef(def_id, substs) => { (Some(ty::Instance::resolve(bx.cx.tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap()), None) } - ty::TyFnPtr(_) => { + ty::FnPtr(_) => { (None, Some(callee.immediate())) } _ => bug!("{} is not callable", callee.layout.ty) @@ -593,11 +602,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // The callee needs to own the argument memory if we pass it // by-ref, so make a local copy of non-immediate constants. match (arg, op.val) { - (&mir::Operand::Copy(_), Ref(..)) | - (&mir::Operand::Constant(_), Ref(..)) => { + (&mir::Operand::Copy(_), Ref(_, None, _)) | + (&mir::Operand::Constant(_), Ref(_, None, _)) => { let tmp = PlaceRef::alloca(&bx, op.layout, "const"); op.val.store(&bx, tmp); - op.val = Ref(tmp.llval, tmp.align); + op.val = Ref(tmp.llval, None, tmp.align); } _ => {} } @@ -627,9 +636,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } fn codegen_argument(&mut self, - bx: &Builder<'a, 'tcx>, - op: OperandRef<'tcx>, - llargs: &mut Vec, + bx: &Builder<'a, 'll, 'tcx>, + op: OperandRef<'ll, 'tcx>, + llargs: &mut Vec<&'ll Value>, arg: &ArgType<'tcx, Ty<'tcx>>) { // Fill padding with undef value, where applicable. if let Some(ty) = arg.pad { @@ -647,7 +656,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { llargs.push(b); return; } - _ => bug!("codegen_argument: {:?} invalid for pair arugment", op) + _ => bug!("codegen_argument: {:?} invalid for pair argument", op) + } + } else if arg.is_unsized_indirect() { + match op.val { + Ref(a, Some(b), _) => { + llargs.push(a); + llargs.push(b); + return; + } + _ => bug!("codegen_argument: {:?} invalid for unsized indirect argument", op) } } @@ -655,7 +673,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let (mut llval, align, by_ref) = match op.val { Immediate(_) | Pair(..) => { match arg.mode { - PassMode::Indirect(_) | PassMode::Cast(_) => { + PassMode::Indirect(..) | PassMode::Cast(_) => { let scratch = PlaceRef::alloca(bx, arg.layout, "arg"); op.val.store(bx, scratch); (scratch.llval, scratch.align, true) @@ -665,7 +683,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } } - Ref(llval, align) => { + Ref(llval, _, align) => { if arg.is_indirect() && align.abi() < arg.layout.align.abi() { // `foo(packed.large_field)`. We can't pass the (unaligned) field directly. I // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't @@ -706,19 +724,21 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } fn codegen_arguments_untupled(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, operand: &mir::Operand<'tcx>, - llargs: &mut Vec, + llargs: &mut Vec<&'ll Value>, args: &[ArgType<'tcx, Ty<'tcx>>]) { let tuple = self.codegen_operand(bx, operand); // Handle both by-ref and immediate tuples. - if let Ref(llval, align) = tuple.val { + if let Ref(llval, None, align) = tuple.val { let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align); for i in 0..tuple.layout.fields.count() { let field_ptr = tuple_ptr.project_field(bx, i); self.codegen_argument(bx, field_ptr.load(bx), llargs, &args[i]); } + } else if let Ref(_, Some(_), _) = tuple.val { + bug!("closure arguments must be sized") } else { // If the tuple is immediate, the elements are as well. for i in 0..tuple.layout.fields.count() { @@ -728,7 +748,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - fn get_personality_slot(&mut self, bx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> { + fn get_personality_slot(&mut self, bx: &Builder<'a, 'll, 'tcx>) -> PlaceRef<'ll, 'tcx> { let cx = bx.cx; if let Some(slot) = self.personality_slot { slot @@ -746,7 +766,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { /// Return the landingpad wrapper around the given basic block /// /// No-op in MSVC SEH scheme. - fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> BasicBlockRef { + fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> &'ll BasicBlock { if let Some(block) = self.landing_pads[target_bb] { return block; } @@ -757,7 +777,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { landing_pad } - fn landing_pad_uncached(&mut self, target_bb: BasicBlockRef) -> BasicBlockRef { + fn landing_pad_uncached(&mut self, target_bb: &'ll BasicBlock) -> &'ll BasicBlock { if base::wants_msvc_seh(self.cx.sess()) { span_bug!(self.mir.span, "landing pad was not inserted?") } @@ -777,12 +797,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { bx.llbb() } - fn landing_pad_type(&self) -> Type { + fn landing_pad_type(&self) -> &'ll Type { let cx = self.cx; Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false) } - fn unreachable_block(&mut self) -> BasicBlockRef { + fn unreachable_block(&mut self) -> &'ll BasicBlock { self.unreachable_block.unwrap_or_else(|| { let bl = self.new_block("unreachable"); bl.unreachable(); @@ -791,20 +811,20 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { }) } - pub fn new_block(&self, name: &str) -> Builder<'a, 'tcx> { + pub fn new_block(&self, name: &str) -> Builder<'a, 'll, 'tcx> { Builder::new_block(self.cx, self.llfn, name) } - pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'tcx> { + pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'll, 'tcx> { let bx = Builder::with_cx(self.cx); bx.position_at_end(self.blocks[bb]); bx } - fn make_return_dest(&mut self, bx: &Builder<'a, 'tcx>, + fn make_return_dest(&mut self, bx: &Builder<'a, 'll, 'tcx>, dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx, Ty<'tcx>>, - llargs: &mut Vec, is_intrinsic: bool) - -> ReturnDest<'tcx> { + llargs: &mut Vec<&'ll Value>, is_intrinsic: bool) + -> ReturnDest<'ll, 'tcx> { // If the return is ignored, we can just return a do-nothing ReturnDest if fn_ret.is_ignore() { return ReturnDest::Nothing; @@ -812,6 +832,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let dest = if let mir::Place::Local(index) = *dest { match self.locals[index] { LocalRef::Place(dest) => dest, + LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), LocalRef::Operand(None) => { // Handle temporary places, specifically Operand ones, as // they don't have allocas @@ -857,12 +878,13 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - fn codegen_transmute(&mut self, bx: &Builder<'a, 'tcx>, + fn codegen_transmute(&mut self, bx: &Builder<'a, 'll, 'tcx>, src: &mir::Operand<'tcx>, dst: &mir::Place<'tcx>) { if let mir::Place::Local(index) = *dst { match self.locals[index] { LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), + LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"), LocalRef::Operand(None) => { let dst_layout = bx.cx.layout_of(self.monomorphized_place_ty(dst)); assert!(!dst_layout.ty.has_erasable_regions()); @@ -884,9 +906,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'tcx>, + fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'll, 'tcx>, src: &mir::Operand<'tcx>, - dst: PlaceRef<'tcx>) { + dst: PlaceRef<'ll, 'tcx>) { let src = self.codegen_operand(bx, src); let llty = src.layout.llvm_type(bx.cx); let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to()); @@ -897,10 +919,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // Stores the return value of a function call into it's final location. fn store_return(&mut self, - bx: &Builder<'a, 'tcx>, - dest: ReturnDest<'tcx>, + bx: &Builder<'a, 'll, 'tcx>, + dest: ReturnDest<'ll, 'tcx>, ret_ty: &ArgType<'tcx, Ty<'tcx>>, - llval: ValueRef) { + llval: &'ll Value) { use self::ReturnDest::*; match dest { @@ -929,13 +951,13 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } -enum ReturnDest<'tcx> { +enum ReturnDest<'ll, 'tcx> { // Do nothing, the return value is indirect or ignored Nothing, // Store the return value to the pointer - Store(PlaceRef<'tcx>), + Store(PlaceRef<'ll, 'tcx>), // Stores an indirect return value to an operand local place - IndirectOperand(PlaceRef<'tcx>, mir::Local), + IndirectOperand(PlaceRef<'ll, 'tcx>, mir::Local), // Stores a direct return value to an operand local place DirectOperand(mir::Local) } diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs index 0d682d5d6f..b6c9658dd6 100644 --- a/src/librustc_codegen_llvm/mir/constant.rs +++ b/src/librustc_codegen_llvm/mir/constant.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef}; -use rustc::mir::interpret::ConstEvalErr; -use rustc_mir::interpret::{read_target_uint, const_val_field}; +use llvm; +use rustc::mir::interpret::{ConstEvalErr, read_target_uint}; +use rustc_mir::interpret::{const_field}; use rustc::hir::def_id::DefId; use rustc::mir; use rustc_data_structures::indexed_vec::Idx; @@ -25,24 +25,29 @@ use consts; use type_of::LayoutLlvmExt; use type_::Type; use syntax::ast::Mutability; -use syntax::codemap::Span; +use syntax::source_map::Span; +use value::Value; use super::super::callee; use super::FunctionCx; -pub fn scalar_to_llvm(cx: &CodegenCx, - cv: Scalar, - layout: &layout::Scalar, - llty: Type) -> ValueRef { +pub fn scalar_to_llvm( + cx: &CodegenCx<'ll, '_>, + cv: Scalar, + layout: &layout::Scalar, + llty: &'ll Type, +) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.value.size(cx).bits() }; match cv { - Scalar::Bits { defined, .. } if (defined as u64) < bitsize || defined == 0 => { - C_undef(Type::ix(cx, bitsize)) + Scalar::Bits { size: 0, .. } => { + assert_eq!(0, layout.value.size(cx).bytes()); + C_undef(Type::ix(cx, 0)) }, - Scalar::Bits { bits, .. } => { + Scalar::Bits { bits, size } => { + assert_eq!(size as u64, layout.value.size(cx).bytes()); let llval = C_uint_big(Type::ix(cx, bitsize), bits); if layout.value == layout::Pointer { - unsafe { llvm::LLVMConstIntToPtr(llval, llty.to_ref()) } + unsafe { llvm::LLVMConstIntToPtr(llval, llty) } } else { consts::bitcast(llval, llty) } @@ -52,10 +57,10 @@ pub fn scalar_to_llvm(cx: &CodegenCx, let base_addr = match alloc_type { Some(AllocType::Memory(alloc)) => { let init = const_alloc_to_llvm(cx, alloc); - if alloc.runtime_mutability == Mutability::Mutable { - consts::addr_of_mut(cx, init, alloc.align, "byte_str") + if alloc.mutability == Mutability::Mutable { + consts::addr_of_mut(cx, init, alloc.align, None) } else { - consts::addr_of(cx, init, alloc.align, "byte_str") + consts::addr_of(cx, init, alloc.align, None) } } Some(AllocType::Function(fn_instance)) => { @@ -73,7 +78,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx, 1, ) }; if layout.value != layout::Pointer { - unsafe { llvm::LLVMConstPtrToInt(llval, llty.to_ref()) } + unsafe { llvm::LLVMConstPtrToInt(llval, llty) } } else { consts::bitcast(llval, llty) } @@ -81,7 +86,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx, } } -pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef { +pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1); let layout = cx.data_layout(); let pointer_size = layout.pointer_size.bytes() as usize; @@ -116,10 +121,10 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef { C_struct(cx, &llvals, true) } -pub fn codegen_static_initializer<'a, 'tcx>( - cx: &CodegenCx<'a, 'tcx>, +pub fn codegen_static_initializer( + cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, -) -> Result<(ValueRef, &'tcx Allocation), Lrc>> { +) -> Result<(&'ll Value, &'tcx Allocation), Lrc>> { let instance = ty::Instance::mono(cx.tcx, def_id); let cid = GlobalId { instance, @@ -129,16 +134,16 @@ pub fn codegen_static_initializer<'a, 'tcx>( let static_ = cx.tcx.const_eval(param_env.and(cid))?; let alloc = match static_.val { - ConstValue::ByRef(alloc, n) if n.bytes() == 0 => alloc, + ConstValue::ByRef(_, alloc, n) if n.bytes() == 0 => alloc, _ => bug!("static const eval returned {:#?}", static_), }; Ok((const_alloc_to_llvm(cx, alloc), alloc)) } -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { fn fully_evaluate( &mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, constant: &'tcx ty::Const<'tcx>, ) -> Result<&'tcx ty::Const<'tcx>, Lrc>> { match constant.val { @@ -158,7 +163,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { pub fn eval_mir_constant( &mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, constant: &mir::Constant<'tcx>, ) -> Result<&'tcx ty::Const<'tcx>, Lrc>> { let c = self.monomorphize(&constant.literal); @@ -168,20 +173,20 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { /// process constant containing SIMD shuffle indices pub fn simd_shuffle_indices( &mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, span: Span, ty: Ty<'tcx>, constant: Result<&'tcx ty::Const<'tcx>, Lrc>>, - ) -> (ValueRef, Ty<'tcx>) { + ) -> (&'ll Value, Ty<'tcx>) { constant .and_then(|c| { let field_ty = c.ty.builtin_index().unwrap(); let fields = match c.ty.sty { - ty::TyArray(_, n) => n.unwrap_usize(bx.tcx()), + ty::Array(_, n) => n.unwrap_usize(bx.tcx()), ref other => bug!("invalid simd shuffle type: {}", other), }; - let values: Result, Lrc<_>> = (0..fields).map(|field| { - let field = const_val_field( + let values: Result, Lrc<_>> = (0..fields).map(|field| { + let field = const_field( bx.tcx(), ty::ParamEnv::reveal_all(), self.instance, @@ -189,7 +194,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { mir::Field::new(field as usize), c, )?; - if let Some(prim) = field.to_scalar() { + if let Some(prim) = field.val.try_to_scalar() { let layout = bx.cx.layout_of(field_ty); let scalar = match layout.abi { layout::Abi::Scalar(ref x) => x, diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs index aaae7b3cf8..258fe643c3 100644 --- a/src/librustc_codegen_llvm/mir/mod.rs +++ b/src/librustc_codegen_llvm/mir/mod.rs @@ -10,13 +10,13 @@ use common::{C_i32, C_null}; use libc::c_uint; -use llvm::{self, ValueRef, BasicBlockRef}; +use llvm::{self, BasicBlock}; use llvm::debuginfo::DIScope; use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts}; use rustc::ty::layout::{LayoutOf, TyLayout}; use rustc::mir::{self, Mir}; use rustc::ty::subst::Substs; -use rustc::session::config::FullDebugInfo; +use rustc::session::config::DebugInfo; use base; use builder::Builder; use common::{CodegenCx, Funclet}; @@ -24,14 +24,15 @@ use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebug use monomorphize::Instance; use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode}; use type_::Type; +use value::Value; use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span}; use syntax::symbol::keywords; use std::iter; -use rustc_data_structures::bitvec::BitVector; -use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::indexed_vec::IndexVec; pub use self::constant::codegen_static_initializer; @@ -42,16 +43,16 @@ use rustc::mir::traversal; use self::operand::{OperandRef, OperandValue}; /// Master context for codegenning from MIR. -pub struct FunctionCx<'a, 'tcx:'a> { +pub struct FunctionCx<'a, 'll: 'a, 'tcx: 'll> { instance: Instance<'tcx>, mir: &'a mir::Mir<'tcx>, - debug_context: debuginfo::FunctionDebugContext, + debug_context: FunctionDebugContext<'ll>, - llfn: ValueRef, + llfn: &'ll Value, - cx: &'a CodegenCx<'a, 'tcx>, + cx: &'a CodegenCx<'ll, 'tcx>, fn_ty: FnType<'tcx, Ty<'tcx>>, @@ -62,24 +63,24 @@ pub struct FunctionCx<'a, 'tcx:'a> { /// don't really care about it very much. Anyway, this value /// contains an alloca into which the personality is stored and /// then later loaded when generating the DIVERGE_BLOCK. - personality_slot: Option>, + personality_slot: Option>, /// A `Block` for each MIR `BasicBlock` - blocks: IndexVec, + blocks: IndexVec, /// The funclet status of each basic block cleanup_kinds: IndexVec, /// When targeting MSVC, this stores the cleanup info for each funclet /// BB. This is initialized as we compute the funclets' head block in RPO. - funclets: &'a IndexVec>, + funclets: &'a IndexVec>>, /// This stores the landing-pad block for a given BB, computed lazily on GNU /// and eagerly on MSVC. - landing_pads: IndexVec>, + landing_pads: IndexVec>, /// Cached unreachable block - unreachable_block: Option, + unreachable_block: Option<&'ll BasicBlock>, /// The location where each MIR arg/var/tmp/ret is stored. This is /// usually an `PlaceRef` representing an alloca, but not always: @@ -96,16 +97,16 @@ pub struct FunctionCx<'a, 'tcx:'a> { /// /// Avoiding allocs can also be important for certain intrinsics, /// notably `expect`. - locals: IndexVec>, + locals: IndexVec>, /// Debug information for MIR scopes. - scopes: IndexVec, + scopes: IndexVec>, /// If this function is being monomorphized, this contains the type substitutions used. param_substs: &'tcx Substs<'tcx>, } -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn monomorphize(&self, value: &T) -> T where T: TypeFoldable<'tcx> { @@ -116,12 +117,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { ) } - pub fn set_debug_loc(&mut self, bx: &Builder, source_info: mir::SourceInfo) { + pub fn set_debug_loc(&mut self, bx: &Builder<'_, 'll, '_>, source_info: mir::SourceInfo) { let (scope, span) = self.debug_loc(source_info); debuginfo::set_source_location(&self.debug_context, bx, scope, span); } - pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) { + pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (Option<&'ll DIScope>, Span) { // Bail out if debug info emission is not enabled. match self.debug_context { FunctionDebugContext::DebugInfoDisabled | @@ -161,29 +162,34 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // corresponding to span's containing source scope. If so, we need to create a DIScope // "extension" into that file. fn scope_metadata_for_loc(&self, scope_id: mir::SourceScope, pos: BytePos) - -> llvm::debuginfo::DIScope { + -> Option<&'ll DIScope> { let scope_metadata = self.scopes[scope_id].scope_metadata; if pos < self.scopes[scope_id].file_start_pos || pos >= self.scopes[scope_id].file_end_pos { - let cm = self.cx.sess().codemap(); + let cm = self.cx.sess().source_map(); let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate; - debuginfo::extend_scope_to_file(self.cx, - scope_metadata, + Some(debuginfo::extend_scope_to_file(self.cx, + scope_metadata.unwrap(), &cm.lookup_char_pos(pos).file, - defining_crate) + defining_crate)) } else { scope_metadata } } } -enum LocalRef<'tcx> { - Place(PlaceRef<'tcx>), - Operand(Option>), +enum LocalRef<'ll, 'tcx> { + Place(PlaceRef<'ll, 'tcx>), + /// `UnsizedPlace(p)`: `p` itself is a thin pointer (indirect place). + /// `*p` is the fat pointer that references the actual unsized place. + /// Every time it is initialized, we have to reallocate the place + /// and update the fat pointer. That's the reason why it is indirect. + UnsizedPlace(PlaceRef<'ll, 'tcx>), + Operand(Option>), } -impl<'a, 'tcx> LocalRef<'tcx> { - fn new_operand(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> { +impl LocalRef<'ll, 'tcx> { + fn new_operand(cx: &CodegenCx<'ll, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'ll, 'tcx> { if layout.is_zst() { // Zero-size temporaries aren't always initialized, which // doesn't matter because they don't contain data, but @@ -197,9 +203,9 @@ impl<'a, 'tcx> LocalRef<'tcx> { /////////////////////////////////////////////////////////////////////////// -pub fn codegen_mir<'a, 'tcx: 'a>( - cx: &'a CodegenCx<'a, 'tcx>, - llfn: ValueRef, +pub fn codegen_mir( + cx: &'a CodegenCx<'ll, 'tcx>, + llfn: &'ll Value, mir: &'a Mir<'tcx>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, @@ -218,7 +224,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>( // Allocate a `Block` for every basic block, except // the start block, if nothing loops back to it. let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty(); - let block_bxs: IndexVec = + let block_bxs: IndexVec = mir.basic_blocks().indices().map(|bb| { if bb == mir::START_BLOCK && !reentrant_start_block { bx.llbb() @@ -266,7 +272,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>( if let Some(name) = decl.name { // User variable let debug_scope = fx.scopes[decl.visibility_scope]; - let dbg = debug_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo; + let dbg = debug_scope.is_valid() && bx.sess().opts.debuginfo == DebugInfo::Full; if !memory_locals.contains(local) && !dbg { debug!("alloc: {:?} ({}) -> operand", local, name); @@ -274,17 +280,24 @@ pub fn codegen_mir<'a, 'tcx: 'a>( } debug!("alloc: {:?} ({}) -> place", local, name); - let place = PlaceRef::alloca(&bx, layout, &name.as_str()); - if dbg { - let (scope, span) = fx.debug_loc(mir::SourceInfo { - span: decl.source_info.span, - scope: decl.visibility_scope, - }); - declare_local(&bx, &fx.debug_context, name, layout.ty, scope, - VariableAccess::DirectVariable { alloca: place.llval }, - VariableKind::LocalVariable, span); + if layout.is_unsized() { + let indirect_place = + PlaceRef::alloca_unsized_indirect(&bx, layout, &name.as_str()); + // FIXME: add an appropriate debuginfo + LocalRef::UnsizedPlace(indirect_place) + } else { + let place = PlaceRef::alloca(&bx, layout, &name.as_str()); + if dbg { + let (scope, span) = fx.debug_loc(mir::SourceInfo { + span: decl.source_info.span, + scope: decl.visibility_scope, + }); + declare_local(&bx, &fx.debug_context, name, layout.ty, scope.unwrap(), + VariableAccess::DirectVariable { alloca: place.llval }, + VariableKind::LocalVariable, span); + } + LocalRef::Place(place) } - LocalRef::Place(place) } else { // Temporary or return place if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() { @@ -293,7 +306,13 @@ pub fn codegen_mir<'a, 'tcx: 'a>( LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align)) } else if memory_locals.contains(local) { debug!("alloc: {:?} -> place", local); - LocalRef::Place(PlaceRef::alloca(&bx, layout, &format!("{:?}", local))) + if layout.is_unsized() { + let indirect_place = + PlaceRef::alloca_unsized_indirect(&bx, layout, &format!("{:?}", local)); + LocalRef::UnsizedPlace(indirect_place) + } else { + LocalRef::Place(PlaceRef::alloca(&bx, layout, &format!("{:?}", local))) + } } else { // If this is an immediate local, we do not create an // alloca in advance. Instead we wait until we see the @@ -322,7 +341,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>( debuginfo::start_emitting_source_locations(&fx.debug_context); let rpo = traversal::reverse_postorder(&mir); - let mut visited = BitVector::new(mir.basic_blocks().len()); + let mut visited = BitArray::new(mir.basic_blocks().len()); // Codegen the body of each block using reverse postorder for (bb, _) in rpo { @@ -343,13 +362,13 @@ pub fn codegen_mir<'a, 'tcx: 'a>( } } -fn create_funclets<'a, 'tcx>( +fn create_funclets( mir: &'a Mir<'tcx>, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, cleanup_kinds: &IndexVec, - block_bxs: &IndexVec) - -> (IndexVec>, - IndexVec>) + block_bxs: &IndexVec) + -> (IndexVec>, + IndexVec>>) { block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| { match *cleanup_kind { @@ -409,14 +428,15 @@ fn create_funclets<'a, 'tcx>( }).unzip() } -/// Produce, for each argument, a `ValueRef` pointing at the +/// Produce, for each argument, a `Value` pointing at the /// argument's value. As arguments are places, these are always /// indirect. -fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - fx: &FunctionCx<'a, 'tcx>, - scopes: &IndexVec, - memory_locals: &BitVector) - -> Vec> { +fn arg_local_refs( + bx: &Builder<'a, 'll, 'tcx>, + fx: &FunctionCx<'a, 'll, 'tcx>, + scopes: &IndexVec>, + memory_locals: &BitArray, +) -> Vec> { let mir = fx.mir; let tcx = bx.tcx(); let mut idx = 0; @@ -424,8 +444,8 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // Get the argument scope, if it exists and if we need it. let arg_scope = scopes[mir::OUTERMOST_SOURCE_SCOPE]; - let arg_scope = if arg_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo { - Some(arg_scope.scope_metadata) + let arg_scope = if bx.sess().opts.debuginfo == DebugInfo::Full { + arg_scope.scope_metadata } else { None }; @@ -447,7 +467,7 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, let arg_ty = fx.monomorphize(&arg_decl.ty); let tupled_arg_tys = match arg_ty.sty { - ty::TyTuple(ref tys) => tys, + ty::Tuple(ref tys) => tys, _ => bug!("spread argument isn't a tuple?!") }; @@ -521,7 +541,7 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, } } - let place = if arg.is_indirect() { + let place = if arg.is_sized_indirect() { // Don't copy an indirect argument to an alloca, the caller // already put it in a temporary alloca and gave it up. // FIXME: lifetimes @@ -529,6 +549,18 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, bx.set_value_name(llarg, &name); llarg_idx += 1; PlaceRef::new_sized(llarg, arg.layout, arg.layout.align) + } else if arg.is_unsized_indirect() { + // As the storage for the indirect argument lives during + // the whole function call, we just copy the fat pointer. + let llarg = llvm::get_param(bx.llfn(), llarg_idx as c_uint); + llarg_idx += 1; + let llextra = llvm::get_param(bx.llfn(), llarg_idx as c_uint); + llarg_idx += 1; + let indirect_operand = OperandValue::Pair(llarg, llextra); + + let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout, &name); + indirect_operand.store(&bx, tmp); + tmp } else { let tmp = PlaceRef::alloca(bx, arg.layout, &name); arg.store_fn_arg(bx, &mut llarg_idx, tmp); @@ -560,14 +592,14 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // Or is it the closure environment? let (closure_layout, env_ref) = match arg.layout.ty.sty { - ty::TyRawPtr(ty::TypeAndMut { ty, .. }) | - ty::TyRef(_, ty, _) => (bx.cx.layout_of(ty), true), + ty::RawPtr(ty::TypeAndMut { ty, .. }) | + ty::Ref(_, ty, _) => (bx.cx.layout_of(ty), true), _ => (arg.layout, false) }; let (def_id, upvar_substs) = match closure_layout.ty.sty { - ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), - ty::TyGenerator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), + ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), + ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), _ => bug!("upvar_decls with non-closure arg0 type `{}`", closure_layout.ty) }; let upvar_tys = upvar_substs.upvar_tys(def_id, tcx); @@ -607,7 +639,7 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // a pointer in an alloca for debuginfo atm. let mut ops = if env_ref || env_alloca { &ops[..] } else { &ops[1..] }; - let ty = if let (true, &ty::TyRef(_, ty, _)) = (decl.by_ref, &ty.sty) { + let ty = if let (true, &ty::Ref(_, ty, _)) = (decl.by_ref, &ty.sty) { ty } else { ops = &ops[..ops.len() - 1]; @@ -630,7 +662,11 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, ); } }); - LocalRef::Place(place) + if arg.is_unsized_indirect() { + LocalRef::UnsizedPlace(place) + } else { + LocalRef::Place(place) + } }).collect() } diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs index c433df5111..bfa0e0a451 100644 --- a/src/librustc_codegen_llvm/mir/operand.rs +++ b/src/librustc_codegen_llvm/mir/operand.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::ValueRef; use rustc::mir::interpret::ConstEvalErr; use rustc::mir; -use rustc::mir::interpret::ConstValue; +use rustc::mir::interpret::{ConstValue, ScalarMaybeUndef}; use rustc::ty; use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; -use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; use base; @@ -22,9 +20,10 @@ use common::{CodegenCx, C_undef, C_usize}; use builder::{Builder, MemFlags}; use value::Value; use type_of::LayoutLlvmExt; +use type_::Type; +use glue; use std::fmt; -use std::ptr; use super::{FunctionCx, LocalRef}; use super::constant::scalar_to_llvm; @@ -33,31 +32,17 @@ use super::place::PlaceRef; /// The representation of a Rust value. The enum variant is in fact /// uniquely determined by the value's type, but is kept as a /// safety check. -#[derive(Copy, Clone)] -pub enum OperandValue { +#[derive(Copy, Clone, Debug)] +pub enum OperandValue<'ll> { /// A reference to the actual operand. The data is guaranteed /// to be valid for the operand's lifetime. - Ref(ValueRef, Align), + /// The second value, if any, is the extra data (vtable or length) + /// which indicates that it refers to an unsized rvalue. + Ref(&'ll Value, Option<&'ll Value>, Align), /// A single LLVM value. - Immediate(ValueRef), + Immediate(&'ll Value), /// A pair of immediate LLVM values. Used by fat pointers too. - Pair(ValueRef, ValueRef) -} - -impl fmt::Debug for OperandValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - OperandValue::Ref(r, align) => { - write!(f, "Ref({:?}, {:?})", Value(r), align) - } - OperandValue::Immediate(i) => { - write!(f, "Immediate({:?})", Value(i)) - } - OperandValue::Pair(a, b) => { - write!(f, "Pair({:?}, {:?})", Value(a), Value(b)) - } - } - } + Pair(&'ll Value, &'ll Value) } /// An `OperandRef` is an "SSA" reference to a Rust value, along with @@ -69,23 +54,23 @@ impl fmt::Debug for OperandValue { /// directly is sure to cause problems -- use `OperandRef::store` /// instead. #[derive(Copy, Clone)] -pub struct OperandRef<'tcx> { +pub struct OperandRef<'ll, 'tcx> { // The value. - pub val: OperandValue, + pub val: OperandValue<'ll>, // The layout of value, based on its Rust type. pub layout: TyLayout<'tcx>, } -impl<'tcx> fmt::Debug for OperandRef<'tcx> { +impl fmt::Debug for OperandRef<'ll, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout) } } -impl<'a, 'tcx> OperandRef<'tcx> { - pub fn new_zst(cx: &CodegenCx<'a, 'tcx>, - layout: TyLayout<'tcx>) -> OperandRef<'tcx> { +impl OperandRef<'ll, 'tcx> { + pub fn new_zst(cx: &CodegenCx<'ll, 'tcx>, + layout: TyLayout<'tcx>) -> OperandRef<'ll, 'tcx> { assert!(layout.is_zst()); OperandRef { val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))), @@ -93,9 +78,9 @@ impl<'a, 'tcx> OperandRef<'tcx> { } } - pub fn from_const(bx: &Builder<'a, 'tcx>, + pub fn from_const(bx: &Builder<'a, 'll, 'tcx>, val: &'tcx ty::Const<'tcx>) - -> Result, Lrc>> { + -> Result, Lrc>> { let layout = bx.cx.layout_of(val.ty); if layout.is_zst() { @@ -128,15 +113,19 @@ impl<'a, 'tcx> OperandRef<'tcx> { a_scalar, layout.scalar_pair_element_llvm_type(bx.cx, 0, true), ); - let b_llval = scalar_to_llvm( - bx.cx, - b, - b_scalar, - layout.scalar_pair_element_llvm_type(bx.cx, 1, true), - ); + let b_layout = layout.scalar_pair_element_llvm_type(bx.cx, 1, true); + let b_llval = match b { + ScalarMaybeUndef::Scalar(b) => scalar_to_llvm( + bx.cx, + b, + b_scalar, + b_layout, + ), + ScalarMaybeUndef::Undef => C_undef(b_layout), + }; OperandValue::Pair(a_llval, b_llval) }, - ConstValue::ByRef(alloc, offset) => { + ConstValue::ByRef(_, alloc, offset) => { return Ok(PlaceRef::from_const_alloc(bx, layout, alloc, offset).load(bx)); }, }; @@ -149,19 +138,19 @@ impl<'a, 'tcx> OperandRef<'tcx> { /// Asserts that this operand refers to a scalar and returns /// a reference to its value. - pub fn immediate(self) -> ValueRef { + pub fn immediate(self) -> &'ll Value { match self.val { OperandValue::Immediate(s) => s, _ => bug!("not immediate: {:?}", self) } } - pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> { + pub fn deref(self, cx: &CodegenCx<'ll, 'tcx>) -> PlaceRef<'ll, 'tcx> { let projected_ty = self.layout.ty.builtin_deref(true) .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty; let (llptr, llextra) = match self.val { - OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()), - OperandValue::Pair(llptr, llextra) => (llptr, llextra), + OperandValue::Immediate(llptr) => (llptr, None), + OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)), OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self) }; let layout = cx.layout_of(projected_ty); @@ -175,7 +164,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { /// If this operand is a `Pair`, we return an aggregate with the two values. /// For other cases, see `immediate`. - pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'tcx>) -> ValueRef { + pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'll, 'tcx>) -> &'ll Value { if let OperandValue::Pair(a, b) = self.val { let llty = self.layout.llvm_type(bx.cx); debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", @@ -191,10 +180,10 @@ impl<'a, 'tcx> OperandRef<'tcx> { } /// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`. - pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'tcx>, - llval: ValueRef, + pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'll, 'tcx>, + llval: &'ll Value, layout: TyLayout<'tcx>) - -> OperandRef<'tcx> { + -> OperandRef<'ll, 'tcx> { let val = if let layout::Abi::ScalarPair(ref a, ref b) = layout.abi { debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", llval, layout); @@ -209,7 +198,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { OperandRef { val, layout } } - pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx> { + pub fn extract_field(&self, bx: &Builder<'a, 'll, 'tcx>, i: usize) -> OperandRef<'ll, 'tcx> { let field = self.layout.field(bx.cx, i); let offset = self.layout.fields.offset(i); @@ -267,24 +256,29 @@ impl<'a, 'tcx> OperandRef<'tcx> { } } -impl<'a, 'tcx> OperandValue { - pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { +impl OperandValue<'ll> { + pub fn store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) { self.store_with_flags(bx, dest, MemFlags::empty()); } - pub fn volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + pub fn volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) { self.store_with_flags(bx, dest, MemFlags::VOLATILE); } - pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) { self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED); } - pub fn nontemporal_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + pub fn nontemporal_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) { self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL); } - fn store_with_flags(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, flags: MemFlags) { + fn store_with_flags( + self, + bx: &Builder<'a, 'll, 'tcx>, + dest: PlaceRef<'ll, 'tcx>, + flags: MemFlags, + ) { debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest); // Avoid generating stores of zero-sized values, because the only way to have a zero-sized // value is through `undef`, and store itself is useless. @@ -292,10 +286,13 @@ impl<'a, 'tcx> OperandValue { return; } match self { - OperandValue::Ref(r, source_align) => { + OperandValue::Ref(r, None, source_align) => { base::memcpy_ty(bx, dest.llval, r, dest.layout, source_align.min(dest.align), flags) } + OperandValue::Ref(_, Some(_), _) => { + bug!("cannot directly store unsized values"); + } OperandValue::Immediate(s) => { let val = base::from_immediate(bx, s); bx.store_with_flags(val, dest.llval, dest.align, flags); @@ -309,13 +306,42 @@ impl<'a, 'tcx> OperandValue { } } } + + pub fn store_unsized(self, bx: &Builder<'a, 'll, 'tcx>, indirect_dest: PlaceRef<'ll, 'tcx>) { + debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest); + let flags = MemFlags::empty(); + + // `indirect_dest` must have `*mut T` type. We extract `T` out of it. + let unsized_ty = indirect_dest.layout.ty.builtin_deref(true) + .unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest)).ty; + + let (llptr, llextra) = + if let OperandValue::Ref(llptr, Some(llextra), _) = self { + (llptr, llextra) + } else { + bug!("store_unsized called with a sized value") + }; + + // FIXME: choose an appropriate alignment, or use dynamic align somehow + let max_align = Align::from_bits(128, 128).unwrap(); + let min_align = Align::from_bits(8, 8).unwrap(); + + // Allocate an appropriate region on the stack, and copy the value into it + let (llsize, _) = glue::size_and_align_of_dst(&bx, unsized_ty, Some(llextra)); + let lldst = bx.array_alloca(Type::i8(bx.cx), llsize, "unsized_tmp", max_align); + base::call_memcpy(&bx, lldst, llptr, llsize, min_align, flags); + + // Store the allocated region and the extra to the indirect place. + let indirect_operand = OperandValue::Pair(lldst, llextra); + indirect_operand.store(&bx, indirect_dest); + } } -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { fn maybe_codegen_consume_direct(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, place: &mir::Place<'tcx>) - -> Option> + -> Option> { debug!("maybe_codegen_consume_direct(place={:?})", place); @@ -329,7 +355,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { LocalRef::Operand(None) => { bug!("use of {:?} before def", place); } - LocalRef::Place(..) => { + LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => { // use path below } } @@ -361,9 +387,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } pub fn codegen_consume(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, place: &mir::Place<'tcx>) - -> OperandRef<'tcx> + -> OperandRef<'ll, 'tcx> { debug!("codegen_consume(place={:?})", place); @@ -385,9 +411,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } pub fn codegen_operand(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, operand: &mir::Operand<'tcx>) - -> OperandRef<'tcx> + -> OperandRef<'ll, 'tcx> { debug!("codegen_operand(operand={:?})", operand); diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs index 9abf9077a9..70ace15e52 100644 --- a/src/librustc_codegen_llvm/mir/place.rs +++ b/src/librustc_codegen_llvm/mir/place.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef, LLVMConstInBoundsGEP}; +use llvm::{self, LLVMConstInBoundsGEP}; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size}; use rustc::mir; use rustc::mir::tcx::PlaceTy; -use rustc_data_structures::indexed_vec::Idx; use base; use builder::Builder; use common::{CodegenCx, C_undef, C_usize, C_u8, C_u32, C_uint, C_null, C_uint_big}; @@ -24,18 +23,16 @@ use value::Value; use glue; use mir::constant::const_alloc_to_llvm; -use std::ptr; - use super::{FunctionCx, LocalRef}; use super::operand::{OperandRef, OperandValue}; #[derive(Copy, Clone, Debug)] -pub struct PlaceRef<'tcx> { +pub struct PlaceRef<'ll, 'tcx> { /// Pointer to the contents of the place - pub llval: ValueRef, + pub llval: &'ll Value, /// This place's extra data if it is unsized, or null - pub llextra: ValueRef, + pub llextra: Option<&'ll Value>, /// Monomorphized type of this place, including variant information pub layout: TyLayout<'tcx>, @@ -44,27 +41,29 @@ pub struct PlaceRef<'tcx> { pub align: Align, } -impl<'a, 'tcx> PlaceRef<'tcx> { - pub fn new_sized(llval: ValueRef, - layout: TyLayout<'tcx>, - align: Align) - -> PlaceRef<'tcx> { +impl PlaceRef<'ll, 'tcx> { + pub fn new_sized( + llval: &'ll Value, + layout: TyLayout<'tcx>, + align: Align, + ) -> PlaceRef<'ll, 'tcx> { + assert!(!layout.is_unsized()); PlaceRef { llval, - llextra: ptr::null_mut(), + llextra: None, layout, align } } pub fn from_const_alloc( - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, layout: TyLayout<'tcx>, alloc: &mir::interpret::Allocation, offset: Size, - ) -> PlaceRef<'tcx> { + ) -> PlaceRef<'ll, 'tcx> { let init = const_alloc_to_llvm(bx.cx, alloc); - let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str"); + let base_addr = consts::addr_of(bx.cx, init, layout.align, None); let llval = unsafe { LLVMConstInBoundsGEP( consts::bitcast(base_addr, Type::i8p(bx.cx)), @@ -75,19 +74,29 @@ impl<'a, 'tcx> PlaceRef<'tcx> { PlaceRef::new_sized(llval, layout, alloc.align) } - pub fn alloca(bx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str) - -> PlaceRef<'tcx> { + pub fn alloca(bx: &Builder<'a, 'll, 'tcx>, layout: TyLayout<'tcx>, name: &str) + -> PlaceRef<'ll, 'tcx> { debug!("alloca({:?}: {:?})", name, layout); + assert!(!layout.is_unsized(), "tried to statically allocate unsized place"); let tmp = bx.alloca(layout.llvm_type(bx.cx), name, layout.align); Self::new_sized(tmp, layout, layout.align) } - pub fn len(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef { + /// Returns a place for an indirect reference to an unsized place. + pub fn alloca_unsized_indirect(bx: &Builder<'a, 'll, 'tcx>, layout: TyLayout<'tcx>, name: &str) + -> PlaceRef<'ll, 'tcx> { + debug!("alloca_unsized_indirect({:?}: {:?})", name, layout); + assert!(layout.is_unsized(), "tried to allocate indirect place for sized values"); + let ptr_ty = bx.cx.tcx.mk_mut_ptr(layout.ty); + let ptr_layout = bx.cx.layout_of(ptr_ty); + Self::alloca(bx, ptr_layout, name) + } + + pub fn len(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Value { if let layout::FieldPlacement::Array { count, .. } = self.layout.fields { if self.layout.is_unsized() { - assert!(self.has_extra()); assert_eq!(count, 0); - self.llextra + self.llextra.unwrap() } else { C_usize(cx, count) } @@ -96,14 +105,10 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } } - pub fn has_extra(&self) -> bool { - !self.llextra.is_null() - } - - pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> { + pub fn load(&self, bx: &Builder<'a, 'll, 'tcx>) -> OperandRef<'ll, 'tcx> { debug!("PlaceRef::load: {:?}", self); - assert!(!self.has_extra()); + assert_eq!(self.llextra.is_some(), self.layout.is_unsized()); if self.layout.is_zst() { return OperandRef::new_zst(bx.cx, self.layout); @@ -125,24 +130,24 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } }; - let val = if self.layout.is_llvm_immediate() { - let mut const_llval = ptr::null_mut(); + let val = if let Some(llextra) = self.llextra { + OperandValue::Ref(self.llval, Some(llextra), self.align) + } else if self.layout.is_llvm_immediate() { + let mut const_llval = None; unsafe { - let global = llvm::LLVMIsAGlobalVariable(self.llval); - if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True { - const_llval = llvm::LLVMGetInitializer(global); + if let Some(global) = llvm::LLVMIsAGlobalVariable(self.llval) { + if llvm::LLVMIsGlobalConstant(global) == llvm::True { + const_llval = llvm::LLVMGetInitializer(global); + } } } - - let llval = if !const_llval.is_null() { - const_llval - } else { + let llval = const_llval.unwrap_or_else(|| { let load = bx.load(self.llval, self.align); if let layout::Abi::Scalar(ref scalar) = self.layout.abi { scalar_load_metadata(load, scalar); } load - }; + }); OperandValue::Immediate(base::to_immediate(bx, llval, self.layout)) } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi { let load = |i, scalar: &layout::Scalar| { @@ -157,18 +162,21 @@ impl<'a, 'tcx> PlaceRef<'tcx> { }; OperandValue::Pair(load(0, a), load(1, b)) } else { - OperandValue::Ref(self.llval, self.align) + OperandValue::Ref(self.llval, None, self.align) }; OperandRef { val, layout: self.layout } } /// Access a field, at a point when the value's case is known. - pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> { + pub fn project_field(self, bx: &Builder<'a, 'll, 'tcx>, ix: usize) -> PlaceRef<'ll, 'tcx> { let cx = bx.cx; let field = self.layout.field(cx, ix); let offset = self.layout.fields.offset(ix); - let align = self.align.min(self.layout.align).min(field.align); + let effective_field_align = self.align + .min(self.layout.align) + .min(field.align) + .restrict_for_offset(offset); let simple = || { // Unions and newtypes only use an offset of 0. @@ -187,10 +195,10 @@ impl<'a, 'tcx> PlaceRef<'tcx> { llextra: if cx.type_has_metadata(field.ty) { self.llextra } else { - ptr::null_mut() + None }, layout: field, - align, + align: effective_field_align, } }; @@ -199,14 +207,14 @@ impl<'a, 'tcx> PlaceRef<'tcx> { // * known alignment - sized types, [T], str or a foreign type // * packed struct - there is no alignment padding match field.ty.sty { - _ if !self.has_extra() => { + _ if self.llextra.is_none() => { debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment", - ix, Value(self.llval)); + ix, self.llval); return simple(); } _ if !field.is_unsized() => return simple(), - ty::TySlice(..) | ty::TyStr | ty::TyForeign(..) => return simple(), - ty::TyAdt(def, _) => { + ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(), + ty::Adt(def, _) => { if def.repr.packed() { // FIXME(eddyb) generalize the adjustment when we // start supporting packing to larger alignments. @@ -249,7 +257,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { let offset = bx.and(bx.add(unaligned_offset, align_sub_1), bx.neg(unsized_align)); - debug!("struct_field_ptr: DST field offset: {:?}", Value(offset)); + debug!("struct_field_ptr: DST field offset: {:?}", offset); // Cast and adjust pointer let byte_ptr = bx.pointercast(self.llval, Type::i8p(cx)); @@ -263,12 +271,12 @@ impl<'a, 'tcx> PlaceRef<'tcx> { llval: bx.pointercast(byte_ptr, ll_fty.ptr_to()), llextra: self.llextra, layout: field, - align, + align: effective_field_align, } } /// Obtain the actual discriminant of a value. - pub fn codegen_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef { + pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value { let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx); if self.layout.abi == layout::Abi::Uninhabited { return C_undef(cast_to); @@ -332,7 +340,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { /// Set the discriminant for a new value of the given case of the given /// representation. - pub fn codegen_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) { + pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) { if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited { return; } @@ -386,18 +394,18 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } } - pub fn project_index(&self, bx: &Builder<'a, 'tcx>, llindex: ValueRef) - -> PlaceRef<'tcx> { + pub fn project_index(&self, bx: &Builder<'a, 'll, 'tcx>, llindex: &'ll Value) + -> PlaceRef<'ll, 'tcx> { PlaceRef { llval: bx.inbounds_gep(self.llval, &[C_usize(bx.cx, 0), llindex]), - llextra: ptr::null_mut(), + llextra: None, layout: self.layout.field(bx.cx, 0), align: self.align } } - pub fn project_downcast(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) - -> PlaceRef<'tcx> { + pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) + -> PlaceRef<'ll, 'tcx> { let mut downcast = *self; downcast.layout = self.layout.for_variant(bx.cx, variant_index); @@ -408,20 +416,20 @@ impl<'a, 'tcx> PlaceRef<'tcx> { downcast } - pub fn storage_live(&self, bx: &Builder<'a, 'tcx>) { + pub fn storage_live(&self, bx: &Builder<'a, 'll, 'tcx>) { bx.lifetime_start(self.llval, self.layout.size); } - pub fn storage_dead(&self, bx: &Builder<'a, 'tcx>) { + pub fn storage_dead(&self, bx: &Builder<'a, 'll, 'tcx>) { bx.lifetime_end(self.llval, self.layout.size); } } -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_place(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, place: &mir::Place<'tcx>) - -> PlaceRef<'tcx> { + -> PlaceRef<'ll, 'tcx> { debug!("codegen_place(place={:?})", place); let cx = bx.cx; @@ -432,6 +440,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { LocalRef::Place(place) => { return place; } + LocalRef::UnsizedPlace(place) => { + return place.load(bx).deref(&cx); + } LocalRef::Operand(..) => { bug!("using operand local {:?} as place", place); } @@ -449,7 +460,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { 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) => { + mir::interpret::ConstValue::ByRef(_, alloc, offset) => { PlaceRef::from_const_alloc(bx, layout, alloc, offset) } _ => bug!("promoteds should have an allocation: {:?}", val), @@ -513,9 +524,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty)); if subslice.layout.is_unsized() { - assert!(cg_base.has_extra()); - subslice.llextra = bx.sub(cg_base.llextra, - C_usize(bx.cx, (from as u64) + (to as u64))); + subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(), + C_usize(bx.cx, (from as u64) + (to as u64)))); } // Cast the place pointer type to the new diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs index 2e81fc16a5..c3ec347f60 100644 --- a/src/librustc_codegen_llvm/mir/rvalue.rs +++ b/src/librustc_codegen_llvm/mir/rvalue.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef}; +use llvm; use rustc::ty::{self, Ty}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf}; @@ -32,15 +32,15 @@ use super::{FunctionCx, LocalRef}; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_rvalue(&mut self, - bx: Builder<'a, 'tcx>, - dest: PlaceRef<'tcx>, + bx: Builder<'a, 'll, 'tcx>, + dest: PlaceRef<'ll, 'tcx>, rvalue: &mir::Rvalue<'tcx>) - -> Builder<'a, 'tcx> + -> Builder<'a, 'll, 'tcx> { debug!("codegen_rvalue(dest.llval={:?}, rvalue={:?})", - Value(dest.llval), rvalue); + dest.llval, rvalue); match *rvalue { mir::Rvalue::Use(ref operand) => { @@ -83,10 +83,13 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { base::coerce_unsized_into(&bx, scratch, dest); scratch.storage_dead(&bx); } - OperandValue::Ref(llref, align) => { + OperandValue::Ref(llref, None, align) => { let source = PlaceRef::new_sized(llref, operand.layout, align); base::coerce_unsized_into(&bx, source, dest); } + OperandValue::Ref(_, Some(_), _) => { + bug!("unsized coercion on an unsized rvalue") + } } bx } @@ -145,7 +148,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { mir::Rvalue::Aggregate(ref kind, ref operands) => { let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => { + mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { dest.codegen_set_discr(&bx, variant_index); if adt_def.is_enum() { (dest.project_downcast(&bx, variant_index), active_field_index) @@ -175,10 +178,30 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } + pub fn codegen_rvalue_unsized(&mut self, + bx: Builder<'a, 'll, 'tcx>, + indirect_dest: PlaceRef<'ll, 'tcx>, + rvalue: &mir::Rvalue<'tcx>) + -> Builder<'a, 'll, 'tcx> + { + debug!("codegen_rvalue_unsized(indirect_dest.llval={:?}, rvalue={:?})", + indirect_dest.llval, rvalue); + + match *rvalue { + mir::Rvalue::Use(ref operand) => { + let cg_operand = self.codegen_operand(&bx, operand); + cg_operand.val.store_unsized(&bx, indirect_dest); + bx + } + + _ => bug!("unsized assignment other than Rvalue::Use"), + } + } + pub fn codegen_rvalue_operand(&mut self, - bx: Builder<'a, 'tcx>, + bx: Builder<'a, 'll, 'tcx>, rvalue: &mir::Rvalue<'tcx>) - -> (Builder<'a, 'tcx>, OperandRef<'tcx>) + -> (Builder<'a, 'll, 'tcx>, OperandRef<'ll, 'tcx>) { assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue); @@ -191,7 +214,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let val = match *kind { mir::CastKind::ReifyFnPointer => { match operand.layout.ty.sty { - ty::TyFnDef(def_id, substs) => { + ty::FnDef(def_id, substs) => { if bx.cx.tcx.has_attr(def_id, "rustc_args_required_const") { bug!("reifying a fn ptr that requires \ const arguments"); @@ -206,7 +229,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } mir::CastKind::ClosureFnPointer => { match operand.layout.ty.sty { - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { let instance = monomorphize::resolve_closure( bx.cx.tcx, def_id, substs, ty::ClosureKind::FnOnce); OperandValue::Immediate(callee::get_fn(bx.cx, instance)) @@ -304,7 +327,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // then `i1 1` (i.e. E::B) is effectively `i8 -1`. signed = !scalar.is_bool() && s; - if scalar.valid_range.end() > scalar.valid_range.start() { + let er = scalar.valid_range_exclusive(bx.cx); + if er.end != er.start && + scalar.valid_range.end() > scalar.valid_range.start() { // We want `table[e as usize]` to not // have bound checks, and this is the most // convenient place to put the `assume`. @@ -371,7 +396,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let val = if !bx.cx.type_has_metadata(ty) { OperandValue::Immediate(cg_place.llval) } else { - OperandValue::Pair(cg_place.llval, cg_place.llextra) + OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap()) }; (bx, OperandRef { val, @@ -511,15 +536,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - fn evaluate_array_len(&mut self, - bx: &Builder<'a, 'tcx>, - place: &mir::Place<'tcx>) -> ValueRef - { + fn evaluate_array_len( + &mut self, + bx: &Builder<'a, 'll, 'tcx>, + place: &mir::Place<'tcx>, + ) -> &'ll Value { // ZST are passed as operands and require special handling // because codegen_place() panics if Local is operand. if let mir::Place::Local(index) = *place { if let LocalRef::Operand(Some(op)) = self.locals[index] { - if let ty::TyArray(_, n) = op.layout.ty.sty { + if let ty::Array(_, n) = op.layout.ty.sty { let n = n.unwrap_usize(bx.cx.tcx); return common::C_usize(bx.cx, n); } @@ -530,15 +556,17 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { return cg_value.len(bx.cx); } - pub fn codegen_scalar_binop(&mut self, - bx: &Builder<'a, 'tcx>, - op: mir::BinOp, - lhs: ValueRef, - rhs: ValueRef, - input_ty: Ty<'tcx>) -> ValueRef { + pub fn codegen_scalar_binop( + &mut self, + bx: &Builder<'a, 'll, 'tcx>, + op: mir::BinOp, + lhs: &'ll Value, + rhs: &'ll Value, + input_ty: Ty<'tcx>, + ) -> &'ll Value { let is_float = input_ty.is_fp(); let is_signed = input_ty.is_signed(); - let is_nil = input_ty.is_nil(); + let is_unit = input_ty.is_unit(); match op { mir::BinOp::Add => if is_float { bx.fadd(lhs, rhs) @@ -576,7 +604,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs), mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs), mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt | - mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_nil { + mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_unit { C_bool(bx.cx, match op { mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false, mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true, @@ -596,15 +624,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - pub fn codegen_fat_ptr_binop(&mut self, - bx: &Builder<'a, 'tcx>, - op: mir::BinOp, - lhs_addr: ValueRef, - lhs_extra: ValueRef, - rhs_addr: ValueRef, - rhs_extra: ValueRef, - _input_ty: Ty<'tcx>) - -> ValueRef { + pub fn codegen_fat_ptr_binop( + &mut self, + bx: &Builder<'a, 'll, 'tcx>, + op: mir::BinOp, + lhs_addr: &'ll Value, + lhs_extra: &'ll Value, + rhs_addr: &'ll Value, + rhs_extra: &'ll Value, + _input_ty: Ty<'tcx>, + ) -> &'ll Value { match op { mir::BinOp::Eq => { bx.and( @@ -644,11 +673,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } pub fn codegen_scalar_checked_binop(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, op: mir::BinOp, - lhs: ValueRef, - rhs: ValueRef, - input_ty: Ty<'tcx>) -> OperandValue { + lhs: &'ll Value, + rhs: &'ll Value, + input_ty: Ty<'tcx>) -> OperandValue<'ll> { // This case can currently arise only from functions marked // with #[rustc_inherit_overflow_checks] and inlined from // another crate (mostly core::num generic/#[inline] fns), @@ -721,73 +750,63 @@ enum OverflowOp { Add, Sub, Mul } -fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef { +fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder<'_, 'll, '_>, ty: Ty) -> &'ll Value { use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; - use rustc::ty::{TyInt, TyUint}; + use rustc::ty::{Int, Uint}; let tcx = bx.tcx(); let new_sty = match ty.sty { - TyInt(Isize) => match &tcx.sess.target.target.target_pointer_width[..] { - "16" => TyInt(I16), - "32" => TyInt(I32), - "64" => TyInt(I64), - _ => panic!("unsupported target word size") - }, - TyUint(Usize) => match &tcx.sess.target.target.target_pointer_width[..] { - "16" => TyUint(U16), - "32" => TyUint(U32), - "64" => TyUint(U64), - _ => panic!("unsupported target word size") - }, - ref t @ TyUint(_) | ref t @ TyInt(_) => t.clone(), + Int(Isize) => Int(tcx.sess.target.isize_ty), + Uint(Usize) => Uint(tcx.sess.target.usize_ty), + ref t @ Uint(_) | ref t @ Int(_) => t.clone(), _ => panic!("tried to get overflow intrinsic for op applied to non-int type") }; let name = match oop { OverflowOp::Add => match new_sty { - TyInt(I8) => "llvm.sadd.with.overflow.i8", - TyInt(I16) => "llvm.sadd.with.overflow.i16", - TyInt(I32) => "llvm.sadd.with.overflow.i32", - TyInt(I64) => "llvm.sadd.with.overflow.i64", - TyInt(I128) => "llvm.sadd.with.overflow.i128", - - TyUint(U8) => "llvm.uadd.with.overflow.i8", - TyUint(U16) => "llvm.uadd.with.overflow.i16", - TyUint(U32) => "llvm.uadd.with.overflow.i32", - TyUint(U64) => "llvm.uadd.with.overflow.i64", - TyUint(U128) => "llvm.uadd.with.overflow.i128", + Int(I8) => "llvm.sadd.with.overflow.i8", + Int(I16) => "llvm.sadd.with.overflow.i16", + Int(I32) => "llvm.sadd.with.overflow.i32", + Int(I64) => "llvm.sadd.with.overflow.i64", + Int(I128) => "llvm.sadd.with.overflow.i128", + + Uint(U8) => "llvm.uadd.with.overflow.i8", + Uint(U16) => "llvm.uadd.with.overflow.i16", + Uint(U32) => "llvm.uadd.with.overflow.i32", + Uint(U64) => "llvm.uadd.with.overflow.i64", + Uint(U128) => "llvm.uadd.with.overflow.i128", _ => unreachable!(), }, OverflowOp::Sub => match new_sty { - TyInt(I8) => "llvm.ssub.with.overflow.i8", - TyInt(I16) => "llvm.ssub.with.overflow.i16", - TyInt(I32) => "llvm.ssub.with.overflow.i32", - TyInt(I64) => "llvm.ssub.with.overflow.i64", - TyInt(I128) => "llvm.ssub.with.overflow.i128", - - TyUint(U8) => "llvm.usub.with.overflow.i8", - TyUint(U16) => "llvm.usub.with.overflow.i16", - TyUint(U32) => "llvm.usub.with.overflow.i32", - TyUint(U64) => "llvm.usub.with.overflow.i64", - TyUint(U128) => "llvm.usub.with.overflow.i128", + Int(I8) => "llvm.ssub.with.overflow.i8", + Int(I16) => "llvm.ssub.with.overflow.i16", + Int(I32) => "llvm.ssub.with.overflow.i32", + Int(I64) => "llvm.ssub.with.overflow.i64", + Int(I128) => "llvm.ssub.with.overflow.i128", + + Uint(U8) => "llvm.usub.with.overflow.i8", + Uint(U16) => "llvm.usub.with.overflow.i16", + Uint(U32) => "llvm.usub.with.overflow.i32", + Uint(U64) => "llvm.usub.with.overflow.i64", + Uint(U128) => "llvm.usub.with.overflow.i128", _ => unreachable!(), }, OverflowOp::Mul => match new_sty { - TyInt(I8) => "llvm.smul.with.overflow.i8", - TyInt(I16) => "llvm.smul.with.overflow.i16", - TyInt(I32) => "llvm.smul.with.overflow.i32", - TyInt(I64) => "llvm.smul.with.overflow.i64", - TyInt(I128) => "llvm.smul.with.overflow.i128", - - TyUint(U8) => "llvm.umul.with.overflow.i8", - TyUint(U16) => "llvm.umul.with.overflow.i16", - TyUint(U32) => "llvm.umul.with.overflow.i32", - TyUint(U64) => "llvm.umul.with.overflow.i64", - TyUint(U128) => "llvm.umul.with.overflow.i128", + Int(I8) => "llvm.smul.with.overflow.i8", + Int(I16) => "llvm.smul.with.overflow.i16", + Int(I32) => "llvm.smul.with.overflow.i32", + Int(I64) => "llvm.smul.with.overflow.i64", + Int(I128) => "llvm.smul.with.overflow.i128", + + Uint(U8) => "llvm.umul.with.overflow.i8", + Uint(U16) => "llvm.umul.with.overflow.i16", + Uint(U32) => "llvm.umul.with.overflow.i32", + Uint(U64) => "llvm.umul.with.overflow.i64", + Uint(U128) => "llvm.umul.with.overflow.i128", _ => unreachable!(), }, @@ -796,11 +815,11 @@ fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef { bx.cx.get_intrinsic(&name) } -fn cast_int_to_float(bx: &Builder, +fn cast_int_to_float(bx: &Builder<'_, 'll, '_>, signed: bool, - x: ValueRef, - int_ty: Type, - float_ty: Type) -> ValueRef { + x: &'ll Value, + int_ty: &'ll Type, + float_ty: &'ll Type) -> &'ll Value { // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding. // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity). // LLVM's uitofp produces undef in those cases, so we manually check for that case. @@ -826,11 +845,11 @@ fn cast_int_to_float(bx: &Builder, } } -fn cast_float_to_int(bx: &Builder, +fn cast_float_to_int(bx: &Builder<'_, 'll, '_>, signed: bool, - x: ValueRef, - float_ty: Type, - int_ty: Type) -> ValueRef { + x: &'ll Value, + float_ty: &'ll Type, + int_ty: &'ll Type) -> &'ll Value { let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { @@ -859,14 +878,14 @@ fn cast_float_to_int(bx: &Builder, // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because // we're rounding towards zero, we just get float_ty::MAX (which is always an integer). // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX. - fn compute_clamp_bounds(signed: bool, int_ty: Type) -> (u128, u128) { + fn compute_clamp_bounds(signed: bool, int_ty: &Type) -> (u128, u128) { let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero); assert_eq!(rounded_min.status, Status::OK); let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero); assert!(rounded_max.value.is_finite()); (rounded_min.value.to_bits(), rounded_max.value.to_bits()) } - fn int_max(signed: bool, int_ty: Type) -> u128 { + fn int_max(signed: bool, int_ty: &Type) -> u128 { let shift_amount = 128 - int_ty.int_width(); if signed { i128::MAX as u128 >> shift_amount @@ -874,7 +893,7 @@ fn cast_float_to_int(bx: &Builder, u128::MAX >> shift_amount } } - fn int_min(signed: bool, int_ty: Type) -> i128 { + fn int_min(signed: bool, int_ty: &Type) -> i128 { if signed { i128::MIN >> (128 - int_ty.int_width()) } else { diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs index c0cce297ef..0cb8f99efc 100644 --- a/src/librustc_codegen_llvm/mir/statement.rs +++ b/src/librustc_codegen_llvm/mir/statement.rs @@ -16,11 +16,11 @@ use builder::Builder; use super::FunctionCx; use super::LocalRef; -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_statement(&mut self, - bx: Builder<'a, 'tcx>, + bx: Builder<'a, 'll, 'tcx>, statement: &mir::Statement<'tcx>) - -> Builder<'a, 'tcx> { + -> Builder<'a, 'll, 'tcx> { debug!("codegen_statement(statement={:?})", statement); self.set_debug_loc(&bx, statement.source_info); @@ -31,6 +31,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { LocalRef::Place(cg_dest) => { self.codegen_rvalue(bx, cg_dest, rvalue) } + LocalRef::UnsizedPlace(cg_indirect_dest) => { + self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue) + } LocalRef::Operand(None) => { let (bx, operand) = self.codegen_rvalue_operand(bx, rvalue); self.locals[index] = LocalRef::Operand(Some(operand)); @@ -61,12 +64,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { mir::StatementKind::StorageLive(local) => { if let LocalRef::Place(cg_place) = self.locals[local] { cg_place.storage_live(&bx); + } else if let LocalRef::UnsizedPlace(cg_indirect_place) = self.locals[local] { + cg_indirect_place.storage_live(&bx); } bx } mir::StatementKind::StorageDead(local) => { if let LocalRef::Place(cg_place) = self.locals[local] { cg_place.storage_dead(&bx); + } else if let LocalRef::UnsizedPlace(cg_indirect_place) = self.locals[local] { + cg_indirect_place.storage_dead(&bx); } bx } @@ -85,7 +92,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { mir::StatementKind::ReadForMatch(_) | mir::StatementKind::EndRegion(_) | mir::StatementKind::Validate(..) | - mir::StatementKind::UserAssertTy(..) | + mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => bx, } } diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index a528008e3b..a8502e9244 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -143,7 +143,6 @@ fn predefine_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } cx.instances.borrow_mut().insert(instance, g); - cx.statics.borrow_mut().insert(g, def_id); } fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, @@ -181,9 +180,9 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance); if instance.def.is_inline(cx.tcx) { - attributes::inline(lldecl, attributes::InlineAttr::Hint); + attributes::inline(cx, lldecl, attributes::InlineAttr::Hint); } - attributes::from_fn_attrs(cx, lldecl, instance.def.def_id()); + attributes::from_fn_attrs(cx, lldecl, Some(instance.def.def_id())); cx.instances.borrow_mut().insert(instance, lldecl); } diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index a77acc4f17..51a233d791 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -10,133 +10,137 @@ #![allow(non_upper_case_globals)] +pub use llvm::Type; + use llvm; -use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind}; -use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128}; +use llvm::{Bool, False, True, TypeKind}; use context::CodegenCx; use syntax::ast; use rustc::ty::layout::{self, Align, Size}; +use rustc_data_structures::small_c_str::SmallCStr; -use std::ffi::CString; use std::fmt; -use std::mem; -use std::ptr; use libc::c_uint; -#[derive(Clone, Copy, PartialEq)] -#[repr(C)] -pub struct Type { - rf: TypeRef +impl PartialEq for Type { + fn eq(&self, other: &Self) -> bool { + self as *const _ == other as *const _ + } } impl fmt::Debug for Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&llvm::build_string(|s| unsafe { - llvm::LLVMRustWriteTypeToString(self.to_ref(), s); + llvm::LLVMRustWriteTypeToString(self, s); }).expect("non-UTF8 type description from LLVM")) } } -macro_rules! ty { - ($e:expr) => ( Type::from_ref(unsafe { $e })) -} - -/// Wrapper for LLVM TypeRef impl Type { - #[inline(always)] - pub fn from_ref(r: TypeRef) -> Type { - Type { - rf: r + pub fn void(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMVoidTypeInContext(cx.llcx) } } - #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler - pub fn to_ref(&self) -> TypeRef { - self.rf - } - - pub fn to_ref_slice(slice: &[Type]) -> &[TypeRef] { - unsafe { mem::transmute(slice) } - } - - pub fn void(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMVoidTypeInContext(cx.llcx)) + pub fn metadata(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMRustMetadataTypeInContext(cx.llcx) + } } - pub fn metadata(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMRustMetadataTypeInContext(cx.llcx)) + pub fn i1(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt1TypeInContext(cx.llcx) + } } - pub fn i1(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt1TypeInContext(cx.llcx)) + pub fn i8(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt8TypeInContext(cx.llcx) + } } - pub fn i8(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt8TypeInContext(cx.llcx)) + pub fn i8_llcx(llcx: &llvm::Context) -> &Type { + unsafe { + llvm::LLVMInt8TypeInContext(llcx) + } } - pub fn i8_llcx(llcx: ContextRef) -> Type { - ty!(llvm::LLVMInt8TypeInContext(llcx)) + pub fn i16(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt16TypeInContext(cx.llcx) + } } - pub fn i16(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt16TypeInContext(cx.llcx)) + pub fn i32(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt32TypeInContext(cx.llcx) + } } - pub fn i32(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt32TypeInContext(cx.llcx)) + pub fn i64(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt64TypeInContext(cx.llcx) + } } - pub fn i64(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt64TypeInContext(cx.llcx)) + pub fn i128(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMIntTypeInContext(cx.llcx, 128) + } } - pub fn i128(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMIntTypeInContext(cx.llcx, 128)) + // Creates an integer type with the given number of bits, e.g. i24 + pub fn ix(cx: &CodegenCx<'ll, '_>, num_bits: u64) -> &'ll Type { + unsafe { + llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint) + } } // Creates an integer type with the given number of bits, e.g. i24 - pub fn ix(cx: &CodegenCx, num_bits: u64) -> Type { - ty!(llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint)) + pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type { + unsafe { + llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) + } } - pub fn f32(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMFloatTypeInContext(cx.llcx)) + pub fn f32(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMFloatTypeInContext(cx.llcx) + } } - pub fn f64(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMDoubleTypeInContext(cx.llcx)) + pub fn f64(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMDoubleTypeInContext(cx.llcx) + } } - pub fn bool(cx: &CodegenCx) -> Type { + pub fn bool(cx: &CodegenCx<'ll, '_>) -> &'ll Type { Type::i8(cx) } - pub fn char(cx: &CodegenCx) -> Type { + pub fn char(cx: &CodegenCx<'ll, '_>) -> &'ll Type { Type::i32(cx) } - pub fn i8p(cx: &CodegenCx) -> Type { + pub fn i8p(cx: &CodegenCx<'ll, '_>) -> &'ll Type { Type::i8(cx).ptr_to() } - pub fn i8p_llcx(llcx: ContextRef) -> Type { + pub fn i8p_llcx(llcx: &llvm::Context) -> &Type { Type::i8_llcx(llcx).ptr_to() } - pub fn isize(cx: &CodegenCx) -> Type { - match &cx.tcx.sess.target.target.target_pointer_width[..] { - "16" => Type::i16(cx), - "32" => Type::i32(cx), - "64" => Type::i64(cx), - tws => bug!("Unsupported target word size for int: {}", tws), - } + pub fn isize(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + cx.isize_ty } - pub fn c_int(cx: &CodegenCx) -> Type { + pub fn c_int(cx: &CodegenCx<'ll, '_>) -> &'ll Type { match &cx.tcx.sess.target.target.target_c_int_width[..] { "16" => Type::i16(cx), "32" => Type::i32(cx), @@ -145,7 +149,7 @@ impl Type { } } - pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type { + pub fn int_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::IntTy) -> &'ll Type { match t { ast::IntTy::Isize => cx.isize_ty, ast::IntTy::I8 => Type::i8(cx), @@ -156,7 +160,7 @@ impl Type { } } - pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type { + pub fn uint_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::UintTy) -> &'ll Type { match t { ast::UintTy::Usize => cx.isize_ty, ast::UintTy::U8 => Type::i8(cx), @@ -167,93 +171,103 @@ impl Type { } } - pub fn float_from_ty(cx: &CodegenCx, t: ast::FloatTy) -> Type { + pub fn float_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::FloatTy) -> &'ll Type { match t { ast::FloatTy::F32 => Type::f32(cx), ast::FloatTy::F64 => Type::f64(cx), } } - pub fn func(args: &[Type], ret: &Type) -> Type { - let slice: &[TypeRef] = Type::to_ref_slice(args); - ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(), - args.len() as c_uint, False)) + pub fn func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { + unsafe { + llvm::LLVMFunctionType(ret, args.as_ptr(), + args.len() as c_uint, False) + } } - pub fn variadic_func(args: &[Type], ret: &Type) -> Type { - let slice: &[TypeRef] = Type::to_ref_slice(args); - ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(), - args.len() as c_uint, True)) + pub fn variadic_func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { + unsafe { + llvm::LLVMFunctionType(ret, args.as_ptr(), + args.len() as c_uint, True) + } } - pub fn struct_(cx: &CodegenCx, els: &[Type], packed: bool) -> Type { - let els: &[TypeRef] = Type::to_ref_slice(els); - ty!(llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(), + pub fn struct_(cx: &CodegenCx<'ll, '_>, els: &[&'ll Type], packed: bool) -> &'ll Type { + unsafe { + llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(), els.len() as c_uint, - packed as Bool)) + packed as Bool) + } } - pub fn named_struct(cx: &CodegenCx, name: &str) -> Type { - let name = CString::new(name).unwrap(); - ty!(llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr())) + pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type { + let name = SmallCStr::new(name); + unsafe { + llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr()) + } } - pub fn array(ty: &Type, len: u64) -> Type { - ty!(llvm::LLVMRustArrayType(ty.to_ref(), len)) + pub fn array(ty: &Type, len: u64) -> &Type { + unsafe { + llvm::LLVMRustArrayType(ty, len) + } } - pub fn vector(ty: &Type, len: u64) -> Type { - ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint)) + pub fn vector(ty: &Type, len: u64) -> &Type { + unsafe { + llvm::LLVMVectorType(ty, len as c_uint) + } } pub fn kind(&self) -> TypeKind { unsafe { - llvm::LLVMRustGetTypeKind(self.to_ref()) + llvm::LLVMRustGetTypeKind(self) } } - pub fn set_struct_body(&mut self, els: &[Type], packed: bool) { - let slice: &[TypeRef] = Type::to_ref_slice(els); + pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) { unsafe { - llvm::LLVMStructSetBody(self.to_ref(), slice.as_ptr(), + llvm::LLVMStructSetBody(self, els.as_ptr(), els.len() as c_uint, packed as Bool) } } - pub fn ptr_to(&self) -> Type { - ty!(llvm::LLVMPointerType(self.to_ref(), 0)) + pub fn ptr_to(&self) -> &Type { + unsafe { + llvm::LLVMPointerType(self, 0) + } } - pub fn element_type(&self) -> Type { + pub fn element_type(&self) -> &Type { unsafe { - Type::from_ref(llvm::LLVMGetElementType(self.to_ref())) + llvm::LLVMGetElementType(self) } } /// Return the number of elements in `self` if it is a LLVM vector type. pub fn vector_length(&self) -> usize { unsafe { - llvm::LLVMGetVectorSize(self.to_ref()) as usize + llvm::LLVMGetVectorSize(self) as usize } } - pub fn func_params(&self) -> Vec { + pub fn func_params(&self) -> Vec<&Type> { unsafe { - let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as usize; - let mut args = vec![Type { rf: ptr::null_mut() }; n_args]; - llvm::LLVMGetParamTypes(self.to_ref(), - args.as_mut_ptr() as *mut TypeRef); + let n_args = llvm::LLVMCountParamTypes(self) as usize; + let mut args = Vec::with_capacity(n_args); + llvm::LLVMGetParamTypes(self, args.as_mut_ptr()); + args.set_len(n_args); args } } pub fn float_width(&self) -> usize { match self.kind() { - Float => 32, - Double => 64, - X86_FP80 => 80, - FP128 | PPC_FP128 => 128, + TypeKind::Float => 32, + TypeKind::Double => 64, + TypeKind::X86_FP80 => 80, + TypeKind::FP128 | TypeKind::PPC_FP128 => 128, _ => bug!("llvm_float_width called on a non-float type") } } @@ -261,11 +275,11 @@ impl Type { /// Retrieve the bit width of the integer type `self`. pub fn int_width(&self) -> u64 { unsafe { - llvm::LLVMGetIntTypeWidth(self.to_ref()) as u64 + llvm::LLVMGetIntTypeWidth(self) as u64 } } - pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type { + pub fn from_integer(cx: &CodegenCx<'ll, '_>, i: layout::Integer) -> &'ll Type { use rustc::ty::layout::Integer::*; match i { I8 => Type::i8(cx), @@ -278,7 +292,7 @@ impl Type { /// Return a LLVM type that has at most the required alignment, /// as a conservative approximation for unknown pointee types. - pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type { + pub fn pointee_for_abi_align(cx: &CodegenCx<'ll, '_>, align: Align) -> &'ll Type { // FIXME(eddyb) We could find a better approximation if ity.align < align. let ity = layout::Integer::approximate_abi_align(cx, align); Type::from_integer(cx, ity) @@ -286,15 +300,17 @@ impl Type { /// Return a LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. - pub fn padding_filler(cx: &CodegenCx, size: Size, align: Align) -> Type { + pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll Type { let unit = layout::Integer::approximate_abi_align(cx, align); let size = size.bytes(); let unit_size = unit.size().bytes(); assert_eq!(size % unit_size, 0); - Type::array(&Type::from_integer(cx, unit), size / unit_size) + Type::array(Type::from_integer(cx, unit), size / unit_size) } - pub fn x86_mmx(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMX86MMXTypeInContext(cx.llcx)) + pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMX86MMXTypeInContext(cx.llcx) + } } } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 4728d7717a..6eec0b0b68 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -23,8 +23,8 @@ use std::fmt::Write; fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>, - defer: &mut Option<(Type, TyLayout<'tcx>)>) - -> Type { + defer: &mut Option<(&'a Type, TyLayout<'tcx>)>) + -> &'a Type { match layout.abi { layout::Abi::Scalar(_) => bug!("handled elsewhere"), layout::Abi::Vector { ref element, count } => { @@ -42,7 +42,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return Type::x86_mmx(cx) } else { let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO); - return Type::vector(&element, count); + return Type::vector(element, count); } } layout::Abi::ScalarPair(..) => { @@ -56,19 +56,19 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } let name = match layout.ty.sty { - ty::TyClosure(..) | - ty::TyGenerator(..) | - ty::TyAdt(..) | + ty::Closure(..) | + ty::Generator(..) | + ty::Adt(..) | // FIXME(eddyb) producing readable type names for trait objects can result // in problematically distinct types due to HRTB and subtyping (see #47638). - // ty::TyDynamic(..) | - ty::TyForeign(..) | - ty::TyStr => { + // ty::Dynamic(..) | + ty::Foreign(..) | + ty::Str => { let mut name = String::with_capacity(32); let printer = DefPathBasedNames::new(cx.tcx, true, true); printer.push_type_name(layout.ty, &mut name); match (&layout.ty.sty, &layout.variants) { - (&ty::TyAdt(def, _), &layout::Variants::Single { index }) => { + (&ty::Adt(def, _), &layout::Variants::Single { index }) => { if def.is_enum() && !def.variants.is_empty() { write!(&mut name, "::{}", def.variants[index].name).unwrap(); } @@ -89,14 +89,14 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, Type::struct_(cx, &[fill], packed) } Some(ref name) => { - let mut llty = Type::named_struct(cx, name); + let llty = Type::named_struct(cx, name); llty.set_struct_body(&[fill], packed); llty } } } layout::FieldPlacement::Array { count, .. } => { - Type::array(&layout.field(cx, 0).llvm_type(cx), count) + Type::array(layout.field(cx, 0).llvm_type(cx), count) } layout::FieldPlacement::Arbitrary { .. } => { match name { @@ -116,31 +116,35 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) - -> (Vec, bool) { + -> (Vec<&'a Type>, bool) { debug!("struct_llfields: {:#?}", layout); let field_count = layout.fields.count(); let mut packed = false; let mut offset = Size::ZERO; - let mut prev_align = layout.align; - let mut result: Vec = Vec::with_capacity(1 + field_count * 2); + let mut prev_effective_align = layout.align; + let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); for i in layout.fields.index_by_increasing_offset() { - let field = layout.field(cx, i); - packed |= layout.align.abi() < field.align.abi(); - let target_offset = layout.fields.offset(i as usize); - debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?}", - i, field, offset, target_offset); + let field = layout.field(cx, i); + let effective_field_align = layout.align + .min(field.align) + .restrict_for_offset(target_offset); + packed |= effective_field_align.abi() < field.align.abi(); + + debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \ + effective_field_align: {}", + i, field, offset, target_offset, effective_field_align.abi()); assert!(target_offset >= offset); let padding = target_offset - offset; - let padding_align = layout.align.min(prev_align).min(field.align); + let padding_align = prev_effective_align.min(effective_field_align); assert_eq!(offset.abi_align(padding_align) + padding, target_offset); result.push(Type::padding_filler(cx, padding, padding_align)); debug!(" padding before: {:?}", padding); result.push(field.llvm_type(cx)); offset = target_offset + field.size; - prev_align = field.align; + prev_effective_align = effective_field_align; } if !layout.is_unsized() && field_count > 0 { if offset > layout.size { @@ -148,7 +152,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout, layout.size, offset); } let padding = layout.size - offset; - let padding_align = layout.align.min(prev_align); + let padding_align = prev_effective_align; assert_eq!(offset.abi_align(padding_align) + padding, layout.size); debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}", padding, offset, layout.size); @@ -201,12 +205,12 @@ pub struct PointeeInfo { pub trait LayoutLlvmExt<'tcx> { fn is_llvm_immediate(&self) -> bool; fn is_llvm_scalar_pair<'a>(&self) -> bool; - fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; - fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; + fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type; + fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type; fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, - scalar: &layout::Scalar, offset: Size) -> Type; + scalar: &layout::Scalar, offset: Size) -> &'a Type; fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>, - index: usize, immediate: bool) -> Type; + index: usize, immediate: bool) -> &'a Type; fn llvm_field_index(&self, index: usize) -> u64; fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option; @@ -244,7 +248,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { /// with the inner-most trailing unsized field using the "minimal unit" /// of that field's type - this is useful for taking the address of /// that field and ensuring the struct has the right alignment. - fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { + fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { if let layout::Abi::Scalar(ref scalar) = self.abi { // Use a different cache for scalars because pointers to DSTs // can be either fat or thin (data pointers of fat pointers). @@ -252,14 +256,14 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { return llty; } let llty = match self.ty.sty { - ty::TyRef(_, ty, _) | - ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => { + ty::Ref(_, ty, _) | + ty::RawPtr(ty::TypeAndMut { ty, .. }) => { cx.layout_of(ty).llvm_type(cx).ptr_to() } - ty::TyAdt(def, _) if def.is_box() => { + ty::Adt(def, _) if def.is_box() => { cx.layout_of(self.ty.boxed_ty()).llvm_type(cx).ptr_to() } - ty::TyFnPtr(sig) => { + ty::FnPtr(sig) => { let sig = cx.tcx.normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), &sig, @@ -304,7 +308,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty); - if let Some((mut llty, layout)) = defer { + if let Some((llty, layout)) = defer { let (llfields, packed) = struct_llfields(cx, layout); llty.set_struct_body(&llfields, packed) } @@ -312,7 +316,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { llty } - fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { + fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { if let layout::Abi::Scalar(ref scalar) = self.abi { if scalar.is_bool() { return Type::i1(cx); @@ -322,7 +326,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { } fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, - scalar: &layout::Scalar, offset: Size) -> Type { + scalar: &layout::Scalar, offset: Size) -> &'a Type { match scalar.value { layout::Int(i, _) => Type::from_integer(cx, i), layout::Float(FloatTy::F32) => Type::f32(cx), @@ -340,15 +344,15 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { } fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>, - index: usize, immediate: bool) -> Type { + index: usize, immediate: bool) -> &'a Type { // HACK(eddyb) special-case fat pointers until LLVM removes // pointee types, to avoid bitcasting every `OperandRef::deref`. match self.ty.sty { - ty::TyRef(..) | - ty::TyRawPtr(_) => { + ty::Ref(..) | + ty::RawPtr(_) => { return self.field(cx, index).llvm_type(cx); } - ty::TyAdt(def, _) if def.is_box() => { + ty::Adt(def, _) if def.is_box() => { let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty()); return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate); } @@ -410,7 +414,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { let mut result = None; match self.ty.sty { - ty::TyRawPtr(mt) if offset.bytes() == 0 => { + ty::RawPtr(mt) if offset.bytes() == 0 => { let (size, align) = cx.size_and_align_of(mt.ty); result = Some(PointeeInfo { size, @@ -419,7 +423,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { }); } - ty::TyRef(_, ty, mt) if offset.bytes() == 0 => { + ty::Ref(_, ty, mt) if offset.bytes() == 0 => { let (size, align) = cx.size_and_align_of(ty); let kind = match mt { @@ -497,7 +501,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { // FIXME(eddyb) This should be for `ptr::Unique`, not `Box`. if let Some(ref mut pointee) = result { - if let ty::TyAdt(def, _) = self.ty.sty { + if let ty::Adt(def, _) = self.ty.sty { if def.is_box() && offset.bytes() == 0 { pointee.safe = Some(PointerKind::UniqueOwned); } diff --git a/src/librustc_codegen_llvm/value.rs b/src/librustc_codegen_llvm/value.rs index 287ad87caa..3328948c29 100644 --- a/src/librustc_codegen_llvm/value.rs +++ b/src/librustc_codegen_llvm/value.rs @@ -8,17 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +pub use llvm::Value; + use llvm; use std::fmt; +use std::hash::{Hash, Hasher}; + +impl PartialEq for Value { + fn eq(&self, other: &Self) -> bool { + self as *const _ == other as *const _ + } +} + +impl Eq for Value {} + +impl Hash for Value { + fn hash(&self, hasher: &mut H) { + (self as *const Self).hash(hasher); + } +} -#[derive(Copy, Clone, PartialEq)] -pub struct Value(pub llvm::ValueRef); impl fmt::Debug for Value { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&llvm::build_string(|s| unsafe { - llvm::LLVMRustWriteValueToString(self.0, s); + llvm::LLVMRustWriteValueToString(self, s); }).expect("nun-UTF8 value description from LLVM")) } } diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index 30f533285d..a1f4a323f8 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -20,3 +20,4 @@ rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_mir = { path = "../librustc_mir" } rustc_incremental = { path = "../librustc_incremental" } +rustc_metadata_utils = { path = "../librustc_metadata_utils" } diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 3f230dd5d4..d693e08836 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -44,7 +44,7 @@ use rustc::dep_graph::DepGraph; use rustc_target::spec::Target; use rustc_data_structures::fx::FxHashMap; use rustc_mir::monomorphize::collector; -use link::{build_link_meta, out_filename}; +use link::out_filename; pub use rustc_data_structures::sync::MetadataRef; @@ -114,10 +114,9 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { fn init(&self, sess: &Session) { for cty in sess.opts.crate_types.iter() { match *cty { - CrateType::CrateTypeRlib | CrateType::CrateTypeDylib | - CrateType::CrateTypeExecutable => {}, + CrateType::Rlib | CrateType::Dylib | CrateType::Executable => {}, _ => { - sess.parse_sess.span_diagnostic.warn( + sess.diagnostic().warn( &format!("LLVM unsupported, so output type {} is not supported", cty) ); }, @@ -181,8 +180,7 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { } tcx.sess.abort_if_errors(); - let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE)); - let metadata = tcx.encode_metadata(&link_meta); + let metadata = tcx.encode_metadata(); box OngoingCodegen { metadata: metadata, @@ -201,13 +199,14 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { let ongoing_codegen = ongoing_codegen.downcast::() .expect("Expected MetadataOnlyCodegenBackend's OngoingCodegen, found Box"); for &crate_type in sess.opts.crate_types.iter() { - if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib { + if crate_type != CrateType::Rlib && + crate_type != CrateType::Dylib { continue; } let output_name = out_filename(sess, crate_type, &outputs, &ongoing_codegen.crate_name.as_str()); let mut compressed = ongoing_codegen.metadata_version.clone(); - let metadata = if crate_type == CrateType::CrateTypeDylib { + let metadata = if crate_type == CrateType::Dylib { DeflateEncoder::new(&mut compressed, Compression::fast()) .write_all(&ongoing_codegen.metadata.raw_data) .unwrap(); @@ -220,8 +219,8 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { } sess.abort_if_errors(); - if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib) - && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) + if !sess.opts.crate_types.contains(&CrateType::Rlib) + && !sess.opts.crate_types.contains(&CrateType::Dylib) { sess.fatal("Executables are not supported by the metadata-only backend."); } diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index f59cf5832f..635819e94e 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -19,6 +19,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(custom_attribute)] +#![cfg_attr(not(stage0), feature(nll))] #![allow(unused_attributes)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] @@ -37,6 +38,7 @@ extern crate rustc_incremental; extern crate syntax; extern crate syntax_pos; #[macro_use] extern crate rustc_data_structures; +extern crate rustc_metadata_utils; use rustc::ty::TyCtxt; diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index aabe931d79..75f1d614ae 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -10,11 +10,10 @@ use rustc::session::config::{self, OutputFilenames, Input, OutputType}; use rustc::session::Session; -use rustc::middle::cstore::{self, LinkMeta}; -use rustc::hir::svh::Svh; use std::path::{Path, PathBuf}; use syntax::{ast, attr}; use syntax_pos::Span; +use rustc_metadata_utils::validate_crate_name; pub fn out_filename(sess: &Session, crate_type: config::CrateType, @@ -49,19 +48,11 @@ fn is_writeable(p: &Path) -> bool { } } -pub fn build_link_meta(crate_hash: Svh) -> LinkMeta { - let r = LinkMeta { - crate_hash, - }; - info!("{:?}", r); - return r; -} - pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: &Input) -> String { let validate = |s: String, span: Option| { - cstore::validate_crate_name(sess, &s, span); + validate_crate_name(sess, &s, span); s }; @@ -113,24 +104,24 @@ pub fn filename_for_input(sess: &Session, let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); match crate_type { - config::CrateTypeRlib => { + config::CrateType::Rlib => { outputs.out_directory.join(&format!("lib{}.rlib", libname)) } - config::CrateTypeCdylib | - config::CrateTypeProcMacro | - config::CrateTypeDylib => { + config::CrateType::Cdylib | + config::CrateType::ProcMacro | + config::CrateType::Dylib => { let (prefix, suffix) = (&sess.target.target.options.dll_prefix, &sess.target.target.options.dll_suffix); outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix)) } - config::CrateTypeStaticlib => { + config::CrateType::Staticlib => { let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix, &sess.target.target.options.staticlib_suffix); outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix)) } - config::CrateTypeExecutable => { + config::CrateType::Executable => { let suffix = &sess.target.target.options.exe_suffix; let out_filename = outputs.path(OutputType::Exe); if suffix.is_empty() { @@ -147,15 +138,15 @@ pub fn filename_for_input(sess: &Session, /// Default crate type is used when crate type isn't provided neither /// through cmd line arguments nor through crate attributes /// -/// It is CrateTypeExecutable for all platforms but iOS as there is no +/// It is CrateType::Executable for all platforms but iOS as there is no /// way to run iOS binaries anyway without jailbreaking and /// interaction with Rust code through static library is the only /// option for now pub fn default_output_for_target(sess: &Session) -> config::CrateType { if !sess.target.target.options.executables { - config::CrateTypeStaticlib + config::CrateType::Staticlib } else { - config::CrateTypeExecutable + config::CrateType::Executable } } @@ -163,9 +154,9 @@ pub fn default_output_for_target(sess: &Session) -> config::CrateType { pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType) -> bool { match crate_type { - config::CrateTypeCdylib | - config::CrateTypeDylib | - config::CrateTypeProcMacro => { + config::CrateType::Cdylib | + config::CrateType::Dylib | + config::CrateType::ProcMacro => { if !sess.target.target.options.dynamic_linking { return true } @@ -177,12 +168,12 @@ pub fn invalid_output_for_target(sess: &Session, } if sess.target.target.options.only_cdylib { match crate_type { - config::CrateTypeProcMacro | config::CrateTypeDylib => return true, + config::CrateType::ProcMacro | config::CrateType::Dylib => return true, _ => {} } } if !sess.target.target.options.executables { - if crate_type == config::CrateTypeExecutable { + if crate_type == config::CrateType::Executable { return true } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index ac71ecff96..39b88b225e 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -98,10 +98,10 @@ //! DefPaths which are much more robust in the face of changes to the code base. use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::hir::map as hir_map; +use rustc::hir::Node; +use rustc::hir::CodegenFnAttrFlags; use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; -use rustc::middle::weak_lang_items; use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; use rustc::ty::query::Providers; use rustc::ty::subst::Substs; @@ -111,7 +111,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_mir::monomorphize::item::{InstantiationMode, MonoItem, MonoItemExt}; use rustc_mir::monomorphize::Instance; -use syntax::attr; use syntax_pos::symbol::Symbol; use std::fmt::Write; @@ -171,7 +170,7 @@ fn get_symbol_hash<'a, 'tcx>( // If this is a function, we hash the signature as well. // This is not *strictly* needed, but it may help in some // situations, see the `run-make/a-b-a-linker-guard` test. - if let ty::TyFnDef(..) = item_type.sty { + if let ty::FnDef(..) = item_type.sty { item_type.fn_sig(tcx).hash_stable(&mut hcx, &mut hasher); } @@ -201,7 +200,7 @@ fn get_symbol_hash<'a, 'tcx>( if avoid_cross_crate_conflicts { let instantiating_crate = if is_generic { - if !def_id.is_local() && tcx.share_generics() { + if !def_id.is_local() && tcx.sess.opts.share_generics() { // If we are re-using a monomorphization from another crate, // we have to compute the symbol hash accordingly. let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id); @@ -260,34 +259,30 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance } // FIXME(eddyb) Precompute a custom symbol name based on attributes. - let attrs = tcx.get_attrs(def_id); let is_foreign = if let Some(id) = node_id { match tcx.hir.get(id) { - hir_map::NodeForeignItem(_) => true, + Node::ForeignItem(_) => true, _ => false, } } else { tcx.is_foreign_item(def_id) }; - if let Some(name) = weak_lang_items::link_name(&attrs) { - return name.to_string(); - } - + let attrs = tcx.codegen_fn_attrs(def_id); if is_foreign { - if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") { + if let Some(name) = attrs.link_name { return name.to_string(); } // Don't mangle foreign items. return tcx.item_name(def_id).to_string(); } - if let Some(name) = tcx.codegen_fn_attrs(def_id).export_name { + if let Some(name) = &attrs.export_name { // Use provided name return name.to_string(); } - if attr::contains_name(&attrs, "no_mangle") { + if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { // Don't mangle return tcx.item_name(def_id).to_string(); } diff --git a/src/librustc_cratesio_shim/Cargo.toml b/src/librustc_cratesio_shim/Cargo.toml index 342c7d1b67..b8e494e404 100644 --- a/src/librustc_cratesio_shim/Cargo.toml +++ b/src/librustc_cratesio_shim/Cargo.toml @@ -22,3 +22,4 @@ crate-type = ["dylib"] [dependencies] bitflags = "1.0" log = "0.4" +unicode-width = "0.1.4" diff --git a/src/librustc_cratesio_shim/src/lib.rs b/src/librustc_cratesio_shim/src/lib.rs index 85a5b331d8..55dec45a09 100644 --- a/src/librustc_cratesio_shim/src/lib.rs +++ b/src/librustc_cratesio_shim/src/lib.rs @@ -11,5 +11,8 @@ // See Cargo.toml for a comment explaining this crate. #![allow(unused_extern_crates)] +#![cfg_attr(not(stage0), feature(nll))] + extern crate bitflags; extern crate log; +extern crate unicode_width; diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index fc5fe91c97..5a72fde6a2 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -19,7 +19,8 @@ parking_lot_core = "0.2.8" rustc-rayon = "0.1.1" rustc-rayon-core = "0.1.1" rustc-hash = "1.0.1" +smallvec = { version = "0.6.5", features = ["union"] } [dependencies.parking_lot] -version = "0.5" +version = "0.6" features = ["nightly"] diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs deleted file mode 100644 index 9423e6b325..0000000000 --- a/src/librustc_data_structures/accumulate_vec.rs +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A vector type intended to be used for collecting from iterators onto the stack. -//! -//! Space for up to N elements is provided on the stack. If more elements are collected, Vec is -//! used to store the values on the heap. -//! -//! The N above is determined by Array's implementor, by way of an associated constant. - -use std::ops::{Deref, DerefMut, RangeBounds}; -use std::iter::{self, IntoIterator, FromIterator}; -use std::slice; -use std::vec; - -use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; - -use array_vec::{self, Array, ArrayVec}; - -#[derive(Hash, Debug)] -pub enum AccumulateVec { - Array(ArrayVec), - Heap(Vec) -} - -impl Clone for AccumulateVec - where A: Array, - A::Element: Clone { - fn clone(&self) -> Self { - match *self { - AccumulateVec::Array(ref arr) => AccumulateVec::Array(arr.clone()), - AccumulateVec::Heap(ref vec) => AccumulateVec::Heap(vec.clone()), - } - } -} - -impl AccumulateVec { - pub fn new() -> AccumulateVec { - AccumulateVec::Array(ArrayVec::new()) - } - - pub fn is_array(&self) -> bool { - match self { - AccumulateVec::Array(..) => true, - AccumulateVec::Heap(..) => false, - } - } - - pub fn one(el: A::Element) -> Self { - iter::once(el).collect() - } - - pub fn many>(iter: I) -> Self { - iter.into_iter().collect() - } - - pub fn len(&self) -> usize { - match *self { - AccumulateVec::Array(ref arr) => arr.len(), - AccumulateVec::Heap(ref vec) => vec.len(), - } - } - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - pub fn pop(&mut self) -> Option { - match *self { - AccumulateVec::Array(ref mut arr) => arr.pop(), - AccumulateVec::Heap(ref mut vec) => vec.pop(), - } - } - - pub fn drain(&mut self, range: R) -> Drain - where R: RangeBounds - { - match *self { - AccumulateVec::Array(ref mut v) => { - Drain::Array(v.drain(range)) - }, - AccumulateVec::Heap(ref mut v) => { - Drain::Heap(v.drain(range)) - }, - } - } -} - -impl Deref for AccumulateVec { - type Target = [A::Element]; - fn deref(&self) -> &Self::Target { - match *self { - AccumulateVec::Array(ref v) => v, - AccumulateVec::Heap(ref v) => v, - } - } -} - -impl DerefMut for AccumulateVec { - fn deref_mut(&mut self) -> &mut [A::Element] { - match *self { - AccumulateVec::Array(ref mut v) => v, - AccumulateVec::Heap(ref mut v) => v, - } - } -} - -impl FromIterator for AccumulateVec { - fn from_iter(iter: I) -> AccumulateVec where I: IntoIterator { - let iter = iter.into_iter(); - if iter.size_hint().1.map_or(false, |n| n <= A::LEN) { - let mut v = ArrayVec::new(); - v.extend(iter); - AccumulateVec::Array(v) - } else { - AccumulateVec::Heap(iter.collect()) - } - } -} - -pub struct IntoIter { - repr: IntoIterRepr, -} - -enum IntoIterRepr { - Array(array_vec::Iter), - Heap(vec::IntoIter), -} - -impl Iterator for IntoIter { - type Item = A::Element; - - fn next(&mut self) -> Option { - match self.repr { - IntoIterRepr::Array(ref mut arr) => arr.next(), - IntoIterRepr::Heap(ref mut iter) => iter.next(), - } - } - - fn size_hint(&self) -> (usize, Option) { - match self.repr { - IntoIterRepr::Array(ref iter) => iter.size_hint(), - IntoIterRepr::Heap(ref iter) => iter.size_hint(), - } - } -} - -pub enum Drain<'a, A: Array> - where A::Element: 'a -{ - Array(array_vec::Drain<'a, A>), - Heap(vec::Drain<'a, A::Element>), -} - -impl<'a, A: Array> Iterator for Drain<'a, A> { - type Item = A::Element; - - fn next(&mut self) -> Option { - match *self { - Drain::Array(ref mut drain) => drain.next(), - Drain::Heap(ref mut drain) => drain.next(), - } - } - - fn size_hint(&self) -> (usize, Option) { - match *self { - Drain::Array(ref drain) => drain.size_hint(), - Drain::Heap(ref drain) => drain.size_hint(), - } - } -} - -impl IntoIterator for AccumulateVec { - type Item = A::Element; - type IntoIter = IntoIter; - fn into_iter(self) -> Self::IntoIter { - IntoIter { - repr: match self { - AccumulateVec::Array(arr) => IntoIterRepr::Array(arr.into_iter()), - AccumulateVec::Heap(vec) => IntoIterRepr::Heap(vec.into_iter()), - } - } - } -} - -impl<'a, A: Array> IntoIterator for &'a AccumulateVec { - type Item = &'a A::Element; - type IntoIter = slice::Iter<'a, A::Element>; - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a, A: Array> IntoIterator for &'a mut AccumulateVec { - type Item = &'a mut A::Element; - type IntoIter = slice::IterMut<'a, A::Element>; - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} - -impl From> for AccumulateVec { - fn from(v: Vec) -> AccumulateVec { - AccumulateVec::many(v) - } -} - -impl Default for AccumulateVec { - fn default() -> AccumulateVec { - AccumulateVec::new() - } -} - -impl Encodable for AccumulateVec - where A: Array, - A::Element: Encodable { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_seq(self.len(), |s| { - for (i, e) in self.iter().enumerate() { - s.emit_seq_elt(i, |s| e.encode(s))?; - } - Ok(()) - }) - } -} - -impl Decodable for AccumulateVec - where A: Array, - A::Element: Decodable { - fn decode(d: &mut D) -> Result, D::Error> { - d.read_seq(|d, len| { - (0..len).map(|i| d.read_seq_elt(i, |d| Decodable::decode(d))).collect() - }) - } -} diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index 56bb961324..45fb565706 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -139,7 +139,7 @@ impl ArrayVec { // whole Drain iterator (like &mut T). let range_slice = { let arr = &mut self.values as &mut [ManuallyDrop<::Element>]; - slice::from_raw_parts_mut(arr.as_mut_ptr().offset(start as isize), + slice::from_raw_parts_mut(arr.as_mut_ptr().add(start), end - start) }; Drain { @@ -262,8 +262,8 @@ impl<'a, A: Array> Drop for Drain<'a, A> { { let arr = &mut source_array_vec.values as &mut [ManuallyDrop<::Element>]; - let src = arr.as_ptr().offset(tail as isize); - let dst = arr.as_mut_ptr().offset(start as isize); + let src = arr.as_ptr().add(tail); + let dst = arr.as_mut_ptr().add(start); ptr::copy(src, dst, self.tail_len); }; source_array_vec.set_len(start + self.tail_len); diff --git a/src/librustc_data_structures/base_n.rs b/src/librustc_data_structures/base_n.rs index d333b6393b..d3b47daa5b 100644 --- a/src/librustc_data_structures/base_n.rs +++ b/src/librustc_data_structures/base_n.rs @@ -17,7 +17,7 @@ pub const MAX_BASE: usize = 64; pub const ALPHANUMERIC_ONLY: usize = 62; pub const CASE_INSENSITIVE: usize = 36; -const BASE_64: &'static [u8; MAX_BASE as usize] = +const BASE_64: &[u8; MAX_BASE as usize] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$"; #[inline] @@ -37,7 +37,8 @@ pub fn push_str(mut n: u128, base: usize, output: &mut String) { break; } } - &mut s[0..index].reverse(); + s[0..index].reverse(); + output.push_str(str::from_utf8(&s[0..index]).unwrap()); } diff --git a/src/librustc_data_structures/bitslice.rs b/src/librustc_data_structures/bitslice.rs deleted file mode 100644 index b8f191c2f5..0000000000 --- a/src/librustc_data_structures/bitslice.rs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// FIXME: merge with `bitvec` - -use std::mem; - -pub type Word = usize; - -/// `BitSlice` provides helper methods for treating a `[Word]` -/// as a bitvector. -pub trait BitSlice { - fn clear_bit(&mut self, idx: usize) -> bool; - fn set_bit(&mut self, idx: usize) -> bool; - fn get_bit(&self, idx: usize) -> bool; -} - -impl BitSlice for [Word] { - /// Clears bit at `idx` to 0; returns true iff this changed `self.` - #[inline] - fn clear_bit(&mut self, idx: usize) -> bool { - let words = self; - debug!("clear_bit: words={} idx={}", - bits_to_string(words, words.len() * mem::size_of::() * 8), idx); - let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); - debug!("word={} bit_in_word={} bit_mask=0x{:x}", word, bit_in_word, bit_mask); - let oldv = words[word]; - let newv = oldv & !bit_mask; - words[word] = newv; - oldv != newv - } - - /// Sets bit at `idx` to 1; returns true iff this changed `self.` - #[inline] - fn set_bit(&mut self, idx: usize) -> bool { - let words = self; - debug!("set_bit: words={} idx={}", - bits_to_string(words, words.len() * mem::size_of::() * 8), idx); - let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); - debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask); - let oldv = words[word]; - let newv = oldv | bit_mask; - words[word] = newv; - oldv != newv - } - - /// Extracts value of bit at `idx` in `self`. - #[inline] - fn get_bit(&self, idx: usize) -> bool { - let words = self; - let BitLookup { word, bit_mask, .. } = bit_lookup(idx); - (words[word] & bit_mask) != 0 - } -} - -struct BitLookup { - /// An index of the word holding the bit in original `[Word]` of query. - word: usize, - /// Index of the particular bit within the word holding the bit. - bit_in_word: usize, - /// Word with single 1-bit set corresponding to where the bit is located. - bit_mask: Word, -} - -#[inline] -fn bit_lookup(bit: usize) -> BitLookup { - let word_bits = mem::size_of::() * 8; - let word = bit / word_bits; - let bit_in_word = bit % word_bits; - let bit_mask = 1 << bit_in_word; - BitLookup { word: word, bit_in_word: bit_in_word, bit_mask: bit_mask } -} - -pub fn bits_to_string(words: &[Word], bits: usize) -> String { - let mut result = String::new(); - let mut sep = '['; - - // Note: this is a little endian printout of bytes. - - // i tracks how many bits we have printed so far. - let mut i = 0; - for &word in words.iter() { - let mut v = word; - for _ in 0..mem::size_of::() { // for each byte in `v`: - let remain = bits - i; - // If less than a byte remains, then mask just that many bits. - let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF }; - assert!(mask <= 0xFF); - let byte = v & mask; - - result.push_str(&format!("{}{:02x}", sep, byte)); - - if remain <= 8 { break; } - v >>= 8; - i += 8; - sep = '-'; - } - sep = '|'; - } - result.push(']'); - return result -} - -#[inline] -pub fn bitwise(out_vec: &mut [Word], - in_vec: &[Word], - op: &Op) -> bool { - assert_eq!(out_vec.len(), in_vec.len()); - let mut changed = false; - for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) { - let old_val = *out_elt; - let new_val = op.join(old_val, *in_elt); - *out_elt = new_val; - changed |= old_val != new_val; - } - changed -} - -pub trait BitwiseOperator { - /// Applies some bit-operation pointwise to each of the bits in the two inputs. - fn join(&self, pred1: Word, pred2: Word) -> Word; -} - -pub struct Intersect; -impl BitwiseOperator for Intersect { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a & b } -} -pub struct Union; -impl BitwiseOperator for Union { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a | b } -} -pub struct Subtract; -impl BitwiseOperator for Subtract { - #[inline] - fn join(&self, a: Word, b: Word) -> Word { a & !b } -} diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 04d6cb5e2a..52cc347f8e 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -9,29 +9,59 @@ // except according to those terms. use indexed_vec::{Idx, IndexVec}; -use std::iter::FromIterator; +use rustc_serialize; +use std::iter; use std::marker::PhantomData; +use std::slice; -type Word = u128; -const WORD_BITS: usize = 128; +pub type Word = u64; +pub const WORD_BYTES: usize = ::std::mem::size_of::(); +pub const WORD_BITS: usize = WORD_BYTES * 8; -/// A very simple BitVector type. -#[derive(Clone, Debug, PartialEq)] -pub struct BitVector { +/// A very simple BitArray type. +/// +/// It does not support resizing after creation; use `BitVector` for that. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct BitArray { data: Vec, marker: PhantomData, } -impl BitVector { +impl BitArray { + // Do not make this method public, instead switch your use case to BitVector. + #[inline] + fn grow(&mut self, num_bits: C) { + let num_words = num_words(num_bits); + if self.data.len() <= num_words { + self.data.resize(num_words + 1, 0) + } + } + #[inline] - pub fn new(num_bits: usize) -> BitVector { - let num_words = words(num_bits); - BitVector { + pub fn new(num_bits: usize) -> BitArray { + BitArray::new_empty(num_bits) + } + + #[inline] + pub fn new_empty(num_bits: usize) -> BitArray { + let num_words = num_words(num_bits); + BitArray { data: vec![0; num_words], marker: PhantomData, } } + #[inline] + pub fn new_filled(num_bits: usize) -> BitArray { + let num_words = num_words(num_bits); + let mut result = BitArray { + data: vec![!0; num_words], + marker: PhantomData, + }; + result.clear_above(num_bits); + result + } + #[inline] pub fn clear(&mut self) { for p in &mut self.data { @@ -39,6 +69,31 @@ impl BitVector { } } + /// Sets all elements up to `num_bits`. + pub fn set_up_to(&mut self, num_bits: usize) { + for p in &mut self.data { + *p = !0; + } + self.clear_above(num_bits); + } + + /// Clear all elements above `num_bits`. + fn clear_above(&mut self, num_bits: usize) { + let first_clear_block = num_bits / WORD_BITS; + + if first_clear_block < self.data.len() { + // Within `first_clear_block`, the `num_bits % WORD_BITS` LSBs + // should remain. + let mask = (1 << (num_bits % WORD_BITS)) - 1; + self.data[first_clear_block] &= mask; + + // All the blocks above `first_clear_block` are fully cleared. + for b in &mut self.data[first_clear_block + 1..] { + *b = 0; + } + } + } + pub fn count(&self) -> usize { self.data.iter().map(|e| e.count_ones() as usize).sum() } @@ -54,7 +109,7 @@ impl BitVector { /// /// The two vectors must have the same length. #[inline] - pub fn contains_all(&self, other: &BitVector) -> bool { + pub fn contains_all(&self, other: &BitArray) -> bool { assert_eq!(self.data.len(), other.data.len()); self.data.iter().zip(&other.data).all(|(a, b)| (a & b) == *b) } @@ -78,7 +133,7 @@ impl BitVector { /// Sets all bits to true. pub fn insert_all(&mut self) { for data in &mut self.data { - *data = u128::max_value(); + *data = !0; } } @@ -94,7 +149,7 @@ impl BitVector { } #[inline] - pub fn merge(&mut self, all: &BitVector) -> bool { + pub fn merge(&mut self, all: &BitArray) -> bool { assert!(self.data.len() == all.data.len()); let mut changed = false; for (i, j) in self.data.iter_mut().zip(&all.data) { @@ -107,83 +162,168 @@ impl BitVector { changed } - #[inline] - pub fn grow(&mut self, num_bits: C) { - let num_words = words(num_bits); - if self.data.len() < num_words { - self.data.resize(num_words, 0) - } + pub fn words(&self) -> &[Word] { + &self.data + } + + pub fn words_mut(&mut self) -> &mut [Word] { + &mut self.data } /// Iterates over indexes of set bits in a sorted order #[inline] - pub fn iter<'a>(&'a self) -> BitVectorIter<'a, C> { - BitVectorIter { - iter: self.data.iter(), - current: 0, - idx: 0, + pub fn iter<'a>(&'a self) -> BitIter<'a, C> { + BitIter { + cur: None, + iter: self.data.iter().enumerate(), marker: PhantomData, } } } -pub struct BitVectorIter<'a, C: Idx> { - iter: ::std::slice::Iter<'a, Word>, - current: Word, - idx: usize, +impl rustc_serialize::Encodable for BitArray { + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { + self.data.encode(encoder) + } +} + +impl rustc_serialize::Decodable for BitArray { + fn decode(d: &mut D) -> Result, D::Error> { + let words: Vec = rustc_serialize::Decodable::decode(d)?; + Ok(BitArray { + data: words, + marker: PhantomData, + }) + } +} + +pub struct BitIter<'a, C: Idx> { + cur: Option<(Word, usize)>, + iter: iter::Enumerate>, marker: PhantomData } -impl<'a, C: Idx> Iterator for BitVectorIter<'a, C> { +impl<'a, C: Idx> Iterator for BitIter<'a, C> { type Item = C; fn next(&mut self) -> Option { - while self.current == 0 { - self.current = if let Some(&i) = self.iter.next() { - if i == 0 { - self.idx += WORD_BITS; - continue; - } else { - self.idx = words(self.idx) * WORD_BITS; - i + loop { + if let Some((ref mut word, offset)) = self.cur { + let bit_pos = word.trailing_zeros() as usize; + if bit_pos != WORD_BITS { + let bit = 1 << bit_pos; + *word ^= bit; + return Some(C::new(bit_pos + offset)) } - } else { - return None; } + + let (i, word) = self.iter.next()?; + self.cur = Some((*word, WORD_BITS * i)); } - let offset = self.current.trailing_zeros() as usize; - self.current >>= offset; - self.current >>= 1; // shift otherwise overflows for 0b1000_0000_…_0000 - self.idx += offset + 1; - return Some(C::new(self.idx - 1)); } +} - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } +pub trait BitwiseOperator { + /// Applies some bit-operation pointwise to each of the bits in the two inputs. + fn join(&self, pred1: Word, pred2: Word) -> Word; } -impl FromIterator for BitVector { - fn from_iter(iter: I) -> BitVector - where - I: IntoIterator, - { - let iter = iter.into_iter(); - let (len, _) = iter.size_hint(); - // Make the minimum length for the bitvector WORD_BITS bits since that's - // the smallest non-zero size anyway. - let len = if len < WORD_BITS { WORD_BITS } else { len }; - let mut bv = BitVector::new(len); - for (idx, val) in iter.enumerate() { - if idx > len { - bv.grow(C::new(idx)); - } - if val { - bv.insert(C::new(idx)); - } +#[inline] +pub fn bitwise(out_vec: &mut [Word], in_vec: &[Word], op: &Op) -> bool +{ + assert_eq!(out_vec.len(), in_vec.len()); + let mut changed = false; + for (out_elem, in_elem) in out_vec.iter_mut().zip(in_vec.iter()) { + let old_val = *out_elem; + let new_val = op.join(old_val, *in_elem); + *out_elem = new_val; + changed |= old_val != new_val; + } + changed +} + +pub struct Intersect; +impl BitwiseOperator for Intersect { + #[inline] + fn join(&self, a: Word, b: Word) -> Word { a & b } +} + +pub struct Union; +impl BitwiseOperator for Union { + #[inline] + fn join(&self, a: Word, b: Word) -> Word { a | b } +} + +pub struct Subtract; +impl BitwiseOperator for Subtract { + #[inline] + fn join(&self, a: Word, b: Word) -> Word { a & !b } +} + +pub fn bits_to_string(words: &[Word], bits: usize) -> String { + let mut result = String::new(); + let mut sep = '['; + + // Note: this is a little endian printout of bytes. + + // i tracks how many bits we have printed so far. + let mut i = 0; + for &word in words.iter() { + let mut v = word; + for _ in 0..WORD_BYTES { // for each byte in `v`: + let remain = bits - i; + // If less than a byte remains, then mask just that many bits. + let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF }; + assert!(mask <= 0xFF); + let byte = v & mask; + + result.push_str(&format!("{}{:02x}", sep, byte)); + + if remain <= 8 { break; } + v >>= 8; + i += 8; + sep = '-'; } + sep = '|'; + } + result.push(']'); + + result +} + +/// A resizable BitVector type. +#[derive(Clone, Debug, PartialEq)] +pub struct BitVector { + data: BitArray, +} + +impl BitVector { + pub fn grow(&mut self, num_bits: C) { + self.data.grow(num_bits) + } + + pub fn new() -> BitVector { + BitVector { data: BitArray::new(0) } + } - bv + pub fn with_capacity(bits: usize) -> BitVector { + BitVector { data: BitArray::new(bits) } + } + + /// Returns true if the bit has changed. + #[inline] + pub fn insert(&mut self, bit: C) -> bool { + self.grow(bit); + self.data.insert(bit) + } + + #[inline] + pub fn contains(&self, bit: C) -> bool { + let (word, mask) = word_mask(bit); + if let Some(word) = self.data.data.get(word) { + (word & mask) != 0 + } else { + false + } } } @@ -202,7 +342,7 @@ impl BitMatrix { pub fn new(rows: usize, columns: usize) -> BitMatrix { // For every element, we need one bit for every other // element. Round up to an even number of words. - let words_per_row = words(columns); + let words_per_row = num_words(columns); BitMatrix { columns, vector: vec![0; rows * words_per_row], @@ -213,7 +353,7 @@ impl BitMatrix { /// The range of bits for a given row. fn range(&self, row: R) -> (usize, usize) { let row = row.index(); - let words_per_row = words(self.columns); + let words_per_row = num_words(self.columns); let start = row * words_per_row; (start, start + words_per_row) } @@ -281,49 +421,58 @@ impl BitMatrix { let v1 = vector[write_index]; let v2 = v1 | vector[read_index]; vector[write_index] = v2; - changed = changed | (v1 != v2); + changed |= v1 != v2; } changed } /// Iterates through all the columns set to true in a given row of /// the matrix. - pub fn iter<'a>(&'a self, row: R) -> BitVectorIter<'a, C> { + pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> { let (start, end) = self.range(row); - BitVectorIter { - iter: self.vector[start..end].iter(), - current: 0, - idx: 0, + BitIter { + cur: None, + iter: self.vector[start..end].iter().enumerate(), marker: PhantomData, } } } -/// A moderately sparse bit matrix: rows are appended lazily, but columns -/// within appended rows are instantiated fully upon creation. +/// A moderately sparse bit matrix, in which rows are instantiated lazily. +/// +/// Initially, every row has no explicit representation. If any bit within a +/// row is set, the entire row is instantiated as +/// `Some()`. Furthermore, any previously +/// uninstantiated rows prior to it will be instantiated as `None`. Those prior +/// rows may themselves become fully instantiated later on if any of their bits +/// are set. #[derive(Clone, Debug)] pub struct SparseBitMatrix where R: Idx, C: Idx, { - columns: usize, - vector: IndexVec>, + num_columns: usize, + rows: IndexVec>>, } impl SparseBitMatrix { /// Create a new empty sparse bit matrix with no rows or columns. - pub fn new(columns: usize) -> Self { + pub fn new(num_columns: usize) -> Self { Self { - columns, - vector: IndexVec::new(), + num_columns, + rows: IndexVec::new(), } } - fn ensure_row(&mut self, row: R) { - let columns = self.columns; - self.vector - .ensure_contains_elem(row, || BitVector::new(columns)); + fn ensure_row(&mut self, row: R) -> &mut BitArray { + // Instantiate any missing rows up to and including row `row` with an + // empty BitArray. + self.rows.ensure_contains_elem(row, || None); + + // Then replace row `row` with a full BitArray if necessary. + let num_columns = self.num_columns; + self.rows[row].get_or_insert_with(|| BitArray::new(num_columns)) } /// Sets the cell at `(row, column)` to true. Put another way, insert @@ -331,8 +480,7 @@ impl SparseBitMatrix { /// /// Returns true if this changed the matrix, and false otherwise. pub fn add(&mut self, row: R, column: C) -> bool { - self.ensure_row(row); - self.vector[row].insert(column) + self.ensure_row(row).insert(column) } /// Do the bits from `row` contain `column`? Put another way, is @@ -340,7 +488,7 @@ impl SparseBitMatrix { /// if the matrix represents (transitive) reachability, can /// `row` reach `column`? pub fn contains(&self, row: R, column: C) -> bool { - self.vector.get(row).map_or(false, |r| r.contains(column)) + self.row(row).map_or(false, |r| r.contains(column)) } /// Add the bits from row `read` to the bits from row `write`, @@ -351,54 +499,49 @@ impl SparseBitMatrix { /// `write` can reach everything that `read` can (and /// potentially more). pub fn merge(&mut self, read: R, write: R) -> bool { - if read == write || self.vector.get(read).is_none() { + if read == write || self.row(read).is_none() { return false; } self.ensure_row(write); - let (bitvec_read, bitvec_write) = self.vector.pick2_mut(read, write); - bitvec_write.merge(bitvec_read) + if let (Some(bitvec_read), Some(bitvec_write)) = self.rows.pick2_mut(read, write) { + bitvec_write.merge(bitvec_read) + } else { + unreachable!() + } } /// Merge a row, `from`, into the `into` row. - pub fn merge_into(&mut self, into: R, from: &BitVector) -> bool { - self.ensure_row(into); - self.vector[into].merge(from) + pub fn merge_into(&mut self, into: R, from: &BitArray) -> bool { + self.ensure_row(into).merge(from) } /// Add all bits to the given row. pub fn add_all(&mut self, row: R) { - self.ensure_row(row); - self.vector[row].insert_all(); - } - - /// Number of elements in the matrix. - pub fn len(&self) -> usize { - self.vector.len() + self.ensure_row(row).insert_all(); } pub fn rows(&self) -> impl Iterator { - self.vector.indices() + self.rows.indices() } /// Iterates through all the columns set to true in a given row of /// the matrix. pub fn iter<'a>(&'a self, row: R) -> impl Iterator + 'a { - self.vector.get(row).into_iter().flat_map(|r| r.iter()) + self.row(row).into_iter().flat_map(|r| r.iter()) } - /// Iterates through each row and the accompanying bit set. - pub fn iter_enumerated<'a>(&'a self) -> impl Iterator)> + 'a { - self.vector.iter_enumerated() - } - - pub fn row(&self, row: R) -> Option<&BitVector> { - self.vector.get(row) + pub fn row(&self, row: R) -> Option<&BitArray> { + if let Some(Some(row)) = self.rows.get(row) { + Some(row) + } else { + None + } } } #[inline] -fn words(elements: C) -> usize { +fn num_words(elements: C) -> usize { (elements.index() + WORD_BITS - 1) / WORD_BITS } @@ -410,9 +553,49 @@ fn word_mask(index: C) -> (usize, Word) { (word, mask) } +#[test] +fn test_clear_above() { + use std::cmp; + + for i in 0..256 { + let mut idx_buf: BitArray = BitArray::new_filled(128); + idx_buf.clear_above(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..cmp::min(i, 128)).collect(); + assert_eq!(elems, expected); + } +} + +#[test] +fn test_set_up_to() { + for i in 0..128 { + for mut idx_buf in + vec![BitArray::new_empty(128), BitArray::new_filled(128)] + .into_iter() + { + idx_buf.set_up_to(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } + } +} + +#[test] +fn test_new_filled() { + for i in 0..128 { + let idx_buf = BitArray::new_filled(i); + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } +} + #[test] fn bitvec_iter_works() { - let mut bitvec: BitVector = BitVector::new(100); + let mut bitvec: BitArray = BitArray::new(100); bitvec.insert(1); bitvec.insert(10); bitvec.insert(19); @@ -430,7 +613,7 @@ fn bitvec_iter_works() { #[test] fn bitvec_iter_works_2() { - let mut bitvec: BitVector = BitVector::new(319); + let mut bitvec: BitArray = BitArray::new(319); bitvec.insert(0); bitvec.insert(127); bitvec.insert(191); @@ -441,8 +624,8 @@ fn bitvec_iter_works_2() { #[test] fn union_two_vecs() { - let mut vec1: BitVector = BitVector::new(65); - let mut vec2: BitVector = BitVector::new(65); + let mut vec1: BitArray = BitArray::new(65); + let mut vec2: BitArray = BitArray::new(65); assert!(vec1.insert(3)); assert!(!vec1.insert(3)); assert!(vec2.insert(5)); @@ -458,7 +641,7 @@ fn union_two_vecs() { #[test] fn grow() { - let mut vec1: BitVector = BitVector::new(65); + let mut vec1: BitVector = BitVector::with_capacity(65); for index in 0..65 { assert!(vec1.insert(index)); assert!(!vec1.insert(index)); diff --git a/src/librustc_data_structures/const_cstr.rs b/src/librustc_data_structures/const_cstr.rs new file mode 100644 index 0000000000..4589d973b6 --- /dev/null +++ b/src/librustc_data_structures/const_cstr.rs @@ -0,0 +1,42 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// This macro creates a zero-overhead &CStr by adding a NUL terminator to +/// the string literal passed into it at compile-time. Use it like: +/// +/// ``` +/// let some_const_cstr = const_cstr!("abc"); +/// ``` +/// +/// The above is roughly equivalent to: +/// +/// ``` +/// let some_const_cstr = CStr::from_bytes_with_nul(b"abc\0").unwrap() +/// ``` +/// +/// Note that macro only checks the string literal for internal NULs if +/// debug-assertions are enabled in order to avoid runtime overhead in release +/// builds. +#[macro_export] +macro_rules! const_cstr { + ($s:expr) => ({ + use std::ffi::CStr; + + let str_plus_nul = concat!($s, "\0"); + + if cfg!(debug_assertions) { + CStr::from_bytes_with_nul(str_plus_nul.as_bytes()).unwrap() + } else { + unsafe { + CStr::from_bytes_with_nul_unchecked(str_plus_nul.as_bytes()) + } + } + }) +} diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc_data_structures/fingerprint.rs similarity index 89% rename from src/librustc/ich/fingerprint.rs rename to src/librustc_data_structures/fingerprint.rs index a6e35d78dc..aa9ddda2b9 100644 --- a/src/librustc/ich/fingerprint.rs +++ b/src/librustc_data_structures/fingerprint.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::mem; -use rustc_data_structures::stable_hasher; +use stable_hasher; use serialize; use serialize::opaque::{EncodeResult, Encoder, Decoder}; @@ -92,14 +92,7 @@ impl stable_hasher::StableHasherResult for Fingerprint { } } -impl stable_hasher::HashStable for Fingerprint { - #[inline] - fn hash_stable(&self, - _: &mut CTX, - hasher: &mut stable_hasher::StableHasher) { - ::std::hash::Hash::hash(self, hasher); - } -} +impl_stable_hash_via_hash!(Fingerprint); impl serialize::UseSpecializedEncodable for Fingerprint { } diff --git a/src/librustc_data_structures/flock.rs b/src/librustc_data_structures/flock.rs index ff1ebb11b7..38ce331051 100644 --- a/src/librustc_data_structures/flock.rs +++ b/src/librustc_data_structures/flock.rs @@ -15,345 +15,351 @@ //! librustdoc, it is not production quality at all. #![allow(non_camel_case_types)] -use std::path::Path; - -pub use self::imp::Lock; +#![allow(nonstandard_style)] -#[cfg(unix)] -mod imp { - use std::ffi::{CString, OsStr}; - use std::os::unix::prelude::*; - use std::path::Path; - use std::io; - use libc; +use std::io; +use std::path::Path; - #[cfg(any(target_os = "linux", target_os = "android"))] - mod os { +cfg_if! { + if #[cfg(unix)] { + use std::ffi::{CString, OsStr}; + use std::os::unix::prelude::*; use libc; - #[repr(C)] - pub struct flock { - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - - // not actually here, but brings in line with freebsd - pub l_sysid: libc::c_int, - } + #[cfg(any(target_os = "linux", target_os = "android"))] + mod os { + use libc; - pub const F_RDLCK: libc::c_short = 0; - pub const F_WRLCK: libc::c_short = 1; - pub const F_UNLCK: libc::c_short = 2; - pub const F_SETLK: libc::c_int = 6; - pub const F_SETLKW: libc::c_int = 7; - } + #[repr(C)] + pub struct flock { + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, - #[cfg(target_os = "freebsd")] - mod os { - use libc; + // not actually here, but brings in line with freebsd + pub l_sysid: libc::c_int, + } - #[repr(C)] - pub struct flock { - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - pub l_sysid: libc::c_int, + pub const F_RDLCK: libc::c_short = 0; + pub const F_WRLCK: libc::c_short = 1; + pub const F_UNLCK: libc::c_short = 2; + pub const F_SETLK: libc::c_int = 6; + pub const F_SETLKW: libc::c_int = 7; } - pub const F_RDLCK: libc::c_short = 1; - pub const F_UNLCK: libc::c_short = 2; - pub const F_WRLCK: libc::c_short = 3; - pub const F_SETLK: libc::c_int = 12; - pub const F_SETLKW: libc::c_int = 13; - } - - #[cfg(any(target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] - mod os { - use libc; + #[cfg(target_os = "freebsd")] + mod os { + use libc; + + #[repr(C)] + pub struct flock { + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + pub l_sysid: libc::c_int, + } - #[repr(C)] - pub struct flock { - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - - // not actually here, but brings in line with freebsd - pub l_sysid: libc::c_int, + pub const F_RDLCK: libc::c_short = 1; + pub const F_UNLCK: libc::c_short = 2; + pub const F_WRLCK: libc::c_short = 3; + pub const F_SETLK: libc::c_int = 12; + pub const F_SETLKW: libc::c_int = 13; } - pub const F_RDLCK: libc::c_short = 1; - pub const F_UNLCK: libc::c_short = 2; - pub const F_WRLCK: libc::c_short = 3; - pub const F_SETLK: libc::c_int = 8; - pub const F_SETLKW: libc::c_int = 9; - } - - #[cfg(target_os = "haiku")] - mod os { - use libc; + #[cfg(any(target_os = "dragonfly", + target_os = "bitrig", + target_os = "netbsd", + target_os = "openbsd"))] + mod os { + use libc; + + #[repr(C)] + pub struct flock { + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + + // not actually here, but brings in line with freebsd + pub l_sysid: libc::c_int, + } - #[repr(C)] - pub struct flock { - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - - // not actually here, but brings in line with freebsd - pub l_sysid: libc::c_int, + pub const F_RDLCK: libc::c_short = 1; + pub const F_UNLCK: libc::c_short = 2; + pub const F_WRLCK: libc::c_short = 3; + pub const F_SETLK: libc::c_int = 8; + pub const F_SETLKW: libc::c_int = 9; } - pub const F_RDLCK: libc::c_short = 0x0040; - pub const F_UNLCK: libc::c_short = 0x0200; - pub const F_WRLCK: libc::c_short = 0x0400; - pub const F_SETLK: libc::c_int = 0x0080; - pub const F_SETLKW: libc::c_int = 0x0100; - } + #[cfg(target_os = "haiku")] + mod os { + use libc; - #[cfg(any(target_os = "macos", target_os = "ios"))] - mod os { - use libc; + #[repr(C)] + pub struct flock { + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, - #[repr(C)] - pub struct flock { - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - - // not actually here, but brings in line with freebsd - pub l_sysid: libc::c_int, + // not actually here, but brings in line with freebsd + pub l_sysid: libc::c_int, + } + + pub const F_RDLCK: libc::c_short = 0x0040; + pub const F_UNLCK: libc::c_short = 0x0200; + pub const F_WRLCK: libc::c_short = 0x0400; + pub const F_SETLK: libc::c_int = 0x0080; + pub const F_SETLKW: libc::c_int = 0x0100; } - pub const F_RDLCK: libc::c_short = 1; - pub const F_UNLCK: libc::c_short = 2; - pub const F_WRLCK: libc::c_short = 3; - pub const F_SETLK: libc::c_int = 8; - pub const F_SETLKW: libc::c_int = 9; - } + #[cfg(any(target_os = "macos", target_os = "ios"))] + mod os { + use libc; - #[cfg(target_os = "solaris")] - mod os { - use libc; + #[repr(C)] + pub struct flock { + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, + pub l_type: libc::c_short, + pub l_whence: libc::c_short, - #[repr(C)] - pub struct flock { - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_sysid: libc::c_int, - pub l_pid: libc::pid_t, + // not actually here, but brings in line with freebsd + pub l_sysid: libc::c_int, + } + + pub const F_RDLCK: libc::c_short = 1; + pub const F_UNLCK: libc::c_short = 2; + pub const F_WRLCK: libc::c_short = 3; + pub const F_SETLK: libc::c_int = 8; + pub const F_SETLKW: libc::c_int = 9; } - pub const F_RDLCK: libc::c_short = 1; - pub const F_WRLCK: libc::c_short = 2; - pub const F_UNLCK: libc::c_short = 3; - pub const F_SETLK: libc::c_int = 6; - pub const F_SETLKW: libc::c_int = 7; - } + #[cfg(target_os = "solaris")] + mod os { + use libc; + + #[repr(C)] + pub struct flock { + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_sysid: libc::c_int, + pub l_pid: libc::pid_t, + } - #[derive(Debug)] - pub struct Lock { - fd: libc::c_int, - } + pub const F_RDLCK: libc::c_short = 1; + pub const F_WRLCK: libc::c_short = 2; + pub const F_UNLCK: libc::c_short = 3; + pub const F_SETLK: libc::c_int = 6; + pub const F_SETLKW: libc::c_int = 7; + } - impl Lock { - pub fn new(p: &Path, - wait: bool, - create: bool, - exclusive: bool) - -> io::Result { - let os: &OsStr = p.as_ref(); - let buf = CString::new(os.as_bytes()).unwrap(); - let open_flags = if create { - libc::O_RDWR | libc::O_CREAT - } else { - libc::O_RDWR - }; - - let fd = unsafe { - libc::open(buf.as_ptr(), open_flags, - libc::S_IRWXU as libc::c_int) - }; - - if fd < 0 { - return Err(io::Error::last_os_error()); - } + #[derive(Debug)] + pub struct Lock { + fd: libc::c_int, + } - let lock_type = if exclusive { - os::F_WRLCK - } else { - os::F_RDLCK - }; - - let flock = os::flock { - l_start: 0, - l_len: 0, - l_pid: 0, - l_whence: libc::SEEK_SET as libc::c_short, - l_type: lock_type, - l_sysid: 0, - }; - let cmd = if wait { os::F_SETLKW } else { os::F_SETLK }; - let ret = unsafe { - libc::fcntl(fd, cmd, &flock) - }; - if ret == -1 { - let err = io::Error::last_os_error(); - unsafe { libc::close(fd); } - Err(err) - } else { - Ok(Lock { fd: fd }) + impl Lock { + pub fn new(p: &Path, + wait: bool, + create: bool, + exclusive: bool) + -> io::Result { + let os: &OsStr = p.as_ref(); + let buf = CString::new(os.as_bytes()).unwrap(); + let open_flags = if create { + libc::O_RDWR | libc::O_CREAT + } else { + libc::O_RDWR + }; + + let fd = unsafe { + libc::open(buf.as_ptr(), open_flags, + libc::S_IRWXU as libc::c_int) + }; + + if fd < 0 { + return Err(io::Error::last_os_error()); + } + + let lock_type = if exclusive { + os::F_WRLCK + } else { + os::F_RDLCK + }; + + let flock = os::flock { + l_start: 0, + l_len: 0, + l_pid: 0, + l_whence: libc::SEEK_SET as libc::c_short, + l_type: lock_type, + l_sysid: 0, + }; + let cmd = if wait { os::F_SETLKW } else { os::F_SETLK }; + let ret = unsafe { + libc::fcntl(fd, cmd, &flock) + }; + if ret == -1 { + let err = io::Error::last_os_error(); + unsafe { libc::close(fd); } + Err(err) + } else { + Ok(Lock { fd: fd }) + } } } - } - impl Drop for Lock { - fn drop(&mut self) { - let flock = os::flock { - l_start: 0, - l_len: 0, - l_pid: 0, - l_whence: libc::SEEK_SET as libc::c_short, - l_type: os::F_UNLCK, - l_sysid: 0, - }; - unsafe { - libc::fcntl(self.fd, os::F_SETLK, &flock); - libc::close(self.fd); + impl Drop for Lock { + fn drop(&mut self) { + let flock = os::flock { + l_start: 0, + l_len: 0, + l_pid: 0, + l_whence: libc::SEEK_SET as libc::c_short, + l_type: os::F_UNLCK, + l_sysid: 0, + }; + unsafe { + libc::fcntl(self.fd, os::F_SETLK, &flock); + libc::close(self.fd); + } } } - } -} + } else if #[cfg(windows)] { + use std::mem; + use std::os::windows::prelude::*; + use std::os::windows::raw::HANDLE; + use std::fs::{File, OpenOptions}; + use std::os::raw::{c_ulong, c_int}; -#[cfg(windows)] -#[allow(bad_style)] -mod imp { - use std::io; - use std::mem; - use std::os::windows::prelude::*; - use std::os::windows::raw::HANDLE; - use std::path::Path; - use std::fs::{File, OpenOptions}; - use std::os::raw::{c_ulong, c_int}; - - type DWORD = c_ulong; - type BOOL = c_int; - type ULONG_PTR = usize; - - type LPOVERLAPPED = *mut OVERLAPPED; - const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x00000002; - const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x00000001; - - const FILE_SHARE_DELETE: DWORD = 0x4; - const FILE_SHARE_READ: DWORD = 0x1; - const FILE_SHARE_WRITE: DWORD = 0x2; - - #[repr(C)] - struct OVERLAPPED { - Internal: ULONG_PTR, - InternalHigh: ULONG_PTR, - Offset: DWORD, - OffsetHigh: DWORD, - hEvent: HANDLE, - } + type DWORD = c_ulong; + type BOOL = c_int; + type ULONG_PTR = usize; - extern "system" { - fn LockFileEx(hFile: HANDLE, - dwFlags: DWORD, - dwReserved: DWORD, - nNumberOfBytesToLockLow: DWORD, - nNumberOfBytesToLockHigh: DWORD, - lpOverlapped: LPOVERLAPPED) -> BOOL; - } + type LPOVERLAPPED = *mut OVERLAPPED; + const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x0000_0002; + const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x0000_0001; - #[derive(Debug)] - pub struct Lock { - _file: File, - } + const FILE_SHARE_DELETE: DWORD = 0x4; + const FILE_SHARE_READ: DWORD = 0x1; + const FILE_SHARE_WRITE: DWORD = 0x2; - impl Lock { - pub fn new(p: &Path, - wait: bool, - create: bool, - exclusive: bool) - -> io::Result { - assert!(p.parent().unwrap().exists(), - "Parent directory of lock-file must exist: {}", - p.display()); - - let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; - - let mut open_options = OpenOptions::new(); - open_options.read(true) - .share_mode(share_mode); - - if create { - open_options.create(true) - .write(true); - } + #[repr(C)] + struct OVERLAPPED { + Internal: ULONG_PTR, + InternalHigh: ULONG_PTR, + Offset: DWORD, + OffsetHigh: DWORD, + hEvent: HANDLE, + } - debug!("Attempting to open lock file `{}`", p.display()); - let file = match open_options.open(p) { - Ok(file) => { - debug!("Lock file opened successfully"); - file - } - Err(err) => { - debug!("Error opening lock file: {}", err); - return Err(err) - } - }; + extern "system" { + fn LockFileEx(hFile: HANDLE, + dwFlags: DWORD, + dwReserved: DWORD, + nNumberOfBytesToLockLow: DWORD, + nNumberOfBytesToLockHigh: DWORD, + lpOverlapped: LPOVERLAPPED) -> BOOL; + } - let ret = unsafe { - let mut overlapped: OVERLAPPED = mem::zeroed(); + #[derive(Debug)] + pub struct Lock { + _file: File, + } - let mut dwFlags = 0; - if !wait { - dwFlags |= LOCKFILE_FAIL_IMMEDIATELY; + impl Lock { + pub fn new(p: &Path, + wait: bool, + create: bool, + exclusive: bool) + -> io::Result { + assert!(p.parent().unwrap().exists(), + "Parent directory of lock-file must exist: {}", + p.display()); + + let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; + + let mut open_options = OpenOptions::new(); + open_options.read(true) + .share_mode(share_mode); + + if create { + open_options.create(true) + .write(true); } - if exclusive { - dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; + debug!("Attempting to open lock file `{}`", p.display()); + let file = match open_options.open(p) { + Ok(file) => { + debug!("Lock file opened successfully"); + file + } + Err(err) => { + debug!("Error opening lock file: {}", err); + return Err(err) + } + }; + + let ret = unsafe { + let mut overlapped: OVERLAPPED = mem::zeroed(); + + let mut dwFlags = 0; + if !wait { + dwFlags |= LOCKFILE_FAIL_IMMEDIATELY; + } + + if exclusive { + dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; + } + + debug!("Attempting to acquire lock on lock file `{}`", + p.display()); + LockFileEx(file.as_raw_handle(), + dwFlags, + 0, + 0xFFFF_FFFF, + 0xFFFF_FFFF, + &mut overlapped) + }; + if ret == 0 { + let err = io::Error::last_os_error(); + debug!("Failed acquiring file lock: {}", err); + Err(err) + } else { + debug!("Successfully acquired lock."); + Ok(Lock { _file: file }) } + } + } - debug!("Attempting to acquire lock on lock file `{}`", - p.display()); - LockFileEx(file.as_raw_handle(), - dwFlags, - 0, - 0xFFFF_FFFF, - 0xFFFF_FFFF, - &mut overlapped) - }; - if ret == 0 { - let err = io::Error::last_os_error(); - debug!("Failed acquiring file lock: {}", err); - Err(err) - } else { - debug!("Successfully acquired lock."); - Ok(Lock { _file: file }) + // Note that we don't need a Drop impl on the Windows: The file is unlocked + // automatically when it's closed. + } else { + #[derive(Debug)] + pub struct Lock(()); + + impl Lock { + pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool) + -> io::Result + { + let msg = "file locks not supported on this platform"; + Err(io::Error::new(io::ErrorKind::Other, msg)) } } } - - // Note that we don't need a Drop impl on the Windows: The file is unlocked - // automatically when it's closed. } -impl imp::Lock { +impl Lock { pub fn panicking_new(p: &Path, wait: bool, create: bool, diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs index d134fad285..9b7f4cec47 100644 --- a/src/librustc_data_structures/graph/dominators/mod.rs +++ b/src/librustc_data_structures/graph/dominators/mod.rs @@ -38,13 +38,13 @@ pub fn dominators_given_rpo( // compute the post order index (rank) for each node let mut post_order_rank: IndexVec = - IndexVec::from_elem_n(usize::default(), graph.num_nodes()); + (0..graph.num_nodes()).map(|_| 0).collect(); for (index, node) in rpo.iter().rev().cloned().enumerate() { post_order_rank[node] = index; } let mut immediate_dominators: IndexVec> = - IndexVec::from_elem_n(Option::default(), graph.num_nodes()); + (0..graph.num_nodes()).map(|_| None).collect(); immediate_dominators[start_node] = Some(start_node); let mut changed = true; @@ -107,7 +107,8 @@ fn intersect( node2 = immediate_dominators[node2].unwrap(); } } - return node1; + + node1 } #[derive(Clone, Debug)] diff --git a/src/librustc_data_structures/graph/implementation/mod.rs b/src/librustc_data_structures/graph/implementation/mod.rs index dbfc09116b..baac756586 100644 --- a/src/librustc_data_structures/graph/implementation/mod.rs +++ b/src/librustc_data_structures/graph/implementation/mod.rs @@ -30,7 +30,7 @@ //! the field `next_edge`). Each of those fields is an array that should //! be indexed by the direction (see the type `Direction`). -use bitvec::BitVector; +use bitvec::BitArray; use std::fmt::Debug; use std::usize; use snapshot_vec::{SnapshotVec, SnapshotVecDelegate}; @@ -90,7 +90,7 @@ pub const INCOMING: Direction = Direction { repr: 1 }; impl NodeIndex { /// Returns unique id (unique with respect to the graph holding associated node). - pub fn node_id(&self) -> usize { + pub fn node_id(self) -> usize { self.0 } } @@ -187,7 +187,7 @@ impl Graph { self.nodes[source.0].first_edge[OUTGOING.repr] = idx; self.nodes[target.0].first_edge[INCOMING.repr] = idx; - return idx; + idx } pub fn edge(&self, idx: EdgeIndex) -> &Edge { @@ -261,12 +261,12 @@ impl Graph { DepthFirstTraversal::with_start_node(self, start, direction) } - pub fn nodes_in_postorder<'a>( - &'a self, + pub fn nodes_in_postorder( + &self, direction: Direction, entry_node: NodeIndex, ) -> Vec { - let mut visited = BitVector::new(self.len_nodes()); + let mut visited = BitArray::new(self.len_nodes()); let mut stack = vec![]; let mut result = Vec::with_capacity(self.len_nodes()); let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| { @@ -348,7 +348,7 @@ where { graph: &'g Graph, stack: Vec, - visited: BitVector, + visited: BitArray, direction: Direction, } @@ -358,7 +358,7 @@ impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> { start_node: NodeIndex, direction: Direction, ) -> Self { - let mut visited = BitVector::new(graph.len_nodes()); + let mut visited = BitArray::new(graph.len_nodes()); visited.insert(start_node.node_id()); DepthFirstTraversal { graph, diff --git a/src/librustc_data_structures/graph/test.rs b/src/librustc_data_structures/graph/test.rs index 48b654726b..26cc2c9f17 100644 --- a/src/librustc_data_structures/graph/test.rs +++ b/src/librustc_data_structures/graph/test.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashMap; +use fx::FxHashMap; use std::cmp::max; use std::slice; use std::iter; @@ -18,8 +18,8 @@ use super::*; pub struct TestGraph { num_nodes: usize, start_node: usize, - successors: HashMap>, - predecessors: HashMap>, + successors: FxHashMap>, + predecessors: FxHashMap>, } impl TestGraph { @@ -27,18 +27,18 @@ impl TestGraph { let mut graph = TestGraph { num_nodes: start_node + 1, start_node, - successors: HashMap::new(), - predecessors: HashMap::new(), + successors: FxHashMap::default(), + predecessors: FxHashMap::default(), }; for &(source, target) in edges { graph.num_nodes = max(graph.num_nodes, source + 1); graph.num_nodes = max(graph.num_nodes, target + 1); - graph.successors.entry(source).or_insert(vec![]).push(target); - graph.predecessors.entry(target).or_insert(vec![]).push(source); + graph.successors.entry(source).or_default().push(target); + graph.predecessors.entry(target).or_default().push(source); } for node in 0..graph.num_nodes { - graph.successors.entry(node).or_insert(vec![]); - graph.predecessors.entry(node).or_insert(vec![]); + graph.successors.entry(node).or_default(); + graph.predecessors.entry(node).or_default(); } graph } diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs index 2e95a45479..5ba8c150e1 100644 --- a/src/librustc_data_structures/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -8,96 +8,47 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::borrow::{Borrow, BorrowMut, ToOwned}; +use array_vec::ArrayVec; use std::fmt; -use std::iter; -use std::marker::PhantomData; use std::mem; -use std::ops::{Deref, DerefMut, Range}; use std::slice; -use bitslice::{BitSlice, Word}; -use bitslice::{bitwise, Union, Subtract, Intersect}; +use bitvec::{bitwise, BitArray, BitIter, Intersect, Subtract, Union, Word, WORD_BITS}; use indexed_vec::Idx; use rustc_serialize; -/// Represents a set (or packed family of sets), of some element type -/// E, where each E is identified by some unique index type `T`. -/// -/// In other words, `T` is the type used to index into the bitvector -/// this type uses to represent the set of object it holds. -#[derive(Eq, PartialEq)] -pub struct IdxSetBuf { - _pd: PhantomData, - bits: Vec, -} - -impl Clone for IdxSetBuf { - fn clone(&self) -> Self { - IdxSetBuf { _pd: PhantomData, bits: self.bits.clone() } - } -} - -impl rustc_serialize::Encodable for IdxSetBuf { - fn encode(&self, - encoder: &mut E) - -> Result<(), E::Error> { - self.bits.encode(encoder) - } +/// This is implemented by all the index sets so that IdxSet::union() can be +/// passed any type of index set. +pub trait UnionIntoIdxSet { + // Performs `other = other | self`. + fn union_into(&self, other: &mut IdxSet) -> bool; } -impl rustc_serialize::Decodable for IdxSetBuf { - fn decode(d: &mut D) -> Result, D::Error> { - let words: Vec = rustc_serialize::Decodable::decode(d)?; - - Ok(IdxSetBuf { - _pd: PhantomData, - bits: words, - }) - } +/// This is implemented by all the index sets so that IdxSet::subtract() can be +/// passed any type of index set. +pub trait SubtractFromIdxSet { + // Performs `other = other - self`. + fn subtract_from(&self, other: &mut IdxSet) -> bool; } - -// pnkfelix wants to have this be `IdxSet([Word]) and then pass -// around `&mut IdxSet` or `&IdxSet`. -// -// WARNING: Mapping a `&IdxSetBuf` to `&IdxSet` (at least today) -// requires a transmute relying on representation guarantees that may -// not hold in the future. - -/// Represents a set (or packed family of sets), of some element type -/// E, where each E is identified by some unique index type `T`. +/// Represents a set of some element type E, where each E is identified by some +/// unique index type `T`. /// -/// In other words, `T` is the type used to index into the bitslice +/// In other words, `T` is the type used to index into the bitvector /// this type uses to represent the set of object it holds. -pub struct IdxSet { - _pd: PhantomData, - bits: [Word], -} - -impl Borrow> for IdxSetBuf { - fn borrow(&self) -> &IdxSet { - &*self - } -} +/// +/// The representation is dense, using one bit per possible element. +#[derive(Clone, Eq, PartialEq)] +pub struct IdxSet(BitArray); -impl BorrowMut> for IdxSetBuf { - fn borrow_mut(&mut self) -> &mut IdxSet { - &mut *self +impl rustc_serialize::Encodable for IdxSet { + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { + self.0.encode(encoder) } } -impl ToOwned for IdxSet { - type Owned = IdxSetBuf; - fn to_owned(&self) -> Self::Owned { - IdxSet::to_owned(self) - } -} - -impl fmt::Debug for IdxSetBuf { - fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { - w.debug_list() - .entries(self.iter()) - .finish() +impl rustc_serialize::Decodable for IdxSet { + fn decode(d: &mut D) -> Result, D::Error> { + Ok(IdxSet(rustc_serialize::Decodable::decode(d)?)) } } @@ -109,128 +60,58 @@ impl fmt::Debug for IdxSet { } } -impl IdxSetBuf { - fn new(init: Word, universe_size: usize) -> Self { - let bits_per_word = mem::size_of::() * 8; - let num_words = (universe_size + (bits_per_word - 1)) / bits_per_word; - IdxSetBuf { - _pd: Default::default(), - bits: vec![init; num_words], - } - } - - /// Creates set holding every element whose index falls in range 0..universe_size. - pub fn new_filled(universe_size: usize) -> Self { - let mut result = Self::new(!0, universe_size); - result.trim_to(universe_size); - result - } - - /// Creates set holding no elements. - pub fn new_empty(universe_size: usize) -> Self { - Self::new(0, universe_size) - } -} - impl IdxSet { - unsafe fn from_slice(s: &[Word]) -> &Self { - mem::transmute(s) // (see above WARNING) - } - - unsafe fn from_slice_mut(s: &mut [Word]) -> &mut Self { - mem::transmute(s) // (see above WARNING) + /// Creates set holding no elements. + pub fn new_empty(domain_size: usize) -> Self { + IdxSet(BitArray::new_empty(domain_size)) } -} -impl Deref for IdxSetBuf { - type Target = IdxSet; - fn deref(&self) -> &IdxSet { - unsafe { IdxSet::from_slice(&self.bits) } + /// Creates set holding every element whose index falls in range 0..domain_size. + pub fn new_filled(domain_size: usize) -> Self { + IdxSet(BitArray::new_filled(domain_size)) } -} -impl DerefMut for IdxSetBuf { - fn deref_mut(&mut self) -> &mut IdxSet { - unsafe { IdxSet::from_slice_mut(&mut self.bits) } - } -} + /// Duplicates as a hybrid set. + pub fn to_hybrid(&self) -> HybridIdxSet { + // This domain_size may be slightly larger than the one specified + // upon creation, due to rounding up to a whole word. That's ok. + let domain_size = self.words().len() * WORD_BITS; -impl IdxSet { - pub fn to_owned(&self) -> IdxSetBuf { - IdxSetBuf { - _pd: Default::default(), - bits: self.bits.to_owned(), - } + // Note: we currently don't bother trying to make a Sparse set. + HybridIdxSet::Dense(self.to_owned(), domain_size) } /// Removes all elements pub fn clear(&mut self) { - for b in &mut self.bits { - *b = 0; - } + self.0.clear(); } - /// Sets all elements up to `universe_size` - pub fn set_up_to(&mut self, universe_size: usize) { - for b in &mut self.bits { - *b = !0; - } - self.trim_to(universe_size); - } - - /// Clear all elements above `universe_size`. - fn trim_to(&mut self, universe_size: usize) { - let word_bits = mem::size_of::() * 8; - - // `trim_block` is the first block where some bits have - // to be cleared. - let trim_block = universe_size / word_bits; - - // all the blocks above it have to be completely cleared. - if trim_block < self.bits.len() { - for b in &mut self.bits[trim_block+1..] { - *b = 0; - } - - // at that block, the `universe_size % word_bits` lsbs - // should remain. - let remaining_bits = universe_size % word_bits; - let mask = (1< bool { - self.bits.clear_bit(elem.index()) + self.0.remove(*elem) } /// Adds `elem` to the set `self`; returns true iff this changed `self`. pub fn add(&mut self, elem: &T) -> bool { - self.bits.set_bit(elem.index()) - } - - pub fn range(&self, elems: &Range) -> &Self { - let elems = elems.start.index()..elems.end.index(); - unsafe { Self::from_slice(&self.bits[elems]) } - } - - pub fn range_mut(&mut self, elems: &Range) -> &mut Self { - let elems = elems.start.index()..elems.end.index(); - unsafe { Self::from_slice_mut(&mut self.bits[elems]) } + self.0.insert(*elem) } /// Returns true iff set `self` contains `elem`. pub fn contains(&self, elem: &T) -> bool { - self.bits.get_bit(elem.index()) + self.0.contains(*elem) } pub fn words(&self) -> &[Word] { - &self.bits + self.0.words() } pub fn words_mut(&mut self) -> &mut [Word] { - &mut self.bits + self.0.words_mut() } /// Efficiently overwrite `self` with `other`. Panics if `self` and `other` @@ -241,14 +122,14 @@ impl IdxSet { /// Set `self = self | other` and return true if `self` changed /// (i.e., if new bits were added). - pub fn union(&mut self, other: &IdxSet) -> bool { - bitwise(self.words_mut(), other.words(), &Union) + pub fn union(&mut self, other: &impl UnionIntoIdxSet) -> bool { + other.union_into(self) } /// Set `self = self - other` and return true if `self` changed. /// (i.e., if any bits were removed). - pub fn subtract(&mut self, other: &IdxSet) -> bool { - bitwise(self.words_mut(), other.words(), &Subtract) + pub fn subtract(&mut self, other: &impl SubtractFromIdxSet) -> bool { + other.subtract_from(self) } /// Set `self = self & other` and return true if `self` changed. @@ -257,78 +138,221 @@ impl IdxSet { bitwise(self.words_mut(), other.words(), &Intersect) } - pub fn iter(&self) -> Iter { - Iter { - cur: None, - iter: self.words().iter().enumerate(), - _pd: PhantomData, + pub fn iter(&self) -> BitIter { + self.0.iter() + } +} + +impl UnionIntoIdxSet for IdxSet { + fn union_into(&self, other: &mut IdxSet) -> bool { + bitwise(other.words_mut(), self.words(), &Union) + } +} + +impl SubtractFromIdxSet for IdxSet { + fn subtract_from(&self, other: &mut IdxSet) -> bool { + bitwise(other.words_mut(), self.words(), &Subtract) + } +} + +const SPARSE_MAX: usize = 8; + +/// A sparse index set with a maximum of SPARSE_MAX elements. Used by +/// HybridIdxSet; do not use directly. +/// +/// The elements are stored as an unsorted vector with no duplicates. +#[derive(Clone, Debug)] +pub struct SparseIdxSet(ArrayVec<[T; SPARSE_MAX]>); + +impl SparseIdxSet { + fn new() -> Self { + SparseIdxSet(ArrayVec::new()) + } + + fn len(&self) -> usize { + self.0.len() + } + + fn contains(&self, elem: &T) -> bool { + self.0.contains(elem) + } + + fn add(&mut self, elem: &T) -> bool { + // Ensure there are no duplicates. + if self.0.contains(elem) { + false + } else { + self.0.push(*elem); + true } } + + fn remove(&mut self, elem: &T) -> bool { + if let Some(i) = self.0.iter().position(|e| e == elem) { + // Swap the found element to the end, then pop it. + let len = self.0.len(); + self.0.swap(i, len - 1); + self.0.pop(); + true + } else { + false + } + } + + fn to_dense(&self, domain_size: usize) -> IdxSet { + let mut dense = IdxSet::new_empty(domain_size); + for elem in self.0.iter() { + dense.add(elem); + } + dense + } + + fn iter(&self) -> slice::Iter { + self.0.iter() + } } -pub struct Iter<'a, T: Idx> { - cur: Option<(Word, usize)>, - iter: iter::Enumerate>, - _pd: PhantomData, +impl UnionIntoIdxSet for SparseIdxSet { + fn union_into(&self, other: &mut IdxSet) -> bool { + let mut changed = false; + for elem in self.iter() { + changed |= other.add(&elem); + } + changed + } } -impl<'a, T: Idx> Iterator for Iter<'a, T> { - type Item = T; +impl SubtractFromIdxSet for SparseIdxSet { + fn subtract_from(&self, other: &mut IdxSet) -> bool { + let mut changed = false; + for elem in self.iter() { + changed |= other.remove(&elem); + } + changed + } +} - fn next(&mut self) -> Option { - let word_bits = mem::size_of::() * 8; - loop { - if let Some((ref mut word, offset)) = self.cur { - let bit_pos = word.trailing_zeros() as usize; - if bit_pos != word_bits { - let bit = 1 << bit_pos; - *word ^= bit; - return Some(T::new(bit_pos + offset)) +/// Like IdxSet, but with a hybrid representation: sparse when there are few +/// elements in the set, but dense when there are many. It's especially +/// efficient for sets that typically have a small number of elements, but a +/// large `domain_size`, and are cleared frequently. +#[derive(Clone, Debug)] +pub enum HybridIdxSet { + Sparse(SparseIdxSet, usize), + Dense(IdxSet, usize), +} + +impl HybridIdxSet { + pub fn new_empty(domain_size: usize) -> Self { + HybridIdxSet::Sparse(SparseIdxSet::new(), domain_size) + } + + pub fn clear(&mut self) { + let domain_size = match *self { + HybridIdxSet::Sparse(_, size) => size, + HybridIdxSet::Dense(_, size) => size, + }; + *self = HybridIdxSet::new_empty(domain_size); + } + + /// Returns true iff set `self` contains `elem`. + pub fn contains(&self, elem: &T) -> bool { + match self { + HybridIdxSet::Sparse(sparse, _) => sparse.contains(elem), + HybridIdxSet::Dense(dense, _) => dense.contains(elem), + } + } + + /// Adds `elem` to the set `self`. + pub fn add(&mut self, elem: &T) -> bool { + match self { + HybridIdxSet::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => { + // The set is sparse and has space for `elem`. + sparse.add(elem) + } + HybridIdxSet::Sparse(sparse, _) if sparse.contains(elem) => { + // The set is sparse and does not have space for `elem`, but + // that doesn't matter because `elem` is already present. + false + } + HybridIdxSet::Sparse(_, _) => { + // The set is sparse and full. Convert to a dense set. + // + // FIXME: This code is awful, but I can't work out how else to + // appease the borrow checker. + let dummy = HybridIdxSet::Sparse(SparseIdxSet::new(), 0); + match mem::replace(self, dummy) { + HybridIdxSet::Sparse(sparse, domain_size) => { + let mut dense = sparse.to_dense(domain_size); + let changed = dense.add(elem); + assert!(changed); + mem::replace(self, HybridIdxSet::Dense(dense, domain_size)); + changed + } + _ => panic!("impossible"), } } - let (i, word) = self.iter.next()?; - self.cur = Some((*word, word_bits * i)); + HybridIdxSet::Dense(dense, _) => dense.add(elem), + } + } + + /// Removes `elem` from the set `self`. + pub fn remove(&mut self, elem: &T) -> bool { + // Note: we currently don't bother going from Dense back to Sparse. + match self { + HybridIdxSet::Sparse(sparse, _) => sparse.remove(elem), + HybridIdxSet::Dense(dense, _) => dense.remove(elem), } } -} -#[test] -fn test_trim_to() { - use std::cmp; + /// Converts to a dense set, consuming itself in the process. + pub fn to_dense(self) -> IdxSet { + match self { + HybridIdxSet::Sparse(sparse, domain_size) => sparse.to_dense(domain_size), + HybridIdxSet::Dense(dense, _) => dense, + } + } - for i in 0..256 { - let mut idx_buf: IdxSetBuf = IdxSetBuf::new_filled(128); - idx_buf.trim_to(i); + /// Iteration order is unspecified. + pub fn iter(&self) -> HybridIter { + match self { + HybridIdxSet::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()), + HybridIdxSet::Dense(dense, _) => HybridIter::Dense(dense.iter()), + } + } +} - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..cmp::min(i, 128)).collect(); - assert_eq!(elems, expected); +impl UnionIntoIdxSet for HybridIdxSet { + fn union_into(&self, other: &mut IdxSet) -> bool { + match self { + HybridIdxSet::Sparse(sparse, _) => sparse.union_into(other), + HybridIdxSet::Dense(dense, _) => dense.union_into(other), + } } } -#[test] -fn test_set_up_to() { - for i in 0..128 { - for mut idx_buf in - vec![IdxSetBuf::new_empty(128), IdxSetBuf::new_filled(128)] - .into_iter() - { - idx_buf.set_up_to(i); - - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..i).collect(); - assert_eq!(elems, expected); +impl SubtractFromIdxSet for HybridIdxSet { + fn subtract_from(&self, other: &mut IdxSet) -> bool { + match self { + HybridIdxSet::Sparse(sparse, _) => sparse.subtract_from(other), + HybridIdxSet::Dense(dense, _) => dense.subtract_from(other), } } } -#[test] -fn test_new_filled() { - for i in 0..128 { - let mut idx_buf = IdxSetBuf::new_filled(i); - let elems: Vec = idx_buf.iter().collect(); - let expected: Vec = (0..i).collect(); - assert_eq!(elems, expected); +pub enum HybridIter<'a, T: Idx> { + Sparse(slice::Iter<'a, T>), + Dense(BitIter<'a, T>), +} + +impl<'a, T: Idx> Iterator for HybridIter<'a, T> { + type Item = T; + + fn next(&mut self) -> Option { + match self { + HybridIter::Sparse(sparse) => sparse.next().map(|e| *e), + HybridIter::Dense(dense) => dense.next(), + } } } diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index c358f2f852..2f11fea46d 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -48,25 +48,44 @@ impl Idx for u32 { fn index(self) -> usize { self as usize } } +/// Creates a struct type `S` that can be used as an index with +/// `IndexVec` and so on. +/// +/// There are two ways of interacting with these indices: +/// +/// - The `From` impls are the preferred way. So you can do +/// `S::from(v)` with a `usize` or `u32`. And you can convert back +/// to an integer with `u32::from(s)`. +/// +/// - Alternatively, you can use the methods `S::new(v)` and `s.index()` +/// to create/return a value. +/// +/// Internally, the index uses a u32, so the index must not exceed +/// `u32::MAX`. You can also customize things like the `Debug` impl, +/// what traits are derived, and so forth via the macro. #[macro_export] macro_rules! newtype_index { // ---- public rules ---- // Use default constants - ($name:ident) => ( + ($v:vis struct $name:ident { .. }) => ( newtype_index!( // Leave out derives marker so we can use its absence to ensure it comes first @type [$name] - @max [::std::u32::MAX] + // shave off 256 indices at the end to allow space for packing these indices into enums + @max [0xFFFF_FF00] + @vis [$v] @debug_format ["{}"]); ); // Define any constants - ($name:ident { $($tokens:tt)+ }) => ( + ($v:vis struct $name:ident { $($tokens:tt)+ }) => ( newtype_index!( // Leave out derives marker so we can use its absence to ensure it comes first @type [$name] - @max [::std::u32::MAX] + // shave off 256 indices at the end to allow space for packing these indices into enums + @max [0xFFFF_FF00] + @vis [$v] @debug_format ["{}"] $($tokens)+); ); @@ -75,27 +94,93 @@ macro_rules! newtype_index { // Base case, user-defined constants (if any) have already been defined (@derives [$($derives:ident,)*] - @pub [$($pub:tt)*] @type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt]) => ( #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)] - pub struct $type($($pub)* u32); + #[rustc_layout_scalar_valid_range_end($max)] + $v struct $type { + private: u32 + } + + impl $type { + $v const MAX_AS_U32: u32 = $max; + + $v const MAX: $type = $type::from_u32_const($max); + + #[inline] + $v fn from_usize(value: usize) -> Self { + assert!(value <= ($max as usize)); + unsafe { + $type::from_u32_unchecked(value as u32) + } + } + + #[inline] + $v fn from_u32(value: u32) -> Self { + assert!(value <= $max); + unsafe { + $type::from_u32_unchecked(value) + } + } + + /// Hacky variant of `from_u32` for use in constants. + /// This version checks the "max" constraint by using an + /// invalid array dereference. + #[inline] + $v const fn from_u32_const(value: u32) -> Self { + // This will fail at const eval time unless `value <= + // max` is true (in which case we get the index 0). + // It will also fail at runtime, of course, but in a + // kind of wacky way. + let _ = ["out of range value used"][ + !(value <= $max) as usize + ]; + + unsafe { + $type { private: value } + } + } + + #[inline] + $v const unsafe fn from_u32_unchecked(value: u32) -> Self { + $type { private: value } + } + + /// Extract value of this index as an integer. + #[inline] + $v fn index(self) -> usize { + self.as_usize() + } + + /// Extract value of this index as a usize. + #[inline] + $v fn as_u32(self) -> u32 { + self.private + } + + /// Extract value of this index as a u32. + #[inline] + $v fn as_usize(self) -> usize { + self.as_u32() as usize + } + } impl Idx for $type { #[inline] fn new(value: usize) -> Self { - assert!(value < ($max) as usize); - $type(value as u32) + Self::from(value) } #[inline] fn index(self) -> usize { - self.0 as usize + usize::from(self) } } impl ::std::iter::Step for $type { + #[inline] fn steps_between(start: &Self, end: &Self) -> Option { ::steps_between( &Idx::index(*start), @@ -103,27 +188,60 @@ macro_rules! newtype_index { ) } + #[inline] fn replace_one(&mut self) -> Self { ::std::mem::replace(self, Self::new(1)) } + #[inline] fn replace_zero(&mut self) -> Self { ::std::mem::replace(self, Self::new(0)) } + #[inline] fn add_one(&self) -> Self { Self::new(Idx::index(*self) + 1) } + #[inline] fn sub_one(&self) -> Self { Self::new(Idx::index(*self) - 1) } + #[inline] fn add_usize(&self, u: usize) -> Option { Idx::index(*self).checked_add(u).map(Self::new) } } + impl From<$type> for u32 { + #[inline] + fn from(v: $type) -> u32 { + v.as_u32() + } + } + + impl From<$type> for usize { + #[inline] + fn from(v: $type) -> usize { + v.as_usize() + } + } + + impl From for $type { + #[inline] + fn from(value: usize) -> Self { + $type::from_usize(value) + } + } + + impl From for $type { + #[inline] + fn from(value: u32) -> Self { + $type::from_u32(value) + } + } + newtype_index!( @handle_debug @derives [$($derives,)*] @@ -144,7 +262,7 @@ macro_rules! newtype_index { @debug_format [$debug_format:tt]) => ( impl ::std::fmt::Debug for $type { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(fmt, $debug_format, self.0) + write!(fmt, $debug_format, self.as_u32()) } } ); @@ -167,44 +285,17 @@ macro_rules! newtype_index { @debug_format [$debug_format]); ); - // Handle the case where someone wants to make the internal field public - (@type [$type:ident] - @max [$max:expr] - @debug_format [$debug_format:tt] - pub idx - $($tokens:tt)*) => ( - newtype_index!( - @pub [pub] - @type [$type] - @max [$max] - @debug_format [$debug_format] - $($tokens)*); - ); - - // The default case is that the internal field is private - (@type [$type:ident] - @max [$max:expr] - @debug_format [$debug_format:tt] - $($tokens:tt)*) => ( - newtype_index!( - @pub [] - @type [$type] - @max [$max] - @debug_format [$debug_format] - $($tokens)*); - ); - // Append comma to end of derives list if it's missing - (@pub [$($pub:tt)*] - @type [$type:ident] + (@type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] derive [$($derives:ident),*] $($tokens:tt)*) => ( newtype_index!( - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] derive [$($derives,)*] $($tokens)*); @@ -212,154 +303,154 @@ macro_rules! newtype_index { // By not including the @derives marker in this list nor in the default args, we can force it // to come first if it exists. When encodable is custom, just use the derives list as-is. - (@pub [$($pub:tt)*] - @type [$type:ident] + (@type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] derive [$($derives:ident,)+] ENCODABLE = custom $($tokens:tt)*) => ( newtype_index!( @derives [$($derives,)+] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $($tokens)*); ); // By not including the @derives marker in this list nor in the default args, we can force it // to come first if it exists. When encodable isn't custom, add serialization traits by default. - (@pub [$($pub:tt)*] - @type [$type:ident] + (@type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] derive [$($derives:ident,)+] $($tokens:tt)*) => ( newtype_index!( @derives [$($derives,)+ RustcDecodable, RustcEncodable,] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $($tokens)*); ); // The case where no derives are added, but encodable is overridden. Don't // derive serialization traits - (@pub [$($pub:tt)*] - @type [$type:ident] + (@type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] ENCODABLE = custom $($tokens:tt)*) => ( newtype_index!( @derives [] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $($tokens)*); ); // The case where no derives are added, add serialization derives by default - (@pub [$($pub:tt)*] - @type [$type:ident] + (@type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] $($tokens:tt)*) => ( newtype_index!( @derives [RustcDecodable, RustcEncodable,] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $($tokens)*); ); // Rewrite final without comma to one that includes comma (@derives [$($derives:ident,)*] - @pub [$($pub:tt)*] @type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] $name:ident = $constant:expr) => ( newtype_index!( @derives [$($derives,)*] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $name = $constant,); ); // Rewrite final const without comma to one that includes comma (@derives [$($derives:ident,)*] - @pub [$($pub:tt)*] @type [$type:ident] @max [$_max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] $(#[doc = $doc:expr])* const $name:ident = $constant:expr) => ( newtype_index!( @derives [$($derives,)*] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $(#[doc = $doc])* const $name = $constant,); ); // Replace existing default for max (@derives [$($derives:ident,)*] - @pub [$($pub:tt)*] @type [$type:ident] @max [$_max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] MAX = $max:expr, $($tokens:tt)*) => ( newtype_index!( @derives [$($derives,)*] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $($tokens)*); ); // Replace existing default for debug_format (@derives [$($derives:ident,)*] - @pub [$($pub:tt)*] @type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$_debug_format:tt] DEBUG_FORMAT = $debug_format:tt, $($tokens:tt)*) => ( newtype_index!( @derives [$($derives,)*] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $($tokens)*); ); // Assign a user-defined constant (@derives [$($derives:ident,)*] - @pub [$($pub:tt)*] @type [$type:ident] @max [$max:expr] + @vis [$v:vis] @debug_format [$debug_format:tt] $(#[doc = $doc:expr])* const $name:ident = $constant:expr, $($tokens:tt)*) => ( $(#[doc = $doc])* - pub const $name: $type = $type($constant); + pub const $name: $type = $type::from_u32_const($constant); newtype_index!( @derives [$($derives,)*] - @pub [$($pub)*] @type [$type] @max [$max] + @vis [$v] @debug_format [$debug_format] $($tokens)*); ); diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index a9e582e510..9435cb3184 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -20,13 +20,15 @@ html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(collections_range)] +#![feature(in_band_lifetimes)] +#![feature(impl_header_lifetime_elision)] #![feature(unboxed_closures)] #![feature(fn_traits)] #![feature(unsize)] #![feature(specialization)] #![feature(optin_builtin_traits)] -#![feature(macro_vis_matcher)] +#![cfg_attr(stage0, feature(macro_vis_matcher))] +#![cfg_attr(not(stage0), feature(nll))] #![feature(allow_internal_unstable)] #![feature(vec_resize_with)] @@ -47,6 +49,9 @@ extern crate stable_deref_trait; extern crate rustc_rayon as rayon; extern crate rustc_rayon_core as rayon_core; extern crate rustc_hash; +extern crate serialize; +#[cfg_attr(test, macro_use)] +extern crate smallvec; // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] @@ -54,11 +59,11 @@ extern crate rustc_cratesio_shim; pub use rustc_serialize::hex::ToHex; -pub mod accumulate_vec; +pub mod svh; pub mod array_vec; pub mod base_n; -pub mod bitslice; pub mod bitvec; +pub mod const_cstr; pub mod flock; pub mod fx; pub mod graph; @@ -68,17 +73,21 @@ pub mod obligation_forest; pub mod owning_ref; pub mod ptr_key; pub mod sip128; +pub mod small_c_str; pub mod small_vec; pub mod snapshot_map; pub use ena::snapshot_vec; pub mod sorted_map; -pub mod stable_hasher; +#[macro_use] pub mod stable_hasher; pub mod sync; pub mod tiny_list; +pub mod thin_vec; pub mod transitive_relation; pub mod tuple_slice; pub use ena::unify; +pub mod vec_linked_list; pub mod work_queue; +pub mod fingerprint; 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 0d6cf260dc..7ef8885268 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -573,7 +573,7 @@ impl ObligationForest { } let mut kill_list = vec![]; - for (predicate, index) in self.waiting_cache.iter_mut() { + for (predicate, index) in &mut self.waiting_cache { let new_index = node_rewrites[index.get()]; if new_index >= nodes_len { kill_list.push(predicate.clone()); diff --git a/src/librustc_data_structures/small_c_str.rs b/src/librustc_data_structures/small_c_str.rs new file mode 100644 index 0000000000..08794fbec8 --- /dev/null +++ b/src/librustc_data_structures/small_c_str.rs @@ -0,0 +1,122 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ffi; +use std::ops::Deref; + +use smallvec::SmallVec; + +const SIZE: usize = 36; + +/// Like SmallVec but for C strings. +#[derive(Clone)] +pub struct SmallCStr { + data: SmallVec<[u8; SIZE]>, +} + +impl SmallCStr { + #[inline] + pub fn new(s: &str) -> SmallCStr { + let len = s.len(); + let len1 = len + 1; + let data = if len < SIZE { + let mut buf = [0; SIZE]; + buf[..len].copy_from_slice(s.as_bytes()); + SmallVec::from_buf_and_len(buf, len1) + } else { + let mut data = Vec::with_capacity(len1); + data.extend_from_slice(s.as_bytes()); + data.push(0); + SmallVec::from_vec(data) + }; + if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) { + panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); + } + SmallCStr { data } + } + + #[inline] + pub fn new_with_nul(s: &str) -> SmallCStr { + let b = s.as_bytes(); + if let Err(e) = ffi::CStr::from_bytes_with_nul(b) { + panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); + } + SmallCStr { data: SmallVec::from_slice(s.as_bytes()) } + } + + + #[inline] + pub fn as_c_str(&self) -> &ffi::CStr { + unsafe { + ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..]) + } + } + + #[inline] + pub fn len_with_nul(&self) -> usize { + self.data.len() + } + + pub fn spilled(&self) -> bool { + self.data.spilled() + } +} + +impl Deref for SmallCStr { + type Target = ffi::CStr; + + fn deref(&self) -> &ffi::CStr { + self.as_c_str() + } +} + +#[test] +fn short() { + const TEXT: &str = "abcd"; + let reference = ffi::CString::new(TEXT.to_string()).unwrap(); + + let scs = SmallCStr::new(TEXT); + + assert_eq!(scs.len_with_nul(), TEXT.len() + 1); + assert_eq!(scs.as_c_str(), reference.as_c_str()); + assert!(!scs.spilled()); +} + +#[test] +fn empty() { + const TEXT: &str = ""; + let reference = ffi::CString::new(TEXT.to_string()).unwrap(); + + let scs = SmallCStr::new(TEXT); + + assert_eq!(scs.len_with_nul(), TEXT.len() + 1); + assert_eq!(scs.as_c_str(), reference.as_c_str()); + assert!(!scs.spilled()); +} + +#[test] +fn long() { + const TEXT: &str = "01234567890123456789012345678901234567890123456789\ + 01234567890123456789012345678901234567890123456789\ + 01234567890123456789012345678901234567890123456789"; + let reference = ffi::CString::new(TEXT.to_string()).unwrap(); + + let scs = SmallCStr::new(TEXT); + + assert_eq!(scs.len_with_nul(), TEXT.len() + 1); + assert_eq!(scs.as_c_str(), reference.as_c_str()); + assert!(scs.spilled()); +} + +#[test] +#[should_panic] +fn internal_nul() { + let _ = SmallCStr::new("abcd\0def"); +} diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs index 4a72ab57fc..075b70c642 100644 --- a/src/librustc_data_structures/small_vec.rs +++ b/src/librustc_data_structures/small_vec.rs @@ -8,208 +8,48 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A vector type intended to be used for collecting from iterators onto the stack. +//! A vector type intended to be used for small vectors. //! -//! Space for up to N elements is provided on the stack. If more elements are collected, Vec is -//! used to store the values on the heap. SmallVec is similar to AccumulateVec, but adds -//! the ability to push elements. +//! Space for up to N elements is provided on the stack. If more elements are collected, Vec is +//! used to store the values on the heap. //! //! The N above is determined by Array's implementor, by way of an associated constant. -use std::ops::{Deref, DerefMut}; -use std::iter::{IntoIterator, FromIterator}; -use std::fmt::{self, Debug}; -use std::mem; -use std::ptr; +use smallvec::{Array, SmallVec}; -use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; +pub type OneVector = SmallVec<[T; 1]>; -use accumulate_vec::{IntoIter, AccumulateVec}; -use array_vec::Array; - -pub struct SmallVec(AccumulateVec); - -impl Clone for SmallVec - where A: Array, - A::Element: Clone { - fn clone(&self) -> Self { - SmallVec(self.0.clone()) - } -} - -impl Debug for SmallVec - where A: Array + Debug, - A::Element: Debug { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("SmallVec").field(&self.0).finish() - } +pub trait ExpectOne { + fn expect_one(self, err: &'static str) -> A::Item; } -impl SmallVec { - pub fn new() -> Self { - SmallVec(AccumulateVec::new()) - } - - pub fn is_array(&self) -> bool { - self.0.is_array() - } - - pub fn with_capacity(cap: usize) -> Self { - let mut vec = SmallVec::new(); - vec.reserve(cap); - vec - } - - pub fn one(el: A::Element) -> Self { - SmallVec(AccumulateVec::one(el)) - } - - pub fn many>(els: I) -> Self { - SmallVec(AccumulateVec::many(els)) - } - - pub fn expect_one(self, err: &'static str) -> A::Element { +impl ExpectOne for SmallVec { + fn expect_one(self, err: &'static str) -> A::Item { assert!(self.len() == 1, err); - match self.0 { - AccumulateVec::Array(arr) => arr.into_iter().next().unwrap(), - AccumulateVec::Heap(vec) => vec.into_iter().next().unwrap(), - } - } - - /// Will reallocate onto the heap if needed. - pub fn push(&mut self, el: A::Element) { - self.reserve(1); - match self.0 { - AccumulateVec::Array(ref mut array) => array.push(el), - AccumulateVec::Heap(ref mut vec) => vec.push(el), - } - } - - pub fn reserve(&mut self, n: usize) { - match self.0 { - AccumulateVec::Array(_) => { - if self.len() + n > A::LEN { - let len = self.len(); - let array = mem::replace(&mut self.0, - AccumulateVec::Heap(Vec::with_capacity(len + n))); - if let AccumulateVec::Array(array) = array { - match self.0 { - AccumulateVec::Heap(ref mut vec) => vec.extend(array), - _ => unreachable!() - } - } - } - } - AccumulateVec::Heap(ref mut vec) => vec.reserve(n) - } - } - - pub unsafe fn set_len(&mut self, len: usize) { - match self.0 { - AccumulateVec::Array(ref mut arr) => arr.set_len(len), - AccumulateVec::Heap(ref mut vec) => vec.set_len(len), - } - } - - pub fn insert(&mut self, index: usize, element: A::Element) { - let len = self.len(); - - // Reserve space for shifting elements to the right - self.reserve(1); - - assert!(index <= len); - - unsafe { - // infallible - // The spot to put the new value - { - let p = self.as_mut_ptr().offset(index as isize); - // Shift everything over to make space. (Duplicating the - // `index`th element into two consecutive places.) - ptr::copy(p, p.offset(1), len - index); - // Write it in, overwriting the first copy of the `index`th - // element. - ptr::write(p, element); - } - self.set_len(len + 1); - } - } - - pub fn truncate(&mut self, len: usize) { - unsafe { - while len < self.len() { - // Decrement len before the drop_in_place(), so a panic on Drop - // doesn't re-drop the just-failed value. - let newlen = self.len() - 1; - self.set_len(newlen); - ::std::ptr::drop_in_place(self.get_unchecked_mut(newlen)); - } - } - } -} - -impl Deref for SmallVec { - type Target = AccumulateVec; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for SmallVec { - fn deref_mut(&mut self) -> &mut AccumulateVec { - &mut self.0 + self.into_iter().next().unwrap() } } -impl FromIterator for SmallVec { - fn from_iter(iter: I) -> Self where I: IntoIterator { - SmallVec(iter.into_iter().collect()) - } -} +#[cfg(test)] +mod tests { + extern crate test; + use super::*; -impl Extend for SmallVec { - fn extend>(&mut self, iter: I) { - let iter = iter.into_iter(); - self.reserve(iter.size_hint().0); - for el in iter { - self.push(el); - } + #[test] + #[should_panic] + fn test_expect_one_zero() { + let _: isize = OneVector::new().expect_one(""); } -} -impl IntoIterator for SmallVec { - type Item = A::Element; - type IntoIter = IntoIter; - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + #[test] + #[should_panic] + fn test_expect_one_many() { + OneVector::from_vec(vec![1, 2]).expect_one(""); } -} - -impl Default for SmallVec { - fn default() -> SmallVec { - SmallVec::new() - } -} - -impl Encodable for SmallVec - where A: Array, - A::Element: Encodable { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_seq(self.len(), |s| { - for (i, e) in self.iter().enumerate() { - s.emit_seq_elt(i, |s| e.encode(s))?; - } - Ok(()) - }) - } -} -impl Decodable for SmallVec - where A: Array, - A::Element: Decodable { - fn decode(d: &mut D) -> Result, D::Error> { - d.read_seq(|d, len| { - (0..len).map(|i| d.read_seq_elt(i, |d| Decodable::decode(d))).collect() - }) + #[test] + fn test_expect_one_one() { + assert_eq!(1, (smallvec![1] as OneVector<_>).expect_one("")); + assert_eq!(1, OneVector::from_vec(vec![1]).expect_one("")); } } diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index 6ee8c3579f..5030bf98df 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -92,7 +92,7 @@ impl SnapshotMap pub fn snapshot(&mut self) -> Snapshot { self.undo_log.push(UndoLog::OpenSnapshot); let len = self.undo_log.len() - 1; - Snapshot { len: len } + Snapshot { len } } fn assert_open_snapshot(&self, snapshot: &Snapshot) { @@ -103,8 +103,8 @@ impl SnapshotMap }); } - pub fn commit(&mut self, snapshot: Snapshot) { - self.assert_open_snapshot(&snapshot); + pub fn commit(&mut self, snapshot: &Snapshot) { + self.assert_open_snapshot(snapshot); if snapshot.len == 0 { // The root snapshot. self.undo_log.truncate(0); @@ -135,8 +135,8 @@ impl SnapshotMap } } - pub fn rollback_to(&mut self, snapshot: Snapshot) { - self.assert_open_snapshot(&snapshot); + pub fn rollback_to(&mut self, snapshot: &Snapshot) { + self.assert_open_snapshot(snapshot); while self.undo_log.len() > snapshot.len + 1 { let entry = self.undo_log.pop().unwrap(); self.reverse(entry); diff --git a/src/librustc_data_structures/snapshot_map/test.rs b/src/librustc_data_structures/snapshot_map/test.rs index 4114082839..b163e0fe42 100644 --- a/src/librustc_data_structures/snapshot_map/test.rs +++ b/src/librustc_data_structures/snapshot_map/test.rs @@ -20,7 +20,7 @@ fn basic() { map.insert(44, "fourty-four"); assert_eq!(map[&44], "fourty-four"); assert_eq!(map.get(&33), None); - map.rollback_to(snapshot); + map.rollback_to(&snapshot); assert_eq!(map[&22], "twenty-two"); assert_eq!(map.get(&33), None); assert_eq!(map.get(&44), None); @@ -33,7 +33,7 @@ fn out_of_order() { map.insert(22, "twenty-two"); let snapshot1 = map.snapshot(); let _snapshot2 = map.snapshot(); - map.rollback_to(snapshot1); + map.rollback_to(&snapshot1); } #[test] @@ -43,8 +43,8 @@ fn nested_commit_then_rollback() { let snapshot1 = map.snapshot(); let snapshot2 = map.snapshot(); map.insert(22, "thirty-three"); - map.commit(snapshot2); + map.commit(&snapshot2); assert_eq!(map[&22], "thirty-three"); - map.rollback_to(snapshot1); + map.rollback_to(&snapshot1); assert_eq!(map[&22], "twenty-two"); } diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index a8f689e5c8..215c44dec6 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -183,13 +183,16 @@ pub trait ToStableHashKey { // Implement HashStable by just calling `Hash::hash()`. This works fine for // self-contained values that don't depend on the hashing context `CTX`. +#[macro_export] macro_rules! impl_stable_hash_via_hash { ($t:ty) => ( - impl HashStable for $t { + impl $crate::stable_hasher::HashStable for $t { #[inline] - fn hash_stable(&self, - _: &mut CTX, - hasher: &mut StableHasher) { + fn hash_stable( + &self, + _: &mut CTX, + hasher: &mut $crate::stable_hasher::StableHasher + ) { ::std::hash::Hash::hash(self, hasher); } } @@ -214,6 +217,14 @@ impl_stable_hash_via_hash!(i128); impl_stable_hash_via_hash!(char); impl_stable_hash_via_hash!(()); +impl HashStable for ::std::num::NonZeroU32 { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + self.get().hash_stable(ctx, hasher) + } +} + impl HashStable for f32 { fn hash_stable(&self, ctx: &mut CTX, @@ -278,6 +289,23 @@ impl HashStable for (T1, T2, T3) } } +impl HashStable for (T1, T2, T3, T4) + where T1: HashStable, + T2: HashStable, + T3: HashStable, + T4: HashStable, +{ + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + let (ref _0, ref _1, ref _2, ref _3) = *self; + _0.hash_stable(ctx, hasher); + _1.hash_stable(ctx, hasher); + _2.hash_stable(ctx, hasher); + _3.hash_stable(ctx, hasher); + } +} + impl, CTX> HashStable for [T] { default fn hash_stable(&self, ctx: &mut CTX, @@ -429,7 +457,7 @@ impl HashStable for ::indexed_vec::IndexVec< } -impl HashStable for ::indexed_set::IdxSetBuf +impl HashStable for ::indexed_set::IdxSet { fn hash_stable(&self, ctx: &mut CTX, diff --git a/src/librustc/hir/svh.rs b/src/librustc_data_structures/svh.rs similarity index 85% rename from src/librustc/hir/svh.rs rename to src/librustc_data_structures/svh.rs index a6cfcb710e..94f132562b 100644 --- a/src/librustc/hir/svh.rs +++ b/src/librustc_data_structures/svh.rs @@ -19,6 +19,8 @@ use std::fmt; use std::hash::{Hash, Hasher}; use serialize::{Encodable, Decodable, Encoder, Decoder}; +use stable_hasher; + #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Svh { hash: u64, @@ -67,6 +69,16 @@ impl Decodable for Svh { } } -impl_stable_hash_for!(struct Svh { - hash -}); +impl stable_hasher::HashStable for Svh { + #[inline] + fn hash_stable( + &self, + ctx: &mut T, + hasher: &mut stable_hasher::StableHasher + ) { + let Svh { + hash + } = *self; + hash.hash_stable(ctx, hasher); + } +} diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index d4c6b1c2ce..a2893a60cb 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -26,7 +26,7 @@ //! //! `MTLock` is a mutex which disappears if cfg!(parallel_queries) is false. //! -//! `MTRef` is a immutable refernce if cfg!(parallel_queries), and an mutable reference otherwise. +//! `MTRef` is a immutable reference if cfg!(parallel_queries), and an mutable reference otherwise. //! //! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync //! depending on the value of cfg!(parallel_queries). @@ -93,8 +93,11 @@ cfg_if! { pub use std::rc::Rc as Lrc; pub use std::rc::Weak as Weak; pub use std::cell::Ref as ReadGuard; + pub use std::cell::Ref as MappedReadGuard; pub use std::cell::RefMut as WriteGuard; + pub use std::cell::RefMut as MappedWriteGuard; pub use std::cell::RefMut as LockGuard; + pub use std::cell::RefMut as MappedLockGuard; use std::cell::RefCell as InnerRwLock; use std::cell::RefCell as InnerLock; @@ -213,9 +216,12 @@ cfg_if! { pub use std::marker::Sync as Sync; pub use parking_lot::RwLockReadGuard as ReadGuard; + pub use parking_lot::MappedRwLockReadGuard as MappedReadGuard; pub use parking_lot::RwLockWriteGuard as WriteGuard; + pub use parking_lot::MappedRwLockWriteGuard as MappedWriteGuard; pub use parking_lot::MutexGuard as LockGuard; + pub use parking_lot::MappedMutexGuard as MappedLockGuard; pub use std::sync::Arc as Lrc; pub use std::sync::Weak as Weak; @@ -432,7 +438,7 @@ impl Once { /// closures may concurrently be computing a value which the inner value should take. /// Only one of these closures are used to actually initialize the value. /// If some other closure already set the value, we assert that it our closure computed - /// a value equal to the value aready set and then + /// a value equal to the value already set and then /// we return the value our closure computed wrapped in a `Option`. /// If our closure set the value, `None` is returned. /// If the value is already initialized, the closure is not called and `None` is returned. diff --git a/src/libsyntax/util/thin_vec.rs b/src/librustc_data_structures/thin_vec.rs similarity index 100% rename from src/libsyntax/util/thin_vec.rs rename to src/librustc_data_structures/thin_vec.rs diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs index 5b1b2aadec..e1bfdf35b2 100644 --- a/src/librustc_data_structures/tiny_list.rs +++ b/src/librustc_data_structures/tiny_list.rs @@ -50,44 +50,22 @@ impl TinyList { #[inline] pub fn insert(&mut self, data: T) { - let current_head = mem::replace(&mut self.head, None); - - if let Some(current_head) = current_head { - let current_head = Box::new(current_head); - self.head = Some(Element { - data, - next: Some(current_head) - }); - } else { - self.head = Some(Element { - data, - next: None, - }) - } + self.head = Some(Element { + data, + next: mem::replace(&mut self.head, None).map(Box::new), + }); } #[inline] pub fn remove(&mut self, data: &T) -> bool { - let remove_head = if let Some(ref mut head) = self.head { - if head.data == *data { - Some(mem::replace(&mut head.next, None)) - } else { - None + self.head = match self.head { + Some(ref mut head) if head.data == *data => { + mem::replace(&mut head.next, None).map(|x| *x) } - } else { - return false + Some(ref mut head) => return head.remove_next(data), + None => return false, }; - - if let Some(remove_head) = remove_head { - if let Some(next) = remove_head { - self.head = Some(*next); - } else { - self.head = None; - } - return true - } - - self.head.as_mut().unwrap().remove_next(data) + true } #[inline] @@ -129,7 +107,8 @@ impl Element { }; self.next = new_next; - return true + + true } fn len(&self) -> usize { @@ -156,6 +135,8 @@ impl Element { #[cfg(test)] mod test { use super::*; + extern crate test; + use self::test::Bencher; #[test] fn test_contains_and_insert() { @@ -248,4 +229,41 @@ mod test { assert_eq!(list.len(), 0); } + + #[bench] + fn bench_insert_empty(b: &mut Bencher) { + b.iter(|| { + let mut list = TinyList::new(); + list.insert(1); + }) + } + + #[bench] + fn bench_insert_one(b: &mut Bencher) { + b.iter(|| { + let mut list = TinyList::new_single(0); + list.insert(1); + }) + } + + #[bench] + fn bench_remove_empty(b: &mut Bencher) { + b.iter(|| { + TinyList::new().remove(&1) + }); + } + + #[bench] + fn bench_remove_unknown(b: &mut Bencher) { + b.iter(|| { + TinyList::new_single(0).remove(&1) + }); + } + + #[bench] + fn bench_remove_one(b: &mut Bencher) { + b.iter(|| { + TinyList::new_single(1).remove(&1) + }); + } } diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index a8124fb7c5..2acc29acb0 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -77,7 +77,7 @@ impl TransitiveRelation { .. } = self; - map.entry(a.clone()) + *map.entry(a.clone()) .or_insert_with(|| { elements.push(a); @@ -86,7 +86,6 @@ impl TransitiveRelation { Index(elements.len() - 1) }) - .clone() } /// Applies the (partial) function to each edge and returns a new @@ -98,14 +97,7 @@ impl TransitiveRelation { { let mut result = TransitiveRelation::new(); for edge in &self.edges { - let r = f(&self.elements[edge.source.0]).and_then(|source| { - f(&self.elements[edge.target.0]).and_then(|target| { - Some(result.add(source, target)) - }) - }); - if r.is_none() { - return None; - } + result.add(f(&self.elements[edge.source.0])?, f(&self.elements[edge.target.0])?); } Some(result) } @@ -372,7 +364,7 @@ impl TransitiveRelation { let mut changed = true; while changed { changed = false; - for edge in self.edges.iter() { + for edge in &self.edges { // add an edge from S -> T changed |= matrix.add(edge.source.0, edge.target.0); diff --git a/src/librustc_data_structures/vec_linked_list.rs b/src/librustc_data_structures/vec_linked_list.rs new file mode 100644 index 0000000000..390dca6b90 --- /dev/null +++ b/src/librustc_data_structures/vec_linked_list.rs @@ -0,0 +1,83 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use indexed_vec::{Idx, IndexVec}; + +pub fn iter( + first: Option, + links: &'a Ls, +) -> impl Iterator + 'a +where + Ls: Links, +{ + VecLinkedListIterator { + links: links, + current: first, + } +} + +pub struct VecLinkedListIterator +where + Ls: Links, +{ + links: Ls, + current: Option, +} + +impl Iterator for VecLinkedListIterator +where + Ls: Links, +{ + type Item = Ls::LinkIndex; + + fn next(&mut self) -> Option { + if let Some(c) = self.current { + self.current = ::next(&self.links, c); + Some(c) + } else { + None + } + } +} + +pub trait Links { + type LinkIndex: Copy; + + fn next(links: &Self, index: Self::LinkIndex) -> Option; +} + +impl Links for &Ls +where + Ls: Links, +{ + type LinkIndex = Ls::LinkIndex; + + fn next(links: &Self, index: Ls::LinkIndex) -> Option { + ::next(links, index) + } +} + +pub trait LinkElem { + type LinkIndex: Copy; + + fn next(elem: &Self) -> Option; +} + +impl Links for IndexVec +where + E: LinkElem, + L: Idx, +{ + type LinkIndex = L; + + fn next(links: &Self, index: L) -> Option { + ::next(&links[index]) + } +} diff --git a/src/librustc_data_structures/work_queue.rs b/src/librustc_data_structures/work_queue.rs index b8e8b249bb..0c8ec753a1 100644 --- a/src/librustc_data_structures/work_queue.rs +++ b/src/librustc_data_structures/work_queue.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use indexed_set::IdxSetBuf; +use indexed_set::IdxSet; use indexed_vec::Idx; use std::collections::VecDeque; @@ -20,7 +20,7 @@ use std::collections::VecDeque; /// and also use a bit set to track occupancy. pub struct WorkQueue { deque: VecDeque, - set: IdxSetBuf, + set: IdxSet, } impl WorkQueue { @@ -29,7 +29,7 @@ impl WorkQueue { pub fn with_all(len: usize) -> Self { WorkQueue { deque: (0..len).map(T::new).collect(), - set: IdxSetBuf::new_filled(len), + set: IdxSet::new_filled(len), } } @@ -38,7 +38,7 @@ impl WorkQueue { pub fn with_none(len: usize) -> Self { WorkQueue { deque: VecDeque::with_capacity(len), - set: IdxSetBuf::new_empty(len), + set: IdxSet::new_empty(len), } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 24a2354775..7fb66ea97f 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -11,7 +11,7 @@ use rustc::dep_graph::DepGraph; use rustc::hir::{self, map as hir_map}; use rustc::hir::lowering::lower_crate; -use rustc::ich::Fingerprint; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::StableHasher; use rustc_mir as mir; use rustc::session::{CompileResult, CrateDisambiguator, Session}; @@ -20,11 +20,11 @@ use rustc::session::config::{self, Input, OutputFilenames, OutputType}; use rustc::session::search_paths::PathKind; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; -use rustc::middle::cstore::CrateStoreDyn; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, AllArenas, Resolutions, TyCtxt}; use rustc::traits; use rustc::util::common::{install_panic_hook, time, ErrorReported}; +use rustc::util::profiling::ProfileCategory; use rustc_allocator as allocator; use rustc_borrowck as borrowck; use rustc_incremental; @@ -57,7 +57,9 @@ use syntax::ext::base::ExtCtxt; use syntax::fold::Folder; use syntax::parse::{self, PResult}; use syntax::util::node_count::NodeCounter; -use syntax_pos::FileName; +use syntax::util::lev_distance::find_best_match_for_name; +use syntax::symbol::Symbol; +use syntax_pos::{FileName, hygiene}; use syntax_ext; use derive_registrar; @@ -352,6 +354,14 @@ pub fn compile_input( sess.print_perf_stats(); } + if sess.opts.debugging_opts.self_profile { + sess.print_profiler_results(); + + if sess.opts.debugging_opts.profile_json { + sess.save_json_results(); + } + } + controller_entry_point!( compilation_done, sess, @@ -475,7 +485,7 @@ impl<'a> ::CompilerCalls<'a> for CompileController<'a> { codegen_backend: &dyn (::CodegenBackend), matches: &::getopts::Matches, sess: &Session, - cstore: &dyn (::CrateStore), + cstore: &CStore, input: &Input, odir: &Option, ofile: &Option, @@ -662,11 +672,13 @@ pub fn phase_1_parse_input<'a>( ) -> PResult<'a, ast::Crate> { sess.diagnostic() .set_continue_after_error(control.continue_parse_after_error); + hygiene::set_default_edition(sess.edition()); if sess.profile_queries() { profile::begin(sess); } + sess.profiler(|p| p.start_activity(ProfileCategory::Parsing)); let krate = time(sess, "parsing", || match *input { Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess), Input::Str { @@ -674,6 +686,7 @@ pub fn phase_1_parse_input<'a>( ref name, } => parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess), })?; + sess.profiler(|p| p.end_activity(ProfileCategory::Parsing)); sess.diagnostic().set_continue_after_error(true); @@ -684,7 +697,7 @@ pub fn phase_1_parse_input<'a>( if sess.opts.debugging_opts.input_stats { println!( "Lines of code: {}", - sess.codemap().count_lines() + sess.source_map().count_lines() ); println!("Pre-expansion node count: {}", count_nodes(&krate)); } @@ -717,9 +730,9 @@ pub struct ExpansionResult { pub hir_forest: hir_map::Forest, } -pub struct InnerExpansionResult<'a> { +pub struct InnerExpansionResult<'a, 'b: 'a> { pub expanded_crate: ast::Crate, - pub resolver: Resolver<'a>, + pub resolver: Resolver<'a, 'b>, pub hir_forest: hir_map::Forest, } @@ -795,7 +808,7 @@ where /// Same as phase_2_configure_and_expand, but doesn't let you keep the resolver /// around -pub fn phase_2_configure_and_expand_inner<'a, F>( +pub fn phase_2_configure_and_expand_inner<'a, 'b: 'a, F>( sess: &'a Session, cstore: &'a CStore, mut krate: ast::Crate, @@ -804,9 +817,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>( addl_plugins: Option>, make_glob_map: MakeGlobMap, resolver_arenas: &'a ResolverArenas<'a>, - crate_loader: &'a mut CrateLoader, + crate_loader: &'a mut CrateLoader<'b>, after_expand: F, -) -> Result, CompileIncomplete> +) -> Result, CompileIncomplete> where F: FnOnce(&ast::Crate) -> CompileResult, { @@ -817,7 +830,6 @@ where let (mut krate, features) = syntax::config::features( krate, &sess.parse_sess, - sess.opts.test, sess.edition(), ); // these need to be set "early" so that expansion sees `quote` if enabled. @@ -855,7 +867,7 @@ where krate = time(sess, "crate injection", || { let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s); - syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name) + syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name, sess.edition()) }); let mut addl_plugins = Some(addl_plugins); @@ -913,8 +925,8 @@ where ls.register_late_pass(Some(sess), true, pass); } - for (name, to) in lint_groups { - ls.register_group(Some(sess), true, name, to); + for (name, (to, deprecated_name)) in lint_groups { + ls.register_group(Some(sess), true, name, deprecated_name, to); } *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; @@ -944,6 +956,7 @@ where syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote); // Expand all macros + sess.profiler(|p| p.start_activity(ProfileCategory::Expansion)); krate = time(sess, "expansion", || { // Windows dlls do not have rpaths, so they don't know how to find their // dependencies. It's up to us to tell the system where to find all the @@ -1021,6 +1034,7 @@ where } krate }); + sess.profiler(|p| p.end_activity(ProfileCategory::Expansion)); krate = time(sess, "maybe building test harness", || { syntax::test::modify_for_testing( @@ -1046,7 +1060,7 @@ where krate = time(sess, "maybe creating a macro crate", || { let crate_types = sess.crate_types.borrow(); let num_crate_types = crate_types.len(); - let is_proc_macro_crate = crate_types.contains(&config::CrateTypeProcMacro); + let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro); let is_test_crate = sess.opts.test; syntax_ext::proc_macro_registrar::modify( &sess.parse_sess, @@ -1121,7 +1135,7 @@ where // Unresolved macros might be due to mistyped `#[macro_use]`, // so abort after checking for unknown attributes. (#49074) if resolver.found_unresolved_macro { - sess.parse_sess.span_diagnostic.abort_if_errors(); + sess.diagnostic().abort_if_errors(); } // Lower ast -> hir. @@ -1196,7 +1210,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>( codegen_backend: &dyn CodegenBackend, control: &CompileController, sess: &'tcx Session, - cstore: &'tcx CrateStoreDyn, + cstore: &'tcx CStore, hir_map: hir_map::Map<'tcx>, mut analysis: ty::CrateAnalysis, resolutions: Resolutions, @@ -1350,7 +1364,9 @@ pub fn phase_4_codegen<'a, 'tcx>( ::rustc::middle::dependency_format::calculate(tcx) }); + tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen)); let codegen = time(tcx.sess, "codegen", move || codegen_backend.codegen_crate(tcx, rx)); + tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen)); if tcx.sess.profile_queries() { profile::dump(&tcx.sess, "profile_queries".to_string()) } @@ -1447,7 +1463,7 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, out_filenames: &[Pa let result = (|| -> io::Result<()> { // Build a list of files used to compile the output and // write Makefile-compatible dependency rules - let files: Vec = sess.codemap() + let files: Vec = sess.source_map() .files() .iter() .filter(|fmap| fmap.is_real_file()) @@ -1487,20 +1503,52 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Some(config::CrateTypeRlib), - Some(ref n) if *n == "dylib" => Some(config::CrateTypeDylib), - Some(ref n) if *n == "cdylib" => Some(config::CrateTypeCdylib), + Some(ref n) if *n == "rlib" => Some(config::CrateType::Rlib), + Some(ref n) if *n == "dylib" => Some(config::CrateType::Dylib), + Some(ref n) if *n == "cdylib" => Some(config::CrateType::Cdylib), Some(ref n) if *n == "lib" => Some(config::default_lib_output()), - Some(ref n) if *n == "staticlib" => Some(config::CrateTypeStaticlib), - Some(ref n) if *n == "proc-macro" => Some(config::CrateTypeProcMacro), - Some(ref n) if *n == "bin" => Some(config::CrateTypeExecutable), - Some(_) => { - session.buffer_lint( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - a.span, - "invalid `crate_type` value", - ); + Some(ref n) if *n == "staticlib" => Some(config::CrateType::Staticlib), + Some(ref n) if *n == "proc-macro" => Some(config::CrateType::ProcMacro), + Some(ref n) if *n == "bin" => Some(config::CrateType::Executable), + Some(ref n) => { + let crate_types = vec![ + Symbol::intern("rlib"), + Symbol::intern("dylib"), + Symbol::intern("cdylib"), + Symbol::intern("lib"), + Symbol::intern("staticlib"), + Symbol::intern("proc-macro"), + Symbol::intern("bin") + ]; + if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().node { + let span = spanned.span; + let lev_candidate = find_best_match_for_name( + crate_types.iter(), + &n.as_str(), + None + ); + if let Some(candidate) = lev_candidate { + session.buffer_lint_with_diagnostic( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + "invalid `crate_type` value", + lint::builtin::BuiltinLintDiagnostics:: + UnknownCrateTypes( + span, + "did you mean".to_string(), + format!("\"{}\"", candidate) + ) + ); + } else { + session.buffer_lint( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + "invalid `crate_type` value" + ); + } + } None } _ => { @@ -1520,7 +1568,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec CrateDisambiguator { let is_exe = session .crate_types .borrow() - .contains(&config::CrateTypeExecutable); + .contains(&config::CrateType::Executable); hasher.write(if is_exe { b"exe" } else { b"lib" }); CrateDisambiguator::from(hasher.finish()) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index df641b8fbc..a96c277d4b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -20,6 +20,8 @@ #![feature(box_syntax)] #![cfg_attr(unix, feature(libc))] +#![cfg_attr(not(stage0), feature(nll))] +#![feature(option_replace)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] @@ -78,7 +80,6 @@ use rustc::session::filesearch; use rustc::session::{early_error, early_warn}; use rustc::lint::Lint; use rustc::lint; -use rustc::middle::cstore::CrateStore; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; use rustc_metadata::dynamic_lib::DynamicLibrary; @@ -106,10 +107,10 @@ use std::sync::{Once, ONCE_INIT}; use std::thread; use syntax::ast; -use syntax::codemap::{CodeMap, FileLoader, RealFileLoader}; +use syntax::source_map::{SourceMap, FileLoader, RealFileLoader}; use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; -use syntax_pos::{hygiene, DUMMY_SP, MultiSpan, FileName}; +use syntax_pos::{DUMMY_SP, MultiSpan, FileName}; #[cfg(test)] mod test; @@ -184,27 +185,29 @@ pub fn run(run_compiler: F) -> isize where F: FnOnce() -> (CompileResult, Option) + Send + 'static { let result = monitor(move || { - let (result, session) = run_compiler(); - if let Err(CompileIncomplete::Errored(_)) = result { - match session { - Some(sess) => { - sess.abort_if_errors(); - panic!("error reported but abort_if_errors didn't abort???"); - } - None => { - let emitter = - errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, - None, - true, - false); - let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); - handler.emit(&MultiSpan::new(), - "aborting due to previous error(s)", - errors::Level::Fatal); - panic::resume_unwind(Box::new(errors::FatalErrorMarker)); + syntax::with_globals(|| { + let (result, session) = run_compiler(); + if let Err(CompileIncomplete::Errored(_)) = result { + match session { + Some(sess) => { + sess.abort_if_errors(); + panic!("error reported but abort_if_errors didn't abort???"); + } + None => { + let emitter = + errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, + None, + true, + false); + let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); + handler.emit(&MultiSpan::new(), + "aborting due to previous error(s)", + errors::Level::Fatal); + panic::resume_unwind(Box::new(errors::FatalErrorMarker)); + } } } - } + }); }); match result { @@ -470,18 +473,15 @@ pub fn run_compiler<'a>(args: &[String], emitter_dest: Option>) -> (CompileResult, Option) { - syntax::with_globals(|| { - let matches = match handle_options(args) { - Some(matches) => matches, - None => return (Ok(()), None), - }; + let matches = match handle_options(args) { + Some(matches) => matches, + None => return (Ok(()), None), + }; - let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); - hygiene::set_default_edition(sopts.edition); + let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); - driver::spawn_thread_pool(sopts, |sopts| { - run_compiler_with_pool(matches, sopts, cfg, callbacks, file_loader, emitter_dest) - }) + driver::spawn_thread_pool(sopts, |sopts| { + run_compiler_with_pool(matches, sopts, cfg, callbacks, file_loader, emitter_dest) }) } @@ -522,9 +522,9 @@ fn run_compiler_with_pool<'a>( }; let loader = file_loader.unwrap_or(box RealFileLoader); - let codemap = Lrc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping())); - let mut sess = session::build_session_with_codemap( - sopts, input_file_path.clone(), descriptions, codemap, emitter_dest, + let source_map = Lrc::new(SourceMap::with_file_loader(loader, sopts.file_path_mapping())); + let mut sess = session::build_session_with_source_map( + sopts, input_file_path.clone(), descriptions, source_map, emitter_dest, ); if let Some(err) = input_err { @@ -676,7 +676,7 @@ pub trait CompilerCalls<'a> { _: &dyn CodegenBackend, _: &getopts::Matches, _: &Session, - _: &dyn CrateStore, + _: &CStore, _: &Input, _: &Option, _: &Option) @@ -884,7 +884,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { codegen_backend: &dyn CodegenBackend, matches: &getopts::Matches, sess: &Session, - cstore: &dyn CrateStore, + cstore: &CStore, input: &Input, odir: &Option, ofile: &Option) @@ -990,7 +990,7 @@ pub fn enable_save_analysis(control: &mut CompileController) { impl RustcDefaultCalls { pub fn list_metadata(sess: &Session, - cstore: &dyn CrateStore, + cstore: &CStore, matches: &getopts::Matches, input: &Input) -> Compilation { @@ -1002,7 +1002,7 @@ impl RustcDefaultCalls { let mut v = Vec::new(); locator::list_file_metadata(&sess.target.target, path, - cstore.metadata_loader(), + &*cstore.metadata_loader, &mut v) .unwrap(); println!("{}", String::from_utf8(v).unwrap()); @@ -1512,7 +1512,7 @@ pub fn in_named_rustc_thread(name: String, f: F) -> Result(name: String, f: F) -> Result(&self, sess: &'tcx Session, - cstore: &'tcx CrateStoreDyn, + cstore: &'tcx CStore, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, @@ -354,33 +355,33 @@ impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> { impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> { fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { - pprust::NodeExpr(_) => s.popen(), + pprust::AnnNode::Expr(_) => s.popen(), _ => Ok(()), } } fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { - pprust::NodeIdent(_) | - pprust::NodeName(_) => Ok(()), + pprust::AnnNode::Ident(_) | + pprust::AnnNode::Name(_) => Ok(()), - pprust::NodeItem(item) => { + pprust::AnnNode::Item(item) => { s.s.space()?; s.synth_comment(item.id.to_string()) } - pprust::NodeSubItem(id) => { + pprust::AnnNode::SubItem(id) => { s.s.space()?; s.synth_comment(id.to_string()) } - pprust::NodeBlock(blk) => { + pprust::AnnNode::Block(blk) => { s.s.space()?; s.synth_comment(format!("block {}", blk.id)) } - pprust::NodeExpr(expr) => { + pprust::AnnNode::Expr(expr) => { s.s.space()?; s.synth_comment(expr.id.to_string())?; s.pclose() } - pprust::NodePat(pat) => { + pprust::AnnNode::Pat(pat) => { s.s.space()?; s.synth_comment(format!("pat {}", pat.id)) } @@ -413,34 +414,34 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { } fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { - pprust_hir::NodeExpr(_) => s.popen(), + pprust_hir::AnnNode::Expr(_) => s.popen(), _ => Ok(()), } } fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { - pprust_hir::NodeName(_) => Ok(()), - pprust_hir::NodeItem(item) => { + pprust_hir::AnnNode::Name(_) => Ok(()), + pprust_hir::AnnNode::Item(item) => { s.s.space()?; s.synth_comment(format!("node_id: {} hir local_id: {}", item.id, item.hir_id.local_id.0)) } - pprust_hir::NodeSubItem(id) => { + pprust_hir::AnnNode::SubItem(id) => { s.s.space()?; s.synth_comment(id.to_string()) } - pprust_hir::NodeBlock(blk) => { + pprust_hir::AnnNode::Block(blk) => { s.s.space()?; s.synth_comment(format!("block node_id: {} hir local_id: {}", blk.id, blk.hir_id.local_id.0)) } - pprust_hir::NodeExpr(expr) => { + pprust_hir::AnnNode::Expr(expr) => { s.s.space()?; s.synth_comment(format!("node_id: {} hir local_id: {}", expr.id, expr.hir_id.local_id.0))?; s.pclose() } - pprust_hir::NodePat(pat) => { + pprust_hir::AnnNode::Pat(pat) => { s.s.space()?; s.synth_comment(format!("pat node_id: {} hir local_id: {}", pat.id, pat.hir_id.local_id.0)) @@ -466,13 +467,13 @@ impl<'a> PrinterSupport for HygieneAnnotation<'a> { impl<'a> pprust::PpAnn for HygieneAnnotation<'a> { fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { - pprust::NodeIdent(&ast::Ident { name, span }) => { + pprust::AnnNode::Ident(&ast::Ident { name, span }) => { s.s.space()?; // FIXME #16420: this doesn't display the connections // between syntax contexts s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt())) } - pprust::NodeName(&name) => { + pprust::AnnNode::Name(&name) => { s.s.space()?; s.synth_comment(name.as_u32().to_string()) } @@ -518,13 +519,13 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { } fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { - pprust_hir::NodeExpr(_) => s.popen(), + pprust_hir::AnnNode::Expr(_) => s.popen(), _ => Ok(()), } } fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { - pprust_hir::NodeExpr(expr) => { + pprust_hir::AnnNode::Expr(expr) => { s.s.space()?; s.s.word("as")?; s.s.space()?; @@ -650,18 +651,25 @@ impl UserIdentifiedItem { // [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 pub struct ReplaceBodyWithLoop<'a> { within_static_or_const: bool, + nested_blocks: Option>, sess: &'a Session, } impl<'a> ReplaceBodyWithLoop<'a> { pub fn new(sess: &'a Session) -> ReplaceBodyWithLoop<'a> { - ReplaceBodyWithLoop { within_static_or_const: false, sess } + ReplaceBodyWithLoop { + within_static_or_const: false, + nested_blocks: None, + sess + } } fn run R>(&mut self, is_const: bool, action: F) -> R { let old_const = mem::replace(&mut self.within_static_or_const, is_const); + let old_blocks = self.nested_blocks.take(); let ret = action(self); self.within_static_or_const = old_const; + self.nested_blocks = old_blocks; ret } @@ -719,7 +727,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { self.run(is_const, |s| fold::noop_fold_item_kind(i, s)) } - fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector { + fn fold_trait_item(&mut self, i: ast::TraitItem) -> OneVector { let is_const = match i.node { ast::TraitItemKind::Const(..) => true, ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) => @@ -729,7 +737,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { self.run(is_const, |s| fold::noop_fold_trait_item(i, s)) } - fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector { + fn fold_impl_item(&mut self, i: ast::ImplItem) -> OneVector { let is_const = match i.node { ast::ImplItemKind::Const(..) => true, ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) => @@ -739,42 +747,88 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { self.run(is_const, |s| fold::noop_fold_impl_item(i, s)) } + fn fold_anon_const(&mut self, c: ast::AnonConst) -> ast::AnonConst { + self.run(true, |s| fold::noop_fold_anon_const(c, s)) + } + fn fold_block(&mut self, b: P) -> P { - fn expr_to_block(rules: ast::BlockCheckMode, + fn stmt_to_block(rules: ast::BlockCheckMode, recovered: bool, - e: Option>, - sess: &Session) -> P { - P(ast::Block { - stmts: e.map(|e| { - ast::Stmt { - id: sess.next_node_id(), - span: e.span, - node: ast::StmtKind::Expr(e), - } - }) - .into_iter() - .collect(), + s: Option, + sess: &Session) -> ast::Block { + ast::Block { + stmts: s.into_iter().collect(), rules, id: sess.next_node_id(), span: syntax_pos::DUMMY_SP, recovered, - }) + } } - if !self.within_static_or_const { - - let empty_block = expr_to_block(BlockCheckMode::Default, false, None, self.sess); - let loop_expr = P(ast::Expr { - node: ast::ExprKind::Loop(empty_block, None), - id: self.sess.next_node_id(), + fn block_to_stmt(b: ast::Block, sess: &Session) -> ast::Stmt { + let expr = P(ast::Expr { + id: sess.next_node_id(), + node: ast::ExprKind::Block(P(b), None), span: syntax_pos::DUMMY_SP, - attrs: ast::ThinVec::new(), + attrs: ThinVec::new(), }); - expr_to_block(b.rules, b.recovered, Some(loop_expr), self.sess) + ast::Stmt { + id: sess.next_node_id(), + node: ast::StmtKind::Expr(expr), + span: syntax_pos::DUMMY_SP, + } + } - } else { + let empty_block = stmt_to_block(BlockCheckMode::Default, false, None, self.sess); + let loop_expr = P(ast::Expr { + node: ast::ExprKind::Loop(P(empty_block), None), + id: self.sess.next_node_id(), + span: syntax_pos::DUMMY_SP, + attrs: ThinVec::new(), + }); + + let loop_stmt = ast::Stmt { + id: self.sess.next_node_id(), + span: syntax_pos::DUMMY_SP, + node: ast::StmtKind::Expr(loop_expr), + }; + + if self.within_static_or_const { fold::noop_fold_block(b, self) + } else { + b.map(|b| { + let mut stmts = vec![]; + for s in b.stmts { + let old_blocks = self.nested_blocks.replace(vec![]); + + stmts.extend(self.fold_stmt(s).into_iter().filter(|s| s.is_item())); + + // we put a Some in there earlier with that replace(), so this is valid + let new_blocks = self.nested_blocks.take().unwrap(); + self.nested_blocks = old_blocks; + stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, &self.sess))); + } + + let mut new_block = ast::Block { + stmts, + ..b + }; + + if let Some(old_blocks) = self.nested_blocks.as_mut() { + //push our fresh block onto the cache and yield an empty block with `loop {}` + if !new_block.stmts.is_empty() { + old_blocks.push(new_block); + } + + stmt_to_block(b.rules, b.recovered, Some(loop_stmt), self.sess) + } else { + //push `loop {}` onto the end of our fresh block and yield that + new_block.stmts.push(loop_stmt); + + new_block + } + }) } } @@ -861,8 +915,8 @@ pub fn fold_crate(sess: &Session, krate: ast::Crate, ppm: PpMode) -> ast::Crate fn get_source(input: &Input, sess: &Session) -> (Vec, FileName) { let src_name = driver::source_name(input); - let src = sess.codemap() - .get_filemap(&src_name) + let src = sess.source_map() + .get_source_file(&src_name) .unwrap() .src .as_ref() @@ -900,7 +954,7 @@ pub fn print_after_parsing(sess: &Session, s.call_with_pp_support(sess, None, move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); - pprust::print_crate(sess.codemap(), + pprust::print_crate(sess.source_map(), &sess.parse_sess, krate, src_name, @@ -918,7 +972,7 @@ pub fn print_after_parsing(sess: &Session, } pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, - cstore: &'tcx CrateStoreDyn, + cstore: &'tcx CStore, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, @@ -957,7 +1011,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, s.call_with_pp_support(sess, Some(hir_map), move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); - pprust::print_crate(sess.codemap(), + pprust::print_crate(sess.source_map(), &sess.parse_sess, krate, src_name, @@ -981,7 +1035,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, move |annotation, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); - pprust_hir::print_crate(sess.codemap(), + pprust_hir::print_crate(sess.source_map(), &sess.parse_sess, krate, src_name, @@ -1022,7 +1076,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, 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.codemap(), + let mut pp_state = pprust_hir::State::new_from_input(sess.source_map(), &sess.parse_sess, src_name, &mut rdr, @@ -1074,7 +1128,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, // with a different callback than the standard driver, so that isn't easy. // Instead, we call that function ourselves. fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, - cstore: &'a CrateStoreDyn, + cstore: &'a CStore, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs index f31111e37b..e329b037d2 100644 --- a/src/librustc_driver/profile/trace.rs +++ b/src/librustc_driver/profile/trace.rs @@ -10,10 +10,10 @@ use super::*; use syntax_pos::SpanData; +use rustc_data_structures::fx::FxHashMap; use rustc::util::common::QueryMsg; use std::fs::File; use std::time::{Duration, Instant}; -use std::collections::hash_map::HashMap; use rustc::dep_graph::{DepNode}; #[derive(Debug, Clone, Eq, PartialEq)] @@ -85,7 +85,7 @@ pub fn html_of_effect(eff: &Effect) -> (String, String) { fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) { use rustc::util::common::duration_to_secs_str; (duration_to_secs_str(dur.clone()), - "".to_string() + String::new() ) } @@ -149,7 +149,7 @@ fn write_traces_rec(file: &mut File, traces: &[Rec], total: Duration, depth: usi } } -fn compute_counts_rec(counts: &mut HashMap, traces: &[Rec]) { +fn compute_counts_rec(counts: &mut FxHashMap, traces: &[Rec]) { for t in traces.iter() { match t.effect { Effect::TimeBegin(ref msg) => { @@ -200,7 +200,7 @@ fn compute_counts_rec(counts: &mut HashMap, traces: &[Rec]) } } -pub fn write_counts(count_file: &mut File, counts: &mut HashMap) { +pub fn write_counts(count_file: &mut File, counts: &mut FxHashMap) { use rustc::util::common::duration_to_secs_str; use std::cmp::Reverse; @@ -219,7 +219,7 @@ pub fn write_counts(count_file: &mut File, counts: &mut HashMap = HashMap::with_capacity(capacity); + let mut counts = FxHashMap::with_capacity_and_hasher(capacity, Default::default()); compute_counts_rec(&mut counts, traces); write_counts(counts_file, &mut counts); diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 5b2092ea9e..0a7bd3d970 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -32,7 +32,7 @@ use rustc_data_structures::sync::{self, Lrc}; use syntax; use syntax::ast; use rustc_target::spec::abi::Abi; -use syntax::codemap::{CodeMap, FilePathMapping, FileName}; +use syntax::source_map::{SourceMap, FilePathMapping, FileName}; use errors; use errors::emitter::Emitter; use errors::{Level, DiagnosticBuilder}; @@ -99,7 +99,7 @@ fn test_env(source_string: &str, where F: FnOnce(Env) { syntax::with_globals(|| { - let mut options = config::basic_options(); + let mut options = config::Options::default(); options.debugging_opts.verbose = true; options.unstable_features = UnstableFeatures::Allow; @@ -121,7 +121,7 @@ fn test_env_with_pool( let sess = session::build_session_(options, None, diagnostic_handler, - Lrc::new(CodeMap::new(FilePathMapping::empty()))); + Lrc::new(SourceMap::new(FilePathMapping::empty()))); let cstore = CStore::new(::get_codegen_backend(&sess).metadata_loader()); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let input = config::Input::Str { @@ -162,7 +162,7 @@ fn test_env_with_pool( &arenas, resolutions, hir_map, - OnDiskCache::new_empty(sess.codemap()), + OnDiskCache::new_empty(sess.source_map()), "test_crate", tx, &outputs, @@ -183,8 +183,13 @@ fn test_env_with_pool( }); } -const D1: ty::DebruijnIndex = ty::INNERMOST; -const D2: ty::DebruijnIndex = D1.shifted_in(1); +fn d1() -> ty::DebruijnIndex { + ty::INNERMOST +} + +fn d2() -> ty::DebruijnIndex { + d1().shifted_in(1) +} impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { @@ -193,7 +198,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn create_region_hierarchy(&mut self, rh: &RH, parent: (region::Scope, region::ScopeDepth)) { - let me = region::Scope::Node(rh.id); + let me = region::Scope { id: rh.id, data: region::ScopeData::Node }; self.region_scope_tree.record_scope_parent(me, Some(parent)); for child_rh in rh.sub { self.create_region_hierarchy(child_rh, (me, parent.1 + 1)); @@ -204,7 +209,10 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { // creates a region hierarchy where 1 is root, 10 and 11 are // children of 1, etc - let dscope = region::Scope::Destruction(hir::ItemLocalId(1)); + let dscope = region::Scope { + id: hir::ItemLocalId(1), + data: region::ScopeData::Destruction + }; self.region_scope_tree.record_scope_parent(dscope, None); self.create_region_hierarchy(&RH { id: hir::ItemLocalId(1), @@ -304,7 +312,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_nil(&self) -> Ty<'tcx> { - self.infcx.tcx.mk_nil() + self.infcx.tcx.mk_unit() } pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> { @@ -337,7 +345,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_rptr_late_bound(&self, id: u32) -> Ty<'tcx> { - let r = self.re_late_bound_with_debruijn(id, D1); + let r = self.re_late_bound_with_debruijn(id, d1()); self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize) } @@ -350,7 +358,10 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> { - let r = ty::ReScope(region::Scope::Node(hir::ItemLocalId(id))); + let r = ty::ReScope(region::Scope { + id: hir::ItemLocalId(id), + data: region::ScopeData::Node + }); self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } @@ -494,7 +505,7 @@ fn subst_ty_renumber_bound() { // t_expected = fn(&'a isize) let t_expected = { - let t_ptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, D2); + let t_ptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2()); env.t_fn(&[t_ptr_bound2], env.t_nil()) }; @@ -531,7 +542,7 @@ fn subst_ty_renumber_some_bounds() { // // but not that the Debruijn index is different in the different cases. let t_expected = { - let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, D2); + let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2()); env.t_pair(t_rptr_bound1, env.t_fn(&[t_rptr_bound2], env.t_nil())) }; @@ -559,10 +570,10 @@ fn escaping() { let t_rptr_free1 = env.t_rptr_free(1); assert!(!t_rptr_free1.has_escaping_regions()); - let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, D1); + let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, d1()); assert!(t_rptr_bound1.has_escaping_regions()); - let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, D2); + let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2()); assert!(t_rptr_bound2.has_escaping_regions()); // t_fn = fn(A) @@ -578,7 +589,7 @@ fn escaping() { #[test] fn subst_region_renumber_region() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { - let re_bound1 = env.re_late_bound_with_debruijn(1, D1); + let re_bound1 = env.re_late_bound_with_debruijn(1, d1()); // type t_source<'a> = fn(&'a isize) let t_source = { @@ -593,7 +604,7 @@ fn subst_region_renumber_region() { // // but not that the Debruijn index is different in the different cases. let t_expected = { - let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, D2); + let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2()); env.t_fn(&[t_rptr_bound2], env.t_nil()) }; diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index e412d1749d..101ca0650c 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -12,6 +12,7 @@ crate-type = ["dylib"] serialize = { path = "../libserialize" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } unicode-width = "0.1.4" atty = "0.2" -termcolor = "0.3" +termcolor = "1.0" diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index a0f3abda07..1b34898b99 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -26,6 +26,7 @@ use syntax_pos::{MultiSpan, Span}; pub struct DiagnosticBuilder<'a> { pub handler: &'a Handler, diagnostic: Diagnostic, + allow_suggestions: bool, } /// In general, the `DiagnosticBuilder` uses deref to allow access to @@ -186,27 +187,67 @@ impl<'a> DiagnosticBuilder<'a> { msg: &str, suggestions: Vec) -> &mut Self); - forward!(pub fn span_suggestion_with_applicability(&mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability) - -> &mut Self); - forward!(pub fn span_suggestions_with_applicability(&mut self, - sp: Span, - msg: &str, - suggestions: Vec, - applicability: Applicability) - -> &mut Self); - forward!(pub fn span_suggestion_short_with_applicability(&mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability) - -> &mut Self); + pub fn span_suggestion_with_applicability(&mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability) + -> &mut Self { + if !self.allow_suggestions { + return self + } + self.diagnostic.span_suggestion_with_applicability( + sp, + msg, + suggestion, + applicability, + ); + self + } + + pub fn span_suggestions_with_applicability(&mut self, + sp: Span, + msg: &str, + suggestions: Vec, + applicability: Applicability) + -> &mut Self { + if !self.allow_suggestions { + return self + } + self.diagnostic.span_suggestions_with_applicability( + sp, + msg, + suggestions, + applicability, + ); + self + } + + pub fn span_suggestion_short_with_applicability(&mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability) + -> &mut Self { + if !self.allow_suggestions { + return self + } + self.diagnostic.span_suggestion_short_with_applicability( + sp, + msg, + suggestion, + applicability, + ); + self + } forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); + pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self { + self.allow_suggestions = allow; + self + } + /// Convenience function for internal use, clients should use one of the /// struct_* methods on Handler. pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> { @@ -228,7 +269,11 @@ impl<'a> DiagnosticBuilder<'a> { /// diagnostic. pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> { - DiagnosticBuilder { handler, diagnostic } + DiagnosticBuilder { + handler, + diagnostic, + allow_suggestions: true, + } } } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 09295e2c7f..5f275b7003 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -10,18 +10,18 @@ use self::Destination::*; -use syntax_pos::{FileMap, Span, MultiSpan}; +use syntax_pos::{SourceFile, Span, MultiSpan}; -use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapperDyn, DiagnosticId}; +use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, SourceMapperDyn, DiagnosticId}; use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; use styled_buffer::StyledBuffer; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use atty; use std::borrow::Cow; use std::io::prelude::*; use std::io; -use std::collections::HashMap; use std::cmp::{min, Reverse}; use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter}; use termcolor::{WriteColor, Color, Buffer}; @@ -120,21 +120,21 @@ impl ColorConfig { pub struct EmitterWriter { dst: Destination, - cm: Option>, + cm: Option>, short_message: bool, teach: bool, ui_testing: bool, } struct FileWithAnnotatedLines { - file: Lrc, + file: Lrc, lines: Vec, multiline_depth: usize, } impl EmitterWriter { pub fn stderr(color_config: ColorConfig, - code_map: Option>, + code_map: Option>, short_message: bool, teach: bool) -> EmitterWriter { @@ -149,7 +149,7 @@ impl EmitterWriter { } pub fn new(dst: Box, - code_map: Option>, + code_map: Option>, short_message: bool, teach: bool) -> EmitterWriter { @@ -177,7 +177,7 @@ impl EmitterWriter { fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec { fn add_annotation_to_file(file_vec: &mut Vec, - file: Lrc, + file: Lrc, line_index: usize, ann: Annotation) { @@ -307,7 +307,7 @@ impl EmitterWriter { fn render_source_line(&self, buffer: &mut StyledBuffer, - file: Lrc, + file: Lrc, line: &Line, width_offset: usize, code_offset: usize) -> Vec<(usize, Style)> { @@ -798,7 +798,7 @@ impl EmitterWriter { // at by "in this macro invocation" format!(" (#{})", i + 1) } else { - "".to_string() + String::new() }))); } // Check to make sure we're not in any <*macros> @@ -813,7 +813,7 @@ impl EmitterWriter { // backtrace is multiple levels deep format!(" (#{})", i + 1) } else { - "".to_string() + String::new() }))); if !always_backtrace { break; @@ -1021,7 +1021,7 @@ impl EmitterWriter { // Print out the annotate source lines that correspond with the error for annotated_file in annotated_files { // we can't annotate anything if the source is unavailable. - if !cm.ensure_filemap_source_present(annotated_file.file.clone()) { + if !cm.ensure_source_file_source_present(annotated_file.file.clone()) { continue; } @@ -1065,7 +1065,7 @@ impl EmitterWriter { let col = if let Some(first_annotation) = first_line.annotations.first() { format!(":{}", first_annotation.start_col + 1) } else { - "".to_string() + String::new() }; format!("{}:{}{}", annotated_file.file.name, @@ -1090,7 +1090,7 @@ impl EmitterWriter { max_line_num_len + 1); // Contains the vertical lines' positions for active multiline annotations - let mut multilines = HashMap::new(); + let mut multilines = FxHashMap::default(); // Next, output the annotate source for this file for line_idx in 0..annotated_file.lines.len() { @@ -1109,7 +1109,7 @@ impl EmitterWriter { width_offset, code_offset); - let mut to_add = HashMap::new(); + let mut to_add = FxHashMap::default(); for (depth, style) in depths { if multilines.get(&depth).is_some() { @@ -1295,7 +1295,7 @@ impl EmitterWriter { } // if we elided some lines, add an ellipsis - if let Some(_) = lines.next() { + if lines.next().is_some() { buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); } else if !show_underline { draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 8254674775..3582c2359c 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -16,6 +16,7 @@ #![allow(unused_attributes)] #![feature(range_contains)] #![cfg_attr(unix, feature(libc))] +#![cfg_attr(not(stage0), feature(nll))] #![feature(optin_builtin_traits)] extern crate atty; @@ -54,7 +55,14 @@ pub mod registry; mod styled_buffer; mod lock; -use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION}; +use syntax_pos::{BytePos, + Loc, + FileLinesResult, + SourceFile, + FileName, + MultiSpan, + Span, + NO_EXPANSION}; #[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] pub enum Applicability { @@ -110,22 +118,22 @@ pub struct SubstitutionPart { pub snippet: String, } -pub type CodeMapperDyn = dyn CodeMapper + sync::Send + sync::Sync; +pub type SourceMapperDyn = dyn SourceMapper + sync::Send + sync::Sync; -pub trait CodeMapper { +pub trait SourceMapper { fn lookup_char_pos(&self, pos: BytePos) -> Loc; fn span_to_lines(&self, sp: Span) -> FileLinesResult; fn span_to_string(&self, sp: Span) -> String; fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; - fn ensure_filemap_source_present(&self, file_map: Lrc) -> bool; + fn ensure_source_file_source_present(&self, file_map: Lrc) -> bool; fn doctest_offset_line(&self, line: usize) -> usize; } impl CodeSuggestion { /// Returns the assembled code suggestions and whether they should be shown with an underline. - pub fn splice_lines(&self, cm: &CodeMapperDyn) + pub fn splice_lines(&self, cm: &SourceMapperDyn) -> Vec<(String, Vec)> { use syntax_pos::{CharPos, Loc, Pos}; @@ -320,7 +328,7 @@ impl Handler { pub fn with_tty_emitter(color_config: ColorConfig, can_emit_warnings: bool, treat_err_as_bug: bool, - cm: Option>) + cm: Option>) -> Handler { Handler::with_tty_emitter_and_flags( color_config, @@ -333,7 +341,7 @@ impl Handler { } pub fn with_tty_emitter_and_flags(color_config: ColorConfig, - cm: Option>, + cm: Option>, flags: HandlerFlags) -> Handler { let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false)); diff --git a/src/librustc_errors/lock.rs b/src/librustc_errors/lock.rs index dff8d53986..ff323073c6 100644 --- a/src/librustc_errors/lock.rs +++ b/src/librustc_errors/lock.rs @@ -22,7 +22,7 @@ use std::any::Any; #[cfg(windows)] -#[allow(bad_style)] +#[allow(nonstandard_style)] pub fn acquire_global_lock(name: &str) -> Box { use std::ffi::CString; use std::io; @@ -109,7 +109,7 @@ pub fn acquire_global_lock(name: &str) -> Box { } } -#[cfg(unix)] +#[cfg(not(windows))] pub fn acquire_global_lock(_name: &str) -> Box { Box::new(()) } diff --git a/src/librustc_errors/registry.rs b/src/librustc_errors/registry.rs index 8373768147..9a2302171b 100644 --- a/src/librustc_errors/registry.rs +++ b/src/librustc_errors/registry.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashMap; +use rustc_data_structures::fx::FxHashMap; #[derive(Clone)] pub struct Registry { - descriptions: HashMap<&'static str, &'static str>, + descriptions: FxHashMap<&'static str, &'static str>, } impl Registry { diff --git a/src/librustc_fs_util/Cargo.toml b/src/librustc_fs_util/Cargo.toml new file mode 100644 index 0000000000..e40b44204b --- /dev/null +++ b/src/librustc_fs_util/Cargo.toml @@ -0,0 +1,11 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_fs_util" +version = "0.0.0" + +[lib] +name = "rustc_fs_util" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] diff --git a/src/librustc_fs_util/lib.rs b/src/librustc_fs_util/lib.rs new file mode 100644 index 0000000000..ffe420b109 --- /dev/null +++ b/src/librustc_fs_util/lib.rs @@ -0,0 +1,128 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::path::{Path, PathBuf}; +use std::ffi::CString; +use std::fs; +use std::io; + +// Unfortunately, on windows, it looks like msvcrt.dll is silently translating +// verbatim paths under the hood to non-verbatim paths! This manifests itself as +// gcc looking like it cannot accept paths of the form `\\?\C:\...`, but the +// real bug seems to lie in msvcrt.dll. +// +// Verbatim paths are generally pretty rare, but the implementation of +// `fs::canonicalize` currently generates paths of this form, meaning that we're +// going to be passing quite a few of these down to gcc, so we need to deal with +// this case. +// +// For now we just strip the "verbatim prefix" of `\\?\` from the path. This +// will probably lose information in some cases, but there's not a whole lot +// more we can do with a buggy msvcrt... +// +// For some more information, see this comment: +// https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737 +#[cfg(windows)] +pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { + use std::path; + use std::ffi::OsString; + let mut components = p.components(); + let prefix = match components.next() { + Some(path::Component::Prefix(p)) => p, + _ => return p.to_path_buf(), + }; + match prefix.kind() { + path::Prefix::VerbatimDisk(disk) => { + let mut base = OsString::from(format!("{}:", disk as char)); + base.push(components.as_path()); + PathBuf::from(base) + } + path::Prefix::VerbatimUNC(server, share) => { + let mut base = OsString::from(r"\\"); + base.push(server); + base.push(r"\"); + base.push(share); + base.push(components.as_path()); + PathBuf::from(base) + } + _ => p.to_path_buf(), + } +} + +#[cfg(not(windows))] +pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { + p.to_path_buf() +} + +pub enum LinkOrCopy { + Link, + Copy, +} + +/// Copy `p` into `q`, preferring to use hard-linking if possible. If +/// `q` already exists, it is removed first. +/// The result indicates which of the two operations has been performed. +pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result { + let p = p.as_ref(); + let q = q.as_ref(); + if q.exists() { + fs::remove_file(&q)?; + } + + match fs::hard_link(p, q) { + Ok(()) => Ok(LinkOrCopy::Link), + Err(_) => { + match fs::copy(p, q) { + Ok(_) => Ok(LinkOrCopy::Copy), + Err(e) => Err(e), + } + } + } +} + +#[derive(Debug)] +pub enum RenameOrCopyRemove { + Rename, + CopyRemove, +} + +/// Rename `p` into `q`, preferring to use `rename` if possible. +/// If `rename` fails (rename may fail for reasons such as crossing +/// filesystem), fallback to copy & remove +pub fn rename_or_copy_remove, Q: AsRef>(p: P, + q: Q) + -> io::Result { + let p = p.as_ref(); + let q = q.as_ref(); + match fs::rename(p, q) { + Ok(()) => Ok(RenameOrCopyRemove::Rename), + Err(_) => { + match fs::copy(p, q) { + Ok(_) => { + fs::remove_file(p)?; + Ok(RenameOrCopyRemove::CopyRemove) + } + Err(e) => Err(e), + } + } + } +} + +#[cfg(unix)] +pub fn path2cstr(p: &Path) -> CString { + use std::os::unix::prelude::*; + use std::ffi::OsStr; + let p: &OsStr = p.as_ref(); + CString::new(p.as_bytes()).unwrap() +} +#[cfg(windows)] +pub fn path2cstr(p: &Path) -> CString { + CString::new(p.to_str().unwrap()).unwrap() +} diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml index dd05679589..b8519ee1ab 100644 --- a/src/librustc_incremental/Cargo.toml +++ b/src/librustc_incremental/Cargo.toml @@ -11,9 +11,10 @@ crate-type = ["dylib"] [dependencies] graphviz = { path = "../libgraphviz" } log = "0.4" -rand = "0.4" +rand = "0.5" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } +rustc_fs_util = { path = "../librustc_fs_util" } diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index df8e0f056a..139159c163 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -27,11 +27,11 @@ //! the HIR doesn't change as a result of the annotations, which might //! perturb the reuse results. +use rustc::hir::def_id::LOCAL_CRATE; use rustc::dep_graph::{DepNode, DepConstructor}; -use rustc::mir::mono::CodegenUnit; +use rustc::mir::mono::CodegenUnitNameBuilder; use rustc::ty::TyCtxt; use syntax::ast; -use syntax_pos::symbol::Symbol; use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED}; const MODULE: &'static str = "module"; @@ -72,12 +72,37 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { return; } - let mname = self.field(attr, MODULE); - let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str()); - let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_interned_str(); + let user_path = self.field(attr, MODULE).as_str().to_string(); + let crate_name = self.tcx.crate_name(LOCAL_CRATE).as_str().to_string(); + + if !user_path.starts_with(&crate_name) { + let msg = format!("Found malformed codegen unit name `{}`. \ + Codegen units names must always start with the name of the \ + crate (`{}` in this case).", user_path, crate_name); + self.tcx.sess.span_fatal(attr.span, &msg); + } + + // Split of the "special suffix" if there is one. + let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind(".") { + (&user_path[..index], Some(&user_path[index + 1 ..])) + } else { + (&user_path[..], None) + }; + + let mut cgu_path_components = user_path.split('-').collect::>(); + + // Remove the crate name + assert_eq!(cgu_path_components.remove(0), crate_name); + + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(self.tcx); + let cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, + cgu_path_components, + cgu_special_suffix); + + debug!("mapping '{}' to cgu name '{}'", self.field(attr, MODULE), cgu_name); let dep_node = DepNode::new(self.tcx, - DepConstructor::CompileCodegenUnit(mangled_cgu_name)); + DepConstructor::CompileCodegenUnit(cgu_name)); if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) { match (disposition, loaded_from_cache) { @@ -85,13 +110,13 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { self.tcx.sess.span_err( attr.span, &format!("expected module named `{}` to be Reused but is Codegened", - mname)); + user_path)); } (Disposition::Codegened, true) => { self.tcx.sess.span_err( attr.span, &format!("expected module named `{}` to be Codegened but is Reused", - mname)); + user_path)); } (Disposition::Reused, true) | (Disposition::Codegened, false) => { @@ -99,7 +124,19 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { } } } else { - self.tcx.sess.span_err(attr.span, &format!("no module named `{}`", mname)); + let available_cgus = self.tcx + .collect_and_partition_mono_items(LOCAL_CRATE) + .1 + .iter() + .map(|cgu| format!("{}", cgu.name())) + .collect::>() + .join(", "); + + self.tcx.sess.span_err(attr.span, + &format!("no module named `{}` (mangled: {}).\nAvailable modules: {}", + user_path, + cgu_name, + available_cgus)); } } diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 3839c133a6..acdcf2b459 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -14,7 +14,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(fs_read_write)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(specialization)] #![recursion_limit="256"] @@ -24,6 +24,7 @@ extern crate graphviz; extern crate rustc_data_structures; extern crate serialize as rustc_serialize; extern crate rand; +extern crate rustc_fs_util; #[macro_use] extern crate log; extern crate syntax; @@ -42,6 +43,7 @@ pub use persist::copy_cgu_workproducts_to_incr_comp_cache_dir; pub use persist::save_dep_graph; pub use persist::save_work_product_index; pub use persist::in_incr_comp_dir; +pub use persist::in_incr_comp_dir_sess; pub use persist::prepare_session_directory; pub use persist::finalize_session_directory; pub use persist::delete_workproduct_files; diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 7f2da5a326..1b3819474c 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -24,13 +24,12 @@ //! the required condition is not met. //! -use std::collections::HashSet; use std::iter::FromIterator; use std::vec::Vec; use rustc::dep_graph::{DepNode, label_strs}; use rustc::hir; use rustc::hir::{ItemKind as HirItem, ImplItemKind, TraitItemKind}; -use rustc::hir::map::Node as HirNode; +use rustc::hir::Node as HirNode; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit; @@ -193,7 +192,7 @@ const LABELS_TRAIT: &[&[&str]] = &[ // // TypeOfItem for these. -type Labels = HashSet; +type Labels = FxHashSet; /// Represents the requested configuration by rustc_clean/dirty struct Assertion { @@ -205,13 +204,13 @@ impl Assertion { fn from_clean_labels(labels: Labels) -> Assertion { Assertion { clean: labels, - dirty: Labels::new(), + dirty: Labels::default(), } } fn from_dirty_labels(labels: Labels) -> Assertion { Assertion { - clean: Labels::new(), + clean: Labels::default(), dirty: labels, } } @@ -328,7 +327,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { } } // if no `label` or `except` is given, only the node's group are asserted - Labels::new() + Labels::default() } /// Return all DepNode labels that should be asserted for this item. @@ -336,7 +335,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static str, Labels) { let node = self.tcx.hir.get(item_id); let (name, labels) = match node { - HirNode::NodeItem(item) => { + HirNode::Item(item) => { match item.node { // note: these are in the same order as hir::Item_; // FIXME(michaelwoerister): do commented out ones @@ -399,22 +398,23 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { _ => self.tcx.sess.span_fatal( attr.span, &format!( - "clean/dirty auto-assertions not yet defined for NodeItem.node={:?}", + "clean/dirty auto-assertions not yet defined \ + for Node::Item.node={:?}", item.node ) ), } }, - HirNode::NodeTraitItem(item) => { + HirNode::TraitItem(item) => { match item.node { - TraitItemKind::Method(..) => ("NodeTraitItem", LABELS_FN_IN_TRAIT), + TraitItemKind::Method(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT), TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_IN_TRAIT), TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT), } }, - HirNode::NodeImplItem(item) => { + HirNode::ImplItem(item) => { match item.node { - ImplItemKind::Method(..) => ("NodeImplItem", LABELS_FN_IN_IMPL), + ImplItemKind::Method(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL), ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), ImplItemKind::Existential(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), @@ -435,7 +435,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { } fn resolve_labels(&self, item: &NestedMetaItem, value: &str) -> Labels { - let mut out: Labels = HashSet::new(); + let mut out = Labels::default(); for label in value.split(',') { let label = label.trim(); if DepNode::has_label_string(label) { diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 795825f180..ec25aef808 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -114,11 +114,11 @@ //! unsupported file system and emit a warning in that case. This is not yet //! implemented. -use rustc::hir::svh::Svh; use rustc::session::{Session, CrateDisambiguator}; -use rustc::util::fs as fs_util; +use rustc_fs_util::{link_or_copy, LinkOrCopy}; use rustc_data_structures::{flock, base_n}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use rustc_data_structures::svh::Svh; use std::fs as std_fs; use std::io; @@ -126,7 +126,7 @@ use std::mem; use std::path::{Path, PathBuf}; use std::time::{UNIX_EPOCH, SystemTime, Duration}; -use rand::{thread_rng, Rng}; +use rand::{RngCore, thread_rng}; const LOCK_FILE_EXT: &'static str = ".lock"; const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin"; @@ -429,11 +429,11 @@ fn copy_files(sess: &Session, let source_path = entry.path(); debug!("copying into session dir: {}", source_path.display()); - match fs_util::link_or_copy(source_path, target_file_path) { - Ok(fs_util::LinkOrCopy::Link) => { + match link_or_copy(source_path, target_file_path) { + Ok(LinkOrCopy::Link) => { files_linked += 1 } - Ok(fs_util::LinkOrCopy::Copy) => { + Ok(LinkOrCopy::Copy) => { files_copied += 1 } Err(_) => return Err(()) diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 9ee3b216dc..fbc3bf0359 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -207,11 +207,11 @@ pub fn load_dep_graph(sess: &Session) -> pub fn load_query_result_cache<'sess>(sess: &'sess Session) -> OnDiskCache<'sess> { if sess.opts.incremental.is_none() || !sess.opts.debugging_opts.incremental_queries { - return OnDiskCache::new_empty(sess.codemap()); + return OnDiskCache::new_empty(sess.source_map()); } match load_data(sess.opts.debugging_opts.incremental_info, &query_cache_path(sess)) { LoadResult::Ok{ data: (bytes, start_pos) } => OnDiskCache::new(sess, bytes, start_pos), - _ => OnDiskCache::new_empty(sess.codemap()) + _ => OnDiskCache::new_empty(sess.source_map()) } } diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs index e1f00db56d..17d36ba3fa 100644 --- a/src/librustc_incremental/persist/mod.rs +++ b/src/librustc_incremental/persist/mod.rs @@ -23,6 +23,7 @@ mod file_format; pub use self::fs::finalize_session_directory; pub use self::fs::garbage_collect_session_directories; pub use self::fs::in_incr_comp_dir; +pub use self::fs::in_incr_comp_dir_sess; pub use self::fs::prepare_session_directory; pub use self::load::dep_graph_tcx_init; pub use self::load::load_dep_graph; diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index c0ccbd67a3..cfe59b1f67 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -13,7 +13,7 @@ use persist::fs::*; use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind}; use rustc::session::Session; -use rustc::util::fs::link_or_copy; +use rustc_fs_util::link_or_copy; use std::path::PathBuf; use std::fs as std_fs; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9dd6bd594b..b662b82501 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -34,18 +34,17 @@ use rustc::cfg; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty}; use rustc::traits; -use rustc::hir::map as hir_map; +use hir::Node; use util::nodemap::NodeSet; use lint::{LateContext, LintContext, LintArray}; use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext}; -use std::collections::HashSet; use rustc::util::nodemap::FxHashSet; use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ast; use syntax::attr; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use syntax::edition::Edition; use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes}; use syntax_pos::{BytePos, Span, SyntaxContext}; @@ -55,7 +54,7 @@ use syntax::errors::{Applicability, DiagnosticBuilder}; use rustc::hir::{self, GenericParamKind, PatKind}; use rustc::hir::intravisit::FnKind; -use bad_style::{MethodLateContext, method_context}; +use nonstandard_style::{MethodLateContext, method_context}; // hardwired lints from librustc pub use lint::builtin::*; @@ -82,9 +81,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WhileTrue { if let ast::LitKind::Bool(true) = lit.node { if lit.span.ctxt() == SyntaxContext::empty() { let msg = "denote infinite loops with `loop { ... }`"; - let condition_span = cx.tcx.sess.codemap().def_span(e.span); + let condition_span = cx.tcx.sess.source_map().def_span(e.span); let mut err = cx.struct_span_lint(WHILE_TRUE, condition_span, msg); - err.span_suggestion_short(condition_span, "use `loop`", "loop".to_owned()); + err.span_suggestion_short_with_applicability( + condition_span, + "use `loop`", + "loop".to_owned(), + Applicability::MachineApplicable + ); err.emit(); } } @@ -190,8 +194,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns { let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, &format!("the `{}:` in this pattern is redundant", ident)); - let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':'); - err.span_suggestion_short(subspan, "remove this", ident.to_string()); + let subspan = cx.tcx.sess.source_map().span_through_char(fieldpat.span, + ':'); + err.span_suggestion_short_with_applicability( + subspan, + "remove this", + ident.to_string(), + Applicability::MachineApplicable + ); err.emit(); } } @@ -294,14 +304,14 @@ pub struct MissingDoc { doc_hidden_stack: Vec, /// Private traits or trait items that leaked through. Don't check their methods. - private_traits: HashSet, + private_traits: FxHashSet, } impl MissingDoc { pub fn new() -> MissingDoc { MissingDoc { doc_hidden_stack: vec![false], - private_traits: HashSet::new(), + private_traits: FxHashSet::default(), } } @@ -358,7 +368,7 @@ impl MissingDoc { let has_doc = attrs.iter().any(|a| has_doc(a)); if !has_doc { cx.span_lint(MISSING_DOCS, - cx.tcx.sess.codemap().def_span(sp), + cx.tcx.sess.source_map().def_span(sp), &format!("missing documentation for {}", desc)); } } @@ -416,7 +426,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let real_trait = trait_ref.path.def.def_id(); if let Some(node_id) = cx.tcx.hir.as_local_node_id(real_trait) { match cx.tcx.hir.find(node_id) { - Some(hir_map::NodeItem(item)) => { + Some(Node::Item(item)) => { if let hir::VisibilityKind::Inherited = item.vis.node { for impl_item_ref in impl_item_refs { self.private_traits.insert(impl_item_ref.id.node_id); @@ -618,8 +628,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { declare_lint! { pub ANONYMOUS_PARAMETERS, Allow, - "detects anonymous parameters", - Edition::Edition2018 => Warn + "detects anonymous parameters" } /// Checks for use of anonymous parameters (RFC 1685) @@ -642,7 +651,7 @@ impl EarlyLintPass for AnonymousParameters { if ident.name == keywords::Invalid.name() { let ty_snip = cx .sess - .codemap() + .source_map() .span_to_snippet(arg.ty.span); let (ty_snip, appl) = if let Ok(snip) = ty_snip { @@ -709,10 +718,11 @@ impl EarlyLintPass for BadRepr { | "i8" | "i16" | "i32" | "i64" | "i128" | "isize" => { // if the literal could have been a valid `repr` arg, // suggest the correct syntax - warn.span_suggestion( + warn.span_suggestion_with_applicability( attr.span, "give `repr` a hint", repr_str(&lit.as_str()), + Applicability::MachineApplicable ); suggested = true; } @@ -780,7 +790,12 @@ impl EarlyLintPass for DeprecatedAttr { let msg = format!("use of deprecated attribute `{}`: {}. See {}", name, reason, link); let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg); - err.span_suggestion_short(attr.span, "remove this attribute", "".to_owned()); + err.span_suggestion_short_with_applicability( + attr.span, + "remove this attribute", + String::new(), + Applicability::MachineApplicable + ); err.emit(); } return; @@ -873,7 +888,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // NB. this has an edge case with non-returning statements, // like `loop {}` or `panic!()`: control flow never reaches // the exit node through these, so one can have a function - // that never actually calls itselfs but is still picked up by + // that never actually calls itself but is still picked up by // this lint: // // fn f(cond: bool) { @@ -886,14 +901,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // considers this to be an error for two reasons, (a) it is // easier to implement, and (b) it seems rare to actually want // to have behaviour like the above, rather than - // e.g. accidentally recurring after an assert. + // e.g. accidentally recursing after an assert. let cfg = cfg::CFG::new(cx.tcx, &body); let mut work_queue = vec![cfg.entry]; let mut reached_exit_without_self_call = false; let mut self_call_spans = vec![]; - let mut visited = HashSet::new(); + let mut visited = FxHashSet::default(); while let Some(idx) = work_queue.pop() { if idx == cfg.exit { @@ -943,11 +958,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // no break */ }`) shouldn't be linted unless it actually // recurs. if !reached_exit_without_self_call && !self_call_spans.is_empty() { - let sp = cx.tcx.sess.codemap().def_span(sp); + let sp = cx.tcx.sess.source_map().def_span(sp); let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, sp, - "function cannot return without recurring"); - db.span_label(sp, "cannot return without recurring"); + "function cannot return without recursing"); + db.span_label(sp, "cannot return without recursing"); // offer some help to the programmer. for call in &self_call_spans { db.span_label(*call, "recursive call site"); @@ -964,7 +979,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { fn expr_refers_to_this_fn(cx: &LateContext, fn_id: ast::NodeId, id: ast::NodeId) -> bool { match cx.tcx.hir.get(id) { - hir_map::NodeExpr(&hir::Expr { node: hir::ExprKind::Call(ref callee, _), .. }) => { + Node::Expr(&hir::Expr { node: hir::ExprKind::Call(ref callee, _), .. }) => { let def = if let hir::ExprKind::Path(ref qpath) = callee.node { cx.tables.qpath_def(qpath, callee.hir_id) } else { @@ -987,7 +1002,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { use rustc::ty::adjustment::*; // Ignore non-expressions. - let expr = if let hir_map::NodeExpr(e) = cx.tcx.hir.get(id) { + let expr = if let Node::Expr(e) = cx.tcx.hir.get(id) { e } else { return false; @@ -1075,7 +1090,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // a default method definition. Ok(Some(traits::VtableParam(_))) => { let on_self = trait_ref.self_ty().is_self(); - // We can only be recurring in a default + // We can only be recursing in a default // method if we're being called literally // on the `Self` type. on_self && callee_id == method.def_id @@ -1202,7 +1217,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { } }; if let Some(replacement) = suggestion { - err.span_suggestion(vis.span, "try making it public", replacement); + err.span_suggestion_with_applicability( + vis.span, + "try making it public", + replacement, + Applicability::MachineApplicable + ); } }; @@ -1226,9 +1246,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { it.span, "functions generic over \ types must be mangled"); - err.span_suggestion_short(no_mangle_attr.span, - "remove this attribute", - "".to_owned()); + err.span_suggestion_short_with_applicability( + no_mangle_attr.span, + "remove this attribute", + String::new(), + // Use of `#[no_mangle]` suggests FFI intent; correct + // fix may be to monomorphize source by hand + Applicability::MaybeIncorrect + ); err.emit(); break; } @@ -1253,14 +1278,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg); // account for "pub const" (#45562) - let start = cx.tcx.sess.codemap().span_to_snippet(it.span) + let start = cx.tcx.sess.source_map().span_to_snippet(it.span) .map(|snippet| snippet.find("const").unwrap_or(0)) .unwrap_or(0) as u32; // `const` is 5 chars let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5)); - err.span_suggestion(const_span, - "try a static value", - "pub static".to_owned()); + err.span_suggestion_with_applicability( + const_span, + "try a static value", + "pub static".to_owned(), + Applicability::MachineApplicable + ); err.emit(); } } @@ -1291,7 +1319,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \ consider instead using an UnsafeCell"; match get_transmute_from_to(cx, expr) { - Some((&ty::TyRef(_, _, from_mt), &ty::TyRef(_, _, to_mt))) => { + Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => { if to_mt == hir::Mutability::MutMutable && from_mt == hir::Mutability::MutImmutable { cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg); @@ -1303,7 +1331,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { fn get_transmute_from_to<'a, 'tcx> (cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) - -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> { + -> Option<(&'tcx ty::TyKind<'tcx>, &'tcx ty::TyKind<'tcx>)> { let def = if let hir::ExprKind::Path(ref qpath) = expr.node { cx.tables.qpath_def(qpath, expr.hir_id) } else { @@ -1412,7 +1440,7 @@ impl UnreachablePub { if span.ctxt().outer().expn_info().is_some() { applicability = Applicability::MaybeIncorrect; } - let def_span = cx.tcx.sess.codemap().def_span(span); + let def_span = cx.tcx.sess.source_map().def_span(span); let mut err = cx.struct_span_lint(UNREACHABLE_PUB, def_span, &format!("unreachable `pub` {}", what)); let replacement = if cx.tcx.features().crate_visibility_modifier { @@ -1498,7 +1526,6 @@ impl TypeAliasBounds { // We use a HIR visitor to walk the type. use rustc::hir::intravisit::{self, Visitor}; - use syntax::ast::NodeId; struct WalkAssocTypes<'a, 'db> where 'db: 'a { err: &'a mut DiagnosticBuilder<'db> } @@ -1508,7 +1535,7 @@ impl TypeAliasBounds { intravisit::NestedVisitorMap::None } - fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: NodeId, span: Span) { + fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: hir::HirId, span: Span) { if TypeAliasBounds::is_type_variable_assoc(qpath) { self.err.span_help(span, "use fully disambiguated paths (i.e., `::Assoc`) to refer to \ @@ -1585,23 +1612,16 @@ fn validate_const<'a, 'tcx>( gid: ::rustc::mir::interpret::GlobalId<'tcx>, what: &str, ) { - let mut ecx = ::rustc_mir::interpret::mk_eval_cx(tcx, gid.instance, param_env).unwrap(); + let ecx = ::rustc_mir::interpret::mk_eval_cx(tcx, gid.instance, param_env).unwrap(); let result = (|| { - let val = ecx.const_to_value(constant.val)?; - use rustc_target::abi::LayoutOf; - let layout = ecx.layout_of(constant.ty)?; - let place = ecx.allocate_place_for_value(val, layout, None)?; - let ptr = place.to_ptr()?; - let mut todo = vec![(ptr, layout.ty, String::new())]; + let op = ecx.const_to_op(constant)?; + let mut todo = vec![(op, Vec::new())]; let mut seen = FxHashSet(); - seen.insert((ptr, layout.ty)); - while let Some((ptr, ty, path)) = todo.pop() { - let layout = ecx.layout_of(ty)?; - ecx.validate_ptr_target( - ptr, - layout.align, - layout, - path, + seen.insert(op); + while let Some((op, mut path)) = todo.pop() { + ecx.validate_operand( + op, + &mut path, &mut seen, &mut todo, )?; @@ -1815,71 +1835,87 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { } declare_lint! { - UNNAMEABLE_TEST_FUNCTIONS, + UNNAMEABLE_TEST_ITEMS, Warn, - "detects an function that cannot be named being marked as #[test]" + "detects an item that cannot be named being marked as #[test_case]", + report_in_external_macro: true } -pub struct UnnameableTestFunctions; +pub struct UnnameableTestItems { + boundary: ast::NodeId, // NodeId of the item under which things are not nameable + items_nameable: bool, +} -impl LintPass for UnnameableTestFunctions { +impl UnnameableTestItems { + pub fn new() -> Self { + Self { + boundary: ast::DUMMY_NODE_ID, + items_nameable: true + } + } +} + +impl LintPass for UnnameableTestItems { fn get_lints(&self) -> LintArray { - lint_array!(UNNAMEABLE_TEST_FUNCTIONS) + lint_array!(UNNAMEABLE_TEST_ITEMS) } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestFunctions { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - match it.node { - hir::ItemKind::Fn(..) => { - for attr in &it.attrs { - if attr.name() == "test" { - let parent = cx.tcx.hir.get_parent(it.id); - match cx.tcx.hir.find(parent) { - Some(hir_map::NodeItem(hir::Item {node: hir::ItemKind::Mod(_), ..})) | - None => {} - _ => { - cx.struct_span_lint( - UNNAMEABLE_TEST_FUNCTIONS, - attr.span, - "cannot test inner function", - ).emit(); - } - } - break; - } - } + if self.items_nameable { + if let hir::ItemKind::Mod(..) = it.node {} + else { + self.items_nameable = false; + self.boundary = it.id; } - _ => return, - }; + return; + } + + if let Some(attr) = attr::find_by_name(&it.attrs, "rustc_test_marker") { + cx.struct_span_lint( + UNNAMEABLE_TEST_ITEMS, + attr.span, + "cannot test inner items", + ).emit(); + } + } + + fn check_item_post(&mut self, _cx: &LateContext, it: &hir::Item) { + if !self.items_nameable && self.boundary == it.id { + self.items_nameable = true; + } } } declare_lint! { - pub ASYNC_IDENTS, + pub KEYWORD_IDENTS, Allow, - "detects `async` being used as an identifier" + "detects edition keywords being used as an identifier" } -/// Checks for uses of `async` as an identifier +/// Checks for uses of edtion keywords used as an identifier #[derive(Clone)] -pub struct Async2018; +pub struct KeywordIdents; -impl LintPass for Async2018 { +impl LintPass for KeywordIdents { fn get_lints(&self) -> LintArray { - lint_array!(ASYNC_IDENTS) + lint_array!(KEYWORD_IDENTS) } } -impl Async2018 { +impl KeywordIdents { fn check_tokens(&mut self, cx: &EarlyContext, tokens: TokenStream) { for tt in tokens.into_trees() { match tt { TokenTree::Token(span, tok) => match tok.ident() { // only report non-raw idents - Some((ident, false)) if ident.as_str() == "async" => { - self.report(cx, span.substitute_dummy(ident.span)) - }, + Some((ident, false)) => { + self.check_ident(cx, ast::Ident { + span: span.substitute_dummy(ident.span), + ..ident + }); + } _ => {}, } TokenTree::Delimited(_, ref delim) => { @@ -1888,31 +1924,9 @@ impl Async2018 { } } } - fn report(&mut self, cx: &EarlyContext, span: Span) { - // don't lint `r#async` - if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&span) { - return; - } - let mut lint = cx.struct_span_lint( - ASYNC_IDENTS, - span, - "`async` is a keyword in the 2018 edition", - ); - - // Don't suggest about raw identifiers if the feature isn't active - if cx.sess.features_untracked().raw_identifiers { - lint.span_suggestion_with_applicability( - span, - "you can use a raw identifier to stay compatible", - "r#async".to_string(), - Applicability::MachineApplicable, - ); - } - lint.emit() - } } -impl EarlyLintPass for Async2018 { +impl EarlyLintPass for KeywordIdents { fn check_mac_def(&mut self, cx: &EarlyContext, mac_def: &ast::MacroDef, _id: ast::NodeId) { self.check_tokens(cx, mac_def.stream()); } @@ -1920,8 +1934,37 @@ impl EarlyLintPass for Async2018 { self.check_tokens(cx, mac.node.tts.clone().into()); } fn check_ident(&mut self, cx: &EarlyContext, ident: ast::Ident) { - if ident.as_str() == "async" { - self.report(cx, ident.span); + let next_edition = match cx.sess.edition() { + Edition::Edition2015 => { + match &ident.as_str()[..] { + "async" | + "try" => Edition::Edition2018, + _ => return, + } + } + + // no new keywords yet for 2018 edition and beyond + _ => return, + }; + + // don't lint `r#foo` + if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&ident.span) { + return; } + + let mut lint = cx.struct_span_lint( + KEYWORD_IDENTS, + ident.span, + &format!("`{}` is a keyword in the {} edition", + ident.as_str(), + next_edition), + ); + lint.span_suggestion_with_applicability( + ident.span, + "you can use a raw identifier to stay compatible", + format!("r#{}", ident.as_str()), + Applicability::MachineApplicable, + ); + lint.emit() } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 78a8c494f4..9ed69a2dc9 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -26,7 +26,8 @@ #![cfg_attr(test, feature(test))] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(macro_vis_matcher)] +#![cfg_attr(stage0, feature(macro_vis_matcher))] +#![cfg_attr(not(stage0), feature(nll))] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(macro_at_most_once_rep)] @@ -45,7 +46,6 @@ use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray}; use rustc::lint::builtin::{ BARE_TRAIT_OBJECTS, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, - MACRO_USE_EXTERN_CRATE, ELIDED_LIFETIMES_IN_PATHS, parser::QUESTION_MARK_MACRO_SEP }; @@ -61,12 +61,12 @@ use syntax::edition::Edition; use lint::LintId; use lint::FutureIncompatibleInfo; -mod bad_style; +mod nonstandard_style; pub mod builtin; mod types; mod unused; -use bad_style::*; +use nonstandard_style::*; use builtin::*; use types::*; use unused::*; @@ -89,7 +89,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { macro_rules! add_pre_expansion_builtin { ($sess:ident, $($name:ident),*,) => ( {$( - store.register_early_pass($sess, false, box $name); + store.register_pre_expansion_pass($sess, box $name); )*} ) } @@ -104,12 +104,12 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { macro_rules! add_lint_group { ($sess:ident, $name:expr, $($lint:ident),*) => ( - store.register_group($sess, false, $name, vec![$(LintId::of($lint)),*]); + store.register_group($sess, false, $name, None, vec![$(LintId::of($lint)),*]); ) } add_pre_expansion_builtin!(sess, - Async2018, + KeywordIdents, ); add_early_builtin!(sess, @@ -148,7 +148,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { MutableTransmutes: MutableTransmutes, UnionsWithDropFields: UnionsWithDropFields, UnreachablePub: UnreachablePub, - UnnameableTestFunctions: UnnameableTestFunctions, + UnnameableTestItems: UnnameableTestItems::new(), TypeAliasBounds: TypeAliasBounds, UnusedBrokenConst: UnusedBrokenConst, TrivialConstraints: TrivialConstraints, @@ -195,11 +195,18 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { add_lint_group!(sess, "rust_2018_idioms", BARE_TRAIT_OBJECTS, - UNREACHABLE_PUB, UNUSED_EXTERN_CRATES, - MACRO_USE_EXTERN_CRATE, - ELIDED_LIFETIMES_IN_PATHS, - ELLIPSIS_INCLUSIVE_RANGE_PATTERNS); + ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, + ELIDED_LIFETIMES_IN_PATHS + + // FIXME(#52665, #47816) not always applicable and not all + // macros are ready for this yet. + // UNREACHABLE_PUB, + + // FIXME macro crates are not up for this yet, too much + // breakage is seen if we try to encourage this lint. + // MACRO_USE_EXTERN_CRATE, + ); // Guidelines for creating a future incompatibility lint: // @@ -232,7 +239,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { edition: Some(Edition::Edition2018), }, FutureIncompatibleInfo { - id: LintId::of(ASYNC_IDENTS), + id: LintId::of(KEYWORD_IDENTS), reference: "issue #49716 ", edition: Some(Edition::Edition2018), }, @@ -269,7 +276,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { FutureIncompatibleInfo { id: LintId::of(ANONYMOUS_PARAMETERS), reference: "issue #41686 ", - edition: None, + edition: Some(Edition::Edition2018), }, FutureIncompatibleInfo { id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES), @@ -327,7 +334,12 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(QUESTION_MARK_MACRO_SEP), reference: "issue #48075 ", edition: Some(Edition::Edition2018), - } + }, + FutureIncompatibleInfo { + id: LintId::of(MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS), + reference: "issue #52234 ", + edition: None, + }, ]); // Register renamed and removed lints @@ -336,7 +348,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_renamed("bare_trait_object", "bare_trait_objects"); store.register_renamed("unstable_name_collision", "unstable_name_collisions"); store.register_renamed("unused_doc_comment", "unused_doc_comments"); - store.register_renamed("unknown_features", "unused_features"); + store.register_renamed("async_idents", "keyword_idents"); + store.register_removed("unknown_features", "replaced by an error"); store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); store.register_removed("negate_unsigned", "cast a signed value instead"); store.register_removed("raw_pointer_derive", "using derive with raw pointers is ok"); diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/nonstandard_style.rs similarity index 100% rename from src/librustc_lint/bad_style.rs rename to src/librustc_lint/nonstandard_style.rs diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index ad4a4fbff6..2bec9203e9 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -10,7 +10,7 @@ #![allow(non_snake_case)] -use rustc::hir::map as hir_map; +use rustc::hir::Node; use rustc::ty::subst::Substs; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, IntegerExt, LayoutOf}; @@ -22,9 +22,10 @@ use std::cmp; use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; use syntax::{ast, attr}; +use syntax::errors::Applicability; use rustc_target::spec::abi::Abi; use syntax_pos::Span; -use syntax::codemap; +use syntax::source_map; use rustc::hir; @@ -83,7 +84,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } hir::ExprKind::Lit(ref lit) => { match cx.tables.node_id_to_type(e.hir_id).sty { - ty::TyInt(t) => { + ty::Int(t) => { match lit.node { ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => { @@ -103,7 +104,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { report_bin_hex_error( cx, e, - ty::TyInt(t), + ty::Int(t), repr_str, v, negative, @@ -121,7 +122,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { _ => bug!(), }; } - ty::TyUint(t) => { + ty::Uint(t) => { let uint_type = if let ast::UintTy::Usize = t { cx.sess().target.usize_ty } else { @@ -136,16 +137,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { }; if lit_val < min || lit_val > max { let parent_id = cx.tcx.hir.get_parent_node(e.id); - if let hir_map::NodeExpr(parent_expr) = cx.tcx.hir.get(parent_id) { + if let Node::Expr(parent_expr) = cx.tcx.hir.get(parent_id) { if let hir::ExprKind::Cast(..) = parent_expr.node { - if let ty::TyChar = cx.tables.expr_ty(parent_expr).sty { + if let ty::Char = cx.tables.expr_ty(parent_expr).sty { let mut err = cx.struct_span_lint( OVERFLOWING_LITERALS, parent_expr.span, "only u8 can be cast into char"); - err.span_suggestion(parent_expr.span, - &"use a char literal instead", - format!("'\\u{{{:X}}}'", lit_val)); + err.span_suggestion_with_applicability( + parent_expr.span, + &"use a char literal instead", + format!("'\\u{{{:X}}}'", lit_val), + Applicability::MachineApplicable + ); err.emit(); return } @@ -155,7 +159,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { report_bin_hex_error( cx, e, - ty::TyUint(t), + ty::Uint(t), repr_str, lit_val, false, @@ -169,7 +173,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { ); } } - ty::TyFloat(t) => { + ty::Float(t) => { let is_infinite = match lit.node { ast::LitKind::Float(v, _) | ast::LitKind::FloatUnsuffixed(v) => { @@ -204,7 +208,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } fn rev_binop(binop: hir::BinOp) -> hir::BinOp { - codemap::respan(binop.span, + source_map::respan(binop.span, match binop.node { hir::BinOpKind::Lt => hir::BinOpKind::Gt, hir::BinOpKind::Le => hir::BinOpKind::Ge, @@ -252,7 +256,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { // the comparison let norm_binop = if swap { rev_binop(binop) } else { binop }; match cx.tables.node_id_to_type(expr.hir_id).sty { - ty::TyInt(int_ty) => { + ty::Int(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i128 = match lit.node { hir::ExprKind::Lit(ref li) => { @@ -266,7 +270,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { }; is_valid(norm_binop, lit_val, min, max) } - ty::TyUint(uint_ty) => { + ty::Uint(uint_ty) => { let (min, max) :(u128, u128) = uint_ty_range(uint_ty); let lit_val: u128 = match lit.node { hir::ExprKind::Lit(ref li) => { @@ -296,7 +300,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } fn get_bin_hex_repr(cx: &LateContext, lit: &ast::Lit) -> Option { - let src = cx.sess().codemap().span_to_snippet(lit.span).ok()?; + let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?; let firstch = src.chars().next()?; if firstch == '0' { @@ -317,7 +321,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { // // No suggestion for: `isize`, `usize`. fn get_type_suggestion<'a>( - t: &ty::TypeVariants, + t: &ty::TyKind, val: u128, negative: bool, ) -> Option { @@ -344,13 +348,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } match t { - &ty::TyInt(i) => find_fit!(i, val, negative, + &ty::Int(i) => find_fit!(i, val, negative, I8 => [U8] => [I16, I32, I64, I128], I16 => [U16] => [I32, I64, I128], I32 => [U32] => [I64, I128], I64 => [U64] => [I128], I128 => [U128] => []), - &ty::TyUint(u) => find_fit!(u, val, negative, + &ty::Uint(u) => find_fit!(u, val, negative, U8 => [U8, U16, U32, U64, U128] => [], U16 => [U16, U32, U64, U128] => [], U32 => [U32, U64, U128] => [], @@ -363,19 +367,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { fn report_bin_hex_error( cx: &LateContext, expr: &hir::Expr, - ty: ty::TypeVariants, + ty: ty::TyKind, repr_str: String, val: u128, negative: bool, ) { let (t, actually) = match ty { - ty::TyInt(t) => { + ty::Int(t) => { let ity = attr::IntType::SignedInt(t); let bits = layout::Integer::from_attr(cx.tcx, ity).size().bits(); let actually = (val << (128 - bits)) as i128 >> (128 - bits); (format!("{:?}", t), actually.to_string()) } - ty::TyUint(t) => { + ty::Uint(t) => { let ity = attr::IntType::UnsignedInt(t); let bits = layout::Integer::from_attr(cx.tcx, ity).size().bits(); let actually = (val << (128 - bits)) >> (128 - bits); @@ -398,10 +402,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { { if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { let (sans_suffix, _) = repr_str.split_at(pos); - err.span_suggestion( + err.span_suggestion_with_applicability( expr.span, &format!("consider using `{}` instead", sugg_ty), format!("{}{}", sans_suffix, sugg_ty), + Applicability::MachineApplicable ); } else { err.help(&format!("consider using `{}` instead", sugg_ty)); @@ -455,10 +460,10 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if def.variants[data_idx].fields.len() == 1 { match def.variants[data_idx].fields[0].ty(tcx, substs).sty { - ty::TyFnPtr(_) => { + ty::FnPtr(_) => { return true; } - ty::TyRef(..) => { + ty::Ref(..) => { return true; } _ => {} @@ -481,13 +486,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Protect against infinite recursion, for example // `struct S(*mut S);`. // FIXME: A recursion limit is necessary as well, for irregular - // recusive types. + // recursive types. if !cache.insert(ty) { return FfiSafe; } match ty.sty { - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { if def.is_phantom_data() { return FfiPhantom(ty); } @@ -628,51 +633,51 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } - ty::TyChar => FfiUnsafe { + ty::Char => FfiUnsafe { ty: ty, reason: "the `char` type has no C equivalent", help: Some("consider using `u32` or `libc::wchar_t` instead"), }, - ty::TyInt(ast::IntTy::I128) | ty::TyUint(ast::UintTy::U128) => FfiUnsafe { + ty::Int(ast::IntTy::I128) | ty::Uint(ast::UintTy::U128) => FfiUnsafe { ty: ty, reason: "128-bit integers don't currently have a known stable ABI", help: None, }, // Primitive types with a stable representation. - ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyNever => FfiSafe, + ty::Bool | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Never => FfiSafe, - ty::TySlice(_) => FfiUnsafe { + ty::Slice(_) => FfiUnsafe { ty: ty, reason: "slices have no C equivalent", help: Some("consider using a raw pointer instead"), }, - ty::TyDynamic(..) => FfiUnsafe { + ty::Dynamic(..) => FfiUnsafe { ty: ty, reason: "trait objects have no C equivalent", help: None, }, - ty::TyStr => FfiUnsafe { + ty::Str => FfiUnsafe { ty: ty, reason: "string slices have no C equivalent", help: Some("consider using `*const u8` and a length instead"), }, - ty::TyTuple(..) => FfiUnsafe { + ty::Tuple(..) => FfiUnsafe { ty: ty, reason: "tuples have unspecified layout", help: Some("consider using a struct instead"), }, - ty::TyRawPtr(ty::TypeAndMut { ty, .. }) | - ty::TyRef(_, ty, _) => self.check_type_for_ffi(cache, ty), + ty::RawPtr(ty::TypeAndMut { ty, .. }) | + ty::Ref(_, ty, _) => self.check_type_for_ffi(cache, ty), - ty::TyArray(ty, _) => self.check_type_for_ffi(cache, ty), + ty::Array(ty, _) => self.check_type_for_ffi(cache, ty), - ty::TyFnPtr(sig) => { + ty::FnPtr(sig) => { match sig.abi() { Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => { return FfiUnsafe { @@ -686,7 +691,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } let sig = cx.erase_late_bound_regions(&sig); - if !sig.output().is_nil() { + if !sig.output().is_unit() { let r = self.check_type_for_ffi(cache, sig.output()); match r { FfiSafe => {} @@ -707,17 +712,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::TyForeign(..) => FfiSafe, - - ty::TyParam(..) | - ty::TyInfer(..) | - ty::TyError | - ty::TyClosure(..) | - ty::TyGenerator(..) | - ty::TyGeneratorWitness(..) | - ty::TyProjection(..) | - ty::TyAnon(..) | - ty::TyFnDef(..) => bug!("Unexpected type in foreign function"), + ty::Foreign(..) => FfiSafe, + + ty::Param(..) | + ty::Infer(..) | + ty::Error | + ty::Closure(..) | + ty::Generator(..) | + ty::GeneratorWitness(..) | + ty::Projection(..) | + ty::Opaque(..) | + ty::FnDef(..) => bug!("Unexpected type in foreign function"), } } @@ -741,7 +746,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(s) = help { diag.help(s); } - if let ty::TyAdt(def, _) = unsafe_ty.sty { + if let ty::Adt(def, _) = unsafe_ty.sty { if let Some(sp) = self.cx.tcx.hir.span_if_local(def.did) { diag.span_note(sp, "type defined here"); } @@ -762,7 +767,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let hir::Return(ref ret_hir) = decl.output { let ret_ty = sig.output(); - if !ret_ty.is_nil() { + if !ret_ty.is_unit() { self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty); } } @@ -785,21 +790,18 @@ impl LintPass for ImproperCTypes { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes { - fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + fn check_foreign_item(&mut self, cx: &LateContext, it: &hir::ForeignItem) { let mut vis = ImproperCTypesVisitor { cx: cx }; - if let hir::ItemKind::ForeignMod(ref nmod) = it.node { - if nmod.abi != Abi::RustIntrinsic && nmod.abi != Abi::PlatformIntrinsic { - for ni in &nmod.items { - match ni.node { - hir::ForeignItemKind::Fn(ref decl, _, _) => { - vis.check_foreign_fn(ni.id, decl); - } - hir::ForeignItemKind::Static(ref ty, _) => { - vis.check_foreign_static(ni.id, ty.span); - } - hir::ForeignItemKind::Type => () - } + let abi = cx.tcx.hir.get_foreign_abi(it.id); + if abi != Abi::RustIntrinsic && abi != Abi::PlatformIntrinsic { + match it.node { + hir::ForeignItemKind::Fn(ref decl, _, _) => { + vis.check_foreign_fn(it.id, decl); + } + hir::ForeignItemKind::Static(ref ty, _) => { + vis.check_foreign_static(it.id, ty.span); } + hir::ForeignItemKind::Type => () } } } @@ -817,14 +819,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemKind::Enum(ref enum_definition, _) = it.node { let item_def_id = cx.tcx.hir.local_def_id(it.id); - let generics = cx.tcx.generics_of(item_def_id); - for param in &generics.params { - match param.kind { - ty::GenericParamDefKind::Lifetime { .. } => {}, - ty::GenericParamDefKind::Type { .. } => return, - } - } - // Sizes only make sense for non-generic types. let t = cx.tcx.type_of(item_def_id); let ty = cx.tcx.erase_regions(&t); match cx.layout_of(ty) { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index da291f56ee..7a9d18676c 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -17,6 +17,7 @@ use lint::{LintPass, EarlyLintPass, LateLintPass}; use syntax::ast; use syntax::attr; +use syntax::errors::Applicability; use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType}; use syntax::print::pprust; use syntax::symbol::keywords; @@ -59,9 +60,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let t = cx.tables.expr_ty(&expr); let ty_warned = match t.sty { - ty::TyTuple(ref tys) if tys.is_empty() => return, - ty::TyNever => return, - ty::TyAdt(def, _) => { + ty::Tuple(ref tys) if tys.is_empty() => return, + ty::Never => return, + ty::Adt(def, _) => { if def.variants.is_empty() { return; } else { @@ -303,9 +304,12 @@ impl UnusedParens { _ => false, } }).to_owned(); - err.span_suggestion_short(value.span, - "remove these parentheses", - parens_removed); + err.span_suggestion_short_with_applicability( + value.span, + "remove these parentheses", + parens_removed, + Applicability::MachineApplicable + ); err.emit(); } } diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index 0978c2ceb1..013badb71c 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -12,11 +12,6 @@ path = "lib.rs" static-libstdcpp = [] emscripten = [] -[dependencies] -bitflags = "1.0" -libc = "0.2" -rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } - [build-dependencies] build_helper = { path = "../build_helper" } cc = "1.0.1" diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs deleted file mode 100644 index 9d86900727..0000000000 --- a/src/librustc_llvm/archive_ro.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A wrapper around LLVM's archive (.a) code - -use ArchiveRef; - -use std::ffi::CString; -use std::marker; -use std::path::Path; -use std::slice; -use std::str; - -pub struct ArchiveRO { - ptr: ArchiveRef, -} - -unsafe impl Send for ArchiveRO {} - -pub struct Iter<'a> { - archive: &'a ArchiveRO, - ptr: ::ArchiveIteratorRef, -} - -pub struct Child<'a> { - ptr: ::ArchiveChildRef, - _data: marker::PhantomData<&'a ArchiveRO>, -} - -impl ArchiveRO { - /// Opens a static archive for read-only purposes. This is more optimized - /// than the `open` method because it uses LLVM's internal `Archive` class - /// rather than shelling out to `ar` for everything. - /// - /// If this archive is used with a mutable method, then an error will be - /// raised. - pub fn open(dst: &Path) -> Result { - return unsafe { - let s = path2cstr(dst); - let ar = ::LLVMRustOpenArchive(s.as_ptr()); - if ar.is_null() { - Err(::last_error().unwrap_or("failed to open archive".to_string())) - } else { - Ok(ArchiveRO { ptr: ar }) - } - }; - - #[cfg(unix)] - fn path2cstr(p: &Path) -> CString { - use std::os::unix::prelude::*; - use std::ffi::OsStr; - let p: &OsStr = p.as_ref(); - CString::new(p.as_bytes()).unwrap() - } - #[cfg(windows)] - fn path2cstr(p: &Path) -> CString { - CString::new(p.to_str().unwrap()).unwrap() - } - } - - pub fn raw(&self) -> ArchiveRef { - self.ptr - } - - pub fn iter(&self) -> Iter { - unsafe { - Iter { - ptr: ::LLVMRustArchiveIteratorNew(self.ptr), - archive: self, - } - } - } -} - -impl Drop for ArchiveRO { - fn drop(&mut self) { - unsafe { - ::LLVMRustDestroyArchive(self.ptr); - } - } -} - -impl<'a> Iterator for Iter<'a> { - type Item = Result, String>; - - fn next(&mut self) -> Option, String>> { - let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) }; - if ptr.is_null() { - ::last_error().map(Err) - } else { - Some(Ok(Child { - ptr, - _data: marker::PhantomData, - })) - } - } -} - -impl<'a> Drop for Iter<'a> { - fn drop(&mut self) { - unsafe { - ::LLVMRustArchiveIteratorFree(self.ptr); - } - } -} - -impl<'a> Child<'a> { - pub fn name(&self) -> Option<&'a str> { - unsafe { - let mut name_len = 0; - let name_ptr = ::LLVMRustArchiveChildName(self.ptr, &mut name_len); - if name_ptr.is_null() { - None - } else { - let name = slice::from_raw_parts(name_ptr as *const u8, name_len as usize); - str::from_utf8(name).ok().map(|s| s.trim()) - } - } - } - - pub fn data(&self) -> &'a [u8] { - unsafe { - let mut data_len = 0; - let data_ptr = ::LLVMRustArchiveChildData(self.ptr, &mut data_len); - if data_ptr.is_null() { - panic!("failed to read data from archive child"); - } - slice::from_raw_parts(data_ptr as *const u8, data_len as usize) - } - } - - pub fn raw(&self) -> ::ArchiveChildRef { - self.ptr - } -} - -impl<'a> Drop for Child<'a> { - fn drop(&mut self) { - unsafe { - ::LLVMRustArchiveChildFree(self.ptr); - } - } -} diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 1619637b82..7d01ed556c 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -81,7 +81,7 @@ fn main() { let is_crossed = target != host; let mut optional_components = - vec!["x86", "arm", "aarch64", "mips", "powerpc", + vec!["x86", "arm", "aarch64", "amdgpu", "mips", "powerpc", "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx"]; let mut version_cmd = Command::new(&llvm_config); @@ -100,6 +100,10 @@ fn main() { optional_components.push("hexagon"); } + if major > 6 { + optional_components.push("riscv"); + } + // FIXME: surely we don't need all these components, right? Stuff like mcjit // or interpreter the compiler itself never uses. let required_components = &["ipo", @@ -271,5 +275,6 @@ fn main() { if target.contains("windows-gnu") { println!("cargo:rustc-link-lib=static-nobundle=gcc_s"); println!("cargo:rustc-link-lib=static-nobundle=pthread"); + println!("cargo:rustc-link-lib=dylib=uuid"); } } diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs deleted file mode 100644 index 8d04438eea..0000000000 --- a/src/librustc_llvm/ffi.rs +++ /dev/null @@ -1,1800 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression' -// once support for LLVM 3.9 is dropped. -// -// This method was changed in this LLVM patch: -// https://reviews.llvm.org/D26769 - -use debuginfo::{DIBuilderRef, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType, - DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable, - DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, - DINameSpace, DIFlags}; - -use libc::{c_uint, c_int, size_t, c_char}; -use libc::{c_longlong, c_ulonglong, c_void}; - -use RustStringRef; - -pub type Opcode = u32; -pub type Bool = c_uint; - -pub const True: Bool = 1 as Bool; -pub const False: Bool = 0 as Bool; - -#[derive(Copy, Clone, PartialEq)] -#[repr(C)] -pub enum LLVMRustResult { - Success, - Failure, -} -// Consts for the LLVM CallConv type, pre-cast to usize. - -/// LLVM CallingConv::ID. Should we wrap this? -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(C)] -pub enum CallConv { - CCallConv = 0, - FastCallConv = 8, - ColdCallConv = 9, - X86StdcallCallConv = 64, - X86FastcallCallConv = 65, - ArmAapcsCallConv = 67, - Msp430Intr = 69, - X86_ThisCall = 70, - PtxKernel = 71, - X86_64_SysV = 78, - X86_64_Win64 = 79, - X86_VectorCall = 80, - X86_Intr = 83, - AmdGpuKernel = 91, -} - -/// LLVMRustLinkage -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -#[repr(C)] -pub enum Linkage { - ExternalLinkage = 0, - AvailableExternallyLinkage = 1, - LinkOnceAnyLinkage = 2, - LinkOnceODRLinkage = 3, - WeakAnyLinkage = 4, - WeakODRLinkage = 5, - AppendingLinkage = 6, - InternalLinkage = 7, - PrivateLinkage = 8, - ExternalWeakLinkage = 9, - CommonLinkage = 10, -} - -// LLVMRustVisibility -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -#[repr(C)] -pub enum Visibility { - Default = 0, - Hidden = 1, - Protected = 2, -} - -/// LLVMDiagnosticSeverity -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub enum DiagnosticSeverity { - Error = 0, - Warning = 1, - Remark = 2, - Note = 3, -} - -/// LLVMDLLStorageClass -#[derive(Copy, Clone)] -#[repr(C)] -pub enum DLLStorageClass { - Default = 0, - DllImport = 1, // Function to be imported from DLL. - DllExport = 2, // Function to be accessible from DLL. -} - -/// Matches LLVMRustAttribute in rustllvm.h -/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind, -/// though it is not ABI compatible (since it's a C++ enum) -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub enum Attribute { - AlwaysInline = 0, - ByVal = 1, - Cold = 2, - InlineHint = 3, - MinSize = 4, - Naked = 5, - NoAlias = 6, - NoCapture = 7, - NoInline = 8, - NonNull = 9, - NoRedZone = 10, - NoReturn = 11, - NoUnwind = 12, - OptimizeForSize = 13, - ReadOnly = 14, - SExt = 15, - StructRet = 16, - UWTable = 17, - ZExt = 18, - InReg = 19, - SanitizeThread = 20, - SanitizeAddress = 21, - SanitizeMemory = 22, -} - -/// LLVMIntPredicate -#[derive(Copy, Clone)] -#[repr(C)] -pub enum IntPredicate { - IntEQ = 32, - IntNE = 33, - IntUGT = 34, - IntUGE = 35, - IntULT = 36, - IntULE = 37, - IntSGT = 38, - IntSGE = 39, - IntSLT = 40, - IntSLE = 41, -} - -/// LLVMRealPredicate -#[derive(Copy, Clone)] -#[repr(C)] -pub enum RealPredicate { - RealPredicateFalse = 0, - RealOEQ = 1, - RealOGT = 2, - RealOGE = 3, - RealOLT = 4, - RealOLE = 5, - RealONE = 6, - RealORD = 7, - RealUNO = 8, - RealUEQ = 9, - RealUGT = 10, - RealUGE = 11, - RealULT = 12, - RealULE = 13, - RealUNE = 14, - RealPredicateTrue = 15, -} - -/// LLVMTypeKind -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(C)] -pub enum TypeKind { - Void = 0, - Half = 1, - Float = 2, - Double = 3, - X86_FP80 = 4, - FP128 = 5, - PPC_FP128 = 6, - Label = 7, - Integer = 8, - Function = 9, - Struct = 10, - Array = 11, - Pointer = 12, - Vector = 13, - Metadata = 14, - X86_MMX = 15, - Token = 16, -} - -/// LLVMAtomicRmwBinOp -#[derive(Copy, Clone)] -#[repr(C)] -pub enum AtomicRmwBinOp { - AtomicXchg = 0, - AtomicAdd = 1, - AtomicSub = 2, - AtomicAnd = 3, - AtomicNand = 4, - AtomicOr = 5, - AtomicXor = 6, - AtomicMax = 7, - AtomicMin = 8, - AtomicUMax = 9, - AtomicUMin = 10, -} - -/// LLVMAtomicOrdering -#[derive(Copy, Clone)] -#[repr(C)] -pub enum AtomicOrdering { - NotAtomic = 0, - Unordered = 1, - Monotonic = 2, - // Consume = 3, // Not specified yet. - Acquire = 4, - Release = 5, - AcquireRelease = 6, - SequentiallyConsistent = 7, -} - -/// LLVMRustSynchronizationScope -#[derive(Copy, Clone)] -#[repr(C)] -pub enum SynchronizationScope { - Other, - SingleThread, - CrossThread, -} - -/// LLVMRustFileType -#[derive(Copy, Clone)] -#[repr(C)] -pub enum FileType { - Other, - AssemblyFile, - ObjectFile, -} - -/// LLVMMetadataType -#[derive(Copy, Clone)] -#[repr(C)] -pub enum MetadataType { - MD_dbg = 0, - MD_tbaa = 1, - MD_prof = 2, - MD_fpmath = 3, - MD_range = 4, - MD_tbaa_struct = 5, - MD_invariant_load = 6, - MD_alias_scope = 7, - MD_noalias = 8, - MD_nontemporal = 9, - MD_mem_parallel_loop_access = 10, - MD_nonnull = 11, -} - -/// LLVMRustAsmDialect -#[derive(Copy, Clone)] -#[repr(C)] -pub enum AsmDialect { - Other, - Att, - Intel, -} - -/// LLVMRustCodeGenOptLevel -#[derive(Copy, Clone, PartialEq)] -#[repr(C)] -pub enum CodeGenOptLevel { - Other, - None, - Less, - Default, - Aggressive, -} - -/// LLVMRelocMode -#[derive(Copy, Clone, PartialEq)] -#[repr(C)] -pub enum RelocMode { - Default, - Static, - PIC, - DynamicNoPic, - ROPI, - RWPI, - ROPI_RWPI, -} - -/// LLVMRustCodeModel -#[derive(Copy, Clone)] -#[repr(C)] -pub enum CodeModel { - Other, - Small, - Kernel, - Medium, - Large, - None, -} - -/// LLVMRustDiagnosticKind -#[derive(Copy, Clone)] -#[repr(C)] -pub enum DiagnosticKind { - Other, - InlineAsm, - StackSize, - DebugMetadataVersion, - SampleProfile, - OptimizationRemark, - OptimizationRemarkMissed, - OptimizationRemarkAnalysis, - OptimizationRemarkAnalysisFPCommute, - OptimizationRemarkAnalysisAliasing, - OptimizationRemarkOther, - OptimizationFailure, - PGOProfile, -} - -/// LLVMRustArchiveKind -#[derive(Copy, Clone)] -#[repr(C)] -pub enum ArchiveKind { - Other, - K_GNU, - K_BSD, - K_COFF, -} - -/// LLVMRustPassKind -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(C)] -pub enum PassKind { - Other, - Function, - Module, -} - -/// LLVMRustThinLTOData -pub enum ThinLTOData {} - -/// LLVMRustThinLTOBuffer -pub enum ThinLTOBuffer {} - -/// LLVMRustThinLTOModule -#[repr(C)] -pub struct ThinLTOModule { - pub identifier: *const c_char, - pub data: *const u8, - pub len: usize, -} - -/// LLVMThreadLocalMode -#[derive(Copy, Clone)] -#[repr(C)] -pub enum ThreadLocalMode { - NotThreadLocal, - GeneralDynamic, - LocalDynamic, - InitialExec, - LocalExec -} - -// Opaque pointer types -#[allow(missing_copy_implementations)] -pub enum Module_opaque {} -pub type ModuleRef = *mut Module_opaque; -#[allow(missing_copy_implementations)] -pub enum Context_opaque {} -pub type ContextRef = *mut Context_opaque; -#[allow(missing_copy_implementations)] -pub enum Type_opaque {} -pub type TypeRef = *mut Type_opaque; -#[allow(missing_copy_implementations)] -pub enum Value_opaque {} -pub type ValueRef = *mut Value_opaque; -#[allow(missing_copy_implementations)] -pub enum Metadata_opaque {} -pub type MetadataRef = *mut Metadata_opaque; -#[allow(missing_copy_implementations)] -pub enum BasicBlock_opaque {} -pub type BasicBlockRef = *mut BasicBlock_opaque; -#[allow(missing_copy_implementations)] -pub enum Builder_opaque {} -pub type BuilderRef = *mut Builder_opaque; -#[allow(missing_copy_implementations)] -pub enum ExecutionEngine_opaque {} -pub type ExecutionEngineRef = *mut ExecutionEngine_opaque; -#[allow(missing_copy_implementations)] -pub enum MemoryBuffer_opaque {} -pub type MemoryBufferRef = *mut MemoryBuffer_opaque; -#[allow(missing_copy_implementations)] -pub enum PassManager_opaque {} -pub type PassManagerRef = *mut PassManager_opaque; -#[allow(missing_copy_implementations)] -pub enum PassManagerBuilder_opaque {} -pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque; -#[allow(missing_copy_implementations)] -pub enum Use_opaque {} -pub type UseRef = *mut Use_opaque; -#[allow(missing_copy_implementations)] -pub enum TargetData_opaque {} -pub type TargetDataRef = *mut TargetData_opaque; -#[allow(missing_copy_implementations)] -pub enum ObjectFile_opaque {} -pub type ObjectFileRef = *mut ObjectFile_opaque; -#[allow(missing_copy_implementations)] -pub enum SectionIterator_opaque {} -pub type SectionIteratorRef = *mut SectionIterator_opaque; -#[allow(missing_copy_implementations)] -pub enum Pass_opaque {} -pub type PassRef = *mut Pass_opaque; -#[allow(missing_copy_implementations)] -pub enum TargetMachine_opaque {} -pub type TargetMachineRef = *mut TargetMachine_opaque; -pub enum Archive_opaque {} -pub type ArchiveRef = *mut Archive_opaque; -pub enum ArchiveIterator_opaque {} -pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque; -pub enum ArchiveChild_opaque {} -pub type ArchiveChildRef = *mut ArchiveChild_opaque; -#[allow(missing_copy_implementations)] -pub enum Twine_opaque {} -pub type TwineRef = *mut Twine_opaque; -#[allow(missing_copy_implementations)] -pub enum DiagnosticInfo_opaque {} -pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque; -#[allow(missing_copy_implementations)] -pub enum DebugLoc_opaque {} -pub type DebugLocRef = *mut DebugLoc_opaque; -#[allow(missing_copy_implementations)] -pub enum SMDiagnostic_opaque {} -pub type SMDiagnosticRef = *mut SMDiagnostic_opaque; -#[allow(missing_copy_implementations)] -pub enum RustArchiveMember_opaque {} -pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque; -#[allow(missing_copy_implementations)] -pub enum OperandBundleDef_opaque {} -pub type OperandBundleDefRef = *mut OperandBundleDef_opaque; -#[allow(missing_copy_implementations)] -pub enum Linker_opaque {} -pub type LinkerRef = *mut Linker_opaque; - -pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void); -pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint); - - -pub mod debuginfo { - use super::MetadataRef; - - #[allow(missing_copy_implementations)] - pub enum DIBuilder_opaque {} - pub type DIBuilderRef = *mut DIBuilder_opaque; - - pub type DIDescriptor = MetadataRef; - pub type DIScope = DIDescriptor; - pub type DILocation = DIDescriptor; - pub type DIFile = DIScope; - pub type DILexicalBlock = DIScope; - pub type DISubprogram = DIScope; - pub type DINameSpace = DIScope; - pub type DIType = DIDescriptor; - pub type DIBasicType = DIType; - pub type DIDerivedType = DIType; - pub type DICompositeType = DIDerivedType; - pub type DIVariable = DIDescriptor; - pub type DIGlobalVariable = DIDescriptor; - pub type DIArray = DIDescriptor; - pub type DISubrange = DIDescriptor; - pub type DIEnumerator = DIDescriptor; - pub type DITemplateTypeParameter = DIDescriptor; - - // These values **must** match with LLVMRustDIFlags!! - bitflags! { - #[repr(C)] - #[derive(Default)] - pub struct DIFlags: ::libc::uint32_t { - const FlagZero = 0; - const FlagPrivate = 1; - const FlagProtected = 2; - const FlagPublic = 3; - const FlagFwdDecl = (1 << 2); - const FlagAppleBlock = (1 << 3); - const FlagBlockByrefStruct = (1 << 4); - const FlagVirtual = (1 << 5); - const FlagArtificial = (1 << 6); - const FlagExplicit = (1 << 7); - const FlagPrototyped = (1 << 8); - const FlagObjcClassComplete = (1 << 9); - const FlagObjectPointer = (1 << 10); - const FlagVector = (1 << 11); - const FlagStaticMember = (1 << 12); - const FlagLValueReference = (1 << 13); - const FlagRValueReference = (1 << 14); - const FlagExternalTypeRef = (1 << 15); - const FlagIntroducedVirtual = (1 << 18); - const FlagBitField = (1 << 19); - const FlagNoReturn = (1 << 20); - const FlagMainSubprogram = (1 << 21); - } - } -} - -pub enum ModuleBuffer {} - -// This annotation is primarily needed for MSVC where attributes like -// dllimport/dllexport are applied and need to be correct for everything to -// link successfully. The #[link] annotation here says "these symbols are -// included statically" which means that they're all exported with dllexport -// and from the rustc_llvm dynamic library. Otherwise the rustc_codegen_llvm dynamic -// library would not be able to access these symbols. -#[link(name = "rustllvm", kind = "static")] -extern "C" { - // Create and destroy contexts. - pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> ContextRef; - pub fn LLVMContextDispose(C: ContextRef); - pub fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *const c_char, SLen: c_uint) -> c_uint; - - // Create and destroy modules. - pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: ContextRef) -> ModuleRef; - pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef; - pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef; - pub fn LLVMDisposeModule(M: ModuleRef); - - /// Data layout. See Module::getDataLayout. - pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char; - pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char); - - /// See Module::dump. - pub fn LLVMDumpModule(M: ModuleRef); - - /// See Module::setModuleInlineAsm. - pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char); - pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char); - - /// See llvm::LLVMTypeKind::getTypeID. - pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind; - - // Operations on integer types - pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef; - - pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint; - - // Operations on real types - pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef; - - // Operations on function types - pub fn LLVMFunctionType(ReturnType: TypeRef, - ParamTypes: *const TypeRef, - ParamCount: c_uint, - IsVarArg: Bool) - -> TypeRef; - pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef; - pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint; - pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef); - - // Operations on struct types - pub fn LLVMStructTypeInContext(C: ContextRef, - ElementTypes: *const TypeRef, - ElementCount: c_uint, - Packed: Bool) - -> TypeRef; - pub fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool; - - // Operations on array, pointer, and vector types (sequence types) - pub fn LLVMRustArrayType(ElementType: TypeRef, ElementCount: u64) -> TypeRef; - pub fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint) -> TypeRef; - pub fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint) -> TypeRef; - - pub fn LLVMGetElementType(Ty: TypeRef) -> TypeRef; - pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint; - - // Operations on other types - pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMX86MMXTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMRustMetadataTypeInContext(C: ContextRef) -> TypeRef; - - // Operations on all values - pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef; - pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char; - pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char); - pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef); - pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef); - - // Operations on Uses - pub fn LLVMGetFirstUse(Val: ValueRef) -> UseRef; - pub fn LLVMGetNextUse(U: UseRef) -> UseRef; - pub fn LLVMGetUser(U: UseRef) -> ValueRef; - - // Operations on Users - pub fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef; - - // Operations on constants of any type - pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef; - pub fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; - pub fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; - pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; - - // Operations on metadata - pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef; - pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef; - pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef); - - // Operations on scalar constants - pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef; - pub fn LLVMConstIntOfArbitraryPrecision(IntTy: TypeRef, Wn: c_uint, Ws: *const u64) -> ValueRef; - pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong; - pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong; - pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool, - high: *mut u64, low: *mut u64) -> bool; - pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64; - - - // Operations on composite constants - pub fn LLVMConstStringInContext(C: ContextRef, - Str: *const c_char, - Length: c_uint, - DontNullTerminate: Bool) - -> ValueRef; - pub fn LLVMConstStructInContext(C: ContextRef, - ConstantVals: *const ValueRef, - Count: c_uint, - Packed: Bool) - -> ValueRef; - - pub fn LLVMConstArray(ElementTy: TypeRef, - ConstantVals: *const ValueRef, - Length: c_uint) - -> ValueRef; - pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint) -> ValueRef; - - // Constant expressions - pub fn LLVMSizeOf(Ty: TypeRef) -> ValueRef; - pub fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef; - pub fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef; - pub fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef; - pub fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstGEP( - ConstantVal: ValueRef, - ConstantIndices: *const ValueRef, - NumIndices: c_uint, - ) -> ValueRef; - pub fn LLVMConstInBoundsGEP( - ConstantVal: ValueRef, - ConstantIndices: *const ValueRef, - NumIndices: c_uint, - ) -> ValueRef; - pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstIntCast(ConstantVal: ValueRef, ToType: TypeRef, isSigned: Bool) -> ValueRef; - pub fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstExtractValue(AggConstant: ValueRef, - IdxList: *const c_uint, - NumIdx: c_uint) - -> ValueRef; - pub fn LLVMConstInlineAsm(Ty: TypeRef, - AsmString: *const c_char, - Constraints: *const c_char, - HasSideEffects: Bool, - IsAlignStack: Bool) - -> ValueRef; - - - // Operations on global variables, functions, and aliases (globals) - pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef; - pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool; - pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage; - pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage); - pub fn LLVMGetSection(Global: ValueRef) -> *const c_char; - pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char); - pub fn LLVMRustGetVisibility(Global: ValueRef) -> Visibility; - pub fn LLVMRustSetVisibility(Global: ValueRef, Viz: Visibility); - pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint; - pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint); - pub fn LLVMSetDLLStorageClass(V: ValueRef, C: DLLStorageClass); - - - // Operations on global variables - pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef; - pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; - pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef; - pub fn LLVMRustGetOrInsertGlobal(M: ModuleRef, Name: *const c_char, T: TypeRef) -> ValueRef; - pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef; - pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef; - pub fn LLVMDeleteGlobal(GlobalVar: ValueRef); - pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef; - pub fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef); - pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool); - pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode); - pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool; - pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool); - pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef; - pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool); - - // Operations on functions - pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; - pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef; - pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef; - pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef; - pub fn LLVMRustGetOrInsertFunction(M: ModuleRef, - Name: *const c_char, - FunctionTy: TypeRef) - -> ValueRef; - pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint); - pub fn LLVMRustAddAlignmentAttr(Fn: ValueRef, index: c_uint, bytes: u32); - pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64); - pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: ValueRef, index: c_uint, bytes: u64); - pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, attr: Attribute); - pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef, - index: c_uint, - Name: *const c_char, - Value: *const c_char); - pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: Attribute); - - // Operations on parameters - pub fn LLVMCountParams(Fn: ValueRef) -> c_uint; - pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef; - - // Operations on basic blocks - pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef; - pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef; - pub fn LLVMAppendBasicBlockInContext(C: ContextRef, - Fn: ValueRef, - Name: *const c_char) - -> BasicBlockRef; - pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef); - - // Operations on instructions - pub fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef; - pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef; - pub fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef; - pub fn LLVMInstructionEraseFromParent(Inst: ValueRef); - - // Operations on call sites - pub fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint); - pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef, index: c_uint, attr: Attribute); - pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u32); - pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u64); - pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: ValueRef, - index: c_uint, - bytes: u64); - - // Operations on load/store instructions (only) - pub fn LLVMSetVolatile(MemoryAccessInst: ValueRef, volatile: Bool); - - // Operations on phi nodes - pub fn LLVMAddIncoming(PhiNode: ValueRef, - IncomingValues: *const ValueRef, - IncomingBlocks: *const BasicBlockRef, - Count: c_uint); - - // Instruction builders - pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef; - pub fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef); - pub fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef); - pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef); - pub fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef; - pub fn LLVMDisposeBuilder(Builder: BuilderRef); - - // Metadata - pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef); - pub fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef; - pub fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef); - - // Terminators - pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef; - pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef; - pub fn LLVMBuildAggregateRet(B: BuilderRef, RetVals: *const ValueRef, N: c_uint) -> ValueRef; - pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef; - pub fn LLVMBuildCondBr(B: BuilderRef, - If: ValueRef, - Then: BasicBlockRef, - Else: BasicBlockRef) - -> ValueRef; - pub fn LLVMBuildSwitch(B: BuilderRef, - V: ValueRef, - Else: BasicBlockRef, - NumCases: c_uint) - -> ValueRef; - pub fn LLVMBuildIndirectBr(B: BuilderRef, Addr: ValueRef, NumDests: c_uint) -> ValueRef; - pub fn LLVMRustBuildInvoke(B: BuilderRef, - Fn: ValueRef, - Args: *const ValueRef, - NumArgs: c_uint, - Then: BasicBlockRef, - Catch: BasicBlockRef, - Bundle: OperandBundleDefRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildLandingPad(B: BuilderRef, - Ty: TypeRef, - PersFn: ValueRef, - NumClauses: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef; - pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef; - - pub fn LLVMRustBuildCleanupPad(B: BuilderRef, - ParentPad: ValueRef, - ArgCnt: c_uint, - Args: *const ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMRustBuildCleanupRet(B: BuilderRef, - CleanupPad: ValueRef, - UnwindBB: BasicBlockRef) - -> ValueRef; - pub fn LLVMRustBuildCatchPad(B: BuilderRef, - ParentPad: ValueRef, - ArgCnt: c_uint, - Args: *const ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMRustBuildCatchRet(B: BuilderRef, Pad: ValueRef, BB: BasicBlockRef) -> ValueRef; - pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef, - ParentPad: ValueRef, - BB: BasicBlockRef, - NumHandlers: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMRustAddHandler(CatchSwitch: ValueRef, Handler: BasicBlockRef); - pub fn LLVMSetPersonalityFn(Func: ValueRef, Pers: ValueRef); - - // Add a case to the switch instruction - pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef); - - // Add a clause to the landing pad instruction - pub fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef); - - // Set the cleanup on a landing pad instruction - pub fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool); - - // Arithmetic - pub fn LLVMBuildAdd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNSWAdd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNUWAdd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFAdd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSub(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNSWSub(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNUWSub(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFSub(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildMul(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNSWMul(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNUWMul(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFMul(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildUDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildExactUDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildExactSDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildURem(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSRem(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFRem(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildShl(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildLShr(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildAShr(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildAnd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildOr(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildXor(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildBinOp(B: BuilderRef, - Op: Opcode, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMRustSetHasUnsafeAlgebra(Instr: ValueRef); - - // Memory - pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef; - pub fn LLVMBuildLoad(B: BuilderRef, PointerVal: ValueRef, Name: *const c_char) -> ValueRef; - - pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) -> ValueRef; - - pub fn LLVMBuildGEP(B: BuilderRef, - Pointer: ValueRef, - Indices: *const ValueRef, - NumIndices: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildInBoundsGEP(B: BuilderRef, - Pointer: ValueRef, - Indices: *const ValueRef, - NumIndices: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildStructGEP(B: BuilderRef, - Pointer: ValueRef, - Idx: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildGlobalString(B: BuilderRef, - Str: *const c_char, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildGlobalStringPtr(B: BuilderRef, - Str: *const c_char, - Name: *const c_char) - -> ValueRef; - - // Casts - pub fn LLVMBuildTrunc(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildZExt(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSExt(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFPToUI(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFPToSI(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildUIToFP(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSIToFP(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFPTrunc(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFPExt(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildPtrToInt(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildIntToPtr(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildBitCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildZExtOrBitCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSExtOrBitCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildTruncOrBitCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildCast(B: BuilderRef, - Op: Opcode, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildPointerCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMRustBuildIntCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - IsSized: bool) - -> ValueRef; - pub fn LLVMBuildFPCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - - // Comparisons - pub fn LLVMBuildICmp(B: BuilderRef, - Op: c_uint, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFCmp(B: BuilderRef, - Op: c_uint, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - - // Miscellaneous instructions - pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; - pub fn LLVMRustBuildCall(B: BuilderRef, - Fn: ValueRef, - Args: *const ValueRef, - NumArgs: c_uint, - Bundle: OperandBundleDefRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSelect(B: BuilderRef, - If: ValueRef, - Then: ValueRef, - Else: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildVAArg(B: BuilderRef, - list: ValueRef, - Ty: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildExtractElement(B: BuilderRef, - VecVal: ValueRef, - Index: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildInsertElement(B: BuilderRef, - VecVal: ValueRef, - EltVal: ValueRef, - Index: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildShuffleVector(B: BuilderRef, - V1: ValueRef, - V2: ValueRef, - Mask: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildExtractValue(B: BuilderRef, - AggVal: ValueRef, - Index: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildInsertValue(B: BuilderRef, - AggVal: ValueRef, - EltVal: ValueRef, - Index: c_uint, - Name: *const c_char) - -> ValueRef; - - pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef, - Acc: ValueRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef, - Acc: ValueRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef, - Src: ValueRef, - IsSigned: bool) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef, - Src: ValueRef, - IsSigned: bool) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef, - Src: ValueRef, - IsNaN: bool) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef, - Src: ValueRef, - IsNaN: bool) - -> ValueRef; - - pub fn LLVMRustBuildMinNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef; - pub fn LLVMRustBuildMaxNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef; - - pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildPtrDiff(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - - // Atomic Operations - pub fn LLVMRustBuildAtomicLoad(B: BuilderRef, - PointerVal: ValueRef, - Name: *const c_char, - Order: AtomicOrdering) - -> ValueRef; - - pub fn LLVMRustBuildAtomicStore(B: BuilderRef, - Val: ValueRef, - Ptr: ValueRef, - Order: AtomicOrdering) - -> ValueRef; - - pub fn LLVMRustBuildAtomicCmpXchg(B: BuilderRef, - LHS: ValueRef, - CMP: ValueRef, - RHS: ValueRef, - Order: AtomicOrdering, - FailureOrder: AtomicOrdering, - Weak: Bool) - -> ValueRef; - - pub fn LLVMBuildAtomicRMW(B: BuilderRef, - Op: AtomicRmwBinOp, - LHS: ValueRef, - RHS: ValueRef, - Order: AtomicOrdering, - SingleThreaded: Bool) - -> ValueRef; - - pub fn LLVMRustBuildAtomicFence(B: BuilderRef, - Order: AtomicOrdering, - Scope: SynchronizationScope); - - - // Selected entries from the downcasts. - pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef; - pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef; - - /// Writes a module to the specified path. Returns 0 on success. - pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int; - - /// Creates target data from a target layout string. - pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef; - - /// Disposes target data. - pub fn LLVMDisposeTargetData(TD: TargetDataRef); - - /// Creates a pass manager. - pub fn LLVMCreatePassManager() -> PassManagerRef; - - /// Creates a function-by-function pass manager - pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef) -> PassManagerRef; - - /// Disposes a pass manager. - pub fn LLVMDisposePassManager(PM: PassManagerRef); - - /// Runs a pass manager on a module. - pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool; - - pub fn LLVMInitializePasses(); - - pub fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef; - pub fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef); - pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef, Value: Bool); - pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: PassManagerBuilderRef, Value: Bool); - pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: PassManagerBuilderRef, - threshold: c_uint); - pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: PassManagerBuilderRef, - PM: PassManagerRef); - - pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: PassManagerBuilderRef, - PM: PassManagerRef); - pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: PassManagerBuilderRef, - PM: PassManagerRef, - Internalize: Bool, - RunInliner: Bool); - pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( - PMB: PassManagerBuilderRef, - PM: PassManagerRef) -> bool; - - // Stuff that's in rustllvm/ because it's not upstream yet. - - /// Opens an object file. - pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef; - /// Closes an object file. - pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef); - - /// Enumerates the sections in an object file. - pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef; - /// Destroys a section iterator. - pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef); - /// Returns true if the section iterator is at the end of the section - /// list: - pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef, SI: SectionIteratorRef) -> Bool; - /// Moves the section iterator to point to the next section. - pub fn LLVMMoveToNextSection(SI: SectionIteratorRef); - /// Returns the current section size. - pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong; - /// Returns the current section contents as a string buffer. - pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char; - - /// Reads the given file and returns it as a memory buffer. Use - /// LLVMDisposeMemoryBuffer() to get rid of it. - pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char) -> MemoryBufferRef; - - pub fn LLVMStartMultithreaded() -> Bool; - - /// Returns a string describing the last error caused by an LLVMRust* call. - pub fn LLVMRustGetLastError() -> *const c_char; - - /// Print the pass timings since static dtors aren't picking them up. - pub fn LLVMRustPrintPassTimings(); - - pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef; - - pub fn LLVMStructSetBody(StructTy: TypeRef, - ElementTypes: *const TypeRef, - ElementCount: c_uint, - Packed: Bool); - - /// Prepares inline assembly. - pub fn LLVMRustInlineAsm(Ty: TypeRef, - AsmString: *const c_char, - Constraints: *const c_char, - SideEffects: Bool, - AlignStack: Bool, - Dialect: AsmDialect) - -> ValueRef; - - pub fn LLVMRustDebugMetadataVersion() -> u32; - pub fn LLVMRustVersionMajor() -> u32; - pub fn LLVMRustVersionMinor() -> u32; - - pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32); - - pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef; - - pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef; - - pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef); - - pub fn LLVMRustDIBuilderFinalize(Builder: DIBuilderRef); - - pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: DIBuilderRef, - Lang: c_uint, - File: DIFile, - Producer: *const c_char, - isOptimized: bool, - Flags: *const c_char, - RuntimeVer: c_uint, - SplitName: *const c_char) - -> DIDescriptor; - - pub fn LLVMRustDIBuilderCreateFile(Builder: DIBuilderRef, - Filename: *const c_char, - Directory: *const c_char) - -> DIFile; - - pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: DIBuilderRef, - File: DIFile, - ParameterTypes: DIArray) - -> DICompositeType; - - pub fn LLVMRustDIBuilderCreateFunction(Builder: DIBuilderRef, - Scope: DIDescriptor, - Name: *const c_char, - LinkageName: *const c_char, - File: DIFile, - LineNo: c_uint, - Ty: DIType, - isLocalToUnit: bool, - isDefinition: bool, - ScopeLine: c_uint, - Flags: DIFlags, - isOptimized: bool, - Fn: ValueRef, - TParam: DIArray, - Decl: DIDescriptor) - -> DISubprogram; - - pub fn LLVMRustDIBuilderCreateBasicType(Builder: DIBuilderRef, - Name: *const c_char, - SizeInBits: u64, - AlignInBits: u32, - Encoding: c_uint) - -> DIBasicType; - - pub fn LLVMRustDIBuilderCreatePointerType(Builder: DIBuilderRef, - PointeeTy: DIType, - SizeInBits: u64, - AlignInBits: u32, - Name: *const c_char) - -> DIDerivedType; - - pub fn LLVMRustDIBuilderCreateStructType(Builder: DIBuilderRef, - Scope: DIDescriptor, - Name: *const c_char, - File: DIFile, - LineNumber: c_uint, - SizeInBits: u64, - AlignInBits: u32, - Flags: DIFlags, - DerivedFrom: DIType, - Elements: DIArray, - RunTimeLang: c_uint, - VTableHolder: DIType, - UniqueId: *const c_char) - -> DICompositeType; - - pub fn LLVMRustDIBuilderCreateMemberType(Builder: DIBuilderRef, - Scope: DIDescriptor, - Name: *const c_char, - File: DIFile, - LineNo: c_uint, - SizeInBits: u64, - AlignInBits: u32, - OffsetInBits: u64, - Flags: DIFlags, - Ty: DIType) - -> DIDerivedType; - - pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: DIBuilderRef, - Scope: DIScope, - File: DIFile, - Line: c_uint, - Col: c_uint) - -> DILexicalBlock; - - pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: DIBuilderRef, - Scope: DIScope, - File: DIFile) - -> DILexicalBlock; - - pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: DIBuilderRef, - Context: DIScope, - Name: *const c_char, - LinkageName: *const c_char, - File: DIFile, - LineNo: c_uint, - Ty: DIType, - isLocalToUnit: bool, - Val: ValueRef, - Decl: DIDescriptor, - AlignInBits: u32) - -> DIGlobalVariable; - - pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef, - Tag: c_uint, - Scope: DIDescriptor, - Name: *const c_char, - File: DIFile, - LineNo: c_uint, - Ty: DIType, - AlwaysPreserve: bool, - Flags: DIFlags, - ArgNo: c_uint, - AlignInBits: u32) - -> DIVariable; - - pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef, - Size: u64, - AlignInBits: u32, - Ty: DIType, - Subscripts: DIArray) - -> DIType; - - pub fn LLVMRustDIBuilderCreateVectorType(Builder: DIBuilderRef, - Size: u64, - AlignInBits: u32, - Ty: DIType, - Subscripts: DIArray) - -> DIType; - - pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: DIBuilderRef, - Lo: i64, - Count: i64) - -> DISubrange; - - pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: DIBuilderRef, - Ptr: *const DIDescriptor, - Count: c_uint) - -> DIArray; - - pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef, - Val: ValueRef, - VarInfo: DIVariable, - AddrOps: *const i64, - AddrOpsCount: c_uint, - DL: ValueRef, - InsertAtEnd: BasicBlockRef) - -> ValueRef; - - pub fn LLVMRustDIBuilderCreateEnumerator(Builder: DIBuilderRef, - Name: *const c_char, - Val: u64) - -> DIEnumerator; - - pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: DIBuilderRef, - Scope: DIScope, - Name: *const c_char, - File: DIFile, - LineNumber: c_uint, - SizeInBits: u64, - AlignInBits: u32, - Elements: DIArray, - ClassType: DIType) - -> DIType; - - pub fn LLVMRustDIBuilderCreateUnionType(Builder: DIBuilderRef, - Scope: DIScope, - Name: *const c_char, - File: DIFile, - LineNumber: c_uint, - SizeInBits: u64, - AlignInBits: u32, - Flags: DIFlags, - Elements: DIArray, - RunTimeLang: c_uint, - UniqueId: *const c_char) - -> DIType; - - pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool); - - pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef, - Scope: DIScope, - Name: *const c_char, - Ty: DIType, - File: DIFile, - LineNo: c_uint, - ColumnNo: c_uint) - -> DITemplateTypeParameter; - - - pub fn LLVMRustDIBuilderCreateNameSpace(Builder: DIBuilderRef, - Scope: DIScope, - Name: *const c_char, - File: DIFile, - LineNo: c_uint) - -> DINameSpace; - pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: DIBuilderRef, - CompositeType: DIType, - TypeArray: DIArray); - - - pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef, - Line: c_uint, - Column: c_uint, - Scope: DIScope, - InlinedAt: MetadataRef) - -> ValueRef; - pub fn LLVMRustDIBuilderCreateOpDeref() -> i64; - pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64; - - pub fn LLVMRustWriteTypeToString(Type: TypeRef, s: RustStringRef); - pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef); - - pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef; - pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef; - - pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind; - pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef; - pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef); - - pub fn LLVMRustHasFeature(T: TargetMachineRef, s: *const c_char) -> bool; - - pub fn LLVMRustPrintTargetCPUs(T: TargetMachineRef); - pub fn LLVMRustPrintTargetFeatures(T: TargetMachineRef); - - pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, - CPU: *const c_char, - Features: *const c_char, - Model: CodeModel, - Reloc: RelocMode, - Level: CodeGenOptLevel, - UseSoftFP: bool, - PositionIndependentExecutable: bool, - FunctionSections: bool, - DataSections: bool, - TrapUnreachable: bool, - Singlethread: bool) - -> TargetMachineRef; - pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef); - pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef); - pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef, - M: ModuleRef, - DisableSimplifyLibCalls: bool); - pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef, - OptLevel: CodeGenOptLevel, - MergeFunctions: bool, - SLPVectorize: bool, - LoopVectorize: bool, - PrepareForThinLTO: bool, - PGOGenPath: *const c_char, - PGOUsePath: *const c_char); - pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, - M: ModuleRef, - DisableSimplifyLibCalls: bool); - pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef); - pub fn LLVMRustWriteOutputFile(T: TargetMachineRef, - PM: PassManagerRef, - M: ModuleRef, - Output: *const c_char, - FileType: FileType) - -> LLVMRustResult; - pub fn LLVMRustPrintModule(PM: PassManagerRef, - M: ModuleRef, - Output: *const c_char, - Demangle: extern fn(*const c_char, - size_t, - *mut c_char, - size_t) -> size_t); - pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); - pub fn LLVMRustPrintPasses(); - pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char); - pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool); - pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t); - pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef); - - pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef; - pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef; - pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef) -> ArchiveChildRef; - pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef, size: *mut size_t) -> *const c_char; - pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef, size: *mut size_t) -> *const c_char; - pub fn LLVMRustArchiveChildFree(ACR: ArchiveChildRef); - pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef); - pub fn LLVMRustDestroyArchive(AR: ArchiveRef); - - pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, data: *mut *const c_char) -> size_t; - - pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef); - - pub fn LLVMContextSetDiagnosticHandler(C: ContextRef, - Handler: DiagnosticHandler, - DiagnosticContext: *mut c_void); - - pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef, - pass_name_out: RustStringRef, - function_out: *mut ValueRef, - loc_line_out: *mut c_uint, - loc_column_out: *mut c_uint, - loc_filename_out: RustStringRef, - message_out: RustStringRef); - pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef, - cookie_out: *mut c_uint, - message_out: *mut TwineRef, - instruction_out: *mut ValueRef); - - pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef); - pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind; - - pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef, - H: InlineAsmDiagHandler, - CX: *mut c_void); - - pub fn LLVMRustWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef); - - pub fn LLVMRustWriteArchive(Dst: *const c_char, - NumMembers: size_t, - Members: *const RustArchiveMemberRef, - WriteSymbtab: bool, - Kind: ArchiveKind) - -> LLVMRustResult; - pub fn LLVMRustArchiveMemberNew(Filename: *const c_char, - Name: *const c_char, - Child: ArchiveChildRef) - -> RustArchiveMemberRef; - pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef); - - pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef, TM: TargetMachineRef); - - pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char, - Inputs: *const ValueRef, - NumInputs: c_uint) - -> OperandBundleDefRef; - pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef); - - pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef); - - pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char); - pub fn LLVMRustUnsetComdat(V: ValueRef); - pub fn LLVMRustSetModulePIELevel(M: ModuleRef); - pub fn LLVMRustModuleBufferCreate(M: ModuleRef) -> *mut ModuleBuffer; - pub fn LLVMRustModuleBufferPtr(p: *const ModuleBuffer) -> *const u8; - pub fn LLVMRustModuleBufferLen(p: *const ModuleBuffer) -> usize; - pub fn LLVMRustModuleBufferFree(p: *mut ModuleBuffer); - pub fn LLVMRustModuleCost(M: ModuleRef) -> u64; - - pub fn LLVMRustThinLTOAvailable() -> bool; - pub fn LLVMRustPGOAvailable() -> bool; - pub fn LLVMRustWriteThinBitcodeToFile(PMR: PassManagerRef, - M: ModuleRef, - BC: *const c_char) -> bool; - pub fn LLVMRustThinLTOBufferCreate(M: ModuleRef) -> *mut ThinLTOBuffer; - pub fn LLVMRustThinLTOBufferFree(M: *mut ThinLTOBuffer); - pub fn LLVMRustThinLTOBufferPtr(M: *const ThinLTOBuffer) -> *const c_char; - pub fn LLVMRustThinLTOBufferLen(M: *const ThinLTOBuffer) -> size_t; - pub fn LLVMRustCreateThinLTOData( - Modules: *const ThinLTOModule, - NumModules: c_uint, - PreservedSymbols: *const *const c_char, - PreservedSymbolsLen: c_uint, - ) -> *mut ThinLTOData; - pub fn LLVMRustPrepareThinLTORename( - Data: *const ThinLTOData, - Module: ModuleRef, - ) -> bool; - pub fn LLVMRustPrepareThinLTOResolveWeak( - Data: *const ThinLTOData, - Module: ModuleRef, - ) -> bool; - pub fn LLVMRustPrepareThinLTOInternalize( - Data: *const ThinLTOData, - Module: ModuleRef, - ) -> bool; - pub fn LLVMRustPrepareThinLTOImport( - Data: *const ThinLTOData, - Module: ModuleRef, - ) -> bool; - pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData); - pub fn LLVMRustParseBitcodeForThinLTO( - Context: ContextRef, - Data: *const u8, - len: usize, - Identifier: *const c_char, - ) -> ModuleRef; - pub fn LLVMGetModuleIdentifier(M: ModuleRef, size: *mut usize) -> *const c_char; - pub fn LLVMRustThinLTOGetDICompileUnit(M: ModuleRef, - CU1: *mut *mut c_void, - CU2: *mut *mut c_void); - pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void); - - pub fn LLVMRustLinkerNew(M: ModuleRef) -> LinkerRef; - pub fn LLVMRustLinkerAdd(linker: LinkerRef, - bytecode: *const c_char, - bytecode_len: usize) -> bool; - pub fn LLVMRustLinkerFree(linker: LinkerRef); -} diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 91f9b4ac03..387660473a 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -8,290 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(dead_code)] +#![cfg_attr(not(stage0), feature(nll))] +#![feature(static_nobundle)] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(box_syntax)] -#![feature(concat_idents)] -#![feature(libc)] -#![feature(link_args)] -#![feature(static_nobundle)] - // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] extern crate rustc_cratesio_shim; -#[macro_use] -extern crate bitflags; -extern crate libc; - -pub use self::IntPredicate::*; -pub use self::RealPredicate::*; -pub use self::TypeKind::*; -pub use self::AtomicRmwBinOp::*; -pub use self::MetadataType::*; -pub use self::CodeGenOptSize::*; -pub use self::CallConv::*; -pub use self::Linkage::*; - -use std::str::FromStr; -use std::slice; -use std::ffi::{CString, CStr}; -use std::cell::RefCell; -use libc::{c_uint, c_char, size_t}; - -pub mod archive_ro; -pub mod diagnostic; -mod ffi; - -pub use ffi::*; - -impl LLVMRustResult { - pub fn into_result(self) -> Result<(), ()> { - match self { - LLVMRustResult::Success => Ok(()), - LLVMRustResult::Failure => Err(()), - } - } -} - -pub fn AddFunctionAttrStringValue(llfn: ValueRef, - idx: AttributePlace, - attr: &CStr, - value: &CStr) { - unsafe { - LLVMRustAddFunctionAttrStringValue(llfn, - idx.as_uint(), - attr.as_ptr(), - value.as_ptr()) - } -} - -#[derive(Copy, Clone)] -pub enum AttributePlace { - ReturnValue, - Argument(u32), - Function, -} - -impl AttributePlace { - pub fn as_uint(self) -> c_uint { - match self { - AttributePlace::ReturnValue => 0, - AttributePlace::Argument(i) => 1 + i, - AttributePlace::Function => !0, - } - } -} - -#[derive(Copy, Clone, PartialEq)] -#[repr(C)] -pub enum CodeGenOptSize { - CodeGenOptSizeNone = 0, - CodeGenOptSizeDefault = 1, - CodeGenOptSizeAggressive = 2, -} - -impl FromStr for ArchiveKind { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - "gnu" => Ok(ArchiveKind::K_GNU), - "bsd" => Ok(ArchiveKind::K_BSD), - "coff" => Ok(ArchiveKind::K_COFF), - _ => Err(()), - } - } -} - -#[allow(missing_copy_implementations)] -pub enum RustString_opaque {} -type RustStringRef = *mut RustString_opaque; -type RustStringRepr = *mut RefCell>; - -/// Appending to a Rust string -- used by RawRustStringOstream. -#[no_mangle] -pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef, - ptr: *const c_char, - size: size_t) { - let slice = slice::from_raw_parts(ptr as *const u8, size as usize); - - let sr = sr as RustStringRepr; - (*sr).borrow_mut().extend_from_slice(slice); -} - -pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) { - unsafe { - LLVMSetInstructionCallConv(instr, cc as c_uint); - } -} -pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) { - unsafe { - LLVMSetFunctionCallConv(fn_, cc as c_uint); - } -} - -// Externally visible symbols that might appear in multiple codegen units need to appear in -// their own comdat section so that the duplicates can be discarded at link time. This can for -// example happen for generics when using multiple codegen units. This function simply uses the -// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the -// function. -// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52 -pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) { - unsafe { - LLVMRustSetComdat(llmod, val, LLVMGetValueName(val)); - } -} - -pub fn UnsetComdat(val: ValueRef) { - unsafe { - LLVMRustUnsetComdat(val); - } -} - -pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) { - unsafe { - LLVMSetUnnamedAddr(global, unnamed as Bool); - } -} - -pub fn set_thread_local(global: ValueRef, is_thread_local: bool) { - unsafe { - LLVMSetThreadLocal(global, is_thread_local as Bool); - } -} -pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) { - unsafe { - LLVMSetThreadLocalMode(global, mode); - } -} - -impl Attribute { - pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { - unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) } - } - - pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { - unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) } - } - - pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { - unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) } - } - - pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) { - if set { - self.apply_llfn(idx, llfn); - } else { - self.unapply_llfn(idx, llfn); - } - } -} - -// Memory-managed interface to target data. - -struct TargetData { - lltd: TargetDataRef, -} - -impl Drop for TargetData { - fn drop(&mut self) { - unsafe { - LLVMDisposeTargetData(self.lltd); - } - } -} - -fn mk_target_data(string_rep: &str) -> TargetData { - let string_rep = CString::new(string_rep).unwrap(); - TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } } -} - -// Memory-managed interface to object files. - -pub struct ObjectFile { - pub llof: ObjectFileRef, -} - -unsafe impl Send for ObjectFile {} - -impl ObjectFile { - // This will take ownership of llmb - pub fn new(llmb: MemoryBufferRef) -> Option { - unsafe { - let llof = LLVMCreateObjectFile(llmb); - if llof as isize == 0 { - // LLVMCreateObjectFile took ownership of llmb - return None; - } - - Some(ObjectFile { llof: llof }) - } - } -} - -impl Drop for ObjectFile { - fn drop(&mut self) { - unsafe { - LLVMDisposeObjectFile(self.llof); - } - } -} - -// Memory-managed interface to section iterators. - -pub struct SectionIter { - pub llsi: SectionIteratorRef, -} - -impl Drop for SectionIter { - fn drop(&mut self) { - unsafe { - LLVMDisposeSectionIterator(self.llsi); - } - } -} - -pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter { - unsafe { SectionIter { llsi: LLVMGetSections(llof) } } -} - -/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun. -pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef { - unsafe { - assert!(index < LLVMCountParams(llfn), - "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn)); - LLVMGetParam(llfn, index) - } -} - -fn get_params(llfn: ValueRef) -> Vec { - unsafe { - let num_params = LLVMCountParams(llfn); - - (0..num_params).map(|idx| LLVMGetParam(llfn, idx)).collect() - } -} - -pub fn build_string(f: F) -> Option - where F: FnOnce(RustStringRef) -{ - let mut buf = RefCell::new(Vec::new()); - f(&mut buf as RustStringRepr as RustStringRef); - String::from_utf8(buf.into_inner()).ok() -} - -pub unsafe fn twine_to_string(tr: TwineRef) -> String { - build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM") -} +// NOTE: This crate only exists to allow linking on mingw targets. +/// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`. +/// NB: this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s. pub fn initialize_available_targets() { macro_rules! init_target( ($cfg:meta, $($method:ident),*) => { { @@ -360,6 +91,12 @@ pub fn initialize_available_targets() { LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetMC, LLVMInitializeMSP430AsmPrinter); + init_target!(llvm_component = "riscv", + LLVMInitializeRISCVTargetInfo, + LLVMInitializeRISCVTarget, + LLVMInitializeRISCVTargetMC, + LLVMInitializeRISCVAsmPrinter, + LLVMInitializeRISCVAsmParser); init_target!(llvm_component = "sparc", LLVMInitializeSparcTargetInfo, LLVMInitializeSparcTarget, @@ -383,43 +120,3 @@ pub fn initialize_available_targets() { LLVMInitializeWebAssemblyTargetMC, LLVMInitializeWebAssemblyAsmPrinter); } - -pub fn last_error() -> Option { - unsafe { - let cstr = LLVMRustGetLastError(); - if cstr.is_null() { - None - } else { - let err = CStr::from_ptr(cstr).to_bytes(); - let err = String::from_utf8_lossy(err).to_string(); - libc::free(cstr as *mut _); - Some(err) - } - } -} - -pub struct OperandBundleDef { - inner: OperandBundleDefRef, -} - -impl OperandBundleDef { - pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef { - let name = CString::new(name).unwrap(); - let def = unsafe { - LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint) - }; - OperandBundleDef { inner: def } - } - - pub fn raw(&self) -> OperandBundleDefRef { - self.inner - } -} - -impl Drop for OperandBundleDef { - fn drop(&mut self) { - unsafe { - LLVMRustFreeOperandBundleDef(self.inner); - } - } -} diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs index 0c78fd74a2..b3ba86ad8a 100644 --- a/src/librustc_lsan/lib.rs +++ b/src/librustc_lsan/lib.rs @@ -10,6 +10,7 @@ #![sanitizer_runtime] #![feature(alloc_system)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 338824d5ef..6142fe7814 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -20,3 +20,4 @@ serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } +rustc_metadata_utils = { path = "../librustc_metadata_utils" } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 4f808dee61..6eef2397f9 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -12,11 +12,12 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use locator::{self, CratePaths}; +use decoder::proc_macro_def_path_table; use schema::CrateRoot; use rustc_data_structures::sync::{Lrc, RwLock, Lock}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX}; -use rustc::hir::svh::Svh; +use rustc_data_structures::svh::Svh; use rustc::middle::allocator::AllocatorKind; use rustc::middle::cstore::DepKind; use rustc::mir::interpret::AllocDecodingState; @@ -24,12 +25,13 @@ use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; -use rustc::middle; -use rustc::middle::cstore::{validate_crate_name, ExternCrate, ExternCrateSource}; +use rustc::middle::cstore::{ExternCrate, ExternCrateSource}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; +use rustc_metadata_utils::validate_crate_name; + use std::ops::Deref; use std::path::PathBuf; use std::{cmp, fs}; @@ -98,6 +100,18 @@ enum LoadResult { Loaded(Library), } +enum LoadError<'a> { + LocatorError(locator::Context<'a>), +} + +impl<'a> LoadError<'a> { + fn report(self) -> ! { + match self { + LoadError::LocatorError(mut locate_ctxt) => locate_ctxt.report_errs(), + } + } +} + impl<'a> CrateLoader<'a> { pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { CrateLoader { @@ -130,7 +144,8 @@ impl<'a> CrateLoader<'a> { // from the strings on the command line. let source = &self.cstore.get_crate_data(cnum).source; if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) { - let found = locs.iter().any(|l| { + // Only use `--extern crate_name=path` here, not `--extern crate_name`. + let found = locs.iter().filter_map(|l| l.as_ref()).any(|l| { let l = fs::canonicalize(l).ok(); source.dylib.as_ref().map(|p| &p.0) == l.as_ref() || source.rlib.as_ref().map(|p| &p.0) == l.as_ref() @@ -218,8 +233,16 @@ impl<'a> CrateLoader<'a> { let dependencies: Vec = cnum_map.iter().cloned().collect(); + let proc_macros = crate_root.macro_derive_registrar.map(|_| { + self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) + }); + let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || { - crate_root.def_path_table.decode((&metadata, self.sess)) + if let Some(proc_macros) = &proc_macros { + proc_macro_def_path_table(&crate_root, proc_macros) + } else { + crate_root.def_path_table.decode((&metadata, self.sess)) + } }); let interpret_alloc_index: Vec = crate_root.interpret_alloc_index @@ -236,15 +259,13 @@ impl<'a> CrateLoader<'a> { extern_crate: Lock::new(None), def_path_table: Lrc::new(def_path_table), trait_impls, - proc_macros: crate_root.macro_derive_registrar.map(|_| { - self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) - }), + proc_macros, root: crate_root, blob: metadata, cnum_map, cnum, dependencies: Lock::new(dependencies), - codemap_import_info: RwLock::new(vec![]), + source_map_import_info: RwLock::new(vec![]), alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index), dep_kind: Lock::new(dep_kind), source: cstore::CrateSource { @@ -259,16 +280,17 @@ impl<'a> CrateLoader<'a> { (cnum, cmeta) } - fn resolve_crate(&mut self, - root: &Option, - ident: Symbol, - name: Symbol, - hash: Option<&Svh>, - extra_filename: Option<&str>, - span: Span, - path_kind: PathKind, - mut dep_kind: DepKind) - -> (CrateNum, Lrc) { + fn resolve_crate<'b>( + &'b mut self, + root: &'b Option, + ident: Symbol, + name: Symbol, + hash: Option<&'b Svh>, + extra_filename: Option<&'b str>, + span: Span, + path_kind: PathKind, + mut dep_kind: DepKind, + ) -> Result<(CrateNum, Lrc), LoadError<'b>> { info!("resolving crate `extern crate {} as {}`", name, ident); let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { LoadResult::Previous(cnum) @@ -312,7 +334,7 @@ impl<'a> CrateLoader<'a> { }; self.load(&mut proc_macro_locator) - }).unwrap_or_else(|| locate_ctxt.report_errs()) + }).ok_or_else(move || LoadError::LocatorError(locate_ctxt))? }; match result { @@ -324,10 +346,10 @@ impl<'a> CrateLoader<'a> { data.dep_kind.with_lock(|data_dep_kind| { *data_dep_kind = cmp::max(*data_dep_kind, dep_kind); }); - (cnum, data) + Ok((cnum, data)) } LoadResult::Loaded(library) => { - self.register_crate(root, ident, span, library, dep_kind) + Ok(self.register_crate(root, ident, span, library, dep_kind)) } } } @@ -432,7 +454,7 @@ impl<'a> CrateLoader<'a> { let (local_cnum, ..) = self.resolve_crate( root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, PathKind::Dependency, dep_kind, - ); + ).unwrap_or_else(|err| err.report()); local_cnum })).collect() } @@ -626,7 +648,7 @@ impl<'a> CrateLoader<'a> { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| { - *ct != config::CrateTypeRlib + *ct != config::CrateType::Rlib }); if !any_non_rlib { info!("panic runtime injection skipped, only generating rlib"); @@ -686,7 +708,8 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; let (cnum, data) = - self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind); + self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -737,13 +760,13 @@ impl<'a> CrateLoader<'a> { if !self.sess.crate_types.borrow().iter().all(|ct| { match *ct { // Link the runtime - config::CrateTypeStaticlib | - config::CrateTypeExecutable => true, + config::CrateType::Staticlib | + config::CrateType::Executable => true, // This crate will be compiled with the required // instrumentation pass - config::CrateTypeRlib | - config::CrateTypeDylib | - config::CrateTypeCdylib => + config::CrateType::Rlib | + config::CrateType::Dylib | + config::CrateType::Cdylib => false, _ => { self.sess.err(&format!("Only executables, staticlibs, \ @@ -759,10 +782,10 @@ impl<'a> CrateLoader<'a> { if !self.sess.crate_types.borrow().iter().all(|ct| { match *ct { // Link the runtime - config::CrateTypeExecutable => true, + config::CrateType::Executable => true, // This crate will be compiled with the required // instrumentation pass - config::CrateTypeRlib => false, + config::CrateType::Rlib => false, _ => { self.sess.err(&format!("Only executables and rlibs can be \ compiled with `-Z sanitizer`")); @@ -794,7 +817,8 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Explicit; let (_, data) = self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, - PathKind::Crate, dep_kind); + PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime if !data.root.sanitizer_runtime { @@ -817,7 +841,8 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; let (_, data) = self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, - PathKind::Crate, dep_kind); + PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.root.profiler_runtime { @@ -852,12 +877,12 @@ impl<'a> CrateLoader<'a> { let mut need_exe_alloc = false; for ct in self.sess.crate_types.borrow().iter() { match *ct { - config::CrateTypeExecutable => need_exe_alloc = true, - config::CrateTypeDylib | - config::CrateTypeProcMacro | - config::CrateTypeCdylib | - config::CrateTypeStaticlib => need_lib_alloc = true, - config::CrateTypeRlib => {} + config::CrateType::Executable => need_exe_alloc = true, + config::CrateType::Dylib | + config::CrateType::ProcMacro | + config::CrateType::Cdylib | + config::CrateType::Staticlib => need_lib_alloc = true, + config::CrateType::Rlib => {} } } if !need_lib_alloc && !need_exe_alloc { @@ -937,7 +962,8 @@ impl<'a> CrateLoader<'a> { None, DUMMY_SP, PathKind::Crate, - DepKind::Implicit); + DepKind::Implicit) + .unwrap_or_else(|err| err.report()); self.sess.injected_allocator.set(Some(cnum)); data }) @@ -1056,8 +1082,8 @@ impl<'a> CrateLoader<'a> { } } -impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { - fn postprocess(&mut self, krate: &ast::Crate) { +impl<'a> CrateLoader<'a> { + pub fn postprocess(&mut self, krate: &ast::Crate) { // inject the sanitizer runtime before the allocator runtime because all // sanitizers force the use of the `alloc_system` allocator self.inject_sanitizer_runtime(); @@ -1070,7 +1096,9 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } } - fn process_extern_crate(&mut self, item: &ast::Item, definitions: &Definitions) -> CrateNum { + pub fn process_extern_crate( + &mut self, item: &ast::Item, definitions: &Definitions, + ) -> CrateNum { match item.node { ast::ItemKind::ExternCrate(orig_name) => { debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", @@ -1092,7 +1120,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { let (cnum, ..) = self.resolve_crate( &None, item.ident.name, orig_name, None, None, item.span, PathKind::Crate, dep_kind, - ); + ).unwrap_or_else(|err| err.report()); let def_id = definitions.opt_local_def_id(item.id).unwrap(); let path_len = definitions.def_path(def_id.index).data.len(); @@ -1113,14 +1141,14 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } } - fn process_path_extern( + pub fn process_path_extern( &mut self, name: Symbol, span: Span, ) -> CrateNum { let cnum = self.resolve_crate( &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit - ).0; + ).unwrap_or_else(|err| err.report()).0; self.update_extern_crate( cnum, @@ -1137,31 +1165,27 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { cnum } - fn process_use_extern( + pub fn maybe_process_path_extern( &mut self, name: Symbol, span: Span, - id: ast::NodeId, - definitions: &Definitions, - ) -> CrateNum { + ) -> Option { let cnum = self.resolve_crate( &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit - ).0; - - let def_id = definitions.opt_local_def_id(id).unwrap(); - let path_len = definitions.def_path(def_id.index).data.len(); + ).ok()?.0; self.update_extern_crate( cnum, ExternCrate { - src: ExternCrateSource::Use, + src: ExternCrateSource::Path, span, - path_len, + // to have the least priority in `update_extern_crate` + path_len: usize::max_value(), direct: true, }, &mut FxHashSet(), ); - cnum + Some(cnum) } } diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index d93a7f9526..aad632f891 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -41,15 +41,15 @@ pub use rustc_data_structures::sync::MetadataRef; pub struct MetadataBlob(pub MetadataRef); -/// Holds information about a syntax_pos::FileMap imported from another crate. -/// See `imported_filemaps()` for more information. -pub struct ImportedFileMap { - /// This FileMap's byte-offset within the codemap of its original crate +/// Holds information about a syntax_pos::SourceFile imported from another crate. +/// See `imported_source_files()` for more information. +pub struct ImportedSourceFile { + /// This SourceFile's byte-offset within the source_map of its original crate pub original_start_pos: syntax_pos::BytePos, - /// The end of this FileMap within the codemap of its original crate + /// The end of this SourceFile within the source_map of its original crate pub original_end_pos: syntax_pos::BytePos, - /// The imported FileMap's representation within the local codemap - pub translated_filemap: Lrc, + /// The imported SourceFile's representation within the local source_map + pub translated_source_file: Lrc, } pub struct CrateMetadata { @@ -64,7 +64,7 @@ pub struct CrateMetadata { pub cnum_map: CrateNumMap, pub cnum: CrateNum, pub dependencies: Lock>, - pub codemap_import_info: RwLock>, + pub source_map_import_info: RwLock>, /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. pub alloc_decoding_state: AllocDecodingState, @@ -93,6 +93,11 @@ pub struct CStore { pub metadata_loader: Box, } +pub enum LoadedMacro { + MacroDef(ast::Item), + ProcMacro(Lrc), +} + impl CStore { pub fn new(metadata_loader: Box) -> CStore { CStore { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e3a7918f8c..4382a3c12c 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use cstore; +use cstore::{self, LoadedMacro}; use encoder; use link_args; use native_libs; @@ -17,8 +17,7 @@ use schema; use rustc::ty::query::QueryConfig; use rustc::middle::cstore::{CrateStore, DepKind, - MetadataLoader, LinkMeta, - LoadedMacro, EncodedMetadata, NativeLibraryKind}; + EncodedMetadata, NativeLibraryKind}; use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; use rustc::hir::def; @@ -30,6 +29,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathHash}; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::definitions::DefPathTable; use rustc::util::nodemap::DefIdMap; +use rustc_data_structures::svh::Svh; use std::any::Any; use rustc_data_structures::sync::Lrc; @@ -37,12 +37,12 @@ use std::sync::Arc; use syntax::ast; use syntax::attr; -use syntax::codemap; +use syntax::source_map; use syntax::edition::Edition; -use syntax::parse::filemap_to_stream; +use syntax::parse::source_file_to_stream; use syntax::symbol::Symbol; use syntax_pos::{Span, NO_EXPANSION, FileName}; -use rustc_data_structures::indexed_set::IdxSetBuf; +use rustc_data_structures::indexed_set::IdxSet; use rustc::hir; macro_rules! provide { @@ -141,7 +141,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, mir } mir_const_qualif => { - (cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSetBuf::new_empty(0))) + (cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSet::new_empty(0))) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } @@ -173,6 +173,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, is_panic_runtime => { cdata.root.panic_runtime } is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } + has_panic_handler => { cdata.root.has_panic_handler } is_sanitizer_runtime => { cdata.root.sanitizer_runtime } is_profiler_runtime => { cdata.root.profiler_runtime } panic_strategy => { cdata.root.panic_strategy } @@ -240,6 +241,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess); Lrc::new(result) } + defined_lib_features => { Lrc::new(cdata.get_lib_features()) } defined_lang_items => { Lrc::new(cdata.get_lang_items()) } missing_lang_items => { Lrc::new(cdata.get_missing_lang_items()) } @@ -257,12 +259,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, let cnum = cdata.cnum; assert!(cnum != LOCAL_CRATE); - // If this crate is a custom derive crate, then we're not even going to - // link those in so we skip those crates. - if cdata.root.macro_derive_registrar.is_some() { - return Arc::new(Vec::new()) - } - Arc::new(cdata.exported_symbols(tcx)) } } @@ -411,36 +407,8 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { }; } -impl CrateStore for cstore::CStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc { - self.get_crate_data(krate) - } - - fn metadata_loader(&self) -> &dyn MetadataLoader { - &*self.metadata_loader - } - - fn visibility_untracked(&self, def: DefId) -> ty::Visibility { - self.get_crate_data(def.krate).get_visibility(def.index) - } - - fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics { - self.get_crate_data(def.krate).get_generics(def.index, sess) - } - - fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem - { - self.get_crate_data(def.krate).get_associated_item(def.index) - } - - fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind - { - let data = self.get_crate_data(cnum); - let r = *data.dep_kind.lock(); - r - } - - fn export_macros_untracked(&self, cnum: CrateNum) { +impl cstore::CStore { + pub fn export_macros_untracked(&self, cnum: CrateNum) { let data = self.get_crate_data(cnum); let mut dep_kind = data.dep_kind.lock(); if *dep_kind == DepKind::UnexportedMacrosOnly { @@ -448,69 +416,28 @@ impl CrateStore for cstore::CStore { } } - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol - { - self.get_crate_data(cnum).name - } - - fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator - { - self.get_crate_data(cnum).root.disambiguator - } - - fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh - { - self.get_crate_data(cnum).root.hash + pub fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { + let data = self.get_crate_data(cnum); + let r = *data.dep_kind.lock(); + r } - fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition - { + pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { self.get_crate_data(cnum).root.edition } - /// Returns the `DefKey` for a given `DefId`. This indicates the - /// parent `DefId` as well as some idea of what kind of data the - /// `DefId` refers to. - fn def_key(&self, def: DefId) -> DefKey { - // Note: loading the def-key (or def-path) for a def-id is not - // a *read* of its metadata. This is because the def-id is - // really just an interned shorthand for a def-path, which is the - // canonical name for an item. - // - // self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).def_key(def.index) - } - - fn def_path(&self, def: DefId) -> DefPath { - // See `Note` above in `def_key()` for why this read is - // commented out: - // - // self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).def_path(def.index) - } - - fn def_path_hash(&self, def: DefId) -> DefPathHash { - self.get_crate_data(def.krate).def_path_hash(def.index) - } - - fn def_path_table(&self, cnum: CrateNum) -> Lrc { - self.get_crate_data(cnum).def_path_table.clone() - } - - fn struct_field_names_untracked(&self, def: DefId) -> Vec - { + pub fn struct_field_names_untracked(&self, def: DefId) -> Vec { self.get_crate_data(def.krate).get_struct_field_names(def.index) } - fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec - { + pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec { let mut result = vec![]; self.get_crate_data(def_id.krate) .each_child_of_item(def_id.index, |child| result.push(child), sess); result } - fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { + pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { let data = self.get_crate_data(id.krate); if let Some(ref proc_macros) = data.proc_macros { return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone()); @@ -530,9 +457,9 @@ impl CrateStore for cstore::CStore { let (name, def) = data.get_macro(id.index); let source_name = FileName::Macros(name.to_string()); - let filemap = sess.parse_sess.codemap().new_filemap(source_name, def.body); - let local_span = Span::new(filemap.start_pos, filemap.end_pos, NO_EXPANSION); - let body = filemap_to_stream(&sess.parse_sess, filemap, None); + let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body); + let local_span = Span::new(source_file.start_pos, source_file.end_pos, NO_EXPANSION); + let body = source_file_to_stream(&sess.parse_sess, source_file, None); // Mark the attrs as used let attrs = data.get_item_attrs(id.index, sess); @@ -554,11 +481,69 @@ impl CrateStore for cstore::CStore { tokens: body.into(), legacy: def.legacy, }), - vis: codemap::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), + vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), tokens: None, }) } + pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem { + self.get_crate_data(def.krate).get_associated_item(def.index) + } +} + +impl CrateStore for cstore::CStore { + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc { + self.get_crate_data(krate) + } + + fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics { + self.get_crate_data(def.krate).get_generics(def.index, sess) + } + + fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol + { + self.get_crate_data(cnum).name + } + + fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator + { + self.get_crate_data(cnum).root.disambiguator + } + + fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh + { + self.get_crate_data(cnum).root.hash + } + + /// Returns the `DefKey` for a given `DefId`. This indicates the + /// parent `DefId` as well as some idea of what kind of data the + /// `DefId` refers to. + fn def_key(&self, def: DefId) -> DefKey { + // Note: loading the def-key (or def-path) for a def-id is not + // a *read* of its metadata. This is because the def-id is + // really just an interned shorthand for a def-path, which is the + // canonical name for an item. + // + // self.dep_graph.read(DepNode::MetaData(def)); + self.get_crate_data(def.krate).def_key(def.index) + } + + fn def_path(&self, def: DefId) -> DefPath { + // See `Note` above in `def_key()` for why this read is + // commented out: + // + // self.dep_graph.read(DepNode::MetaData(def)); + self.get_crate_data(def.krate).def_path(def.index) + } + + fn def_path_hash(&self, def: DefId) -> DefPathHash { + self.get_crate_data(def.krate).def_path_hash(def.index) + } + + fn def_path_table(&self, cnum: CrateNum) -> Lrc { + self.get_crate_data(cnum).def_path_table.clone() + } + fn crates_untracked(&self) -> Vec { let mut result = vec![]; @@ -576,11 +561,10 @@ impl CrateStore for cstore::CStore { } fn encode_metadata<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta) + tcx: TyCtxt<'a, 'tcx, 'tcx>) -> EncodedMetadata { - encoder::encode_metadata(tcx, link_meta) + encoder::encode_metadata(tcx) } fn metadata_encoding_version(&self) -> &[u8] diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ab566654c3..43b03cb863 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -14,15 +14,15 @@ use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use schema::*; use rustc_data_structures::sync::{Lrc, ReadGuard}; -use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, - DisambiguatedDefPathData}; +use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions}; use rustc::hir; use rustc::middle::cstore::LinkagePreference; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Def, CtorKind}; -use rustc::hir::def_id::{CrateNum, DefId, DefIndex, +use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId}; -use rustc::ich::Fingerprint; +use rustc::hir::map::definitions::DefPathTable; +use rustc_data_structures::fingerprint::Fingerprint; use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::mir::interpret::AllocDecodingSession; @@ -39,9 +39,10 @@ use std::u32; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; -use syntax::codemap; +use syntax::source_map; use syntax::symbol::InternedString; -use syntax::ext::base::MacroKind; +use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::hygiene::Mark; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; pub struct DecodeContext<'a, 'tcx: 'a> { @@ -50,8 +51,8 @@ pub struct DecodeContext<'a, 'tcx: 'a> { sess: Option<&'a Session>, tcx: Option>, - // Cache the last used filemap for translating spans as an optimization. - last_filemap_index: usize, + // Cache the last used source_file for translating spans as an optimization. + last_source_file_index: usize, lazy_state: LazyState, @@ -73,7 +74,7 @@ pub trait Metadata<'a, 'tcx>: Copy { cdata: self.cdata(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), tcx, - last_filemap_index: 0, + last_source_file_index: 0, lazy_state: LazyState::NoNode, alloc_decoding_session: self.cdata().map(|cdata| { cdata.alloc_decoding_state.new_decoding_session() @@ -314,43 +315,45 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { bug!("Cannot decode Span without Session.") }; - let imported_filemaps = self.cdata().imported_filemaps(&sess.codemap()); - let filemap = { + let imported_source_files = self.cdata().imported_source_files(&sess.source_map()); + let source_file = { // Optimize for the case that most spans within a translated item - // originate from the same filemap. - let last_filemap = &imported_filemaps[self.last_filemap_index]; + // originate from the same source_file. + let last_source_file = &imported_source_files[self.last_source_file_index]; - if lo >= last_filemap.original_start_pos && - lo <= last_filemap.original_end_pos { - last_filemap + if lo >= last_source_file.original_start_pos && + lo <= last_source_file.original_end_pos { + last_source_file } else { let mut a = 0; - let mut b = imported_filemaps.len(); + let mut b = imported_source_files.len(); while b - a > 1 { let m = (a + b) / 2; - if imported_filemaps[m].original_start_pos > lo { + if imported_source_files[m].original_start_pos > lo { b = m; } else { a = m; } } - self.last_filemap_index = a; - &imported_filemaps[a] + self.last_source_file_index = a; + &imported_source_files[a] } }; // Make sure our binary search above is correct. - debug_assert!(lo >= filemap.original_start_pos && - lo <= filemap.original_end_pos); + debug_assert!(lo >= source_file.original_start_pos && + lo <= source_file.original_end_pos); // Make sure we correctly filtered out invalid spans during encoding - debug_assert!(hi >= filemap.original_start_pos && - hi <= filemap.original_end_pos); + debug_assert!(hi >= source_file.original_start_pos && + hi <= source_file.original_end_pos); - let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos; - let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos; + let lo = (lo + source_file.translated_source_file.start_pos) + - source_file.original_start_pos; + let hi = (hi + source_file.translated_source_file.start_pos) + - source_file.original_start_pos; Ok(Span::new(lo, hi, NO_EXPANSION)) } @@ -427,10 +430,10 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Trait(_) => Def::Trait(did), EntryKind::Enum(..) => Def::Enum(did), EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang), - EntryKind::GlobalAsm => Def::GlobalAsm(did), - EntryKind::ForeignType => Def::TyForeign(did), + EntryKind::ForeignType => Def::ForeignTy(did), EntryKind::ForeignMod | + EntryKind::GlobalAsm | EntryKind::Impl(_) | EntryKind::Field | EntryKind::Generator(_) | @@ -439,6 +442,40 @@ impl<'tcx> EntryKind<'tcx> { } } +/// Create the "fake" DefPathTable for a given proc macro crate. +/// +/// The DefPathTable is as follows: +/// +/// CRATE_ROOT (DefIndex 0:0) +/// |- GlobalMetaDataKind data (DefIndex 1:0 .. DefIndex 1:N) +/// |- proc macro #0 (DefIndex 1:N) +/// |- proc macro #1 (DefIndex 1:N+1) +/// \- ... +crate fn proc_macro_def_path_table(crate_root: &CrateRoot, + proc_macros: &[(ast::Name, Lrc)]) + -> DefPathTable +{ + let mut definitions = Definitions::new(); + + let name = crate_root.name.as_str(); + let disambiguator = crate_root.disambiguator; + debug!("creating proc macro def path table for {:?}/{:?}", name, disambiguator); + let crate_root = definitions.create_root_def(&name, disambiguator); + for (index, (name, _)) in proc_macros.iter().enumerate() { + let def_index = definitions.create_def_with_parent( + crate_root, + ast::DUMMY_NODE_ID, + DefPathData::MacroDef(name.as_interned_str()), + DefIndexAddressSpace::High, + Mark::root(), + DUMMY_SP); + debug!("definition for {:?} is {:?}", name, def_index); + assert_eq!(def_index, DefIndex::from_proc_macro_index(index)); + } + + definitions.def_path_table().clone() +} + impl<'a, 'tcx> CrateMetadata { fn is_proc_macro(&self, id: DefIndex) -> bool { self.proc_macros.is_some() && id != CRATE_DEF_INDEX @@ -505,7 +542,13 @@ impl<'a, 'tcx> CrateMetadata { self.def_path_table.def_path_hash(item_id)) } - fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef { + fn get_variant(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &Entry, + index: DefIndex, + adt_kind: ty::AdtKind) + -> ty::VariantDef + { let data = match item.kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | @@ -513,10 +556,12 @@ impl<'a, 'tcx> CrateMetadata { _ => bug!(), }; - ty::VariantDef { - did: self.local_def_id(data.struct_ctor.unwrap_or(index)), - name: self.item_name(index).as_symbol(), - fields: item.children.decode(self).map(|index| { + ty::VariantDef::new( + tcx, + self.local_def_id(data.struct_ctor.unwrap_or(index)), + self.item_name(index).as_symbol(), + data.discr, + item.children.decode(self).map(|index| { let f = self.entry(index); ty::FieldDef { did: self.local_def_id(index), @@ -524,9 +569,9 @@ impl<'a, 'tcx> CrateMetadata { vis: f.visibility.decode(self) } }).collect(), - discr: data.discr, - ctor_kind: data.ctor_kind, - } + adt_kind, + data.ctor_kind + ) } pub fn get_adt_def(&self, @@ -547,11 +592,11 @@ impl<'a, 'tcx> CrateMetadata { item.children .decode(self) .map(|index| { - self.get_variant(&self.entry(index), index) + self.get_variant(tcx, &self.entry(index), index, kind) }) .collect() } else { - vec![self.get_variant(&item, item_id)] + vec![self.get_variant(tcx, &item, item_id, kind)] }; tcx.alloc_adt_def(did, kind, variants, repr) @@ -645,20 +690,39 @@ impl<'a, 'tcx> CrateMetadata { self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx))) } - /// Iterates over the language items in the given crate. - pub fn get_lang_items(&self) -> Vec<(DefId, usize)> { + /// Iterates over all the stability attributes in the given crate. + pub fn get_lib_features(&self) -> Vec<(ast::Name, Option)> { + // FIXME: For a proc macro crate, not sure whether we should return the "host" + // features or an empty Vec. Both don't cause ICEs. self.root - .lang_items + .lib_features .decode(self) - .map(|(def_index, index)| (self.local_def_id(def_index), index)) .collect() } + /// Iterates over the language items in the given crate. + pub fn get_lang_items(&self) -> Vec<(DefId, usize)> { + if self.proc_macros.is_some() { + // Proc macro crates do not export any lang-items to the target. + vec![] + } else { + self.root + .lang_items + .decode(self) + .map(|(def_index, index)| (self.local_def_id(def_index), index)) + .collect() + } + } + /// Iterates over each child of the given item. pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) where F: FnMut(def::Export) { if let Some(ref proc_macros) = self.proc_macros { + /* If we are loading as a proc macro, we want to return the view of this crate + * as a proc macro crate, not as a Rust crate. See `proc_macro_def_path_table` + * for the DefPathTable we are corresponding to. + */ if id == CRATE_DEF_INDEX { for (id, &(name, ref ext)) in proc_macros.iter().enumerate() { let def = Def::Macro( @@ -921,12 +985,16 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_implementations_for_trait(&self, filter: Option, result: &mut Vec) { + if self.proc_macros.is_some() { + // proc-macro crates export no trait impls. + return + } + // Do a reverse lookup beforehand to avoid touching the crate_num // hash map in the loop below. let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) { Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)), Some(None) => return, - None if self.proc_macros.is_some() => return, None => None, }; @@ -959,11 +1027,21 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_native_libraries(&self, sess: &Session) -> Vec { - self.root.native_libraries.decode((self, sess)).collect() + if self.proc_macros.is_some() { + // Proc macro crates do not have any *target* native libraries. + vec![] + } else { + self.root.native_libraries.decode((self, sess)).collect() + } } pub fn get_foreign_modules(&self, sess: &Session) -> Vec { - self.root.foreign_modules.decode((self, sess)).collect() + if self.proc_macros.is_some() { + // Proc macro crates do not have any *target* foreign modules. + vec![] + } else { + self.root.foreign_modules.decode((self, sess)).collect() + } } pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> { @@ -979,10 +1057,15 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_missing_lang_items(&self) -> Vec { - self.root - .lang_items_missing - .decode(self) - .collect() + if self.proc_macros.is_some() { + // Proc macro crates do not depend on any target weak lang-items. + vec![] + } else { + self.root + .lang_items_missing + .decode(self) + .collect() + } } pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { @@ -998,10 +1081,16 @@ impl<'a, 'tcx> CrateMetadata { pub fn exported_symbols(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> { - let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> = - LazySeq::with_position_and_length(self.root.exported_symbols.position, - self.root.exported_symbols.len); - lazy_seq.decode((self, tcx)).collect() + if self.proc_macros.is_some() { + // If this crate is a custom derive crate, then we're not even going to + // link those in so we skip those crates. + vec![] + } else { + let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> = + LazySeq::with_position_and_length(self.root.exported_symbols.position, + self.root.exported_symbols.len); + lazy_seq.decode((self, tcx)).collect() + } } pub fn get_rendered_const(&self, id: DefIndex) -> String { @@ -1056,28 +1145,12 @@ impl<'a, 'tcx> CrateMetadata { #[inline] pub fn def_key(&self, index: DefIndex) -> DefKey { - if !self.is_proc_macro(index) { - self.def_path_table.def_key(index) - } else { - // FIXME(#49271) - It would be better if the DefIds were consistent - // with the DefPathTable, but for proc-macro crates - // they aren't. - let name = self.proc_macros - .as_ref() - .unwrap()[index.to_proc_macro_index()].0; - DefKey { - parent: Some(CRATE_DEF_INDEX), - disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::MacroDef(name.as_interned_str()), - disambiguator: 0, - } - } - } + self.def_path_table.def_key(index) } // Returns the path leading to the thing with this `id`. pub fn def_path(&self, id: DefIndex) -> DefPath { - debug!("def_path(id={:?})", id); + debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent)) } @@ -1086,52 +1159,55 @@ impl<'a, 'tcx> CrateMetadata { self.def_path_table.def_path_hash(index) } - /// Imports the codemap from an external crate into the codemap of the crate + /// Imports the source_map from an external crate into the source_map of the crate /// currently being compiled (the "local crate"). /// /// The import algorithm works analogous to how AST items are inlined from an /// external crate's metadata: - /// For every FileMap in the external codemap an 'inline' copy is created in the - /// local codemap. The correspondence relation between external and local - /// FileMaps is recorded in the `ImportedFileMap` objects returned from this + /// For every SourceFile in the external source_map an 'inline' copy is created in the + /// local source_map. The correspondence relation between external and local + /// SourceFiles is recorded in the `ImportedSourceFile` objects returned from this /// function. When an item from an external crate is later inlined into this /// crate, this correspondence information is used to translate the span /// information of the inlined item so that it refers the correct positions in - /// the local codemap (see `>`). + /// the local source_map (see `>`). /// - /// The import algorithm in the function below will reuse FileMaps already - /// existing in the local codemap. For example, even if the FileMap of some + /// The import algorithm in the function below will reuse SourceFiles already + /// existing in the local source_map. For example, even if the SourceFile of some /// source file of libstd gets imported many times, there will only ever be - /// one FileMap object for the corresponding file in the local codemap. + /// one SourceFile object for the corresponding file in the local source_map. /// - /// Note that imported FileMaps do not actually contain the source code of the + /// Note that imported SourceFiles do not actually contain the source code of the /// file they represent, just information about length, line breaks, and /// multibyte characters. This information is enough to generate valid debuginfo /// for items inlined from other crates. - pub fn imported_filemaps(&'a self, - local_codemap: &codemap::CodeMap) - -> ReadGuard<'a, Vec> { + /// + /// Proc macro crates don't currently export spans, so this function does not have + /// to work for them. + pub fn imported_source_files(&'a self, + local_source_map: &source_map::SourceMap) + -> ReadGuard<'a, Vec> { { - let filemaps = self.codemap_import_info.borrow(); - if !filemaps.is_empty() { - return filemaps; + let source_files = self.source_map_import_info.borrow(); + if !source_files.is_empty() { + return source_files; } } - // Lock the codemap_import_info to ensure this only happens once - let mut codemap_import_info = self.codemap_import_info.borrow_mut(); + // Lock the source_map_import_info to ensure this only happens once + let mut source_map_import_info = self.source_map_import_info.borrow_mut(); - if !codemap_import_info.is_empty() { - drop(codemap_import_info); - return self.codemap_import_info.borrow(); + if !source_map_import_info.is_empty() { + drop(source_map_import_info); + return self.source_map_import_info.borrow(); } - let external_codemap = self.root.codemap.decode(self); + let external_source_map = self.root.source_map.decode(self); - let imported_filemaps = external_codemap.map(|filemap_to_import| { - // We can't reuse an existing FileMap, so allocate a new one + let imported_source_files = external_source_map.map(|source_file_to_import| { + // We can't reuse an existing SourceFile, so allocate a new one // containing the information we need. - let syntax_pos::FileMap { name, + let syntax_pos::SourceFile { name, name_was_remapped, src_hash, start_pos, @@ -1140,15 +1216,15 @@ impl<'a, 'tcx> CrateMetadata { mut multibyte_chars, mut non_narrow_chars, name_hash, - .. } = filemap_to_import; + .. } = source_file_to_import; let source_length = (end_pos - start_pos).to_usize(); // Translate line-start positions and multibyte character // position into frame of reference local to file. - // `CodeMap::new_imported_filemap()` will then translate those + // `SourceMap::new_imported_source_file()` will then translate those // coordinates to their new global frame of reference when the - // offset of the FileMap is known. + // offset of the SourceFile is known. for pos in &mut lines { *pos = *pos - start_pos; } @@ -1159,7 +1235,7 @@ impl<'a, 'tcx> CrateMetadata { *swc = *swc - start_pos; } - let local_version = local_codemap.new_imported_filemap(name, + let local_version = local_source_map.new_imported_source_file(name, name_was_remapped, self.cnum.as_u32(), src_hash, @@ -1168,23 +1244,23 @@ impl<'a, 'tcx> CrateMetadata { lines, multibyte_chars, non_narrow_chars); - debug!("CrateMetaData::imported_filemaps alloc \ - filemap {:?} original (start_pos {:?} end_pos {:?}) \ + debug!("CrateMetaData::imported_source_files alloc \ + source_file {:?} original (start_pos {:?} end_pos {:?}) \ translated (start_pos {:?} end_pos {:?})", local_version.name, start_pos, end_pos, local_version.start_pos, local_version.end_pos); - cstore::ImportedFileMap { + cstore::ImportedSourceFile { original_start_pos: start_pos, original_end_pos: end_pos, - translated_filemap: local_version, + translated_source_file: local_version, } }).collect(); - *codemap_import_info = imported_filemaps; - drop(codemap_import_info); + *source_map_import_info = imported_source_files; + drop(source_map_import_info); // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. - self.codemap_import_info.borrow() + self.source_map_import_info.borrow() } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 7ed991e0de..56b38cfbc8 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -13,12 +13,12 @@ use index_builder::{FromId, IndexBuilder, Untracked}; use isolated_encoder::IsolatedEncoder; use schema::*; -use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, +use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE}; use rustc::hir::map::definitions::DefPathTable; -use rustc::ich::Fingerprint; +use rustc_data_structures::fingerprint::Fingerprint; use rustc::middle::dependency_format::Linkage; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, metadata_symbol_name}; @@ -28,7 +28,7 @@ use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; -use rustc::session::config::{self, CrateTypeProcMacro}; +use rustc::session::config::{self, CrateType}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; @@ -40,9 +40,9 @@ use rustc_data_structures::sync::Lrc; use std::u32; use syntax::ast::{self, CRATE_NODE_ID}; use syntax::attr; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use syntax::symbol::keywords; -use syntax_pos::{self, hygiene, FileName, FileMap, Span}; +use syntax_pos::{self, hygiene, FileName, SourceFile, Span}; use rustc::hir::{self, PatKind}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -52,7 +52,6 @@ use rustc::hir::intravisit; pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &'a LinkMeta, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -62,7 +61,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { interpret_allocs_inverse: Vec, // This is used to speed up Span encoding. - filemap_cache: Lrc, + source_file_cache: Lrc, } macro_rules! encoder_methods { @@ -76,7 +75,7 @@ macro_rules! encoder_methods { impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { type Error = ::Error; - fn emit_nil(&mut self) -> Result<(), Self::Error> { + fn emit_unit(&mut self) -> Result<(), Self::Error> { Ok(()) } @@ -157,13 +156,13 @@ impl<'a, 'tcx> SpecializedEncoder for EncodeContext<'a, 'tcx> { // The Span infrastructure should make sure that this invariant holds: debug_assert!(span.lo <= span.hi); - if !self.filemap_cache.contains(span.lo) { - let codemap = self.tcx.sess.codemap(); - let filemap_index = codemap.lookup_filemap_idx(span.lo); - self.filemap_cache = codemap.files()[filemap_index].clone(); + if !self.source_file_cache.contains(span.lo) { + let source_map = self.tcx.sess.source_map(); + let source_file_index = source_map.lookup_source_file_idx(span.lo); + self.source_file_cache = source_map.files()[source_file_index].clone(); } - if !self.filemap_cache.contains(span.hi) { + if !self.source_file_cache.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. return TAG_INVALID_SPAN.encode(self) @@ -337,36 +336,36 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(definitions.def_path_table()) } - fn encode_codemap(&mut self) -> LazySeq { - let codemap = self.tcx.sess.codemap(); - let all_filemaps = codemap.files(); + fn encode_source_map(&mut self) -> LazySeq { + let source_map = self.tcx.sess.source_map(); + let all_source_files = source_map.files(); let (working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir.clone(); - let adapted = all_filemaps.iter() - .filter(|filemap| { - // No need to re-export imported filemaps, as any downstream + let adapted = all_source_files.iter() + .filter(|source_file| { + // No need to re-export imported source_files, as any downstream // crate will import them from their original source. - !filemap.is_imported() + !source_file.is_imported() }) - .map(|filemap| { - // When exporting FileMaps, we expand all paths to absolute + .map(|source_file| { + // When exporting SourceFiles, we expand all paths to absolute // paths because any relative paths are potentially relative to // a wrong directory. // However, if a path has been modified via // `--remap-path-prefix` we assume the user has already set // things up the way they want and don't touch the path values // anymore. - match filemap.name { + match source_file.name { FileName::Real(ref name) => { - if filemap.name_was_remapped || + if source_file.name_was_remapped || (name.is_relative() && working_dir_was_remapped) { - // This path of this FileMap has been modified by + // This path of this SourceFile has been modified by // path-remapping, so we use it verbatim (and avoid cloning // the whole map in the process). - filemap.clone() + source_file.clone() } else { - let mut adapted = (**filemap).clone(); + let mut adapted = (**source_file).clone(); adapted.name = Path::new(&working_dir).join(name).into(); adapted.name_hash = { let mut hasher: StableHasher = StableHasher::new(); @@ -377,7 +376,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } }, // expanded code, not from a file - _ => filemap.clone(), + _ => source_file.clone(), } }) .collect::>(); @@ -394,6 +393,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ()); let dep_bytes = self.position() - i; + // Encode the lib features. + i = self.position(); + let lib_features = self.tracked(IsolatedEncoder::encode_lib_features, ()); + let lib_feature_bytes = self.position() - i; + // Encode the language items. i = self.position(); let lang_items = self.tracked(IsolatedEncoder::encode_lang_items, ()); @@ -413,10 +417,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { IsolatedEncoder::encode_foreign_modules, ()); - // Encode codemap + // Encode source_map i = self.position(); - let codemap = self.encode_codemap(); - let codemap_bytes = self.position() - i; + let source_map = self.encode_source_map(); + let source_map_bytes = self.position() - i; // Encode DefPathTable i = self.position(); @@ -477,20 +481,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let index_bytes = self.position() - i; let attrs = tcx.hir.krate_attrs(); - let link_meta = self.link_meta; - let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro); + let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); let has_default_lib_allocator = attr::contains_name(&attrs, "default_lib_allocator"); let has_global_allocator = *tcx.sess.has_global_allocator.get(); + let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false); let root = self.lazy(&CrateRoot { name: tcx.crate_name(LOCAL_CRATE), extra_filename: tcx.sess.opts.cg.extra_filename.clone(), triple: tcx.sess.opts.target_triple.clone(), - hash: link_meta.crate_hash, + hash: tcx.crate_hash(LOCAL_CRATE), disambiguator: tcx.sess.local_crate_disambiguator(), panic_strategy: tcx.sess.panic_strategy(), edition: hygiene::default_edition(), has_global_allocator: has_global_allocator, + has_panic_handler: has_panic_handler, has_default_lib_allocator: has_default_lib_allocator, plugin_registrar_fn: tcx.sess .plugin_registrar_fn @@ -513,11 +518,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { crate_deps, dylib_dependency_formats, + lib_features, lang_items, lang_items_missing, native_libraries, foreign_modules, - codemap, + source_map, def_path_table, impls, exported_symbols, @@ -537,9 +543,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!("metadata stats:"); println!(" dep bytes: {}", dep_bytes); + println!(" lib feature bytes: {}", lib_feature_bytes); println!(" lang item bytes: {}", lang_item_bytes); println!(" native bytes: {}", native_lib_bytes); - println!(" codemap bytes: {}", codemap_bytes); + println!(" source_map bytes: {}", source_map_bytes); println!(" impl bytes: {}", impl_bytes); println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); @@ -735,7 +742,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // If the structure is marked as non_exhaustive then lower the visibility // to within the crate. - if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public { + if adt_def.non_enum_variant().is_field_list_non_exhaustive() && + ctor_vis == ty::Visibility::Public + { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } @@ -1106,7 +1115,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let trait_ref = tcx.impl_trait_ref(def_id); let parent = if let Some(trait_ref) = trait_ref { let trait_def = tcx.trait_def(trait_ref.def_id); - trait_def.ancestors(tcx, def_id).skip(1).next().and_then(|node| { + trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| { match node { specialization_graph::Node::Impl(parent) => Some(parent), _ => None, @@ -1255,12 +1264,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), hir::ItemKind::Fn(_, header, ..) => { let generics = tcx.generics_of(def_id); - let has_types = generics.params.iter().any(|param| match param.kind { - ty::GenericParamDefKind::Type { .. } => true, - _ => false, - }); let needs_inline = - (has_types || tcx.codegen_fn_attrs(def_id).requests_inline()) && + (generics.requires_monomorphization(tcx) || + tcx.codegen_fn_attrs(def_id).requests_inline()) && !self.metadata_output_only(); let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; if needs_inline @@ -1340,7 +1346,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let hir_id = self.tcx.hir.node_to_hir_id(node_id); let kind = match tables.node_id_to_type(hir_id).sty { - ty::TyGenerator(def_id, ..) => { + ty::Generator(def_id, ..) => { let layout = self.tcx.generator_layout(def_id); let data = GeneratorData { layout: layout.clone(), @@ -1348,7 +1354,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { EntryKind::Generator(self.lazy(&data)) } - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { let sig = substs.closure_sig(def_id, self.tcx); let data = ClosureData { sig: self.lazy(&sig) }; EntryKind::Closure(self.lazy(&data)) @@ -1456,6 +1462,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep)) } + fn encode_lib_features(&mut self, _: ()) -> LazySeq<(ast::Name, Option)> { + let tcx = self.tcx; + let lib_features = tcx.lib_features(); + self.lazy_seq(lib_features.to_vec()) + } + fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> { let tcx = self.tcx; let lang_items = tcx.lang_items(); @@ -1542,7 +1554,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { - match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { + match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) { Some(arr) => { self.lazy_seq(arr.iter().map(|slot| { match *slot { @@ -1670,15 +1682,17 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { } fn encode_info_for_generics(&mut self, generics: &hir::Generics) { - generics.params.iter().for_each(|param| match param.kind { - hir::GenericParamKind::Lifetime { .. } => {} - hir::GenericParamKind::Type { ref default, .. } => { - let def_id = self.tcx.hir.local_def_id(param.id); - let has_default = Untracked(default.is_some()); - let encode_info = IsolatedEncoder::encode_info_for_ty_param; - self.record(def_id, encode_info, (def_id, has_default)); + for param in &generics.params { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => {} + hir::GenericParamKind::Type { ref default, .. } => { + let def_id = self.tcx.hir.local_def_id(param.id); + let has_default = Untracked(default.is_some()); + let encode_info = IsolatedEncoder::encode_info_for_ty_param; + self.record(def_id, encode_info, (def_id, has_default)); + } } - }); + } } fn encode_info_for_ty(&mut self, ty: &hir::Ty) { @@ -1775,7 +1789,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) { self.impls .entry(trait_ref.def_id) - .or_insert(vec![]) + .or_default() .push(impl_id.index); } } @@ -1811,8 +1825,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { // will allow us to slice the metadata to the precise length that we just // generated regardless of trailing bytes that end up in it. -pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta) +pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> EncodedMetadata { let mut encoder = opaque::Encoder::new(vec![]); @@ -1825,11 +1838,10 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut ecx = EncodeContext { opaque: encoder, tcx, - link_meta, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), - filemap_cache: tcx.sess.codemap().files()[0].clone(), + source_file_cache: tcx.sess.source_map().files()[0].clone(), interpret_allocs: Default::default(), interpret_allocs_inverse: Default::default(), }; @@ -1857,7 +1869,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions { let ty = tcx.type_of(did); match ty.sty { - ty::TyAdt(ref def, _) => return def.repr, + ty::Adt(ref def, _) => return def.repr, _ => bug!("{} is not an ADT", ty), } } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 5cba0387d1..09a8bea094 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -13,14 +13,15 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(box_patterns)] -#![feature(fs_read_write)] #![feature(libc)] #![feature(macro_at_most_once_rep)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] +#![feature(crate_visibility_modifier)] #![feature(specialization)] #![feature(rustc_private)] @@ -37,6 +38,7 @@ extern crate serialize as rustc_serialize; // used by deriving extern crate rustc_errors as errors; extern crate syntax_ext; extern crate proc_macro; +extern crate rustc_metadata_utils; #[macro_use] extern crate rustc; diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index f68bcdd62c..02207c63b3 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -226,7 +226,8 @@ use cstore::{MetadataRef, MetadataBlob}; use creader::Library; use schema::{METADATA_HEADER, rustc_version}; -use rustc::hir::svh::Svh; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::svh::Svh; use rustc::middle::cstore::MetadataLoader; use rustc::session::{config, Session}; use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; @@ -239,7 +240,6 @@ use syntax_pos::Span; use rustc_target::spec::{Target, TargetTriple}; use std::cmp; -use std::collections::HashSet; use std::fmt; use std::fs; use std::io::{self, Read}; @@ -308,7 +308,7 @@ impl CratePaths { impl<'a> Context<'a> { pub fn maybe_load_library_crate(&mut self) -> Option { - let mut seen_paths = HashSet::new(); + let mut seen_paths = FxHashSet::default(); match self.extra_filename { Some(s) => self.find_library_crate(s, &mut seen_paths) .or_else(|| self.find_library_crate("", &mut seen_paths)), @@ -431,14 +431,19 @@ impl<'a> Context<'a> { fn find_library_crate(&mut self, extra_prefix: &str, - seen_paths: &mut HashSet) + seen_paths: &mut FxHashSet) -> Option { // If an SVH is specified, then this is a transitive dependency that // must be loaded via -L plus some filtering. if self.hash.is_none() { self.should_match_name = false; if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) { - return self.find_commandline_library(s.iter()); + // Only use `--extern crate_name=path` here, not `--extern crate_name`. + if s.iter().any(|l| l.is_some()) { + return self.find_commandline_library( + s.iter().filter_map(|l| l.as_ref()), + ); + } } self.should_match_name = true; } @@ -451,7 +456,10 @@ impl<'a> Context<'a> { let rlib_prefix = format!("lib{}{}", self.crate_name, extra_prefix); let staticlib_prefix = format!("{}{}{}", staticpair.0, self.crate_name, extra_prefix); - let mut candidates = FxHashMap(); + let mut candidates: FxHashMap< + _, + (FxHashMap<_, _>, FxHashMap<_, _>, FxHashMap<_, _>), + > = FxHashMap(); let mut staticlibs = vec![]; // First, find all possible candidate rlibs and dylibs purely based on @@ -493,8 +501,7 @@ impl<'a> Context<'a> { info!("lib candidate: {}", path.display()); let hash_str = hash.to_string(); - let slot = candidates.entry(hash_str) - .or_insert_with(|| (FxHashMap(), FxHashMap(), FxHashMap())); + let slot = candidates.entry(hash_str).or_default(); let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot; fs::canonicalize(path) .map(|p| { diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 078295c99b..446ea6c324 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -16,7 +16,7 @@ use rustc::ty::TyCtxt; use rustc::util::nodemap::FxHashSet; use rustc_target::spec::abi::Abi; use syntax::attr; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::feature_gate::{self, GateIssue}; use syntax::symbol::Symbol; @@ -207,7 +207,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { } } - // Update kind and, optionally, the name of all native libaries + // Update kind and, optionally, the name of all native libraries // (there may be more than one) with the specified name. for &(ref name, ref new_name, kind) in &self.tcx.sess.opts.libs { let mut found = false; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d7c54cbc81..ab22a8e4db 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -20,6 +20,7 @@ use rustc::mir; use rustc::session::CrateDisambiguator; use rustc::ty::{self, Ty, ReprOptions}; use rustc_target::spec::{PanicStrategy, TargetTriple}; +use rustc_data_structures::svh::Svh; use rustc_serialize as serialize; use syntax::{ast, attr}; @@ -187,22 +188,24 @@ pub struct CrateRoot { pub name: Symbol, pub triple: TargetTriple, pub extra_filename: String, - pub hash: hir::svh::Svh, + pub hash: Svh, pub disambiguator: CrateDisambiguator, pub panic_strategy: PanicStrategy, pub edition: Edition, pub has_global_allocator: bool, + pub has_panic_handler: bool, pub has_default_lib_allocator: bool, pub plugin_registrar_fn: Option, pub macro_derive_registrar: Option, pub crate_deps: LazySeq, pub dylib_dependency_formats: LazySeq>, + pub lib_features: LazySeq<(Symbol, Option)>, pub lang_items: LazySeq<(DefIndex, usize)>, pub lang_items_missing: LazySeq, pub native_libraries: LazySeq, pub foreign_modules: LazySeq, - pub codemap: LazySeq, + pub source_map: LazySeq, pub def_path_table: Lazy, pub impls: LazySeq, pub exported_symbols: EncodedExportedSymbols, @@ -222,7 +225,7 @@ pub struct CrateRoot { #[derive(RustcEncodable, RustcDecodable)] pub struct CrateDep { pub name: ast::Name, - pub hash: hir::svh::Svh, + pub hash: Svh, pub kind: DepKind, pub extra_filename: String, } diff --git a/src/librustc_metadata_utils/Cargo.toml b/src/librustc_metadata_utils/Cargo.toml new file mode 100644 index 0000000000..4a5e20376b --- /dev/null +++ b/src/librustc_metadata_utils/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_metadata_utils" +version = "0.0.0" + +[lib] +name = "rustc_metadata_utils" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +rustc = { path = "../librustc" } +syntax = { path = "../libsyntax" } +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_metadata_utils/lib.rs b/src/librustc_metadata_utils/lib.rs new file mode 100644 index 0000000000..a1e5150390 --- /dev/null +++ b/src/librustc_metadata_utils/lib.rs @@ -0,0 +1,42 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate rustc; +extern crate syntax_pos; + +use rustc::session::Session; +use syntax_pos::Span; + +pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { + let mut err_count = 0; + { + let mut say = |s: &str| { + match (sp, sess) { + (_, None) => bug!("{}", s), + (Some(sp), Some(sess)) => sess.span_err(sp, s), + (None, Some(sess)) => sess.err(s), + } + err_count += 1; + }; + if s.is_empty() { + say("crate name must not be empty"); + } + for c in s.chars() { + if c.is_alphanumeric() { continue } + if c == '_' { continue } + say(&format!("invalid character `{}` in crate name: `{}`", c, s)); + } + } + + if err_count > 0 { + sess.unwrap().abort_if_errors(); + } +} diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 0fd1f92a51..2da0ede9d1 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -25,3 +25,4 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } byteorder = { version = "1.1", features = ["i128"] } rustc_apfloat = { path = "../librustc_apfloat" } +smallvec = { version = "0.6.5", features = ["union"] } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index fe33dc0a58..8ddcfa0543 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -10,12 +10,14 @@ use borrow_check::place_ext::PlaceExt; use dataflow::indexes::BorrowIndex; +use dataflow::move_paths::MoveData; use rustc::mir::traversal; use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{self, Location, Mir, Place}; +use rustc::mir::{self, Location, Mir, Place, Local}; use rustc::ty::{Region, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::bitvec::BitArray; use std::fmt; use std::hash::Hash; use std::ops::Index; @@ -43,6 +45,8 @@ crate struct BorrowSet<'tcx> { /// Map from local to all the borrows on that local crate local_map: FxHashMap>, + + crate locals_state_at_exit: LocalsStateAtExit, } impl<'tcx> Index for BorrowSet<'tcx> { @@ -96,8 +100,52 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { } } +crate enum LocalsStateAtExit { + AllAreInvalidated, + SomeAreInvalidated { has_storage_dead_or_moved: BitArray } +} + +impl LocalsStateAtExit { + fn build( + locals_are_invalidated_at_exit: bool, + mir: &Mir<'tcx>, + move_data: &MoveData<'tcx> + ) -> Self { + struct HasStorageDead(BitArray); + + impl<'tcx> Visitor<'tcx> for HasStorageDead { + fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) { + if ctx == PlaceContext::StorageDead { + self.0.insert(*local); + } + } + } + + if locals_are_invalidated_at_exit { + LocalsStateAtExit::AllAreInvalidated + } else { + let mut has_storage_dead = HasStorageDead(BitArray::new(mir.local_decls.len())); + has_storage_dead.visit_mir(mir); + let mut has_storage_dead_or_moved = has_storage_dead.0; + for move_out in &move_data.moves { + if let Some(index) = move_data.base_local(move_out.path) { + has_storage_dead_or_moved.insert(index); + + } + } + LocalsStateAtExit::SomeAreInvalidated{ has_storage_dead_or_moved } + } + } +} + impl<'tcx> BorrowSet<'tcx> { - pub fn build(tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> Self { + pub fn build( + tcx: TyCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + locals_are_invalidated_at_exit: bool, + move_data: &MoveData<'tcx> + ) -> Self { + let mut visitor = GatherBorrows { tcx, mir, @@ -107,6 +155,8 @@ impl<'tcx> BorrowSet<'tcx> { region_map: FxHashMap(), local_map: FxHashMap(), pending_activations: FxHashMap(), + locals_state_at_exit: + LocalsStateAtExit::build(locals_are_invalidated_at_exit, mir, move_data), }; for (block, block_data) in traversal::preorder(mir) { @@ -119,6 +169,7 @@ impl<'tcx> BorrowSet<'tcx> { activation_map: visitor.activation_map, region_map: visitor.region_map, local_map: visitor.local_map, + locals_state_at_exit: visitor.locals_state_at_exit, } } @@ -148,6 +199,8 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { /// the borrow. When we find a later use of this activation, we /// remove from the map (and add to the "tombstone" set below). pending_activations: FxHashMap, + + locals_state_at_exit: LocalsStateAtExit, } impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { @@ -159,7 +212,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { location: mir::Location, ) { if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue { - if borrowed_place.is_unsafe_place(self.tcx, self.mir) { + if borrowed_place.ignore_borrow( + self.tcx, self.mir, &self.locals_state_at_exit) { return; } @@ -248,7 +302,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { self.activation_map .entry(location) - .or_insert(Vec::new()) + .or_default() .push(borrow_index); TwoPhaseActivation::ActivatedAt(location) } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index e2ac7dde55..4671332f28 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -10,36 +10,41 @@ use borrow_check::WriteKind; use rustc::middle::region::ScopeTree; +use rustc::mir::VarBindingForm; use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local}; use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place}; use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind}; -use rustc::mir::VarBindingForm; use rustc::ty; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; +use rustc_errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; use super::borrow_set::BorrowData; use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; +use borrow_check::nll::explain_borrow::BorrowContainsPointReason; +use dataflow::drop_flag_effects; +use dataflow::move_paths::indexes::MoveOutIndex; use dataflow::move_paths::MovePathIndex; -use dataflow::{FlowAtLocation, MovingOutStatements}; use util::borrowck_errors::{BorrowckErrors, Origin}; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_use_of_moved_or_uninitialized( &mut self, - _context: Context, + context: Context, desired_action: InitializationRequiringAction, (place, span): (&Place<'tcx>, Span), mpi: MovePathIndex, - curr_move_out: &FlowAtLocation>, ) { - let mois = self.move_data.path_map[mpi] - .iter() - .filter(|moi| curr_move_out.contains(moi)) - .collect::>(); + let use_spans = self + .move_spans(place, context.loc) + .or_else(|| self.borrow_spans(span, context.loc)); + let span = use_spans.args_or_use(); + + let mois = self.get_moved_indexes(context, mpi); + debug!("report_use_of_moved_or_uninitialized: mois={:?}", mois); if mois.is_empty() { let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap(); @@ -58,16 +63,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; - let mut err = self.tcx - .cannot_act_on_uninitialized_variable( - span, - desired_action.as_noun(), - &self - .describe_place_with_options(place, IncludingDowncast(true)) - .unwrap_or("_".to_owned()), - Origin::Mir, - ); + let mut err = self.tcx.cannot_act_on_uninitialized_variable( + span, + desired_action.as_noun(), + &self + .describe_place_with_options(place, IncludingDowncast(true)) + .unwrap_or("_".to_owned()), + Origin::Mir, + ); err.span_label(span, format!("use of possibly uninitialized {}", item_msg)); + + use_spans.var_span_label( + &mut err, + format!("{} occurs due to use in closure", desired_action.as_noun()), + ); + err.buffer(&mut self.errors_buffer); } else { let msg = ""; //FIXME: add "partially " or "collaterally " @@ -82,11 +92,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut is_loop_move = false; for moi in &mois { - let move_msg = ""; //FIXME: add " (into closure)" - let move_span = self - .mir - .source_info(self.move_data.moves[**moi].source) - .span; + let move_out = self.move_data.moves[*moi]; + let moved_place = &self.move_data.move_paths[move_out.path].place; + + let move_spans = self.move_spans(moved_place, move_out.source); + let move_span = move_spans.args_or_use(); + + let move_msg = if move_spans.for_closure() { + " into closure" + } else { + "" + }; + if span == move_span { err.span_label( span, @@ -95,8 +112,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { is_loop_move = true; } else { err.span_label(move_span, format!("value moved{} here", move_msg)); + move_spans.var_span_label(&mut err, "variable moved due to use in closure"); }; } + + use_spans.var_span_label( + &mut err, + format!("{} occurs due to use in closure", desired_action.as_noun()), + ); + if !is_loop_move { err.span_label( span, @@ -109,11 +133,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let Some(ty) = self.retrieve_type_for_place(place) { let needs_note = match ty.sty { - ty::TypeVariants::TyClosure(id, _) => { + ty::Closure(id, _) => { let tables = self.tcx.typeck_tables_of(id); let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); let hir_id = self.tcx.hir.node_to_hir_id(node_id); - if let Some(_) = tables.closure_kind_origins().get(hir_id) { + if tables.closure_kind_origins().get(hir_id).is_some() { false } else { true @@ -123,7 +147,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }; if needs_note { - let mpi = self.move_data.moves[*mois[0]].path; + let mpi = self.move_data.moves[mois[0]].path; let place = &self.move_data.move_paths[mpi].place; if let Some(ty) = self.retrieve_type_for_place(place) { @@ -150,7 +174,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_move_out_while_borrowed( &mut self, context: Context, - (place, span): (&Place<'tcx>, Span), + (place, _span): (&Place<'tcx>, Span), borrow: &BorrowData<'tcx>, ) { let tcx = self.tcx; @@ -162,16 +186,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.args_or_use(); + + let move_spans = self.move_spans(place, context.loc); + let span = move_spans.args_or_use(); + let mut err = tcx.cannot_move_when_borrowed( span, &self.describe_place(place).unwrap_or("_".to_owned()), Origin::Mir, ); - err.span_label( - self.retrieve_borrow_span(borrow), - format!("borrow of {} occurs here", borrow_msg), - ); + err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); err.span_label(span, format!("move out of {} occurs here", value_msg)); + + borrow_spans.var_span_label(&mut err, "borrow occurs due to use in closure"); + + move_spans.var_span_label(&mut err, "move occurs due to use in closure"); + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); err.buffer(&mut self.errors_buffer); } @@ -179,92 +212,38 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_use_while_mutably_borrowed( &mut self, context: Context, - (place, span): (&Place<'tcx>, Span), + (place, _span): (&Place<'tcx>, Span), borrow: &BorrowData<'tcx>, ) { let tcx = self.tcx; + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.args_or_use(); + + // Conflicting borrows are reported separately, so only check for move + // captures. + let use_spans = self.move_spans(place, context.loc); + let span = use_spans.var_or_use(); + let mut err = tcx.cannot_use_when_mutably_borrowed( span, &self.describe_place(place).unwrap_or("_".to_owned()), - self.retrieve_borrow_span(borrow), + borrow_span, &self .describe_place(&borrow.borrowed_place) .unwrap_or("_".to_owned()), Origin::Mir, ); - self.explain_why_borrow_contains_point(context, borrow, None, &mut err); - err.buffer(&mut self.errors_buffer); - } - - /// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of - /// the local assigned at `location`. - /// This is done by searching in statements succeeding `location` - /// and originating from `maybe_closure_span`. - pub(super) fn find_closure_span( - &self, - maybe_closure_span: Span, - location: Location, - ) -> Option<(Span, Span)> { - use rustc::hir::ExprKind::Closure; - use rustc::mir::AggregateKind; - - let local = match self.mir[location.block] - .statements - .get(location.statement_index) - { - Some(&Statement { - kind: StatementKind::Assign(Place::Local(local), _), - .. - }) => local, - _ => return None, - }; - - for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { - if maybe_closure_span != stmt.source_info.span { - break; - } - - if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { - if let AggregateKind::Closure(def_id, _) = **kind { - debug!("find_closure_span: found closure {:?}", places); - - return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { - let args_span = if let Closure(_, _, _, span, _) = - self.tcx.hir.expect_expr(node_id).node - { - span - } else { - return None; - }; + borrow_spans.var_span_label(&mut err, { + let place = &borrow.borrowed_place; + let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); - self.tcx - .with_freevars(node_id, |freevars| { - for (v, place) in freevars.iter().zip(places) { - match *place { - Operand::Copy(Place::Local(l)) - | Operand::Move(Place::Local(l)) if local == l => - { - debug!( - "find_closure_span: found captured local {:?}", - l - ); - return Some(v.span); - } - _ => {} - } - } - None - }) - .map(|var_span| (args_span, var_span)) - } else { - None - }; - } - } - } + format!("borrow occurs due to use of `{}` in closure", desc_place) + }); - None + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); + err.buffer(&mut self.errors_buffer); } pub(super) fn report_conflicting_borrow( @@ -274,14 +253,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, ) { - let issued_span = self.retrieve_borrow_span(issued_borrow); + let issued_spans = self.retrieve_borrow_spans(issued_borrow); + let issued_span = issued_spans.args_or_use(); - let new_closure_span = self.find_closure_span(span, context.loc); - let span = new_closure_span.map(|(args, _)| args).unwrap_or(span); - let old_closure_span = self.find_closure_span(issued_span, issued_borrow.reserve_location); - let issued_span = old_closure_span - .map(|(args, _)| args) - .unwrap_or(issued_span); + let borrow_spans = self.borrow_spans(span, context.loc); + let span = borrow_spans.args_or_use(); let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); let tcx = self.tcx; @@ -368,23 +344,28 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(), }; - if let Some((_, var_span)) = old_closure_span { - let place = &issued_borrow.borrowed_place; - let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); - - err.span_label( - var_span, + if issued_spans == borrow_spans { + borrow_spans.var_span_label( + &mut err, + format!("borrows occur due to use of `{}` in closure", desc_place), + ); + } else { + let borrow_place = &issued_borrow.borrowed_place; + let borrow_place_desc = self.describe_place(borrow_place).unwrap_or("_".to_owned()); + issued_spans.var_span_label( + &mut err, format!( - "previous borrow occurs due to use of `{}` in closure", - desc_place + "first borrow occurs due to use of `{}` in closure", + borrow_place_desc ), ); - } - if let Some((_, var_span)) = new_closure_span { - err.span_label( - var_span, - format!("borrow occurs due to use of `{}` in closure", desc_place), + borrow_spans.var_span_label( + &mut err, + format!( + "second borrow occurs due to use of `{}` in closure", + desc_place + ), ); } @@ -407,7 +388,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .last() .unwrap(); - let borrow_span = self.mir.source_info(borrow.reserve_location).span; + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.var_or_use(); + let proper_span = match *root_place { Place::Local(local) => self.mir.local_decls[local].source_info.span, _ => drop_span, @@ -427,30 +410,35 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.access_place_error_reported .insert((root_place.clone(), borrow_span)); - match &self.describe_place(&borrow.borrowed_place) { - Some(name) => { - self.report_local_value_does_not_live_long_enough( - context, - name, - &scope_tree, - &borrow, - drop_span, - borrow_span, - proper_span, - kind.map(|k| (k, place_span.0)), - ); - } - None => { - self.report_temporary_value_does_not_live_long_enough( - context, - &scope_tree, - &borrow, - drop_span, - borrow_span, - proper_span, - ); + let borrow_reason = self.find_why_borrow_contains_point(context, borrow); + + let mut err = match &self.describe_place(&borrow.borrowed_place) { + Some(_) if self.is_place_thread_local(root_place) => { + self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span) } - } + Some(name) => self.report_local_value_does_not_live_long_enough( + context, + name, + &scope_tree, + &borrow, + borrow_reason, + drop_span, + borrow_span, + kind.map(|k| (k, place_span.0)), + ), + None => self.report_temporary_value_does_not_live_long_enough( + context, + &scope_tree, + &borrow, + borrow_reason, + drop_span, + proper_span, + ), + }; + + borrow_spans.args_span_label(&mut err, "value captured here"); + + err.buffer(&mut self.errors_buffer); } fn report_local_value_does_not_live_long_enough( @@ -459,29 +447,56 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { name: &String, scope_tree: &Lrc, borrow: &BorrowData<'tcx>, + reason: BorrowContainsPointReason<'tcx>, drop_span: Span, borrow_span: Span, - _proper_span: Span, kind_place: Option<(WriteKind, &Place<'tcx>)>, - ) { + ) -> DiagnosticBuilder<'cx> { debug!( "report_local_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ + {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ )", - context, name, scope_tree, borrow, drop_span, borrow_span + context, name, scope_tree, borrow, reason, drop_span, borrow_span + ); + + let mut err = self.tcx.path_does_not_live_long_enough( + borrow_span, + &format!("`{}`", name), + Origin::Mir, ); - let tcx = self.tcx; - let mut err = - tcx.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name), Origin::Mir); err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label( drop_span, format!("`{}` dropped here while still borrowed", name), ); - self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err); - err.buffer(&mut self.errors_buffer); + self.report_why_borrow_contains_point(&mut err, reason, kind_place); + err + } + + fn report_thread_local_value_does_not_live_long_enough( + &mut self, + drop_span: Span, + borrow_span: Span, + ) -> DiagnosticBuilder<'cx> { + debug!( + "report_thread_local_value_does_not_live_long_enough(\ + {:?}, {:?}\ + )", + drop_span, borrow_span + ); + + let mut err = self + .tcx + .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir); + + err.span_label( + borrow_span, + "thread-local variables cannot be borrowed beyond the end of the function", + ); + err.span_label(drop_span, "end of enclosing function is here"); + err } fn report_temporary_value_does_not_live_long_enough( @@ -489,15 +504,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context: Context, scope_tree: &Lrc, borrow: &BorrowData<'tcx>, + reason: BorrowContainsPointReason<'tcx>, drop_span: Span, - _borrow_span: Span, proper_span: Span, - ) { + ) -> DiagnosticBuilder<'cx> { debug!( "report_temporary_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}, {:?}\ + {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ )", - context, scope_tree, borrow, drop_span, proper_span + context, scope_tree, borrow, reason, drop_span, proper_span ); let tcx = self.tcx; @@ -506,8 +521,91 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(proper_span, "temporary value does not live long enough"); err.span_label(drop_span, "temporary value only lives until here"); - self.explain_why_borrow_contains_point(context, borrow, None, &mut err); - err.buffer(&mut self.errors_buffer); + // Only give this note and suggestion if they could be relevant + match reason { + BorrowContainsPointReason::Liveness {..} + | BorrowContainsPointReason::DropLiveness {..} => { + err.note("consider using a `let` binding to create a longer lived value"); + } + BorrowContainsPointReason::OutlivesFreeRegion {..} => (), + } + + self.report_why_borrow_contains_point(&mut err, reason, None); + err + } + + fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec { + let mir = self.mir; + + let mut stack = Vec::new(); + stack.extend(mir.predecessor_locations(context.loc)); + + let mut visited = FxHashSet(); + let mut result = vec![]; + + 'dfs: while let Some(l) = stack.pop() { + debug!( + "report_use_of_moved_or_uninitialized: current_location={:?}", + l + ); + + if !visited.insert(l) { + continue; + } + + // check for moves + let stmt_kind = mir[l.block] + .statements + .get(l.statement_index) + .map(|s| &s.kind); + if let Some(StatementKind::StorageDead(..)) = stmt_kind { + // this analysis only tries to find moves explicitly + // written by the user, so we ignore the move-outs + // created by `StorageDead` and at the beginning + // of a function. + } else { + for moi in &self.move_data.loc_map[l] { + debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi); + if self.move_data.moves[*moi].path == mpi { + debug!("report_use_of_moved_or_uninitialized: found"); + result.push(*moi); + + // Strictly speaking, we could continue our DFS here. There may be + // other moves that can reach the point of error. But it is kind of + // confusing to highlight them. + // + // Example: + // + // ``` + // let a = vec![]; + // let b = a; + // let c = a; + // drop(a); // <-- current point of error + // ``` + // + // Because we stop the DFS here, we only highlight `let c = a`, + // and not `let b = a`. We will of course also report an error at + // `let c = a` which highlights `let b = a` as the move. + continue 'dfs; + } + } + } + + // check for inits + let mut any_match = false; + drop_flag_effects::for_location_inits(self.tcx, self.mir, self.move_data, l, |m| { + if m == mpi { + any_match = true; + } + }); + if any_match { + continue 'dfs; + } + + stack.extend(mir.predecessor_locations(l)); + } + + result } pub(super) fn report_illegal_mutation_of_borrowed( @@ -516,14 +614,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (place, span): (&Place<'tcx>, Span), loan: &BorrowData<'tcx>, ) { + let loan_spans = self.retrieve_borrow_spans(loan); + let loan_span = loan_spans.args_or_use(); + let tcx = self.tcx; let mut err = tcx.cannot_assign_to_borrowed( span, - self.retrieve_borrow_span(loan), + loan_span, &self.describe_place(place).unwrap_or("_".to_owned()), Origin::Mir, ); + loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure"); + self.explain_why_borrow_contains_point(context, loan, None, &mut err); err.buffer(&mut self.errors_buffer); @@ -556,12 +659,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // PATTERN;) then make the error refer to that local, rather than the // place being assigned later. let (place_description, assigned_span) = match local_decl { - Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Clear), .. }) - | Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Set( - BindingForm::Var(VarBindingForm { - opt_match_place: None, .. - }))), ..}) - | Some(LocalDecl { is_user_variable: None, .. }) + Some(LocalDecl { + is_user_variable: Some(ClearCrossCrate::Clear), + .. + }) + | Some(LocalDecl { + is_user_variable: + Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + opt_match_place: None, + .. + }))), + .. + }) + | Some(LocalDecl { + is_user_variable: None, + .. + }) | None => (self.describe_place(place), assigned_span), Some(decl) => (self.describe_place(err_place), decl.source_info.span), }; @@ -589,9 +702,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let Some(decl) = local_decl { if let Some(name) = decl.name { if decl.can_be_made_mutable() { - err.span_label( + err.span_suggestion_with_applicability( decl.source_info.span, - format!("consider changing this to `mut {}`", name), + "make this binding mutable", + format!("mut {}", name), + Applicability::MachineApplicable, ); } } @@ -647,8 +762,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Projection(ref proj) => { match proj.elem { ProjectionElem::Deref => { - let upvar_field_projection = place.is_upvar_field_projection( - self.mir, &self.tcx); + let upvar_field_projection = + place.is_upvar_field_projection(self.mir, &self.tcx); if let Some(field) = upvar_field_projection { let var_index = field.index(); let name = self.mir.upvar_decls[var_index].debug_name.to_string(); @@ -666,8 +781,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &including_downcast, )?; } else if let Place::Local(local) = proj.base { - if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) - = self.mir.local_decls[local].is_user_variable { + if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) = + self.mir.local_decls[local].is_user_variable + { self.append_place_to_string( &proj.base, buf, @@ -708,8 +824,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ProjectionElem::Field(field, _ty) => { autoderef = true; - let upvar_field_projection = place.is_upvar_field_projection( - self.mir, &self.tcx); + let upvar_field_projection = + place.is_upvar_field_projection(self.mir, &self.tcx); if let Some(field) = upvar_field_projection { let var_index = field.index(); let name = self.mir.upvar_decls[var_index].debug_name.to_string(); @@ -735,7 +851,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &including_downcast, )?; buf.push_str("["); - if let Err(_) = self.append_local_to_string(index, buf) { + if self.append_local_to_string(index, buf).is_err() { buf.push_str(".."); } buf.push_str("]"); @@ -807,17 +923,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.describe_field_from_ty(&ty.boxed_ty(), field) } else { match ty.sty { - ty::TyAdt(def, _) => if def.is_enum() { + ty::Adt(def, _) => if def.is_enum() { field.index().to_string() } else { - def.non_enum_variant().fields[field.index()].ident.to_string() + def.non_enum_variant().fields[field.index()] + .ident + .to_string() }, - ty::TyTuple(_) => field.index().to_string(), - ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => { + ty::Tuple(_) => field.index().to_string(), + ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { self.describe_field_from_ty(&ty, field) } - ty::TyArray(ty, _) | ty::TySlice(ty) => self.describe_field_from_ty(&ty, field), - ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => { + ty::Array(ty, _) | ty::Slice(ty) => self.describe_field_from_ty(&ty, field), + ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => { // Convert the def-id into a node-id. node-ids are only valid for // the local code in the current crate, so this returns an `Option` in case // the closure comes from another crate. But in that case we wouldn't @@ -839,11 +957,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - // Retrieve span of given borrow from the current MIR representation - crate fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { - self.mir.source_info(borrow.reserve_location).span - } - // Retrieve type of a place for the current MIR representation fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option { match place { @@ -859,4 +972,223 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }, } } + + /// Check if a place is a thread-local static. + pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool { + if let Place::Static(statik) = place { + let attrs = self.tcx.get_attrs(statik.def_id); + let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local")); + + debug!( + "is_place_thread_local: attrs={:?} is_thread_local={:?}", + attrs, is_thread_local + ); + is_thread_local + } else { + debug!("is_place_thread_local: no"); + false + } + } +} + +// The span(s) associated to a use of a place. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub(super) enum UseSpans { + // The access is caused by capturing a variable for a closure. + ClosureUse { + // The span of the args of the closure, including the `move` keyword if + // it's present. + args_span: Span, + // The span of the first use of the captured variable inside the closure. + var_span: Span, + }, + // This access has a single span associated to it: common case. + OtherUse(Span), +} + +impl UseSpans { + pub(super) fn args_or_use(self) -> Span { + match self { + UseSpans::ClosureUse { + args_span: span, .. + } + | UseSpans::OtherUse(span) => span, + } + } + + pub(super) fn var_or_use(self) -> Span { + match self { + UseSpans::ClosureUse { var_span: span, .. } | UseSpans::OtherUse(span) => span, + } + } + + // Add a span label to the arguments of the closure, if it exists. + pub(super) fn args_span_label(self, err: &mut DiagnosticBuilder, message: impl Into) { + if let UseSpans::ClosureUse { args_span, .. } = self { + err.span_label(args_span, message); + } + } + + // Add a span label to the use of the captured variable, if it exists. + pub(super) fn var_span_label(self, err: &mut DiagnosticBuilder, message: impl Into) { + if let UseSpans::ClosureUse { var_span, .. } = self { + err.span_label(var_span, message); + } + } + + pub(super) fn for_closure(self) -> bool { + match self { + UseSpans::ClosureUse { .. } => true, + UseSpans::OtherUse(_) => false, + } + } + + pub(super) fn or_else(self, if_other: F) -> Self + where + F: FnOnce() -> Self, + { + match self { + closure @ UseSpans::ClosureUse { .. } => closure, + UseSpans::OtherUse(_) => if_other(), + } + } +} + +impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { + /// Finds the spans associated to a move or copy of move_place at location. + pub(super) fn move_spans( + &self, + moved_place: &Place<'tcx>, // Could also be an upvar. + location: Location, + ) -> UseSpans { + use self::UseSpans::*; + use rustc::hir::ExprKind::Closure; + use rustc::mir::AggregateKind; + + let stmt = match self.mir[location.block] + .statements + .get(location.statement_index) + { + Some(stmt) => stmt, + None => return OtherUse(self.mir.source_info(location).span), + }; + + if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { + if let AggregateKind::Closure(def_id, _) = **kind { + debug!("find_closure_move_span: found closure {:?}", places); + + if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + if let Closure(_, _, _, args_span, _) = self.tcx.hir.expect_expr(node_id).node { + if let Some(var_span) = self.tcx.with_freevars(node_id, |freevars| { + for (v, place) in freevars.iter().zip(places) { + match place { + Operand::Copy(place) | Operand::Move(place) + if moved_place == place => + { + debug!( + "find_closure_move_span: found captured local {:?}", + place + ); + return Some(v.span); + } + _ => {} + } + } + None + }) { + return ClosureUse { + args_span, + var_span, + }; + } + } + } + } + } + + return OtherUse(stmt.source_info.span); + } + + /// Finds the span of arguments of a closure (within `maybe_closure_span`) + /// and its usage of the local assigned at `location`. + /// This is done by searching in statements succeeding `location` + /// and originating from `maybe_closure_span`. + pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans { + use self::UseSpans::*; + use rustc::hir::ExprKind::Closure; + use rustc::mir::AggregateKind; + + let local = match self.mir[location.block] + .statements + .get(location.statement_index) + { + Some(&Statement { + kind: StatementKind::Assign(Place::Local(local), _), + .. + }) => local, + _ => return OtherUse(use_span), + }; + + if self.mir.local_kind(local) != LocalKind::Temp { + // operands are always temporaries. + return OtherUse(use_span); + } + + for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { + if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { + if let AggregateKind::Closure(def_id, _) = **kind { + debug!("find_closure_borrow_span: found closure {:?}", places); + + return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + let args_span = if let Closure(_, _, _, span, _) = + self.tcx.hir.expect_expr(node_id).node + { + span + } else { + return OtherUse(use_span); + }; + + self.tcx + .with_freevars(node_id, |freevars| { + for (v, place) in freevars.iter().zip(places) { + match *place { + Operand::Copy(Place::Local(l)) + | Operand::Move(Place::Local(l)) + if local == l => + { + debug!( + "find_closure_borrow_span: found captured local \ + {:?}", + l + ); + return Some(v.span); + } + _ => {} + } + } + None + }).map(|var_span| ClosureUse { + args_span, + var_span, + }).unwrap_or(OtherUse(use_span)) + } else { + OtherUse(use_span) + }; + } + } + + if use_span != stmt.source_info.span { + break; + } + } + + OtherUse(use_span) + } + + /// Helper to retrieve span(s) of given borrow from the current MIR + /// representation + pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData) -> UseSpans { + let span = self.mir.source_info(borrow.reserve_location).span; + self.borrow_spans(span, borrow.reserve_location) + } } diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index 90dc96cbd3..a4900ab57f 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -15,7 +15,7 @@ use rustc::mir::{BasicBlock, Location}; use rustc::ty::RegionVid; -use rustc_data_structures::indexed_set::Iter; +use rustc_data_structures::bitvec::BitIter; use borrow_check::location::LocationIndex; @@ -24,7 +24,7 @@ use polonius_engine::Output; use dataflow::move_paths::indexes::BorrowIndex; use dataflow::move_paths::HasMoveData; use dataflow::Borrows; -use dataflow::{EverInitializedPlaces, MovingOutStatements}; +use dataflow::EverInitializedPlaces; use dataflow::{FlowAtLocation, FlowsAtLocation}; use dataflow::MaybeUninitializedPlaces; use either::Either; @@ -35,7 +35,6 @@ use std::rc::Rc; crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { borrows: FlowAtLocation>, pub uninits: FlowAtLocation>, - pub move_outs: FlowAtLocation>, pub ever_inits: FlowAtLocation>, /// Polonius Output @@ -46,14 +45,12 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { crate fn new( borrows: FlowAtLocation>, uninits: FlowAtLocation>, - move_outs: FlowAtLocation>, ever_inits: FlowAtLocation>, polonius_output: Option>>, ) -> Self { Flows { borrows, uninits, - move_outs, ever_inits, polonius_output, } @@ -70,7 +67,7 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { } } - crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter)) { + crate fn with_outgoing_borrows(&self, op: impl FnOnce(BitIter)) { self.borrows.with_iter_outgoing(op) } } @@ -79,7 +76,6 @@ macro_rules! each_flow { ($this:ident, $meth:ident($arg:ident)) => { FlowAtLocation::$meth(&mut $this.borrows, $arg); FlowAtLocation::$meth(&mut $this.uninits, $arg); - FlowAtLocation::$meth(&mut $this.move_outs, $arg); FlowAtLocation::$meth(&mut $this.ever_inits, $arg); }; } @@ -89,6 +85,10 @@ impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> { each_flow!(self, reset_to_entry_of(bb)); } + fn reset_to_exit_of(&mut self, bb: BasicBlock) { + each_flow!(self, reset_to_exit_of(bb)); + } + fn reconstruct_statement_effect(&mut self, location: Location) { each_flow!(self, reconstruct_statement_effect(location)); } @@ -142,18 +142,6 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> { }); s.push_str("] "); - s.push_str("move_out: ["); - let mut saw_one = false; - self.move_outs.each_state_bit(|mpi_move_out| { - if saw_one { - s.push_str(", "); - }; - saw_one = true; - let move_out = &self.move_outs.operator().move_data().moves[mpi_move_out]; - s.push_str(&format!("{:?}", move_out)); - }); - s.push_str("] "); - s.push_str("ever_init: ["); let mut saw_one = false; self.ever_inits.each_state_bit(|mpi_ever_init| { diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs index 28da1b2d73..91008e8f96 100644 --- a/src/librustc_mir/borrow_check/location.rs +++ b/src/librustc_mir/borrow_check/location.rs @@ -27,7 +27,11 @@ crate struct LocationTable { statements_before_block: IndexVec, } -newtype_index!(LocationIndex { DEBUG_FORMAT = "LocationIndex({})" }); +newtype_index! { + pub struct LocationIndex { + DEBUG_FORMAT = "LocationIndex({})" + } +} #[derive(Copy, Clone, Debug)] crate enum RichLocation { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4ba96f643b..3c694fe7b4 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -12,6 +12,7 @@ use borrow_check::nll::region_infer::RegionInferenceContext; use rustc::hir; +use rustc::hir::Node; use rustc::hir::def_id::DefId; use rustc::hir::map::definitions::DefPathData; use rustc::infer::InferCtxt; @@ -22,14 +23,14 @@ use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Pla use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; -use rustc::ty::{self, ParamEnv, TyCtxt}; +use rustc::ty::{self, ParamEnv, TyCtxt, Ty}; -use rustc_errors::{Diagnostic, DiagnosticBuilder, Level}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level}; use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::indexed_set::IdxSetBuf; +use rustc_data_structures::indexed_set::IdxSet; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; use std::rc::Rc; @@ -42,7 +43,7 @@ use dataflow::DataflowResultsConsumer; use dataflow::FlowAtLocation; use dataflow::MoveDataParamEnv; use dataflow::{do_dataflow, DebugFormatted}; -use dataflow::{EverInitializedPlaces, MovingOutStatements}; +use dataflow::EverInitializedPlaces; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use util::borrowck_errors::{BorrowckErrors, Origin}; @@ -151,7 +152,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let location_table = &LocationTable::new(mir); let mut errors_buffer = Vec::new(); - let (move_data, move_errors): (MoveData<'tcx>, Option>>) = + let (move_data, move_errors): (MoveData<'tcx>, Option, MoveError<'tcx>)>>) = match MoveData::gather_moves(mir, tcx) { Ok(move_data) => (move_data, None), Err((move_data, move_errors)) => (move_data, Some(move_errors)), @@ -166,7 +167,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( _ => Some(tcx.hir.body_owned_by(id)), }; - let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); + let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len()); let mut flow_inits = FlowAtLocation::new(do_dataflow( tcx, mir, @@ -176,35 +177,13 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( MaybeInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); - let flow_uninits = FlowAtLocation::new(do_dataflow( - tcx, - mir, - id, - &attributes, - &dead_unwinds, - MaybeUninitializedPlaces::new(tcx, mir, &mdpe), - |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), - )); - let flow_move_outs = FlowAtLocation::new(do_dataflow( - tcx, - mir, - id, - &attributes, - &dead_unwinds, - MovingOutStatements::new(tcx, mir, &mdpe), - |bd, i| DebugFormatted::new(&bd.move_data().moves[i]), - )); - let flow_ever_inits = FlowAtLocation::new(do_dataflow( - tcx, - mir, - id, - &attributes, - &dead_unwinds, - EverInitializedPlaces::new(tcx, mir, &mdpe), - |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), - )); - let borrow_set = Rc::new(BorrowSet::build(tcx, mir)); + let locals_are_invalidated_at_exit = match tcx.hir.body_owner_kind(id) { + hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, + hir::BodyOwnerKind::Fn => true, + }; + let borrow_set = Rc::new(BorrowSet::build( + tcx, mir, locals_are_invalidated_at_exit, &mdpe.move_data)); // If we are in non-lexical mode, compute the non-lexical lifetimes. let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( @@ -219,6 +198,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( &borrow_set, &mut errors_buffer, ); + + // The various `flow_*` structures can be large. We drop `flow_inits` here + // so it doesn't overlap with the others below. This reduces peak memory + // usage significantly on some benchmarks. + drop(flow_inits); + let regioncx = Rc::new(regioncx); let flow_borrows = FlowAtLocation::new(do_dataflow( @@ -230,9 +215,27 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( Borrows::new(tcx, mir, regioncx.clone(), def_id, body_id, &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); + let flow_uninits = FlowAtLocation::new(do_dataflow( + tcx, + mir, + id, + &attributes, + &dead_unwinds, + MaybeUninitializedPlaces::new(tcx, mir, &mdpe), + |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), + )); + let flow_ever_inits = FlowAtLocation::new(do_dataflow( + tcx, + mir, + id, + &attributes, + &dead_unwinds, + EverInitializedPlaces::new(tcx, mir, &mdpe), + |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), + )); let movable_generator = match tcx.hir.get(id) { - hir::map::Node::NodeExpr(&hir::Expr { + Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(.., Some(hir::GeneratorMovability::Static)), .. }) => false, @@ -249,10 +252,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( param_env: param_env, location_table, movable_generator, - locals_are_invalidated_at_exit: match tcx.hir.body_owner_kind(id) { - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, - hir::BodyOwnerKind::Fn => true, - }, + locals_are_invalidated_at_exit, access_place_error_reported: FxHashSet(), reservation_error_reported: FxHashSet(), moved_error_reported: FxHashSet(), @@ -267,7 +267,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let mut state = Flows::new( flow_borrows, flow_uninits, - flow_move_outs, flow_ever_inits, polonius_output, ); @@ -316,7 +315,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } let span = local_decl.source_info.span; - let mut_span = tcx.sess.codemap().span_until_non_whitespace(span); + let mut_span = tcx.sess.source_map().span_until_non_whitespace(span); let mut err = tcx.struct_span_lint_node( UNUSED_MUT, @@ -324,13 +323,19 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( span, "variable does not need to be mutable", ); - err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()); + err.span_suggestion_short_with_applicability( + mut_span, + "remove this `mut`", + String::new(), + Applicability::MachineApplicable); err.buffer(&mut mbcx.errors_buffer); } } if mbcx.errors_buffer.len() > 0 { + mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span()); + if tcx.migrate_borrowck() { match tcx.borrowck(def_id).signalled_any_error { SignalledError::NoErrorsSeen => { @@ -536,10 +541,10 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // flow_state already handled). } StatementKind::Nop - | StatementKind::UserAssertTy(..) + | StatementKind::AscribeUserType(..) | StatementKind::Validate(..) | StatementKind::StorageLive(..) => { - // `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant + // `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant // to borrow check. } StatementKind::StorageDead(local) => { @@ -596,7 +601,12 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // that is useful later. let drop_place_ty = gcx.lift(&drop_place_ty).unwrap(); - self.visit_terminator_drop(loc, term, flow_state, drop_place, drop_place_ty, span); + debug!("visit_terminator_drop \ + loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}", + loc, term, drop_place, drop_place_ty, span); + + self.visit_terminator_drop( + loc, term, flow_state, drop_place, drop_place_ty, span, SeenTy(None)); } TerminatorKind::DropAndReplace { location: ref drop_place, @@ -791,12 +801,6 @@ enum LocalMutationIsAllowed { No, } -struct AccessErrorsReported { - mutability_error: bool, - #[allow(dead_code)] - conflict_error: bool, -} - #[derive(Copy, Clone)] enum InitializationRequiringAction { Update, @@ -830,6 +834,35 @@ impl InitializationRequiringAction { } } +/// A simple linked-list threaded up the stack of recursive calls in `visit_terminator_drop`. +#[derive(Copy, Clone, Debug)] +struct SeenTy<'a, 'gcx: 'a>(Option<(Ty<'gcx>, &'a SeenTy<'a, 'gcx>)>); + +impl<'a, 'gcx> SeenTy<'a, 'gcx> { + /// Return a new list with `ty` prepended to the front of `self`. + fn cons(&'a self, ty: Ty<'gcx>) -> Self { + SeenTy(Some((ty, self))) + } + + /// True if and only if `ty` occurs on the linked list `self`. + fn have_seen(self, ty: Ty) -> bool { + let mut this = self.0; + loop { + match this { + None => return false, + Some((seen_ty, recur)) => { + if seen_ty == ty { + return true; + } else { + this = recur.0; + continue; + } + } + } + } + } +} + impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Invokes `access_place` as appropriate for dropping the value /// at `drop_place`. Note that the *actual* `Drop` in the MIR is @@ -845,14 +878,57 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_place: &Place<'tcx>, erased_drop_place_ty: ty::Ty<'gcx>, span: Span, + prev_seen: SeenTy<'_, 'gcx>, ) { + if prev_seen.have_seen(erased_drop_place_ty) { + // if we have directly seen the input ty `T`, then we must + // have had some *direct* ownership loop between `T` and + // some directly-owned (as in, actually traversed by + // recursive calls below) part that is also of type `T`. + // + // Note: in *all* such cases, the data in question cannot + // be constructed (nor destructed) in finite time/space. + // + // Proper examples, some of which are statically rejected: + // + // * `struct A { field: A, ... }`: + // statically rejected as infinite size + // + // * `type B = (B, ...);`: + // statically rejected as cyclic + // + // * `struct C { field: Box, ... }` + // * `struct D { field: Box<(D, D)>, ... }`: + // *accepted*, though impossible to construct + // + // Here is *NOT* an example: + // * `struct Z { field: Option>, ... }`: + // Here, the type is both representable in finite space (due to the boxed indirection) + // and constructable in finite time (since the recursion can bottom out with `None`). + // This is an obvious instance of something the compiler must accept. + // + // Since some of the above impossible cases like `C` and + // `D` are accepted by the compiler, we must take care not + // to infinite-loop while processing them. But since such + // cases cannot actually arise, it is sound for us to just + // skip them during drop. If the developer uses unsafe + // code to construct them, they should not be surprised by + // weird drop behavior in their resulting code. + debug!("visit_terminator_drop previously seen \ + erased_drop_place_ty: {:?} on prev_seen: {:?}; returning early.", + erased_drop_place_ty, prev_seen); + return; + } + let gcx = self.tcx.global_tcx(); let drop_field = |mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, (index, field): (usize, ty::Ty<'gcx>)| { let field_ty = gcx.normalize_erasing_regions(mir.param_env, field); let place = drop_place.clone().field(Field::new(index), field_ty); - mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span); + debug!("visit_terminator_drop drop_field place: {:?} field_ty: {:?}", place, field_ty); + let seen = prev_seen.cons(erased_drop_place_ty); + mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span, seen); }; match erased_drop_place_ty.sty { @@ -862,14 +938,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // individual fields instead. This way if `foo` has a // destructor but `bar` does not, we will only check for // borrows of `x.foo` and not `x.bar`. See #47703. - ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => { + ty::Adt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => { def.all_fields() .map(|field| field.ty(gcx, substs)) .enumerate() .for_each(|field| drop_field(self, field)); } // Same as above, but for tuples. - ty::TyTuple(tys) => { + ty::Tuple(tys) => { tys.iter() .cloned() .enumerate() @@ -877,7 +953,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } // Closures also have disjoint fields, but they are only // directly accessed in the body of the closure. - ty::TyClosure(def, substs) + ty::Closure(def, substs) if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() => { @@ -888,7 +964,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } // Generators also have disjoint fields, but they are only // directly accessed in the body of the generator. - ty::TyGenerator(def, substs, _) + ty::Generator(def, substs, _) if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() => { @@ -897,13 +973,42 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .enumerate() .for_each(|field| drop_field(self, field)); } + + // #45696: special-case Box by treating its dtor as + // only deep *across owned content*. Namely, we know + // dropping a box does not touch data behind any + // references it holds; if we were to instead fall into + // the base case below, we would have a Deep Write due to + // the box being `needs_drop`, and that Deep Write would + // touch `&mut` data in the box. + ty::Adt(def, _) if def.is_box() => { + // When/if we add a `&own T` type, this action would + // be like running the destructor of the `&own T`. + // (And the owner of backing storage referenced by the + // `&own T` would be responsible for deallocating that + // backing storage.) + + // we model dropping any content owned by the box by + // recurring on box contents. This catches cases like + // `Box>>`, while + // still restricting Write to *owned* content. + let ty = erased_drop_place_ty.boxed_ty(); + let deref_place = drop_place.clone().deref(); + debug!("visit_terminator_drop drop-box-content deref_place: {:?} ty: {:?}", + deref_place, ty); + let seen = prev_seen.cons(erased_drop_place_ty); + self.visit_terminator_drop( + loc, term, flow_state, &deref_place, ty, span, seen); + } + _ => { // We have now refined the type of the value being // dropped (potentially) to just the type of a // subfield; so check whether that field's type still - // "needs drop". If so, we assume that the destructor - // may access any data it likes (i.e., a Deep Write). + // "needs drop". if erased_drop_place_ty.needs_drop(gcx, self.param_env) { + // If so, we assume that the destructor may access + // any data it likes (i.e., a Deep Write). self.access_place( ContextKind::Drop.new(loc), (drop_place, span), @@ -911,6 +1016,41 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { LocalMutationIsAllowed::Yes, flow_state, ); + } else { + // If there is no destructor, we still include a + // *shallow* write. This essentially ensures that + // borrows of the memory directly at `drop_place` + // cannot continue to be borrowed across the drop. + // + // If we were to use a Deep Write here, then any + // `&mut T` that is reachable from `drop_place` + // would get invalidated; fixing that is the + // essence of resolving issue #45696. + // + // * Note: In the compiler today, doing a Deep + // Write here would not actually break + // anything beyond #45696; for example it does not + // break this example: + // + // ```rust + // fn reborrow(x: &mut i32) -> &mut i32 { &mut *x } + // ``` + // + // Why? Because we do not schedule/emit + // `Drop(x)` in the MIR unless `x` needs drop in + // the first place. + // + // FIXME: Its possible this logic actually should + // be attached to the `StorageDead` statement + // rather than the `Drop`. See discussion on PR + // #52782. + self.access_place( + ContextKind::Drop.new(loc), + (drop_place, span), + (Shallow(None), Write(WriteKind::StorageDeadOrDrop)), + LocalMutationIsAllowed::Yes, + flow_state, + ); } } } @@ -929,7 +1069,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { kind: (ShallowOrDeep, ReadOrWrite), is_local_mutation_allowed: LocalMutationIsAllowed, flow_state: &Flows<'cx, 'gcx, 'tcx>, - ) -> AccessErrorsReported { + ) { let (sd, rw) = kind; if let Activation(_, borrow_index) = rw { @@ -939,14 +1079,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place: {:?} borrow_index: {:?}", place_span.0, borrow_index ); - return AccessErrorsReported { - mutability_error: false, - conflict_error: true, - }; + return; } } - if self + // Check is_empty() first because it's the common case, and doing that + // way we avoid the clone() call. + if !self.access_place_error_reported.is_empty() && + self .access_place_error_reported .contains(&(place_span.0.clone(), place_span.1)) { @@ -954,10 +1094,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "access_place: suppressing error place_span=`{:?}` kind=`{:?}`", place_span, kind ); - return AccessErrorsReported { - mutability_error: false, - conflict_error: true, - }; + return; } let mutability_error = @@ -979,11 +1116,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.access_place_error_reported .insert((place_span.0.clone(), place_span.1)); } - - AccessErrorsReported { - mutability_error, - conflict_error, - } } fn check_access_for_conflict( @@ -1132,23 +1264,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - let errors_reported = self.access_place( + // Special case: you can assign a immutable local variable + // (e.g., `x = ...`) so long as it has never been initialized + // before (at this point in the flow). + if let &Place::Local(local) = place_span.0 { + if let Mutability::Not = self.mir.local_decls[local].mutability { + // check for reassignments to immutable local variables + self.check_if_reassignment_to_immutable_state( + context, + local, + place_span, + flow_state, + ); + return; + } + } + + // Otherwise, use the normal access permission rules. + self.access_place( context, place_span, (kind, Write(WriteKind::Mutate)), - // We want immutable upvars to cause an "assignment to immutable var" - // error, not an "reassignment of immutable var" error, because the - // latter can't find a good previous assignment span. - // - // There's probably a better way to do this. - LocalMutationIsAllowed::ExceptUpvars, + LocalMutationIsAllowed::No, flow_state, ); - - if !errors_reported.mutability_error { - // check for reassignments to immutable local variables - self.check_if_reassignment_to_immutable_state(context, place_span, flow_state); - } } fn consume_rvalue( @@ -1344,15 +1483,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // FIXME: allow thread-locals to borrow other thread locals? let (might_be_alive, will_be_dropped) = match root_place { Place::Promoted(_) => (true, false), - Place::Static(statik) => { + Place::Static(_) => { // Thread-locals might be dropped after the function exits, but // "true" statics will never be. - let is_thread_local = self - .tcx - .get_attrs(statik.def_id) - .iter() - .any(|attr| attr.check_name("thread_local")); - + let is_thread_local = self.is_place_thread_local(&root_place); (true, is_thread_local) } Place::Local(_) => { @@ -1381,7 +1515,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { debug!("check_for_invalidation_at_exit({:?}): INVALID", place); // FIXME: should be talking about the region lifetime instead // of just a span here. - let span = self.tcx.sess.codemap().end_point(span); + let span = self.tcx.sess.source_map().end_point(span); self.report_borrowed_value_does_not_live_long_enough( context, borrow, @@ -1399,7 +1533,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if borrow_of_local_data(&borrow.borrowed_place) { let err = self.tcx .cannot_borrow_across_generator_yield( - self.retrieve_borrow_span(borrow), + self.retrieve_borrow_spans(borrow).var_or_use(), yield_span, Origin::Mir, ); @@ -1452,27 +1586,23 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn check_if_reassignment_to_immutable_state( &mut self, context: Context, - (place, span): (&Place<'tcx>, Span), + local: Local, + place_span: (&Place<'tcx>, Span), flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { - debug!("check_if_reassignment_to_immutable_state({:?})", place); - // determine if this path has a non-mut owner (and thus needs checking). - let err_place = match self.is_mutable(place, LocalMutationIsAllowed::No) { - Ok(..) => return, - Err(place) => place, - }; - debug!( - "check_if_reassignment_to_immutable_state({:?}) - is an imm local", - place - ); - - for i in flow_state.ever_inits.iter_incoming() { - let init = self.move_data.inits[i]; - let init_place = &self.move_data.move_paths[init.path].place; - if places_conflict::places_conflict(self.tcx, self.mir, &init_place, place, Deep) { - self.report_illegal_reassignment(context, (place, span), init.span, err_place); - break; - } + debug!("check_if_reassignment_to_immutable_state({:?})", local); + + // Check if any of the initializiations of `local` have happened yet: + let mpi = self.move_data.rev_lookup.find_local(local); + let init_indices = &self.move_data.init_path_map[mpi]; + let first_init_index = init_indices.iter().find(|ii| flow_state.ever_inits.contains(ii)); + if let Some(&init_index) = first_init_index { + // And, if so, report an error. + let init = &self.move_data.inits[init_index]; + let span = init.span(&self.mir); + self.report_illegal_reassignment( + context, place_span, span, place_span.0 + ); } } @@ -1483,12 +1613,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place_span: (&Place<'tcx>, Span), flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { - // FIXME: analogous code in check_loans first maps `place` to - // its base_path ... but is that what we want here? - let place = self.base_path(place_span.0); - let maybe_uninits = &flow_state.uninits; - let curr_move_outs = &flow_state.move_outs; // Bad scenarios: // @@ -1525,8 +1650,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // This code covers scenarios 1, 2, and 3. - debug!("check_if_full_path_is_moved place: {:?}", place); - match self.move_path_closest_to(place) { + debug!("check_if_full_path_is_moved place: {:?}", place_span.0); + match self.move_path_closest_to(place_span.0) { Ok(mpi) => { if maybe_uninits.contains(&mpi) { self.report_use_of_moved_or_uninitialized( @@ -1534,7 +1659,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { desired_action, place_span, mpi, - curr_move_outs, ); return; // don't bother finding other problems. } @@ -1557,12 +1681,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place_span: (&Place<'tcx>, Span), flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { - // FIXME: analogous code in check_loans first maps `place` to - // its base_path ... but is that what we want here? - let place = self.base_path(place_span.0); - let maybe_uninits = &flow_state.uninits; - let curr_move_outs = &flow_state.move_outs; // Bad scenarios: // @@ -1590,15 +1709,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // This code covers scenario 1. - debug!("check_if_path_or_subpath_is_moved place: {:?}", place); - if let Some(mpi) = self.move_path_for_place(place) { + debug!("check_if_path_or_subpath_is_moved place: {:?}", place_span.0); + if let Some(mpi) = self.move_path_for_place(place_span.0) { if let Some(child_mpi) = maybe_uninits.has_any_child_of(mpi) { self.report_use_of_moved_or_uninitialized( context, desired_action, place_span, child_mpi, - curr_move_outs, ); return; // don't bother finding other problems. } @@ -1694,12 +1812,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // be already initialized let tcx = self.tcx; match base.ty(self.mir, tcx).to_ty(tcx).sty { - ty::TyAdt(def, _) if def.has_dtor(tcx) => { - - // FIXME: analogous code in - // check_loans.rs first maps - // `base` to its base_path. - + ty::Adt(def, _) if def.has_dtor(tcx) => { self.check_if_path_or_subpath_is_moved( context, InitializationRequiringAction::Assignment, (base, span), flow_state); @@ -1938,7 +2051,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Check the kind of deref to decide match base_ty.sty { - ty::TyRef(_, _, mutbl) => { + ty::Ref(_, _, mutbl) => { match mutbl { // Shared borrowed data is never mutable hir::MutImmutable => Err(place), @@ -1962,7 +2075,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } } - ty::TyRawPtr(tnm) => { + ty::RawPtr(tnm) => { match tnm.mutbl { // `*const` raw pointers are not mutable hir::MutImmutable => return Err(place), @@ -2072,35 +2185,6 @@ enum Overlap { Disjoint, } -impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { - // FIXME (#16118): function intended to allow the borrow checker - // to be less precise in its handling of Box while still allowing - // moves out of a Box. They should be removed when/if we stop - // treating Box specially (e.g. when/if DerefMove is added...) - - fn base_path<'d>(&self, place: &'d Place<'tcx>) -> &'d Place<'tcx> { - //! Returns the base of the leftmost (deepest) dereference of an - //! Box in `place`. If there is no dereference of an Box - //! in `place`, then it just returns `place` itself. - - let mut cursor = place; - let mut deepest = place; - loop { - let proj = match *cursor { - Place::Promoted(_) | - Place::Local(..) | Place::Static(..) => return deepest, - Place::Projection(ref proj) => proj, - }; - if proj.elem == ProjectionElem::Deref - && place.ty(self.mir, self.tcx).to_ty(self.tcx).is_box() - { - deepest = &proj.base; - } - cursor = &proj.base; - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Debug)] struct Context { kind: ContextKind, diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 103f431d4b..290c703238 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir; +use core::unicode::property::Pattern_White_Space; use rustc::mir::*; use rustc::ty; -use rustc_data_structures::indexed_vec::Idx; use rustc_errors::DiagnosticBuilder; use syntax_pos::Span; use borrow_check::MirBorrowckCtxt; +use borrow_check::prefixes::PrefixSet; use dataflow::move_paths::{IllegalMoveOrigin, IllegalMoveOriginKind}; use dataflow::move_paths::{LookupResult, MoveError, MovePathIndex}; use util::borrowck_errors::{BorrowckErrors, Origin}; @@ -35,17 +35,19 @@ use util::borrowck_errors::{BorrowckErrors, Origin}; // let (&x, &y) = (&String::new(), &String::new()); #[derive(Debug)] enum GroupedMoveError<'tcx> { - // Match place can't be moved from + // Place expression can't be moved from, // e.g. match x[0] { s => (), } where x: &[String] - MovesFromMatchPlace { + MovesFromPlace { + original_path: Place<'tcx>, span: Span, move_from: Place<'tcx>, kind: IllegalMoveOriginKind<'tcx>, binds_to: Vec, }, - // Part of a pattern can't be moved from, + // Part of a value expression can't be moved from, // e.g. match &String::new() { &x => (), } - MovesFromPattern { + MovesFromValue { + original_path: Place<'tcx>, span: Span, move_from: MovePathIndex, kind: IllegalMoveOriginKind<'tcx>, @@ -53,23 +55,27 @@ enum GroupedMoveError<'tcx> { }, // Everything that isn't from pattern matching. OtherIllegalMove { + original_path: Place<'tcx>, span: Span, kind: IllegalMoveOriginKind<'tcx>, }, } impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { - pub(crate) fn report_move_errors(&mut self, move_errors: Vec>) { + pub(crate) fn report_move_errors(&mut self, move_errors: Vec<(Place<'tcx>, MoveError<'tcx>)>) { let grouped_errors = self.group_move_errors(move_errors); for error in grouped_errors { self.report(error); } } - fn group_move_errors(&self, errors: Vec>) -> Vec> { + fn group_move_errors( + &self, + errors: Vec<(Place<'tcx>, MoveError<'tcx>)> + ) -> Vec> { let mut grouped_errors = Vec::new(); - for error in errors { - self.append_to_grouped_errors(&mut grouped_errors, error); + for (original_path, error) in errors { + self.append_to_grouped_errors(&mut grouped_errors, original_path, error); } grouped_errors } @@ -77,6 +83,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { fn append_to_grouped_errors( &self, grouped_errors: &mut Vec>, + original_path: Place<'tcx>, error: MoveError<'tcx>, ) { match error { @@ -111,11 +118,13 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { opt_match_place: Some((ref opt_match_place, match_span)), binding_mode: _, opt_ty_info: _, + pat_span: _, }))) = local_decl.is_user_variable { self.append_binding_error( grouped_errors, kind, + original_path, move_from, *local, opt_match_place, @@ -127,6 +136,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } grouped_errors.push(GroupedMoveError::OtherIllegalMove { span: stmt_source_info.span, + original_path, kind, }); } @@ -137,6 +147,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { &self, grouped_errors: &mut Vec>, kind: IllegalMoveOriginKind<'tcx>, + original_path: Place<'tcx>, move_from: &Place<'tcx>, bind_to: Local, match_place: &Option>, @@ -144,7 +155,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { statement_span: Span, ) { debug!( - "append_to_grouped_errors(match_place={:?}, match_span={:?})", + "append_binding_error(match_place={:?}, match_span={:?})", match_place, match_span ); @@ -155,7 +166,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { // Error with the match place LookupResult::Parent(_) => { for ge in &mut *grouped_errors { - if let GroupedMoveError::MovesFromMatchPlace { span, binds_to, .. } = ge { + if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge { if match_span == *span { debug!("appending local({:?}) to list", bind_to); if !binds_to.is_empty() { @@ -173,9 +184,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } else { (vec![bind_to], match_span) }; - grouped_errors.push(GroupedMoveError::MovesFromMatchPlace { + grouped_errors.push(GroupedMoveError::MovesFromPlace { span, move_from: match_place.clone(), + original_path, kind, binds_to, }); @@ -188,7 +200,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { _ => unreachable!("Probably not unreachable..."), }; for ge in &mut *grouped_errors { - if let GroupedMoveError::MovesFromPattern { + if let GroupedMoveError::MovesFromValue { span, move_from: other_mpi, binds_to, @@ -203,9 +215,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } } debug!("found a new move error location"); - grouped_errors.push(GroupedMoveError::MovesFromPattern { + grouped_errors.push(GroupedMoveError::MovesFromValue { span: match_span, move_from: mpi, + original_path, kind, binds_to: vec![bind_to], }); @@ -215,12 +228,23 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { fn report(&mut self, error: GroupedMoveError<'tcx>) { let (mut err, err_span) = { - let (span, kind): (Span, &IllegalMoveOriginKind) = match error { - GroupedMoveError::MovesFromMatchPlace { span, ref kind, .. } - | GroupedMoveError::MovesFromPattern { span, ref kind, .. } - | GroupedMoveError::OtherIllegalMove { span, ref kind } => (span, kind), - }; + let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind) = + match error { + GroupedMoveError::MovesFromPlace { + span, + ref original_path, + ref kind, + .. + } | + GroupedMoveError::MovesFromValue { span, ref original_path, ref kind, .. } | + GroupedMoveError::OtherIllegalMove { span, ref original_path, ref kind } => { + (span, original_path, kind) + }, + }; let origin = Origin::Mir; + debug!("report: original_path={:?} span={:?}, kind={:?} \ + original_path.is_upvar_field_projection={:?}", original_path, span, kind, + original_path.is_upvar_field_projection(self.mir, &self.tcx)); ( match kind { IllegalMoveOriginKind::Static => { @@ -231,22 +255,17 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { // borrow to provide feedback about why this // was a move rather than a copy. let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx); + let is_upvar_field_projection = + self.prefixes(&original_path, PrefixSet::All) + .any(|p| p.is_upvar_field_projection(self.mir, &self.tcx) + .is_some()); match ty.sty { - ty::TyArray(..) | ty::TySlice(..) => self + ty::Array(..) | ty::Slice(..) => self .tcx .cannot_move_out_of_interior_noncopy(span, ty, None, origin), - ty::TyClosure(def_id, closure_substs) - if !self.mir.upvar_decls.is_empty() - && { - match place { - Place::Projection(ref proj) => { - proj.base == Place::Local(Local::new(1)) - } - Place::Promoted(_) | - Place::Local(_) | Place::Static(_) => unreachable!(), - } - } => - { + ty::Closure(def_id, closure_substs) + if !self.mir.upvar_decls.is_empty() && is_upvar_field_projection + => { let closure_kind_ty = closure_substs.closure_kind_ty(def_id, self.tcx); let closure_kind = closure_kind_ty.to_opt_closure_kind(); @@ -262,7 +281,28 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } None => bug!("closure kind not inferred by borrowck"), }; - self.tcx.cannot_move_out_of(span, place_description, origin) + debug!("report: closure_kind_ty={:?} closure_kind={:?} \ + place_description={:?}", closure_kind_ty, closure_kind, + place_description); + + let mut diag = self.tcx.cannot_move_out_of( + span, place_description, origin); + + for prefix in self.prefixes(&original_path, PrefixSet::All) { + if let Some(field) = prefix.is_upvar_field_projection( + self.mir, &self.tcx) { + let upvar_decl = &self.mir.upvar_decls[field.index()]; + let upvar_hir_id = + upvar_decl.var_hir_id.assert_crate_local(); + let upvar_node_id = + self.tcx.hir.hir_to_node_id(upvar_hir_id); + let upvar_span = self.tcx.hir.span(upvar_node_id); + diag.span_label(upvar_span, "captured outer variable"); + break; + } + } + + diag } _ => self .tcx @@ -291,106 +331,140 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { err: &mut DiagnosticBuilder<'a>, span: Span, ) { + let snippet = self.tcx.sess.source_map().span_to_snippet(span).unwrap(); match error { - GroupedMoveError::MovesFromMatchPlace { + GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => { - // Ok to suggest a borrow, since the target can't be moved from - // anyway. - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { - match move_from { - Place::Projection(ref proj) - if self.suitable_to_remove_deref(proj, &snippet) => - { - err.span_suggestion( - span, - "consider removing this dereference operator", - (&snippet[1..]).to_owned(), - ); - } - _ => { - err.span_suggestion( - span, - "consider using a reference instead", - format!("&{}", snippet), - ); - } - } - - binds_to.sort(); - binds_to.dedup(); - for local in binds_to { - let bind_to = &self.mir.local_decls[local]; - let binding_span = bind_to.source_info.span; - err.span_label( - binding_span, - format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - bind_to.name.unwrap(), - bind_to.ty - ), - ); - } + let try_remove_deref = match move_from { + Place::Projection(box PlaceProjection { + elem: ProjectionElem::Deref, + .. + }) => true, + _ => false, + }; + if try_remove_deref && snippet.starts_with('*') { + // The snippet doesn't start with `*` in (e.g.) index + // expressions `a[b]`, which roughly desugar to + // `*Index::index(&a, b)` or + // `*IndexMut::index_mut(&mut a, b)`. + err.span_suggestion( + span, + "consider removing the `*`", + snippet[1..].to_owned(), + ); + } else { + err.span_suggestion( + span, + "consider borrowing here", + format!("&{}", snippet), + ); } + + binds_to.sort(); + binds_to.dedup(); + self.add_move_error_details(err, &binds_to); } - GroupedMoveError::MovesFromPattern { mut binds_to, .. } => { - // Suggest ref, since there might be a move in - // another match arm + GroupedMoveError::MovesFromValue { mut binds_to, .. } => { binds_to.sort(); binds_to.dedup(); - for local in binds_to { - let bind_to = &self.mir.local_decls[local]; - let binding_span = bind_to.source_info.span; + self.add_move_error_suggestions(err, &binds_to); + self.add_move_error_details(err, &binds_to); + } + // No binding. Nothing to suggest. + GroupedMoveError::OtherIllegalMove { .. } => (), + } + } - // Suggest ref mut when the user has already written mut. - let ref_kind = match bind_to.mutability { - Mutability::Not => "ref", - Mutability::Mut => "ref mut", - }; - match bind_to.name { - Some(name) => { - err.span_suggestion( - binding_span, - "to prevent move, use ref or ref mut", - format!("{} {:?}", ref_kind, name), - ); - } - None => { - err.span_label( - span, - format!("Local {:?} is not suitable for ref", bind_to), - ); - } + fn add_move_error_suggestions( + &self, + err: &mut DiagnosticBuilder<'a>, + binds_to: &[Local], + ) { + let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); + for local in binds_to { + let bind_to = &self.mir.local_decls[*local]; + if let Some( + ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + pat_span, + .. + })) + ) = bind_to.is_user_variable { + let pat_snippet = self + .tcx.sess.source_map() + .span_to_snippet(pat_span) + .unwrap(); + if pat_snippet.starts_with('&') { + let pat_snippet = pat_snippet[1..].trim_left(); + let suggestion; + let to_remove; + if pat_snippet.starts_with("mut") + && pat_snippet["mut".len()..].starts_with(Pattern_White_Space) + { + suggestion = pat_snippet["mut".len()..].trim_left(); + to_remove = "&mut"; + } else { + suggestion = pat_snippet; + to_remove = "&"; } + suggestions.push(( + pat_span, + to_remove, + suggestion.to_owned(), + )); } } - // Nothing to suggest. - GroupedMoveError::OtherIllegalMove { .. } => (), + } + suggestions.sort_unstable_by_key(|&(span, _, _)| span); + suggestions.dedup_by_key(|&mut (span, _, _)| span); + for (span, to_remove, suggestion) in suggestions { + err.span_suggestion( + span, + &format!("consider removing the `{}`", to_remove), + suggestion + ); } } - fn suitable_to_remove_deref(&self, proj: &PlaceProjection<'tcx>, snippet: &str) -> bool { - let is_shared_ref = |ty: ty::Ty| match ty.sty { - ty::TypeVariants::TyRef(.., hir::Mutability::MutImmutable) => true, - _ => false, - }; + fn add_move_error_details( + &self, + err: &mut DiagnosticBuilder<'a>, + binds_to: &[Local], + ) { + let mut noncopy_var_spans = Vec::new(); + for (j, local) in binds_to.into_iter().enumerate() { + let bind_to = &self.mir.local_decls[*local]; + let binding_span = bind_to.source_info.span; + + if j == 0 { + err.span_label(binding_span, format!("data moved here")); + } else { + err.span_label(binding_span, format!("...and here")); + } - proj.elem == ProjectionElem::Deref && snippet.starts_with('*') && match proj.base { - Place::Local(local) => { - let local_decl = &self.mir.local_decls[local]; - // If this is a temporary, then this could be from an - // overloaded * operator. - local_decl.is_user_variable.is_some() && is_shared_ref(local_decl.ty) + if binds_to.len() == 1 { + err.span_note( + binding_span, + &format!( + "move occurs because `{}` has type `{}`, \ + which does not implement the `Copy` trait", + bind_to.name.unwrap(), + bind_to.ty + ), + ); + } else { + noncopy_var_spans.push(binding_span); } - Place::Promoted(_) => true, - Place::Static(ref st) => is_shared_ref(st.ty), - Place::Projection(ref proj) => match proj.elem { - ProjectionElem::Field(_, ty) => is_shared_ref(ty), - _ => false, - }, + } + + if binds_to.len() > 1 { + err.span_note( + noncopy_var_spans, + "move occurs because these variables have types that \ + don't implement the `Copy` trait", + ); } } } diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 9a84daf53d..78ab772d9a 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -9,18 +9,21 @@ // except according to those terms. use rustc::hir; -use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Mir}; -use rustc::mir::{Mutability, Place, Projection, ProjectionElem, Static}; -use rustc::ty::{self, TyCtxt}; +use rustc::hir::Node; +use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir}; +use rustc::mir::{Mutability, Operand, Place, Projection, ProjectionElem, Static, Terminator}; +use rustc::mir::TerminatorKind; +use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt}; use rustc_data_structures::indexed_vec::Idx; use syntax_pos::Span; +use dataflow::move_paths::InitLocation; use borrow_check::MirBorrowckCtxt; use util::borrowck_errors::{BorrowckErrors, Origin}; use util::collect_writes::FindAssignments; use util::suggest_ref_mut; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(super) enum AccessKind { MutableBorrow, Mutate, @@ -36,10 +39,18 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { error_access: AccessKind, location: Location, ) { + debug!( + "report_mutability_error(\ + access_place={:?}, span={:?}, the_place_err={:?}, error_access={:?}, location={:?},\ + )", + access_place, span, the_place_err, error_access, location, + ); + let mut err; let item_msg; let reason; let access_place_desc = self.describe_place(access_place); + debug!("report_mutability_error: access_place_desc={:?}", access_place_desc); match the_place_err { Place::Local(local) => { @@ -63,7 +74,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { )); item_msg = format!("`{}`", access_place_desc.unwrap()); - if self.is_upvar(access_place) { + if access_place.is_upvar_field_projection(self.mir, &self.tcx).is_some() { reason = ", as it is not declared as mutable".to_string(); } else { let name = self.mir.upvar_decls[upvar_index.index()].debug_name; @@ -82,7 +93,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { the_place_err.ty(self.mir, self.tcx).to_ty(self.tcx) )); - reason = if self.is_upvar(access_place) { + reason = if access_place.is_upvar_field_projection(self.mir, + &self.tcx).is_some() { ", as it is a captured variable in a `Fn` closure".to_string() } else { ", as `Fn` closures cannot mutate their captured variables".to_string() @@ -119,7 +131,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } } else { item_msg = format!("data in a {}", pointer_type); - reason = "".to_string(); + reason = String::new(); } } } @@ -129,7 +141,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { Place::Static(box Static { def_id, ty: _ }) => { if let Place::Static(_) = access_place { item_msg = format!("immutable static item `{}`", access_place_desc.unwrap()); - reason = "".to_string(); + reason = String::new(); } else { item_msg = format!("`{}`", access_place_desc.unwrap()); let static_name = &self.tcx.item_name(*def_id); @@ -155,12 +167,13 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { }) => bug!("Unexpected immutable place."), } + debug!("report_mutability_error: item_msg={:?}, reason={:?}", item_msg, reason); + // `act` and `acted_on` are strings that let us abstract over // the verbs used in some diagnostic messages. let act; let acted_on; - let span = match error_access { AccessKind::Move => { err = self.tcx @@ -180,34 +193,28 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { act = "borrow as mutable"; acted_on = "borrowed as mutable"; - let closure_span = self.find_closure_span(span, location); - if let Some((args, var)) = closure_span { - err = self.tcx.cannot_borrow_path_as_mutable_because( - args, - &item_msg, - &reason, - Origin::Mir, - ); - err.span_label( - var, - format!( - "mutable borrow occurs due to use of `{}` in closure", - self.describe_place(access_place).unwrap(), - ), - ); - args - } else { - err = self.tcx.cannot_borrow_path_as_mutable_because( - span, - &item_msg, - &reason, - Origin::Mir, - ); - span - } + let borrow_spans = self.borrow_spans(span, location); + let borrow_span = borrow_spans.args_or_use(); + err = self.tcx.cannot_borrow_path_as_mutable_because( + borrow_span, + &item_msg, + &reason, + Origin::Mir, + ); + borrow_spans.var_span_label( + &mut err, + format!( + "mutable borrow occurs due to use of `{}` in closure", + // always Some() if the message is printed. + self.describe_place(access_place).unwrap_or(String::new()), + ) + ); + borrow_span } }; + debug!("report_mutability_error: act={:?}, acted_on={:?}", act, acted_on); + match the_place_err { // We want to suggest users use `let mut` for local (user // variable) mutations... @@ -242,7 +249,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { .var_hir_id .assert_crate_local(); let upvar_node_id = self.tcx.hir.hir_to_node_id(upvar_hir_id); - if let Some(hir::map::NodeBinding(pat)) = self.tcx.hir.find(upvar_node_id) { + if let Some(Node::Binding(pat)) = self.tcx.hir.find(upvar_node_id) { if let hir::PatKind::Binding( hir::BindingAnnotation::Unannotated, _, @@ -264,7 +271,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { // a local variable, then just suggest the user remove it. Place::Local(_) if { - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { snippet.starts_with("&mut ") } else { false @@ -307,7 +314,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { let local_decl = &self.mir.local_decls[*local]; let suggestion = match local_decl.is_user_variable.as_ref().unwrap() { ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => { - Some(suggest_ampmut_self(local_decl)) + Some(suggest_ampmut_self(self.tcx, local_decl)) } ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { @@ -325,7 +332,11 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { binding_mode: ty::BindingMode::BindByReference(_), .. - })) => suggest_ref_mut(self.tcx, local_decl.source_info.span), + })) => { + let pattern_span = local_decl.source_info.span; + suggest_ref_mut(self.tcx, pattern_span) + .map(|replacement| (pattern_span, replacement)) + } // ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => unreachable!(), @@ -384,6 +395,63 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { ); } + Place::Projection(box Projection { + base: Place::Local(local), + elem: ProjectionElem::Deref, + }) if error_access == AccessKind::MutableBorrow => { + err.span_label(span, format!("cannot {ACT}", ACT = act)); + + let mpi = self.move_data.rev_lookup.find_local(*local); + for i in self.move_data.init_path_map[mpi].iter() { + if let InitLocation::Statement(location) = self.move_data.inits[*i].location { + if let Some( + Terminator { + kind: TerminatorKind::Call { + func: Operand::Constant(box Constant { + literal: Const { + ty: &TyS { + sty: TyKind::FnDef(id, substs), + .. + }, + .. + }, + .. + }), + .. + }, + .. + } + ) = &self.mir.basic_blocks()[location.block].terminator { + if self.tcx.parent(id) == self.tcx.lang_items().index_trait() { + + let mut found = false; + self.tcx.for_each_relevant_impl( + self.tcx.lang_items().index_mut_trait().unwrap(), + substs.type_at(0), + |_relevant_impl| { + found = true; + } + ); + + let extra = if found { + String::from("") + } else { + format!(", but it is not implemented for `{}`", + substs.type_at(0)) + }; + + err.help( + &format!( + "trait `IndexMut` is required to modify indexed content{}", + extra, + ), + ); + } + } + } + } + } + _ => { err.span_label(span, format!("cannot {ACT}", ACT = act)); } @@ -391,35 +459,24 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { err.buffer(&mut self.errors_buffer); } +} - // Does this place refer to what the user sees as an upvar - fn is_upvar(&self, place: &Place<'tcx>) -> bool { - match *place { - Place::Projection(box Projection { - ref base, - elem: ProjectionElem::Field(_, _), - }) => { - let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx); - is_closure_or_generator(base_ty) - } - Place::Projection(box Projection { - base: - Place::Projection(box Projection { - ref base, - elem: ProjectionElem::Field(upvar_index, _), - }), - elem: ProjectionElem::Deref, - }) => { - let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx); - is_closure_or_generator(base_ty) && self.mir.upvar_decls[upvar_index.index()].by_ref +fn suggest_ampmut_self<'cx, 'gcx, 'tcx>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + local_decl: &mir::LocalDecl<'tcx>, +) -> (Span, String) { + let sp = local_decl.source_info.span; + (sp, match tcx.sess.source_map().span_to_snippet(sp) { + Ok(snippet) => { + let lt_pos = snippet.find('\''); + if let Some(lt_pos) = lt_pos { + format!("&{}mut self", &snippet[lt_pos..snippet.len() - 4]) + } else { + "&mut self".to_string() } - _ => false, } - } -} - -fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(local_decl: &mir::LocalDecl<'tcx>) -> (Span, String) { - (local_decl.source_info.span, "&mut self".to_string()) + _ => "&mut self".to_string() + }) } // When we want to suggest a user change a local variable to be a `&mut`, there @@ -447,9 +504,15 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>( let locations = mir.find_assignments(local); if locations.len() > 0 { let assignment_rhs_span = mir.source_info(locations[0]).span; - let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span); - if let Ok(src) = snippet { - if src.starts_with('&') { + if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { + if let (true, Some(ws_pos)) = ( + src.starts_with("&'"), + src.find(|c: char| -> bool { c.is_whitespace() }), + ) { + let lt_name = &src[1..ws_pos]; + let ty = &src[ws_pos..]; + return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty)); + } else if src.starts_with('&') { let borrowed_expr = src[1..].to_string(); return (assignment_rhs_span, format!("&mut {}", borrowed_expr)); } @@ -466,13 +529,25 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>( None => local_decl.source_info.span, }; + if let Ok(src) = tcx.sess.source_map().span_to_snippet(highlight_span) { + if let (true, Some(ws_pos)) = ( + src.starts_with("&'"), + src.find(|c: char| -> bool { c.is_whitespace() }), + ) { + let lt_name = &src[1..ws_pos]; + let ty = &src[ws_pos..]; + return (highlight_span, format!("&{} mut{}", lt_name, ty)); + } + } + let ty_mut = local_decl.ty.builtin_deref(true).unwrap(); assert_eq!(ty_mut.mutbl, hir::MutImmutable); - if local_decl.ty.is_region_ptr() { - (highlight_span, format!("&mut {}", ty_mut.ty)) - } else { - (highlight_span, format!("*mut {}", ty_mut.ty)) - } + (highlight_span, + if local_decl.ty.is_region_ptr() { + format!("&mut {}", ty_mut.ty) + } else { + format!("*mut {}", ty_mut.ty) + }) } fn is_closure_or_generator(ty: ty::Ty) -> bool { diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 457499ded5..7e8e1b32d4 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -17,7 +17,7 @@ use rustc::infer::InferCtxt; use rustc::mir::visit::TyContext; use rustc::mir::visit::Visitor; use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue}; -use rustc::mir::{Local, Statement, Terminator}; +use rustc::mir::{Statement, Terminator}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::Substs; use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, RegionVid}; @@ -175,10 +175,11 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx self.super_terminator(block, terminator, location); } - fn visit_user_assert_ty( + fn visit_ascribe_user_ty( &mut self, + _place: &Place<'tcx>, + _variance: &ty::Variance, _c_ty: &CanonicalTy<'tcx>, - _local: &Local, _location: Location, ) { } diff --git a/src/librustc_mir/borrow_check/nll/constraints/graph.rs b/src/librustc_mir/borrow_check/nll/constraints/graph.rs index 5f05ae8ade..b1e8b97437 100644 --- a/src/librustc_mir/borrow_check/nll/constraints/graph.rs +++ b/src/librustc_mir/borrow_check/nll/constraints/graph.rs @@ -8,27 +8,90 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet}; +use borrow_check::nll::type_check::Locations; +use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet, OutlivesConstraint}; use rustc::ty::RegionVid; use rustc_data_structures::graph; use rustc_data_structures::indexed_vec::IndexVec; -crate struct ConstraintGraph { +/// The construct graph organizes the constraints by their end-points. +/// It can be used to view a `R1: R2` constraint as either an edge `R1 +/// -> R2` or `R2 -> R1` depending on the direction type `D`. +crate struct ConstraintGraph { + _direction: D, first_constraints: IndexVec>, next_constraints: IndexVec>, } -impl ConstraintGraph { +crate type NormalConstraintGraph = ConstraintGraph; + +crate type ReverseConstraintGraph = ConstraintGraph; + +/// Marker trait that controls whether a `R1: R2` constraint +/// represents an edge `R1 -> R2` or `R2 -> R1`. +crate trait ConstraintGraphDirecton: Copy + 'static { + fn start_region(c: &OutlivesConstraint) -> RegionVid; + fn end_region(c: &OutlivesConstraint) -> RegionVid; + fn is_normal() -> bool; +} + +/// In normal mode, a `R1: R2` constraint results in an edge `R1 -> +/// R2`. This is what we use when constructing the SCCs for +/// inference. This is because we compute the value of R1 by union'ing +/// all the things that it relies on. +#[derive(Copy, Clone, Debug)] +crate struct Normal; + +impl ConstraintGraphDirecton for Normal { + fn start_region(c: &OutlivesConstraint) -> RegionVid { + c.sup + } + + fn end_region(c: &OutlivesConstraint) -> RegionVid { + c.sub + } + + fn is_normal() -> bool { + true + } +} + +/// In reverse mode, a `R1: R2` constraint results in an edge `R2 -> +/// R1`. We use this for optimizing liveness computation, because then +/// we wish to iterate from a region (e.g., R2) to all the regions +/// that will outlive it (e.g., R1). +#[derive(Copy, Clone, Debug)] +crate struct Reverse; + +impl ConstraintGraphDirecton for Reverse { + fn start_region(c: &OutlivesConstraint) -> RegionVid { + c.sub + } + + fn end_region(c: &OutlivesConstraint) -> RegionVid { + c.sup + } + + fn is_normal() -> bool { + false + } +} + +impl ConstraintGraph { /// Create a "dependency graph" where each region constraint `R1: /// R2` is treated as an edge `R1 -> R2`. We use this graph to /// construct SCCs for region inference but also for error /// reporting. - crate fn new(set: &ConstraintSet, num_region_vars: usize) -> Self { + crate fn new( + direction: D, + set: &ConstraintSet, + num_region_vars: usize, + ) -> Self { let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars); let mut next_constraints = IndexVec::from_elem(None, &set.constraints); for (idx, constraint) in set.constraints.iter_enumerated().rev() { - let head = &mut first_constraints[constraint.sup]; + let head = &mut first_constraints[D::start_region(constraint)]; let next = &mut next_constraints[idx]; debug_assert!(next.is_none()); *next = *head; @@ -36,99 +99,156 @@ impl ConstraintGraph { } Self { + _direction: direction, first_constraints, next_constraints, } } + /// Given the constraint set from which this graph was built + /// creates a region graph so that you can iterate over *regions* + /// and not constraints. + crate fn region_graph<'rg>( + &'rg self, + set: &'rg ConstraintSet, + static_region: RegionVid, + ) -> RegionGraph<'rg, D> { + RegionGraph::new(set, self, static_region) + } + /// Given a region `R`, iterate over all constraints `R: R1`. - crate fn outgoing_edges(&self, region_sup: RegionVid) -> Edges<'_> { - let first = self.first_constraints[region_sup]; - Edges { - graph: self, - pointer: first, + crate fn outgoing_edges<'a>( + &'a self, + region_sup: RegionVid, + constraints: &'a ConstraintSet, + static_region: RegionVid, + ) -> Edges<'a, D> { + //if this is the `'static` region and the graph's direction is normal, + //then setup the Edges iterator to return all regions #53178 + if region_sup == static_region && D::is_normal() { + Edges { + graph: self, + constraints, + pointer: None, + next_static_idx: Some(0), + static_region, + } + } else { + //otherwise, just setup the iterator as normal + let first = self.first_constraints[region_sup]; + Edges { + graph: self, + constraints, + pointer: first, + next_static_idx: None, + static_region, + } } } } -crate struct Edges<'s> { - graph: &'s ConstraintGraph, +crate struct Edges<'s, D: ConstraintGraphDirecton> { + graph: &'s ConstraintGraph, + constraints: &'s ConstraintSet, pointer: Option, + next_static_idx: Option, + static_region: RegionVid, } -impl<'s> Iterator for Edges<'s> { - type Item = ConstraintIndex; +impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> { + type Item = OutlivesConstraint; fn next(&mut self) -> Option { if let Some(p) = self.pointer { self.pointer = self.graph.next_constraints[p]; - Some(p) + + Some(self.constraints[p]) + } else if let Some(next_static_idx) = self.next_static_idx { + self.next_static_idx = + if next_static_idx == (self.graph.first_constraints.len() - 1) { + None + } else { + Some(next_static_idx + 1) + }; + + Some(OutlivesConstraint { + sup: self.static_region, + sub: next_static_idx.into(), + locations: Locations::All, + }) } else { None } } } -crate struct RegionGraph<'s> { +/// This struct brings together a constraint set and a (normal, not +/// reverse) constraint graph. It implements the graph traits and is +/// usd for doing the SCC computation. +crate struct RegionGraph<'s, D: ConstraintGraphDirecton> { set: &'s ConstraintSet, - constraint_graph: &'s ConstraintGraph, + constraint_graph: &'s ConstraintGraph, + static_region: RegionVid, } -impl<'s> RegionGraph<'s> { +impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> { /// Create a "dependency graph" where each region constraint `R1: /// R2` is treated as an edge `R1 -> R2`. We use this graph to /// construct SCCs for region inference but also for error /// reporting. - crate fn new(set: &'s ConstraintSet, constraint_graph: &'s ConstraintGraph) -> Self { + crate fn new( + set: &'s ConstraintSet, + constraint_graph: &'s ConstraintGraph, + static_region: RegionVid, + ) -> Self { Self { set, constraint_graph, + static_region, } } /// Given a region `R`, iterate over all regions `R1` such that /// there exists a constraint `R: R1`. - crate fn sub_regions(&self, region_sup: RegionVid) -> Successors<'_> { + crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, D> { Successors { - set: self.set, - edges: self.constraint_graph.outgoing_edges(region_sup), + edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region), } } } -crate struct Successors<'s> { - set: &'s ConstraintSet, - edges: Edges<'s>, +crate struct Successors<'s, D: ConstraintGraphDirecton> { + edges: Edges<'s, D>, } -impl<'s> Iterator for Successors<'s> { +impl<'s, D: ConstraintGraphDirecton> Iterator for Successors<'s, D> { type Item = RegionVid; fn next(&mut self) -> Option { - self.edges.next().map(|c| self.set[c].sub) + self.edges.next().map(|c| D::end_region(&c)) } } -impl<'s> graph::DirectedGraph for RegionGraph<'s> { +impl<'s, D: ConstraintGraphDirecton> graph::DirectedGraph for RegionGraph<'s, D> { type Node = RegionVid; } -impl<'s> graph::WithNumNodes for RegionGraph<'s> { +impl<'s, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, D> { fn num_nodes(&self) -> usize { self.constraint_graph.first_constraints.len() } } -impl<'s> graph::WithSuccessors for RegionGraph<'s> { +impl<'s, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, D> { fn successors<'graph>( &'graph self, node: Self::Node, ) -> >::Iter { - self.sub_regions(node) + self.outgoing_regions(node) } } -impl<'s, 'graph> graph::GraphSuccessors<'graph> for RegionGraph<'s> { +impl<'s, 'graph, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph> for RegionGraph<'s, D> { type Item = RegionVid; - type Iter = Successors<'graph>; + type Iter = Successors<'graph, D>; } diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/nll/constraints/mod.rs index 597241234c..41c846509c 100644 --- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs +++ b/src/librustc_mir/borrow_check/nll/constraints/mod.rs @@ -36,12 +36,20 @@ impl ConstraintSet { self.constraints.push(constraint); } - /// Constructs a graph from the constraint set; the graph makes it - /// easy to find the constraints affecting a particular region - /// (you should not mutate the set once this graph is - /// constructed). - crate fn graph(&self, num_region_vars: usize) -> graph::ConstraintGraph { - graph::ConstraintGraph::new(self, num_region_vars) + /// Constructs a "normal" graph from the constraint set; the graph makes it + /// easy to find the constraints affecting a particular region. + /// + /// NB: This graph contains a "frozen" view of the current + /// constraints. any new constraints added to the `ConstraintSet` + /// after the graph is built will not be present in the graph. + crate fn graph(&self, num_region_vars: usize) -> graph::NormalConstraintGraph { + graph::ConstraintGraph::new(graph::Normal, self, num_region_vars) + } + + /// Like `graph`, but constraints a reverse graph where `R1: R2` + /// represents an edge `R2 -> R1`. + crate fn reverse_graph(&self, num_region_vars: usize) -> graph::ReverseConstraintGraph { + graph::ConstraintGraph::new(graph::Reverse, self, num_region_vars) } /// Compute cycles (SCCs) in the graph of regions. In particular, @@ -49,9 +57,10 @@ impl ConstraintSet { /// them into an SCC, and find the relationships between SCCs. crate fn compute_sccs( &self, - constraint_graph: &graph::ConstraintGraph, + constraint_graph: &graph::NormalConstraintGraph, + static_region: RegionVid, ) -> Sccs { - let region_graph = &graph::RegionGraph::new(self, constraint_graph); + let region_graph = &constraint_graph.region_graph(self, static_region); Sccs::new(region_graph) } } @@ -90,6 +99,14 @@ impl fmt::Debug for OutlivesConstraint { } } -newtype_index!(ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" }); +newtype_index! { + pub struct ConstraintIndex { + DEBUG_FORMAT = "ConstraintIndex({})" + } +} -newtype_index!(ConstraintSccIndex { DEBUG_FORMAT = "ConstraintSccIndex({})" }); +newtype_index! { + pub struct ConstraintSccIndex { + DEBUG_FORMAT = "ConstraintSccIndex({})" + } +} diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs index aa88fa1117..a35117f2e3 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs @@ -17,7 +17,7 @@ use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor}; use rustc::mir::{Local, Location, Mir}; use rustc::ty::{RegionVid, TyCtxt}; use rustc_data_structures::fx::FxHashSet; -use util::liveness::{self, DefUse, LivenessMode}; +use util::liveness::{self, DefUse}; crate fn find<'tcx>( mir: &Mir<'tcx>, @@ -32,10 +32,6 @@ crate fn find<'tcx>( tcx, region_vid, start_point, - liveness_mode: LivenessMode { - include_regular_use: true, - include_drops: true, - }, }; uf.find() @@ -47,7 +43,6 @@ struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'gcx, 'tcx>, region_vid: RegionVid, start_point: Location, - liveness_mode: LivenessMode, } impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> { @@ -108,7 +103,6 @@ impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> { mir: self.mir, tcx: self.tcx, region_vid: self.region_vid, - liveness_mode: self.liveness_mode, def_use_result: None, }; @@ -122,7 +116,6 @@ struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> { mir: &'cx Mir<'tcx>, tcx: TyCtxt<'cx, 'gcx, 'tcx>, region_vid: RegionVid, - liveness_mode: LivenessMode, def_use_result: Option, } @@ -146,23 +139,12 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> { }); if found_it { - match liveness::categorize(context, self.liveness_mode) { - Some(DefUse::Def) => { - self.def_use_result = Some(DefUseResult::Def); - } - - Some(DefUse::Use) => { - self.def_use_result = if context.is_drop() { - Some(DefUseResult::UseDrop { local }) - } else { - Some(DefUseResult::UseLive { local }) - }; - } - - None => { - self.def_use_result = None; - } - } + self.def_use_result = match liveness::categorize(context) { + Some(DefUse::Def) => Some(DefUseResult::Def), + Some(DefUse::Use) => Some(DefUseResult::UseLive { local }), + Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }), + None => None, + }; } } } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index cdb0351d9a..414cb1d6f0 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -11,11 +11,28 @@ use borrow_check::borrow_set::BorrowData; use borrow_check::nll::region_infer::Cause; use borrow_check::{Context, MirBorrowckCtxt, WriteKind}; -use rustc::mir::Place; +use rustc::mir::{Local, Location, Place, TerminatorKind}; use rustc_errors::DiagnosticBuilder; +use rustc::ty::Region; mod find_use; +#[derive(Copy, Clone, Debug)] +pub enum BorrowContainsPointReason<'tcx> { + Liveness { + local: Local, + location: Location, + in_loop: bool, + }, + DropLiveness { + local: Local, + location: Location, + }, + OutlivesFreeRegion { + outlived_region: Option>, + }, +} + impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Adds annotations to `err` explaining *why* the borrow contains the /// point from `context`. This is key for the "3-point errors" @@ -32,15 +49,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points pub(in borrow_check) fn explain_why_borrow_contains_point( - &mut self, + &self, context: Context, borrow: &BorrowData<'tcx>, kind_place: Option<(WriteKind, &Place<'tcx>)>, err: &mut DiagnosticBuilder<'_>, ) { + let reason = self.find_why_borrow_contains_point(context, borrow); + self.report_why_borrow_contains_point(err, reason, kind_place); + } + + /// Finds the reason that [explain_why_borrow_contains_point] will report + /// but doesn't add it to any message. This is a separate function in case + /// the caller wants to change the error they report based on the reason + /// that will be reported. + pub(in borrow_check) fn find_why_borrow_contains_point( + &self, + context: Context, + borrow: &BorrowData<'tcx> + ) -> BorrowContainsPointReason<'tcx> { + use self::BorrowContainsPointReason::*; + debug!( - "explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})", - context, borrow, kind_place, + "find_why_borrow_contains_point(context={:?}, borrow={:?})", + context, borrow, ); let regioncx = &self.nonlexical_regioncx; @@ -62,14 +94,60 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); match find_use::find(mir, regioncx, tcx, region_sub, context.loc) { - Some(Cause::LiveVar(_local, location)) => { - err.span_label( - mir.source_info(location).span, - "borrow later used here".to_string(), - ); - } + Some(Cause::LiveVar(local, location)) => Liveness { + local, + location, + in_loop: self.is_borrow_location_in_loop(context.loc), + }, + Some(Cause::DropVar(local, location)) => DropLiveness { + local, + location, + }, + None => OutlivesFreeRegion { + outlived_region: regioncx.to_error_region(region_sub), + }, + } + } + + /// Adds annotations to `err` for the explanation `reason`. This is a + /// separate method so that the caller can change their error message based + /// on the reason that is going to be reported. + pub (in borrow_check) fn report_why_borrow_contains_point( + &self, + err: &mut DiagnosticBuilder, + reason: BorrowContainsPointReason<'tcx>, + kind_place: Option<(WriteKind, &Place<'tcx>)>, + ) { + use self::BorrowContainsPointReason::*; - Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name { + debug!( + "find_why_borrow_contains_point(reason={:?}, kind_place={:?})", + reason, kind_place, + ); + + let mir = self.mir; + + match reason { + Liveness { local, location, in_loop } => { + let span = mir.source_info(location).span; + let spans = self.move_spans(&Place::Local(local), location) + .or_else(|| self.borrow_spans(span, location)); + let message = if in_loop { + if spans.for_closure() { + "borrow captured here by closure in later iteration of loop" + } else { + "borrow used here in later iteration of loop" + } + } else { + if spans.for_closure() { + "borrow later captured here by closure" + } else { + "borrow later used here" + } + }; + err.span_label(spans.var_or_use(), message); + } + DropLiveness { local, location } => match &mir.local_decls[local].name { Some(local_name) => { err.span_label( mir.source_info(location).span, @@ -80,12 +158,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let Place::Local(borrowed_local) = place { let dropped_local_scope = mir.local_decls[local].visibility_scope; let borrowed_local_scope = - mir.local_decls[*borrowed_local].visibility_scope; + mir.local_decls[*borrowed_local].visibility_scope; if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) { err.note( - "values in a scope are dropped \ - in the opposite order they are defined", + "values in a scope are dropped \ + in the opposite order they are defined", ); } } @@ -93,18 +171,89 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } None => {} - }, + } + OutlivesFreeRegion { outlived_region: Some(region) } => { + self.tcx.note_and_explain_free_region( + err, + "borrowed value must be valid for ", + region, + "...", + ); + } + OutlivesFreeRegion { outlived_region: None } => (), + } + } - None => { - if let Some(region) = regioncx.to_error_region(region_sub) { - self.tcx.note_and_explain_free_region( - err, - "borrowed value must be valid for ", - region, - "...", - ); + /// Check if a borrow location is within a loop. + fn is_borrow_location_in_loop( + &self, + borrow_location: Location, + ) -> bool { + let mut visited_locations = Vec::new(); + let mut pending_locations = vec![ borrow_location ]; + debug!("is_in_loop: borrow_location={:?}", borrow_location); + + while let Some(location) = pending_locations.pop() { + debug!("is_in_loop: location={:?} pending_locations={:?} visited_locations={:?}", + location, pending_locations, visited_locations); + if location == borrow_location && visited_locations.contains(&borrow_location) { + // We've managed to return to where we started (and this isn't the start of the + // search). + debug!("is_in_loop: found!"); + return true; + } + + // Skip locations we've been. + if visited_locations.contains(&location) { continue; } + + let block = &self.mir.basic_blocks()[location.block]; + if location.statement_index == block.statements.len() { + // Add start location of the next blocks to pending locations. + match block.terminator().kind { + TerminatorKind::Goto { target } => { + pending_locations.push(target.start_location()); + }, + TerminatorKind::SwitchInt { ref targets, .. } => { + for target in targets { + pending_locations.push(target.start_location()); + } + }, + TerminatorKind::Drop { target, unwind, .. } | + TerminatorKind::DropAndReplace { target, unwind, .. } | + TerminatorKind::Assert { target, cleanup: unwind, .. } | + TerminatorKind::Yield { resume: target, drop: unwind, .. } | + TerminatorKind::FalseUnwind { real_target: target, unwind, .. } => { + pending_locations.push(target.start_location()); + if let Some(unwind) = unwind { + pending_locations.push(unwind.start_location()); + } + }, + TerminatorKind::Call { ref destination, cleanup, .. } => { + if let Some((_, destination)) = destination { + pending_locations.push(destination.start_location()); + } + if let Some(cleanup) = cleanup { + pending_locations.push(cleanup.start_location()); + } + }, + TerminatorKind::FalseEdges { real_target, ref imaginary_targets, .. } => { + pending_locations.push(real_target.start_location()); + for target in imaginary_targets { + pending_locations.push(target.start_location()); + } + }, + _ => {}, } + } else { + // Add the next statement to pending locations. + pending_locations.push(location.successor_within_block()); } + + // Keep track of where we have visited. + visited_locations.push(location); } + + false } } + diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 8eb052f88e..465707ecc1 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -100,18 +100,6 @@ impl Atom for LocationIndex { } } -impl From for LocationIndex { - fn from(i: usize) -> LocationIndex { - LocationIndex::new(i) - } -} - -impl From for usize { - fn from(vid: LocationIndex) -> usize { - Idx::index(vid) - } -} - struct FactWriter<'w> { location_table: &'w LocationTable, dir: &'w Path, diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 301999cc4a..71345f22e4 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -144,10 +144,10 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc // EndRegion matters to older NLL/MIR AST borrowck, not to alias NLL StatementKind::EndRegion(..) | StatementKind::Nop | - StatementKind::UserAssertTy(..) | + StatementKind::AscribeUserType(..) | StatementKind::Validate(..) | StatementKind::StorageLive(..) => { - // `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant + // `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant // to borrow check. } StatementKind::StorageDead(local) => { @@ -312,26 +312,26 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> { // individual fields instead. This way if `foo` has a // destructor but `bar` does not, we will only check for // borrows of `x.foo` and not `x.bar`. See #47703. - ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.infcx.tcx) => { + ty::Adt(def, substs) if def.is_struct() && !def.has_dtor(self.infcx.tcx) => { def.all_fields() .map(|field| field.ty(gcx, substs)) .enumerate() .for_each(|field| drop_field(self, field)); } // Same as above, but for tuples. - ty::TyTuple(tys) => { + ty::Tuple(tys) => { tys.iter().cloned().enumerate() .for_each(|field| drop_field(self, field)); } // Closures and generators also have disjoint fields, but they are only // directly accessed in the body of the closure/generator. - ty::TyGenerator(def, substs, ..) + ty::Generator(def, substs, ..) if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() => { substs.upvar_tys(def, self.infcx.tcx).enumerate() .for_each(|field| drop_field(self, field)); } - ty::TyClosure(def, substs) + ty::Closure(def, substs) if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() => { substs.upvar_tys(def, self.infcx.tcx).enumerate() @@ -541,7 +541,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> { // unique or mutable borrows are invalidated by writes. // Reservations count as writes since we need to check // that activating the borrow will be OK - // TOOD(bob_twinkles) is this actually the right thing to do? + // FIXME(bob_twinkles) is this actually the right thing to do? this.generate_invalidates(borrow_index, context.loc); } } diff --git a/src/librustc_mir/borrow_check/nll/liveness_map.rs b/src/librustc_mir/borrow_check/nll/liveness_map.rs deleted file mode 100644 index cbd9c9a4e1..0000000000 --- a/src/librustc_mir/borrow_check/nll/liveness_map.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! For the NLL computation, we need to compute liveness, but only for those -//! local variables whose types contain regions. The others are not of interest -//! to us. This file defines a new index type (LocalWithRegion) that indexes into -//! a list of "variables whose type contain regions". It also defines a map from -//! Local to LocalWithRegion and vice versa -- this map can be given to the -//! liveness code so that it only operates over variables with regions in their -//! types, instead of all variables. - -use rustc::ty::TypeFoldable; -use rustc_data_structures::indexed_vec::IndexVec; -use rustc::mir::{Mir, Local}; -use util::liveness::LiveVariableMap; - -use rustc_data_structures::indexed_vec::Idx; - -/// Map between Local and LocalWithRegion indices: this map is supplied to the -/// liveness code so that it will only analyze those variables whose types -/// contain regions. -crate struct NllLivenessMap { - /// For each local variable, contains either None (if the type has no regions) - /// or Some(i) with a suitable index. - pub from_local: IndexVec>, - /// For each LocalWithRegion, maps back to the original Local index. - pub to_local: IndexVec, - -} - -impl LiveVariableMap for NllLivenessMap { - - fn from_local(&self, local: Local) -> Option { - self.from_local[local] - } - - type LiveVar = LocalWithRegion; - - fn from_live_var(&self, local: Self::LiveVar) -> Local { - self.to_local[local] - } - - fn num_variables(&self) -> usize { - self.to_local.len() - } -} - -impl NllLivenessMap { - /// Iterates over the variables in Mir and assigns each Local whose type contains - /// regions a LocalWithRegion index. Returns a map for converting back and forth. - pub fn compute(mir: &Mir) -> Self { - let mut to_local = IndexVec::default(); - let from_local: IndexVec> = mir - .local_decls - .iter_enumerated() - .map(|(local, local_decl)| { - if local_decl.ty.has_free_regions() { - Some(to_local.push(local)) - } - else { - None - } - }).collect(); - - Self { from_local, to_local } - } -} - -/// Index given to each local variable whose type contains a region. -newtype_index!(LocalWithRegion); diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 973568a67f..7cab0acb43 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -11,9 +11,9 @@ use borrow_check::borrow_set::BorrowSet; use borrow_check::location::{LocationIndex, LocationTable}; use borrow_check::nll::facts::AllFactsExt; -use borrow_check::nll::type_check::MirTypeckRegionConstraints; +use borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints}; +use borrow_check::nll::type_check::liveness::liveness_map::NllLivenessMap; use borrow_check::nll::region_infer::values::RegionValueElements; -use borrow_check::nll::liveness_map::{NllLivenessMap, LocalWithRegion}; use dataflow::indexes::BorrowIndex; use dataflow::move_paths::MoveData; use dataflow::FlowAtLocation; @@ -22,9 +22,7 @@ use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir}; use rustc::ty::{self, RegionKind, RegionVid}; -use rustc::util::nodemap::FxHashMap; use rustc_errors::Diagnostic; -use std::collections::BTreeSet; use std::fmt::Debug; use std::env; use std::io; @@ -32,12 +30,11 @@ use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; use transform::MirSource; -use util::liveness::{LivenessResults, LiveVarSet}; use self::mir_util::PassWhere; use polonius_engine::{Algorithm, Output}; use util as mir_util; -use util::pretty::{self, ALIGN}; +use util::pretty; mod constraint_generation; pub mod explain_borrow; @@ -47,7 +44,6 @@ crate mod region_infer; mod renumber; crate mod type_check; mod universal_regions; -crate mod liveness_map; mod constraints; @@ -109,9 +105,10 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( let elements = &Rc::new(RegionValueElements::new(mir)); // Run the MIR type-checker. - let liveness_map = NllLivenessMap::compute(&mir); - let liveness = LivenessResults::compute(mir, &liveness_map); - let (constraint_sets, universal_region_relations) = type_check::type_check( + let MirTypeckResults { + constraints, + universal_region_relations, + } = type_check::type_check( infcx, param_env, mir, @@ -119,12 +116,10 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( &universal_regions, location_table, borrow_set, - &liveness, &mut all_facts, flow_inits, move_data, elements, - errors_buffer, ); if let Some(all_facts) = &mut all_facts { @@ -141,7 +136,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( mut liveness_constraints, outlives_constraints, type_tests, - } = constraint_sets; + } = constraints; constraint_generation::generate_constraints( infcx, @@ -204,7 +199,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( // write unit-tests, as well as helping with debugging. dump_mir_results( infcx, - &liveness, MirSource::item(def_id), &mir, ®ioncx, @@ -220,7 +214,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( fn dump_mir_results<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, - liveness: &LivenessResults, source: MirSource, mir: &Mir<'tcx>, regioncx: &RegionInferenceContext, @@ -230,36 +223,6 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( return; } - let map = &NllLivenessMap::compute(mir); - - let regular_liveness_per_location: FxHashMap<_, _> = mir - .basic_blocks() - .indices() - .flat_map(|bb| { - let mut results = vec![]; - liveness - .regular - .simulate_block(&mir, bb, map, |location, local_set| { - results.push((location, local_set.clone())); - }); - results - }) - .collect(); - - let drop_liveness_per_location: FxHashMap<_, _> = mir - .basic_blocks() - .indices() - .flat_map(|bb| { - let mut results = vec![]; - liveness - .drop - .simulate_block(&mir, bb, map, |location, local_set| { - results.push((location, local_set.clone())); - }); - results - }) - .collect(); - mir_util::dump_mir( infcx.tcx, None, @@ -282,26 +245,10 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( } } - PassWhere::BeforeLocation(location) => { - let s = live_variable_set( - ®ular_liveness_per_location[&location], - &drop_liveness_per_location[&location], - ); - writeln!( - out, - "{:ALIGN$} | Live variables on entry to {:?}: {}", - "", - location, - s, - ALIGN = ALIGN - )?; + PassWhere::BeforeLocation(_) => { } - // After each basic block, dump out the values - // that are live on exit from the basic block. - PassWhere::AfterTerminator(bb) => { - let s = live_variable_set(&liveness.regular.outs[bb], &liveness.drop.outs[bb]); - writeln!(out, " | Live variables on exit from {:?}: {}", bb, s)?; + PassWhere::AfterTerminator(_) => { } PassWhere::BeforeBlock(_) | PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {} @@ -311,14 +258,14 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( ); // Also dump the inference graph constraints as a graphviz file. - let _: io::Result<()> = do catch { + let _: io::Result<()> = try_block! { let mut file = pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, source)?; regioncx.dump_graphviz_raw_constraints(&mut file)?; }; // Also dump the inference graph constraints as a graphviz file. - let _: io::Result<()> = do catch { + let _: io::Result<()> = try_block! { let mut file = pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, source)?; regioncx.dump_graphviz_scc_constraints(&mut file)?; @@ -329,7 +276,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, mir: &Mir<'tcx>, mir_def_id: DefId, - regioncx: &RegionInferenceContext, + regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option, errors_buffer: &mut Vec, ) { @@ -352,7 +299,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>( .diagnostic() .span_note_diag(mir.span, "External requirements"); - regioncx.annotate(&mut err); + regioncx.annotate(tcx, &mut err); err.note(&format!( "number of external vids: {}", @@ -372,7 +319,7 @@ fn dump_annotation<'a, 'gcx, 'tcx>( .sess .diagnostic() .span_note_diag(mir.span, "No external requirements"); - regioncx.annotate(&mut err); + regioncx.annotate(tcx, &mut err); err.buffer(errors_buffer); } @@ -419,33 +366,3 @@ impl ToRegionVid for RegionVid { self } } - -fn live_variable_set( - regular: &LiveVarSet, - drops: &LiveVarSet -) -> String { - // sort and deduplicate: - let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect(); - - // construct a string with each local, including `(drop)` if it is - // only dropped, versus a regular use. - let mut string = String::new(); - for local in all_locals { - string.push_str(&format!("{:?}", local)); - - if !regular.contains(&local) { - assert!(drops.contains(&local)); - string.push_str(" (drop)"); - } - - string.push_str(", "); - } - - let len = if string.is_empty() { - 0 - } else { - string.len() - 2 - }; - - format!("[{}]", &string[..len]) -} diff --git a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs deleted file mode 100644 index 7cde06be0c..0000000000 --- a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! As part of the NLL unit tests, you can annotate a function with -//! `#[rustc_regions]`, and we will emit information about the region -//! inference context and -- in particular -- the external constraints -//! that this region imposes on others. The methods in this file -//! handle the part about dumping the inference context internal -//! state. - -use borrow_check::nll::region_infer::RegionInferenceContext; -use borrow_check::nll::universal_regions::DefiningTy; -use rustc_errors::DiagnosticBuilder; - -impl<'tcx> RegionInferenceContext<'tcx> { - /// Write out our state into the `.mir` files. - pub(crate) fn annotate(&self, err: &mut DiagnosticBuilder<'_>) { - match self.universal_regions.defining_ty { - DefiningTy::Closure(def_id, substs) => { - err.note(&format!( - "defining type: {:?} with closure substs {:#?}", - def_id, - &substs.substs[..] - )); - } - DefiningTy::Generator(def_id, substs, _) => { - err.note(&format!( - "defining type: {:?} with generator substs {:#?}", - def_id, - &substs.substs[..] - )); - } - DefiningTy::FnDef(def_id, substs) => { - err.note(&format!( - "defining type: {:?} with substs {:#?}", - def_id, - &substs[..] - )); - } - DefiningTy::Const(def_id, substs) => { - err.note(&format!( - "defining constant type: {:?} with substs {:#?}", - def_id, - &substs[..] - )); - } - } - } -} diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index 8fbb4aafc1..0b9b9b33b3 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext}; +use borrow_check::nll::constraints::OutlivesConstraint; +use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::type_check::Locations; use rustc::hir::def_id::DefId; use rustc::infer::error_reporting::nice_region_error::NiceRegionError; use rustc::infer::InferCtxt; use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind}; -use rustc::ty::RegionVid; +use rustc::ty::{TyCtxt, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; use std::collections::VecDeque; @@ -42,7 +43,7 @@ impl fmt::Display for ConstraintCategory { // Must end with a space. Allows for empty names to be provided. match self { ConstraintCategory::Assignment => write!(f, "assignment "), - ConstraintCategory::Return => write!(f, "return "), + ConstraintCategory::Return => write!(f, "returning this value "), ConstraintCategory::Cast => write!(f, "cast "), ConstraintCategory::CallArgument => write!(f, "argument "), _ => write!(f, ""), @@ -53,7 +54,7 @@ impl fmt::Display for ConstraintCategory { #[derive(Copy, Clone, PartialEq, Eq)] enum Trace { StartRegion, - FromConstraint(ConstraintIndex), + FromOutlivesConstraint(OutlivesConstraint), NotVisited, } @@ -67,6 +68,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn best_blame_constraint( &self, mir: &Mir<'tcx>, + tcx: TyCtxt<'_, '_, 'tcx>, from_region: RegionVid, target_test: impl Fn(RegionVid) -> bool, ) -> (ConstraintCategory, Span, RegionVid) { @@ -79,12 +81,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!( "best_blame_constraint: path={:#?}", path.iter() - .map(|&ci| format!( - "{:?}: {:?} ({:?}: {:?})", - ci, - &self.constraints[ci], - self.constraint_sccs.scc(self.constraints[ci].sup), - self.constraint_sccs.scc(self.constraints[ci].sub), + .map(|&c| format!( + "{:?} ({:?}: {:?})", + c, + self.constraint_sccs.scc(c.sup), + self.constraint_sccs.scc(c.sub), )) .collect::>() ); @@ -92,7 +93,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Classify each of the constraints along the path. let mut categorized_path: Vec<(ConstraintCategory, Span)> = path .iter() - .map(|&index| self.classify_constraint(index, mir)) + .map(|&index| self.classify_constraint(index, mir, tcx)) .collect(); debug!( "best_blame_constraint: categorized_path={:#?}", @@ -120,16 +121,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { // highlight (e.g., a call site or something). let target_scc = self.constraint_sccs.scc(target_region); let best_choice = (0..path.len()).rev().find(|&i| { - let constraint = &self.constraints[path[i]]; + let constraint = path[i]; let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); - if constraint_sup_scc == target_scc { - return false; - } match categorized_path[i].0 { ConstraintCategory::Boring => false, - _ => true, + ConstraintCategory::Other => { + // other isn't interesting when the two lifetimes + // are unified. + constraint_sup_scc != self.constraint_sccs.scc(constraint.sub) + } + _ => constraint_sup_scc != target_scc, } }); if let Some(i) = best_choice { @@ -161,7 +164,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, from_region: RegionVid, target_test: impl Fn(RegionVid) -> bool, - ) -> Option<(Vec, RegionVid)> { + ) -> Option<(Vec, RegionVid)> { let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions); context[from_region] = Trace::StartRegion; @@ -182,9 +185,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { Trace::NotVisited => { bug!("found unvisited region {:?} on path to {:?}", p, r) } - Trace::FromConstraint(c) => { + Trace::FromOutlivesConstraint(c) => { result.push(c); - p = self.constraints[c].sup; + p = c.sup; } Trace::StartRegion => { @@ -198,11 +201,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Otherwise, walk over the outgoing constraints and // enqueue any regions we find, keeping track of how we // reached them. - for constraint in self.constraint_graph.outgoing_edges(r) { - assert_eq!(self.constraints[constraint].sup, r); - let sub_region = self.constraints[constraint].sub; + let fr_static = self.universal_regions.fr_static; + for constraint in self.constraint_graph.outgoing_edges(r, + &self.constraints, + fr_static) { + assert_eq!(constraint.sup, r); + let sub_region = constraint.sub; if let Trace::NotVisited = context[sub_region] { - context[sub_region] = Trace::FromConstraint(constraint); + context[sub_region] = Trace::FromOutlivesConstraint(constraint); deque.push_back(sub_region); } } @@ -213,8 +219,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// This function will return true if a constraint is interesting and false if a constraint /// is not. It is useful in filtering constraint paths to only interesting points. - fn constraint_is_interesting(&self, index: ConstraintIndex) -> bool { - let constraint = self.constraints[index]; + fn constraint_is_interesting(&self, constraint: OutlivesConstraint) -> bool { debug!( "constraint_is_interesting: locations={:?} constraint={:?}", constraint.locations, constraint @@ -229,10 +234,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// This function classifies a constraint from a location. fn classify_constraint( &self, - index: ConstraintIndex, + constraint: OutlivesConstraint, mir: &Mir<'tcx>, + tcx: TyCtxt<'_, '_, 'tcx>, ) -> (ConstraintCategory, Span) { - let constraint = self.constraints[index]; debug!("classify_constraint: constraint={:?}", constraint); let span = constraint.locations.span(mir); let location = constraint @@ -240,7 +245,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { .from_location() .unwrap_or(Location::START); - if !self.constraint_is_interesting(index) { + if !self.constraint_is_interesting(constraint) { return (ConstraintCategory::Boring, span); } @@ -254,7 +259,34 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!("classify_constraint: terminator.kind={:?}", terminator.kind); match terminator.kind { TerminatorKind::DropAndReplace { .. } => ConstraintCategory::Assignment, - TerminatorKind::Call { .. } => ConstraintCategory::CallArgument, + // Classify calls differently depending on whether or not + // the sub region appears in the destination type (so the + // sup region is in the return type). If the return type + // contains the sub-region, then this is either an + // assignment or a return, depending on whether we are + // writing to the RETURN_PLACE or not. + // + // The idea here is that the region is being propagated + // from an input into the output place, so it's a kind of + // assignment. Otherwise, if the sub-region only appears in + // the argument types, then use the CallArgument + // classification. + TerminatorKind::Call { destination: Some((ref place, _)), .. } => { + if tcx.any_free_region_meets( + &place.ty(mir, tcx).to_ty(tcx), + |region| self.to_region_vid(region) == constraint.sub, + ) { + match place { + Place::Local(mir::RETURN_PLACE) => ConstraintCategory::Return, + _ => ConstraintCategory::Assignment, + } + } else { + ConstraintCategory::CallArgument + } + } + TerminatorKind::Call { destination: None, .. } => { + ConstraintCategory::CallArgument + } _ => ConstraintCategory::Other, } } else { @@ -304,13 +336,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) { debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let (category, span, _) = self.best_blame_constraint(mir, fr, |r| r == outlived_fr); + let (category, span, _) = self.best_blame_constraint( + mir, + infcx.tcx, + fr, + |r| r == outlived_fr + ); // Check if we can use one of the "nice region errors". if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { let tables = infcx.tcx.typeck_tables_of(mir_def_id); let nice = NiceRegionError::new_from_span(infcx.tcx, span, o, f, Some(tables)); - if let Some(_error_reported) = nice.try_report() { + if let Some(_error_reported) = nice.try_report_from_nll() { return; } } @@ -417,7 +454,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { diag.span_label(span, format!( "{} was supposed to return data with lifetime `{}` but it is returning \ data with lifetime `{}`", - mir_def_name, fr_name, outlived_fr_name, + mir_def_name, outlived_fr_name, fr_name )); }, _ => { @@ -446,10 +483,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { crate fn find_outlives_blame_span( &self, mir: &Mir<'tcx>, + tcx: TyCtxt<'_, '_, 'tcx>, fr1: RegionVid, fr2: RegionVid, ) -> Span { - let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2); + let (_, span, _) = self.best_blame_constraint(mir, tcx, fr1, |r| r == fr2); span } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 8505d8e1ef..5ae123bdc1 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -9,16 +9,17 @@ // except according to those terms. use borrow_check::nll::region_infer::RegionInferenceContext; +use borrow_check::nll::universal_regions::DefiningTy; use borrow_check::nll::ToRegionVid; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::mir::Mir; use rustc::ty::subst::{Substs, UnpackedKind}; -use rustc::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; use rustc::util::ppaux::with_highlight_region; use rustc_errors::DiagnosticBuilder; -use syntax::ast::Name; +use syntax::ast::{Name, DUMMY_NODE_ID}; use syntax::symbol::keywords; use syntax_pos::symbol::InternedString; @@ -61,20 +62,26 @@ impl<'tcx> RegionInferenceContext<'tcx> { assert!(self.universal_regions.is_universal_region(fr)); - self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter, diag) + let value = self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter, diag) .or_else(|| { self.give_name_if_anonymous_region_appears_in_arguments( - infcx, mir, mir_def_id, fr, counter, diag) + infcx, mir, mir_def_id, fr, counter, diag, + ) }) .or_else(|| { self.give_name_if_anonymous_region_appears_in_upvars( - infcx.tcx, mir, fr, counter, diag) + infcx.tcx, mir, fr, counter, diag, + ) }) .or_else(|| { self.give_name_if_anonymous_region_appears_in_output( - infcx.tcx, mir, fr, counter, diag) + infcx, mir, mir_def_id, fr, counter, diag, + ) }) - .unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr)) + .unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr)); + + debug!("give_region_a_name: gave name {:?}", value); + value } /// Check for the case where `fr` maps to something that the @@ -90,23 +97,67 @@ impl<'tcx> RegionInferenceContext<'tcx> { diag: &mut DiagnosticBuilder<'_>, ) -> Option { let error_region = self.to_error_region(fr)?; + debug!("give_region_a_name: error_region = {:?}", error_region); match error_region { - ty::ReEarlyBound(ebr) => Some(ebr.name), + ty::ReEarlyBound(ebr) => { + if ebr.has_name() { + self.highlight_named_span(tcx, error_region, &ebr.name, diag); + Some(ebr.name) + } else { + None + } + } ty::ReStatic => Some(keywords::StaticLifetime.name().as_interned_str()), ty::ReFree(free_region) => match free_region.bound_region { - ty::BoundRegion::BrNamed(_, name) => Some(name), + ty::BoundRegion::BrNamed(_, name) => { + self.highlight_named_span(tcx, error_region, &name, diag); + Some(name) + } ty::BoundRegion::BrEnv => { - let closure_span = tcx.hir.span_if_local(mir_def_id).unwrap(); - let region_name = self.synthesize_region_name(counter); - diag.span_label( - closure_span, - format!("lifetime `{}` represents the closure body", region_name), - ); - Some(region_name) + let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); + let def_ty = self.universal_regions.defining_ty; + + if let DefiningTy::Closure(def_id, substs) = def_ty { + let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) = + tcx.hir.expect_expr(mir_node_id).node + { + span + } else { + bug!("Closure is not defined by a closure expr"); + }; + let region_name = self.synthesize_region_name(counter); + diag.span_label( + args_span, + format!("lifetime `{}` represents this closure's body", region_name), + ); + + let closure_kind_ty = substs.closure_kind_ty(def_id, tcx); + let note = match closure_kind_ty.to_opt_closure_kind() { + Some(ty::ClosureKind::Fn) => { + "closure implements `Fn`, so references to captured variables \ + can't escape the closure" + } + Some(ty::ClosureKind::FnMut) => { + "closure implements `FnMut`, so references to captured variables \ + can't escape the closure" + } + Some(ty::ClosureKind::FnOnce) => { + bug!("BrEnv in a `FnOnce` closure"); + } + None => bug!("Closure kind not inferred in borrow check"), + }; + + diag.note(note); + + Some(region_name) + } else { + // Can't have BrEnv in functions, constants or generators. + bug!("BrEnv outside of closure."); + } } ty::BoundRegion::BrAnon(_) | ty::BoundRegion::BrFresh(_) => None, @@ -123,6 +174,43 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } + /// Highlight a named span to provide context for error messages that + /// mention that span, for example: + /// + /// ``` + /// | + /// | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + /// | -- -- lifetime `'b` defined here + /// | | + /// | lifetime `'a` defined here + /// | + /// | with_signature(cell, t, |cell, t| require(cell, t)); + /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must + /// | outlive `'a` + /// ``` + fn highlight_named_span( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + error_region: &RegionKind, + name: &InternedString, + diag: &mut DiagnosticBuilder<'_>, + ) { + let cm = tcx.sess.source_map(); + + let scope = error_region.free_region_binding_scope(tcx); + let node = tcx.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); + + let mut sp = cm.def_span(tcx.hir.span(node)); + if let Some(param) = tcx.hir + .get_generics(scope) + .and_then(|generics| generics.get_named(name)) + { + sp = param.span; + } + + diag.span_label(sp, format!("lifetime `{}` defined here", name)); + } + /// Find an argument that contains `fr` and label it with a fully /// elaborated type, returning something like `'1`. Result looks /// like: @@ -158,17 +246,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { return Some(region_name); } - let (_argument_name, argument_span) = self.get_argument_name_and_span_for_region( - mir, argument_index); - - let region_name = self.synthesize_region_name(counter); - - diag.span_label( - argument_span, - format!("lifetime `{}` appears in this argument", region_name,), - ); - - Some(region_name) + self.give_name_if_we_cannot_match_hir_ty(infcx, mir, fr, arg_ty, counter, diag) } fn give_name_if_we_can_match_hir_ty_from_argument( @@ -233,8 +311,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx.extract_type_name(&argument_ty) }); - debug!("give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", - type_name, needle_fr); + debug!( + "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", + type_name, needle_fr + ); let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() { // Only add a label if we can confirm that a region was labelled. let argument_index = self.get_argument_index_for_region(infcx.tcx, needle_fr)?; @@ -286,14 +366,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { search_stack.push((argument_ty, argument_hir_ty)); - let mut closest_match: &hir::Ty = argument_hir_ty; - while let Some((ty, hir_ty)) = search_stack.pop() { - // While we search, also track the closet match. - if tcx.any_free_region_meets(&ty, |r| r.to_region_vid() == needle_fr) { - closest_match = hir_ty; - } - match (&ty.sty, &hir_ty.node) { // Check if the `argument_ty` is `&'X ..` where `'X` // is the region we are looking for -- if so, and we have a `&T` @@ -302,15 +375,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { // & // - let's call the lifetime of this reference `'1` ( - ty::TyRef(region, referent_ty, _), + ty::Ref(region, referent_ty, _), hir::TyKind::Rptr(_lifetime, referent_hir_ty), ) => { if region.to_region_vid() == needle_fr { let region_name = self.synthesize_region_name(counter); // Just grab the first character, the `&`. - let codemap = tcx.sess.codemap(); - let ampersand_span = codemap.start_point(hir_ty.span); + let source_map = tcx.sess.source_map(); + let ampersand_span = source_map.start_point(hir_ty.span); diag.span_label( ampersand_span, @@ -329,7 +402,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Match up something like `Foo<'1>` ( - ty::TyAdt(_adt_def, substs), + ty::Adt(_adt_def, substs), hir::TyKind::Path(hir::QPath::Resolved(None, path)), ) => { if let Some(last_segment) = path.segments.last() { @@ -349,16 +422,16 @@ impl<'tcx> RegionInferenceContext<'tcx> { // The following cases don't have lifetimes, so we // just worry about trying to match up the rustc type // with the HIR types: - (ty::TyTuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => { + (ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => { search_stack.extend(elem_tys.iter().cloned().zip(elem_hir_tys)); } - (ty::TySlice(elem_ty), hir::TyKind::Slice(elem_hir_ty)) - | (ty::TyArray(elem_ty, _), hir::TyKind::Array(elem_hir_ty, _)) => { + (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty)) + | (ty::Array(elem_ty, _), hir::TyKind::Array(elem_hir_ty, _)) => { search_stack.push((elem_ty, elem_hir_ty)); } - (ty::TyRawPtr(mut_ty), hir::TyKind::Ptr(mut_hir_ty)) => { + (ty::RawPtr(mut_ty), hir::TyKind::Ptr(mut_hir_ty)) => { search_stack.push((mut_ty.ty, &mut_hir_ty.ty)); } @@ -368,13 +441,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - let region_name = self.synthesize_region_name(counter); - diag.span_label( - closest_match.span, - format!("lifetime `{}` appears in this type", region_name), - ); - - return Some(region_name); + return None; } /// We've found an enum/struct/union type with the substitutions @@ -479,13 +546,16 @@ impl<'tcx> RegionInferenceContext<'tcx> { diag: &mut DiagnosticBuilder<'_>, ) -> Option { let upvar_index = self.get_upvar_index_for_region(tcx, fr)?; - let (upvar_name, upvar_span) = self.get_upvar_name_and_span_for_region(tcx, mir, - upvar_index); + let (upvar_name, upvar_span) = + self.get_upvar_name_and_span_for_region(tcx, mir, upvar_index); let region_name = self.synthesize_region_name(counter); diag.span_label( upvar_span, - format!("lifetime `{}` appears in the type of `{}`", region_name, upvar_name), + format!( + "lifetime `{}` appears in the type of `{}`", + region_name, upvar_name + ), ); Some(region_name) @@ -497,28 +567,57 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// or be early bound (named, not in argument). fn give_name_if_anonymous_region_appears_in_output( &self, - tcx: TyCtxt<'_, '_, 'tcx>, + infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>, + mir_def_id: DefId, fr: RegionVid, counter: &mut usize, diag: &mut DiagnosticBuilder<'_>, ) -> Option { + let tcx = infcx.tcx; + let return_ty = self.universal_regions.unnormalized_output_ty; debug!( "give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty ); - if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { + if !infcx + .tcx + .any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) + { return None; } - let region_name = self.synthesize_region_name(counter); + let type_name = with_highlight_region(fr, *counter, || infcx.extract_type_name(&return_ty)); + + let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir"); + + let (return_span, mir_description) = + if let hir::ExprKind::Closure(_, _, _, span, gen_move) = + tcx.hir.expect_expr(mir_node_id).node + { + ( + tcx.sess.source_map().end_point(span), + if gen_move.is_some() { + " of generator" + } else { + " of closure" + }, + ) + } else { + // unreachable? + (mir.span, "") + }; + diag.span_label( - mir.span, - format!("lifetime `{}` appears in return type", region_name), + return_span, + format!("return type{} is {}", mir_description, type_name), ); - Some(region_name) + // This counter value will already have been used, so this function will increment it + // so the next value will be used next and return the region name that would have been + // used. + Some(self.synthesize_region_name(counter)) } /// Create a synthetic region named `'1`, incrementing the diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs index f1c3a7489e..57ff0f4c10 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs @@ -13,7 +13,7 @@ use borrow_check::nll::ToRegionVid; use rustc::mir::{Local, Mir}; use rustc::ty::{RegionVid, TyCtxt}; use rustc_data_structures::indexed_vec::Idx; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax_pos::symbol::Symbol; impl<'tcx> RegionInferenceContext<'tcx> { diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs index dd508084d7..34e893d2a5 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs @@ -15,7 +15,6 @@ use super::*; use borrow_check::nll::constraints::OutlivesConstraint; use dot::{self, IntoCow}; -use rustc_data_structures::indexed_vec::Idx; use std::borrow::Cow; use std::io::{self, Write}; diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index afd4e2859a..214628600b 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -9,9 +9,9 @@ // except according to those terms. use super::universal_regions::UniversalRegions; -use borrow_check::nll::constraints::graph::ConstraintGraph; +use borrow_check::nll::constraints::graph::NormalConstraintGraph; use borrow_check::nll::constraints::{ - ConstraintIndex, ConstraintSccIndex, ConstraintSet, OutlivesConstraint, + ConstraintSccIndex, ConstraintSet, OutlivesConstraint, }; use borrow_check::nll::region_infer::values::{RegionElement, ToElementIndex}; use borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations; @@ -27,13 +27,12 @@ use rustc::mir::{ use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc::util::common; use rustc_data_structures::graph::scc::Sccs; -use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; +use rustc_data_structures::indexed_set::IdxSet; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_errors::Diagnostic; +use rustc_errors::{DiagnosticBuilder, Diagnostic}; use std::rc::Rc; -mod annotation; mod dump_mir; mod error_reporting; mod graphviz; @@ -61,7 +60,7 @@ pub struct RegionInferenceContext<'tcx> { /// The constraint-set, but in graph form, making it easy to traverse /// the constraints adjacent to a particular region. Used to construct /// the SCC (see `constraint_sccs`) and for error reporting. - constraint_graph: Rc, + constraint_graph: Rc, /// The SCC computed from `constraints` and the constraint graph. Used to compute the values /// of each region. @@ -234,7 +233,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { let constraints = Rc::new(outlives_constraints); // freeze constraints let constraint_graph = Rc::new(constraints.graph(definitions.len())); - let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph)); + let fr_static = universal_regions.fr_static; + let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static)); let mut scc_values = RegionValues::new(elements, universal_regions.len(), max_universe); @@ -319,23 +319,34 @@ impl<'tcx> RegionInferenceContext<'tcx> { } for variable in self.definitions.indices() { + let scc = self.constraint_sccs.scc(variable); + match self.definitions[variable].origin { NLLRegionVariableOrigin::FreeRegion => { // For each free, universally quantified region X: // Add all nodes in the CFG to liveness constraints - let variable_scc = self.constraint_sccs.scc(variable); self.liveness_constraints.add_all_points(variable); - self.scc_values.add_all_points(variable_scc); + self.scc_values.add_all_points(scc); // Add `end(X)` into the set for X. - self.add_element_to_scc_of(variable, variable); + self.scc_values.add_element(scc, variable); } NLLRegionVariableOrigin::BoundRegion(ui) => { // Each placeholder region X outlives its - // associated universe but nothing else. - self.add_element_to_scc_of(variable, ui); + // associated universe but nothing else. Every + // placeholder region is always in a universe that + // contains `ui` -- but when placeholder regions + // are placed into an SCC, that SCC may include + // things from other universes that do not include + // `ui`. + let scc_universe = self.scc_universes[scc]; + if ui.is_subset_of(scc_universe) { + self.scc_values.add_element(scc, ui); + } else { + self.add_incompatible_universe(scc); + } } NLLRegionVariableOrigin::Existential => { @@ -358,6 +369,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.universal_regions.to_region_vid(r) } + /// Add annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`. + crate fn annotate(&self, tcx: TyCtxt<'_, '_, 'tcx>, err: &mut DiagnosticBuilder<'_>) { + self.universal_regions.annotate(tcx, err) + } + /// Returns true if the region `r` contains the point `p`. /// /// Panics if called before `solve()` executes, @@ -378,13 +394,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.scc_universes[scc] } - /// Adds `elem` to the value of the SCC in which `v` appears. - fn add_element_to_scc_of(&mut self, v: RegionVid, elem: impl ToElementIndex) { - debug!("add_live_element({:?}, {:?})", v, elem); - let scc = self.constraint_sccs.scc(v); - self.scc_values.add_element(scc, elem); - } - /// Perform region inference and report errors if we see any /// unsatisfiable constraints. If this is a closure, returns the /// region requirements to propagate to our creator, if any. @@ -468,7 +477,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // SCC. For each SCC, we visit its successors and compute // their values, then we union all those values to get our // own. - let visited = &mut IdxSetBuf::new_empty(self.constraint_sccs.num_sccs()); + let visited = &mut IdxSet::new_empty(self.constraint_sccs.num_sccs()); for scc_index in self.constraint_sccs.all_sccs() { self.propagate_constraint_sccs_if_new(scc_index, visited); } @@ -511,22 +520,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // merge the bits. self.scc_values.add_region(scc_a, scc_b); } else { - // Otherwise, the only way for `A` to outlive `B` - // is for it to outlive static. This is actually stricter - // than necessary: ideally, we'd support bounds like `for<'a: 'b`>` - // that might then allow us to approximate `'a` with `'b` and not - // `'static`. But it will have to do for now. - // - // The code here is a bit hacky: we grab the current - // value of the SCC in which `'static` appears, but - // this value may not be fully computed yet. That's ok - // though: it will contain the base liveness values, - // which include (a) the static free region element - // and (b) all the points in the CFG, so it is "good - // enough" to bring it in here for our purposes. - let fr_static = self.universal_regions.fr_static; - let scc_static = constraint_sccs.scc(fr_static); - self.scc_values.add_region(scc_a, scc_static); + self.add_incompatible_universe(scc_a); } } @@ -558,6 +552,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { .all(|u| u.is_subset_of(universe_a)) } + /// Extend `scc` so that it can outlive some placeholder region + /// from a universe it can't name; at present, the only way for + /// this to be true is if `scc` outlives `'static`. This is + /// actually stricter than necessary: ideally, we'd support bounds + /// like `for<'a: 'b`>` that might then allow us to approximate + /// `'a` with `'b` and not `'static`. But it will have to do for + /// now. + fn add_incompatible_universe(&mut self, scc: ConstraintSccIndex) { + let fr_static = self.universal_regions.fr_static; + self.scc_values.add_all_points(scc); + self.scc_values.add_element(scc, fr_static); + } + /// Once regions have been propagated, this method is used to see /// whether the "type tests" produced by typeck were satisfied; /// type tests encode type-outlives relationships like `T: @@ -645,6 +652,30 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } + /// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot + /// prove to be satisfied. If this is a closure, we will attempt to + /// "promote" this type-test into our `ClosureRegionRequirements` and + /// hence pass it up the creator. To do this, we have to phrase the + /// type-test in terms of external free regions, as local free + /// regions are not nameable by the closure's creator. + /// + /// Promotion works as follows: we first check that the type `T` + /// contains only regions that the creator knows about. If this is + /// true, then -- as a consequence -- we know that all regions in + /// the type `T` are free regions that outlive the closure body. If + /// false, then promotion fails. + /// + /// Once we've promoted T, we have to "promote" `'X` to some region + /// that is "external" to the closure. Generally speaking, a region + /// may be the union of some points in the closure body as well as + /// various free lifetimes. We can ignore the points in the closure + /// body: if the type T can be expressed in terms of external regions, + /// we know it outlives the points in the closure body. That + /// just leaves the free regions. + /// + /// The idea then is to lower the `T: 'X` constraint into multiple + /// bounds -- e.g., if `'X` is the union of two free lifetimes, + /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. fn try_promote_type_test<'gcx>( &self, infcx: &InferCtxt<'_, 'gcx, 'tcx>, @@ -667,22 +698,44 @@ impl<'tcx> RegionInferenceContext<'tcx> { None => return false, }; - // Find some bounding subject-region R+ that is a super-region - // of the existing subject-region R. This should be a non-local, universal - // region, which ensures it can be encoded in a `ClosureOutlivesRequirement`. - let lower_bound_plus = self.non_local_universal_upper_bound(*lower_bound); - assert!(self.universal_regions.is_universal_region(lower_bound_plus)); - assert!( - !self - .universal_regions - .is_local_free_region(lower_bound_plus) - ); + // For each region outlived by lower_bound find a non-local, + // universal region (it may be the same region) and add it to + // `ClosureOutlivesRequirement`. + let r_scc = self.constraint_sccs.scc(*lower_bound); + for ur in self.scc_values.universal_regions_outlived_by(r_scc) { + // Check whether we can already prove that the "subject" outlives `ur`. + // If so, we don't have to propagate this requirement to our caller. + // + // To continue the example from the function, if we are trying to promote + // a requirement that `T: 'X`, and we know that `'X = '1 + '2` (i.e., the union + // `'1` and `'2`), then in this loop `ur` will be `'1` (and `'2`). So here + // we check whether `T: '1` is something we *can* prove. If so, no need + // to propagate that requirement. + // + // This is needed because -- particularly in the case + // where `ur` is a local bound -- we are sometimes in a + // position to prove things that our caller cannot. See + // #53570 for an example. + if self.eval_region_test(mir, ur, &type_test.test) { + continue; + } - propagated_outlives_requirements.push(ClosureOutlivesRequirement { - subject, - outlived_free_region: lower_bound_plus, - blame_span: locations.span(mir), - }); + debug!("try_promote_type_test: ur={:?}", ur); + + let non_local_ub = self.universal_region_relations.non_local_upper_bound(ur); + debug!("try_promote_type_test: non_local_ub={:?}", non_local_ub); + + assert!(self.universal_regions.is_universal_region(non_local_ub)); + assert!(!self.universal_regions.is_local_free_region(non_local_ub)); + + let requirement = ClosureOutlivesRequirement { + subject, + outlived_free_region: non_local_ub, + blame_span: locations.span(mir), + }; + debug!("try_promote_type_test: pushing {:#?}", requirement); + propagated_outlives_requirements.push(requirement); + } true } @@ -887,8 +940,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // now). Therefore, the sup-region outlives the sub-region if, // for each universal region R1 in the sub-region, there // exists some region R2 in the sup-region that outlives R1. - let universal_outlives = self - .scc_values + let universal_outlives = self.scc_values .universal_regions_outlived_by(sub_region_scc) .all(|r1| { self.scc_values @@ -999,8 +1051,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // (because `fr` includes `end(o)`). for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) { // If it is known that `fr: o`, carry on. - if self - .universal_region_relations + if self.universal_region_relations .outlives(longer_fr, shorter_fr) { continue; @@ -1011,13 +1062,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { longer_fr, shorter_fr, ); - let blame_span = self.find_outlives_blame_span(mir, longer_fr, shorter_fr); + let blame_span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, shorter_fr); if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { // Shrink `fr` until we find a non-local region (if we do). // We'll call that `fr-` -- it's ever so slightly smaller than `fr`. - if let Some(fr_minus) = self - .universal_region_relations + if let Some(fr_minus) = self.universal_region_relations .non_local_lower_bound(longer_fr) { debug!("check_universal_region: fr_minus={:?}", fr_minus); @@ -1026,8 +1076,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // region. (We always will.) We'll call that // `shorter_fr+` -- it's ever so slightly larger than // `fr`. - let shorter_fr_plus = self - .universal_region_relations + let shorter_fr_plus = self.universal_region_relations .non_local_upper_bound(shorter_fr); debug!( "check_universal_region: shorter_fr_plus={:?}", @@ -1087,8 +1136,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let error_region = match error_element { RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), RegionElement::RootUniversalRegion(r) => r, - RegionElement::SubUniversalRegion(error_ui) => self - .definitions + RegionElement::SubUniversalRegion(error_ui) => self.definitions .iter_enumerated() .filter_map(|(r, definition)| match definition.origin { NLLRegionVariableOrigin::BoundRegion(ui) if error_ui == ui => Some(r), @@ -1099,7 +1147,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }; // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let span = self.find_outlives_blame_span(mir, longer_fr, error_region); + let span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, error_region); // Obviously, this error message is far from satisfactory. // At present, though, it only appears in unit tests -- @@ -1185,7 +1233,11 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi // into a vector. These are the regions that we will be // relating to one another. let closure_mapping = &UniversalRegions::closure_mapping( - tcx, user_closure_ty, self.num_external_vids, tcx.closure_base_def_id(closure_def_id)); + tcx, + user_closure_ty, + self.num_external_vids, + tcx.closure_base_def_id(closure_def_id), + ); debug!("apply_requirements: closure_mapping={:?}", closure_mapping); // Create the predicates. diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 8db5809e53..3dafab2f5a 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -10,7 +10,7 @@ use rustc::mir::{BasicBlock, Location, Mir}; use rustc::ty::{self, RegionVid}; -use rustc_data_structures::bitvec::SparseBitMatrix; +use rustc_data_structures::bitvec::{BitArray, SparseBitMatrix}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::IndexVec; use std::fmt::Debug; @@ -20,13 +20,18 @@ use std::rc::Rc; crate struct RegionValueElements { /// For each basic block, how many points are contained within? statements_before_block: IndexVec, + + /// Map backward from each point to the basic block that it + /// belongs to. + basic_blocks: IndexVec, + num_points: usize, } impl RegionValueElements { crate fn new(mir: &Mir<'_>) -> Self { let mut num_points = 0; - let statements_before_block = mir + let statements_before_block: IndexVec = mir .basic_blocks() .iter() .map(|block_data| { @@ -41,14 +46,25 @@ impl RegionValueElements { ); debug!("RegionValueElements: num_points={:#?}", num_points); + let mut basic_blocks = IndexVec::with_capacity(num_points); + for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { + basic_blocks.extend((0 .. bb_data.statements.len() + 1).map(|_| bb)); + } + Self { statements_before_block, + basic_blocks, num_points, } } + /// Total number of point indices + crate fn num_points(&self) -> usize { + self.num_points + } + /// Converts a `Location` into a `PointIndex`. O(1). - fn point_from_location(&self, location: Location) -> PointIndex { + crate fn point_from_location(&self, location: Location) -> PointIndex { let Location { block, statement_index, @@ -57,52 +73,67 @@ impl RegionValueElements { PointIndex::new(start_index + statement_index) } - /// Converts a `PointIndex` back to a location. O(N) where N is - /// the number of blocks; could be faster if we ever cared. - crate fn to_location(&self, i: PointIndex) -> Location { - let point_index = i.index(); - - // Find the basic block. We have a vector with the - // starting index of the statement in each block. Imagine - // we have statement #22, and we have a vector like: - // - // [0, 10, 20] - // - // In that case, this represents point_index 2 of - // basic block BB2. We know this because BB0 accounts for - // 0..10, BB1 accounts for 11..20, and BB2 accounts for - // 20... - // - // To compute this, we could do a binary search, but - // because I am lazy we instead iterate through to find - // the last point where the "first index" (0, 10, or 20) - // was less than the statement index (22). In our case, this will - // be (BB2, 20). - // - // Nit: we could do a binary search here but I'm too lazy. - let (block, &first_index) = self - .statements_before_block - .iter_enumerated() - .filter(|(_, first_index)| **first_index <= point_index) - .last() - .unwrap(); - - Location { - block, - statement_index: point_index - first_index, + /// Converts a `Location` into a `PointIndex`. O(1). + crate fn entry_point(&self, block: BasicBlock) -> PointIndex { + let start_index = self.statements_before_block[block]; + PointIndex::new(start_index) + } + + /// Converts a `PointIndex` back to a location. O(1). + crate fn to_location(&self, index: PointIndex) -> Location { + assert!(index.index() < self.num_points); + let block = self.basic_blocks[index]; + let start_index = self.statements_before_block[block]; + let statement_index = index.index() - start_index; + Location { block, statement_index } + } + + /// Sometimes we get point-indices back from bitsets that may be + /// out of range (because they round up to the nearest 2^N number + /// of bits). Use this function to filter such points out if you + /// like. + crate fn point_in_range(&self, index: PointIndex) -> bool { + index.index() < self.num_points + } + + /// Pushes all predecessors of `index` onto `stack`. + crate fn push_predecessors( + &self, + mir: &Mir<'_>, + index: PointIndex, + stack: &mut Vec, + ) { + let Location { block, statement_index } = self.to_location(index); + if statement_index == 0 { + // If this is a basic block head, then the predecessors are + // the the terminators of other basic blocks + stack.extend( + mir + .predecessors_for(block) + .iter() + .map(|&pred_bb| mir.terminator_loc(pred_bb)) + .map(|pred_loc| self.point_from_location(pred_loc)), + ); + } else { + // Otherwise, the pred is just the previous statement + stack.push(PointIndex::new(index.index() - 1)); } } } /// A single integer representing a `Location` in the MIR control-flow /// graph. Constructed efficiently from `RegionValueElements`. -newtype_index!(PointIndex { DEBUG_FORMAT = "PointIndex({})" }); +newtype_index! { + pub struct PointIndex { DEBUG_FORMAT = "PointIndex({})" } +} /// A single integer representing a (non-zero) `UniverseIndex`. /// Computed just by subtracting one from `UniverseIndex`; this is /// because the `0` value for `UniverseIndex` represents the root /// universe, and we don't need/want a bit for that one. -newtype_index!(PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" }); +newtype_index! { + pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" } +} /// An individual element in a region value -- the value of a /// particular region variable consists of a set of these elements. @@ -151,6 +182,13 @@ impl LivenessValues { self.points.add(row, index) } + /// Adds all the elements in the given bit array into the given + /// region. Returns true if any of them are newly added. + crate fn add_elements(&mut self, row: N, locations: &BitArray) -> bool { + debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations); + self.points.merge_into(row, locations) + } + /// Adds all the control-flow points to the values for `r`. crate fn add_all_points(&mut self, row: N) { self.points.add_all(row); @@ -169,6 +207,7 @@ impl LivenessValues { .row(r) .into_iter() .flat_map(|set| set.iter()) + .take_while(|&p| self.elements.point_in_range(p)) .map(|p| self.elements.to_location(p)) .map(RegionElement::Location), ) @@ -277,7 +316,11 @@ impl RegionValues { self.points .row(r) .into_iter() - .flat_map(move |set| set.iter().map(move |p| self.elements.to_location(p))) + .flat_map(move |set| { + set.iter() + .take_while(move |&p| self.elements.point_in_range(p)) + .map(move |p| self.elements.to_location(p)) + }) } /// Returns just the universal regions that are contained in a given region's value. @@ -366,6 +409,19 @@ impl ToElementIndex for ty::UniverseIndex { } } +crate fn location_set_str( + elements: &RegionValueElements, + points: impl IntoIterator, +) -> String { + region_value_str( + points + .into_iter() + .take_while(|&p| elements.point_in_range(p)) + .map(|p| elements.to_location(p)) + .map(RegionElement::Location), + ) +} + fn region_value_str(elements: impl IntoIterator) -> String { let mut result = String::new(); result.push_str("{"); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index e1bd853062..d77863d598 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -10,7 +10,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; -use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind}; +use rustc::mir::{BasicBlock, Location, Mir, Place, Statement, StatementKind}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; @@ -112,8 +112,13 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { debug!("visit_closure_substs: substs={:?}", substs); } - fn visit_user_assert_ty(&mut self, _c_ty: &mut CanonicalTy<'tcx>, _local: &mut Local, - _location: Location) { + fn visit_ascribe_user_ty( + &mut self, + _place: &mut Place<'tcx>, + _variance: &mut ty::Variance, + _c_ty: &mut CanonicalTy<'tcx>, + _location: Location, + ) { // User-assert-ty statements represent types that the user added explicitly. // We don't want to erase the regions from these types: rather, we want to // add them as constraints at type-check time. diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs index e4b1aacd34..e21c490622 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs @@ -14,7 +14,7 @@ use borrow_check::nll::type_check::constraint_conversion; use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints}; use borrow_check::nll::universal_regions::UniversalRegions; use borrow_check::nll::ToRegionVid; -use rustc::hir::def_id::DefId; +use rustc::infer::canonical::QueryRegionConstraint; use rustc::infer::outlives::free_region_map::FreeRegionRelations; use rustc::infer::region_constraints::GenericKind; use rustc::infer::InferCtxt; @@ -23,7 +23,6 @@ use rustc::traits::query::type_op::{self, TypeOp}; use rustc::ty::{self, RegionVid, Ty}; use rustc_data_structures::transitive_relation::TransitiveRelation; use std::rc::Rc; -use syntax::ast; #[derive(Debug)] crate struct UniversalRegionRelations<'tcx> { @@ -67,7 +66,6 @@ crate struct CreateResult<'tcx> { crate fn create( infcx: &InferCtxt<'_, '_, 'tcx>, - mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, location_table: &LocationTable, implicit_region_bound: Option>, @@ -75,11 +73,8 @@ crate fn create( constraints: &mut MirTypeckRegionConstraints<'tcx>, all_facts: &mut Option, ) -> CreateResult<'tcx> { - let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap(); UniversalRegionRelationsBuilder { infcx, - mir_def_id, - mir_node_id, param_env, implicit_region_bound, constraints, @@ -212,8 +207,6 @@ impl UniversalRegionRelations<'tcx> { struct UniversalRegionRelationsBuilder<'this, 'gcx: 'tcx, 'tcx: 'this> { infcx: &'this InferCtxt<'this, 'gcx, 'tcx>, - mir_def_id: DefId, - mir_node_id: ast::NodeId, param_env: ty::ParamEnv<'tcx>, location_table: &'this LocationTable, universal_regions: Rc>, @@ -248,14 +241,16 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> { let constraint_sets: Vec<_> = unnormalized_input_output_tys .flat_map(|ty| { debug!("build: input_or_output={:?}", ty); - let (ty, constraints) = self + let (ty, constraints1) = self .param_env .and(type_op::normalize::Normalize::new(ty)) .fully_perform(self.infcx) .unwrap_or_else(|_| bug!("failed to normalize {:?}", ty)); - self.add_implied_bounds(ty); + let constraints2 = self.add_implied_bounds(ty); normalized_inputs_and_output.push(ty); - constraints + constraints1 + .into_iter() + .chain(constraints2) }) .collect(); @@ -306,13 +301,15 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> { /// either the return type of the MIR or one of its arguments. At /// the same time, compute and add any implied bounds that come /// from this local. - fn add_implied_bounds(&mut self, ty: Ty<'tcx>) { + fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option>>> { debug!("add_implied_bounds(ty={:?})", ty); - let span = self.infcx.tcx.def_span(self.mir_def_id); - let bounds = self - .infcx - .implied_outlives_bounds(self.param_env, self.mir_node_id, ty, span); + let (bounds, constraints) = + self.param_env + .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) + .fully_perform(self.infcx) + .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty)); self.add_outlives_bounds(bounds); + constraints } /// Registers the `OutlivesBound` items from `outlives_bounds` in diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs index af42667016..265cd305eb 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs @@ -72,7 +72,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // types. let param_env = self.param_env; let mir_output_ty = mir.local_decls[RETURN_PLACE].ty; - let anon_type_map = + let opaque_type_map = self.fully_perform_op( Locations::All, CustomTypeOp::new( @@ -80,8 +80,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let mut obligations = ObligationAccumulator::default(); let dummy_body_id = ObligationCause::dummy().body_id; - let (output_ty, anon_type_map) = - obligations.add(infcx.instantiate_anon_types( + let (output_ty, opaque_type_map) = + obligations.add(infcx.instantiate_opaque_types( mir_def_id, dummy_body_id, param_env, @@ -92,8 +92,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { output_ty ); debug!( - "equate_inputs_and_outputs: anon_type_map={:#?}", - anon_type_map + "equate_inputs_and_outputs: opaque_type_map={:#?}", + opaque_type_map ); debug!( @@ -106,29 +106,30 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { .eq(output_ty, mir_output_ty)?, ); - for (&anon_def_id, anon_decl) in &anon_type_map { - let anon_defn_ty = tcx.type_of(anon_def_id); - let anon_defn_ty = anon_defn_ty.subst(tcx, anon_decl.substs); - let anon_defn_ty = renumber::renumber_regions( + for (&opaque_def_id, opaque_decl) in &opaque_type_map { + let opaque_defn_ty = tcx.type_of(opaque_def_id); + let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs); + let opaque_defn_ty = renumber::renumber_regions( infcx, - &anon_defn_ty, + &opaque_defn_ty, ); debug!( "equate_inputs_and_outputs: concrete_ty={:?}", - anon_decl.concrete_ty + opaque_decl.concrete_ty ); - debug!("equate_inputs_and_outputs: anon_defn_ty={:?}", anon_defn_ty); + debug!("equate_inputs_and_outputs: opaque_defn_ty={:?}", + opaque_defn_ty); obligations.add( infcx .at(&ObligationCause::dummy(), param_env) - .eq(anon_decl.concrete_ty, anon_defn_ty)?, + .eq(opaque_decl.concrete_ty, opaque_defn_ty)?, ); } debug!("equate_inputs_and_outputs: equated"); Ok(InferOk { - value: Some(anon_type_map), + value: Some(opaque_type_map), obligations: obligations.into_vec(), }) }, @@ -146,22 +147,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { None }); - // Finally, if we instantiated the anon types successfully, we + // Finally, if we instantiated the opaque types successfully, we // have to solve any bounds (e.g., `-> impl Iterator` needs to // prove that `T: Iterator` where `T` is the type we // instantiated it with). - if let Some(anon_type_map) = anon_type_map { + if let Some(opaque_type_map) = opaque_type_map { self.fully_perform_op( Locations::All, CustomTypeOp::new( |_cx| { - infcx.constrain_anon_types(&anon_type_map, universal_region_relations); + infcx.constrain_opaque_types(&opaque_type_map, universal_region_relations); Ok(InferOk { value: (), obligations: vec![], }) }, - || "anon_type_map".to_string(), + || "opaque_type_map".to_string(), ), ).unwrap(); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs deleted file mode 100644 index 2b9307db59..0000000000 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use borrow_check::nll::{NllLivenessMap, LocalWithRegion}; -use borrow_check::nll::type_check::AtLocation; -use dataflow::move_paths::{HasMoveData, MoveData}; -use dataflow::MaybeInitializedPlaces; -use dataflow::{FlowAtLocation, FlowsAtLocation}; -use rustc::infer::canonical::QueryRegionConstraint; -use rustc::mir::{BasicBlock, Location, Mir}; -use rustc::traits::query::dropck_outlives::DropckOutlivesResult; -use rustc::traits::query::type_op::outlives::DropckOutlives; -use rustc::traits::query::type_op::TypeOp; -use rustc::ty::{Ty, TypeFoldable}; -use rustc_data_structures::fx::FxHashMap; -use std::rc::Rc; -use util::liveness::{LivenessResults, LiveVariableMap }; - -use super::TypeChecker; - -/// Combines liveness analysis with initialization analysis to -/// determine which variables are live at which points, both due to -/// ordinary uses and drops. Returns a set of (ty, location) pairs -/// that indicate which types must be live at which point in the CFG. -/// This vector is consumed by `constraint_generation`. -/// -/// NB. This computation requires normalization; therefore, it must be -/// performed before -pub(super) fn generate<'gcx, 'tcx>( - cx: &mut TypeChecker<'_, 'gcx, 'tcx>, - mir: &Mir<'tcx>, - liveness: &LivenessResults, - flow_inits: &mut FlowAtLocation>, - move_data: &MoveData<'tcx>, -) { - let mut generator = TypeLivenessGenerator { - cx, - mir, - liveness, - flow_inits, - move_data, - drop_data: FxHashMap(), - map: &NllLivenessMap::compute(mir), - }; - - for bb in mir.basic_blocks().indices() { - generator.add_liveness_constraints(bb); - } -} - -struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> -where - 'typeck: 'gen, - 'flow: 'gen, - 'tcx: 'typeck + 'flow, - 'gcx: 'tcx, -{ - cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>, - mir: &'gen Mir<'tcx>, - liveness: &'gen LivenessResults, - flow_inits: &'gen mut FlowAtLocation>, - move_data: &'gen MoveData<'tcx>, - drop_data: FxHashMap, DropData<'tcx>>, - map: &'gen NllLivenessMap, -} - -struct DropData<'tcx> { - dropck_result: DropckOutlivesResult<'tcx>, - region_constraint_data: Option>>>, -} - -impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> { - /// Liveness constraints: - /// - /// > If a variable V is live at point P, then all regions R in the type of V - /// > must include the point P. - fn add_liveness_constraints(&mut self, bb: BasicBlock) { - debug!("add_liveness_constraints(bb={:?})", bb); - - self.liveness - .regular - .simulate_block(self.mir, bb, self.map, |location, live_locals| { - for live_local in live_locals.iter() { - let local = self.map.from_live_var(live_local); - let live_local_ty = self.mir.local_decls[local].ty; - Self::push_type_live_constraint(&mut self.cx, live_local_ty, location); - } - }); - - let mut all_live_locals: Vec<(Location, Vec)> = vec![]; - self.liveness - .drop - .simulate_block(self.mir, bb, self.map, |location, live_locals| { - all_live_locals.push((location, live_locals.iter().collect())); - }); - debug!( - "add_liveness_constraints: all_live_locals={:#?}", - all_live_locals - ); - - let terminator_index = self.mir.basic_blocks()[bb].statements.len(); - self.flow_inits.reset_to_entry_of(bb); - while let Some((location, live_locals)) = all_live_locals.pop() { - for live_local in live_locals { - debug!( - "add_liveness_constraints: location={:?} live_local={:?}", - location, live_local - ); - - if log_enabled!(::log::Level::Debug) { - self.flow_inits.each_state_bit(|mpi_init| { - debug!( - "add_liveness_constraints: location={:?} initialized={:?}", - location, - &self.flow_inits.operator().move_data().move_paths[mpi_init] - ); - }); - } - - let local = self.map.from_live_var(live_local); - let mpi = self.move_data.rev_lookup.find_local(local); - if let Some(initialized_child) = self.flow_inits.has_any_child_of(mpi) { - debug!( - "add_liveness_constraints: mpi={:?} has initialized child {:?}", - self.move_data.move_paths[mpi], - self.move_data.move_paths[initialized_child] - ); - - let local = self.map.from_live_var(live_local); - let live_local_ty = self.mir.local_decls[local].ty; - self.add_drop_live_constraint(live_local, live_local_ty, location); - } - } - - if location.statement_index == terminator_index { - debug!( - "add_liveness_constraints: reconstruct_terminator_effect from {:#?}", - location - ); - self.flow_inits.reconstruct_terminator_effect(location); - } else { - debug!( - "add_liveness_constraints: reconstruct_statement_effect from {:#?}", - location - ); - self.flow_inits.reconstruct_statement_effect(location); - } - self.flow_inits.apply_local_effect(location); - } - } - - /// Some variable with type `live_ty` is "regular live" at - /// `location` -- i.e., it may be used later. This means that all - /// regions appearing in the type `live_ty` must be live at - /// `location`. - fn push_type_live_constraint( - cx: &mut TypeChecker<'_, 'gcx, 'tcx>, - value: T, - location: Location, - ) where - T: TypeFoldable<'tcx>, - { - debug!( - "push_type_live_constraint(live_ty={:?}, location={:?})", - value, location - ); - - cx.tcx().for_each_free_region(&value, |live_region| { - if let Some(ref mut borrowck_context) = cx.borrowck_context { - let region_vid = borrowck_context.universal_regions.to_region_vid(live_region); - borrowck_context.constraints.liveness_constraints.add_element(region_vid, location); - - if let Some(all_facts) = borrowck_context.all_facts { - let start_index = borrowck_context.location_table.start_index(location); - all_facts.region_live_at.push((region_vid, start_index)); - - let mid_index = borrowck_context.location_table.mid_index(location); - all_facts.region_live_at.push((region_vid, mid_index)); - } - } - }); - } - - /// Some variable with type `live_ty` is "drop live" at `location` - /// -- i.e., it may be dropped later. This means that *some* of - /// the regions in its type must be live at `location`. The - /// precise set will depend on the dropck constraints, and in - /// particular this takes `#[may_dangle]` into account. - fn add_drop_live_constraint( - &mut self, - dropped_local: LocalWithRegion, - dropped_ty: Ty<'tcx>, - location: Location, - ) { - debug!( - "add_drop_live_constraint(dropped_local={:?}, dropped_ty={:?}, location={:?})", - dropped_local, dropped_ty, location - ); - - let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({ - let cx = &mut self.cx; - move || Self::compute_drop_data(cx, dropped_ty) - }); - - if let Some(data) = &drop_data.region_constraint_data { - self.cx.push_region_constraints(location.boring(), data); - } - - drop_data.dropck_result.report_overflows( - self.cx.infcx.tcx, - self.mir.source_info(location).span, - dropped_ty, - ); - - // All things in the `outlives` array may be touched by - // the destructor and must be live at this point. - for &kind in &drop_data.dropck_result.kinds { - Self::push_type_live_constraint(&mut self.cx, kind, location); - } - } - - fn compute_drop_data( - cx: &mut TypeChecker<'_, 'gcx, 'tcx>, - dropped_ty: Ty<'tcx>, - ) -> DropData<'tcx> { - debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,); - - let param_env = cx.param_env; - let (dropck_result, region_constraint_data) = param_env - .and(DropckOutlives::new(dropped_ty)) - .fully_perform(cx.infcx) - .unwrap(); - - DropData { - dropck_result, - region_constraint_data, - } - } -} diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs new file mode 100644 index 0000000000..467554dc38 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs @@ -0,0 +1,102 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! For the NLL computation, we need to compute liveness, but only for those +//! local variables whose types contain regions. The others are not of interest +//! to us. This file defines a new index type (LiveVar) that indexes into +//! a list of "variables whose type contain regions". It also defines a map from +//! Local to LiveVar and vice versa -- this map can be given to the +//! liveness code so that it only operates over variables with regions in their +//! types, instead of all variables. + +use borrow_check::nll::ToRegionVid; +use rustc::mir::{Local, Mir}; +use rustc::ty::{RegionVid, TyCtxt}; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use util::liveness::LiveVariableMap; + +/// Map between Local and LiveVar indices: the purpose of this +/// map is to define the subset of local variables for which we need +/// to do a liveness computation. We only need to compute whether a +/// variable `X` is live if that variable contains some region `R` in +/// its type where `R` is not known to outlive a free region (i.e., +/// where `R` may be valid for just a subset of the fn body). +crate struct NllLivenessMap { + /// For each local variable, contains `Some(i)` if liveness is + /// needed for this variable. + pub from_local: IndexVec>, + + /// For each `LiveVar`, maps back to the original `Local` index. + pub to_local: IndexVec, +} + +impl LiveVariableMap for NllLivenessMap { + fn from_local(&self, local: Local) -> Option { + self.from_local[local] + } + + type LiveVar = LiveVar; + + fn from_live_var(&self, local: Self::LiveVar) -> Local { + self.to_local[local] + } + + fn num_variables(&self) -> usize { + self.to_local.len() + } +} + +impl NllLivenessMap { + crate fn compute( + tcx: TyCtxt<'_, '_, 'tcx>, + free_regions: &FxHashSet, + mir: &Mir<'tcx>, + ) -> Self { + let mut to_local = IndexVec::default(); + let from_local: IndexVec> = mir.local_decls + .iter_enumerated() + .map(|(local, local_decl)| { + if tcx.all_free_regions_meet(&local_decl.ty, |r| { + free_regions.contains(&r.to_region_vid()) + }) { + // If all the regions in the type are free regions + // (or there are no regions), then we don't need + // to track liveness for this variable. + None + } else { + Some(to_local.push(local)) + } + }) + .collect(); + + debug!("{} total variables", mir.local_decls.len()); + debug!("{} variables need liveness", to_local.len()); + debug!("{} regions outlive free regions", free_regions.len()); + + Self { + from_local, + to_local, + } + } + + /// True if there are no local variables that need liveness computation. + crate fn is_empty(&self) -> bool { + self.to_local.is_empty() + } +} + +/// Index given to each local variable for which we need to +/// compute liveness information. For many locals, we are able to +/// skip liveness information: for example, those variables whose +/// types contain no regions. +newtype_index! { + pub struct LiveVar { .. } +} diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs new file mode 100644 index 0000000000..4b39d58cd9 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -0,0 +1,161 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements}; +use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap}; +use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::{Local, Location, Mir}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::vec_linked_list as vll; +use util::liveness::{categorize, DefUse, LiveVariableMap}; + +/// A map that cross references each local with the locations where it +/// is defined (assigned), used, or dropped. Used during liveness +/// computation. +crate struct LocalUseMap<'me> { + liveness_map: &'me NllLivenessMap, + + /// Head of a linked list of **definitions** of each variable -- + /// definition in this context means assignment, e.g. `x` is + /// defined in `x = y` but not `y`; that first def is the head of + /// a linked list that lets you enumerate all places the variable + /// is assigned. + first_def_at: IndexVec>, + + /// Head of a linked list of **uses** of each variable -- use in + /// this context means that the existing value of the variable is + /// read or modified. e.g., `y` is used in `x = y` but not `x`. + /// Note that `DROP(x)` terminators are excluded from this list. + first_use_at: IndexVec>, + + /// Head of a linked list of **drops** of each variable -- these + /// are a special category of uses corresponding to the drop that + /// we add for each local variable. + first_drop_at: IndexVec>, + + appearances: IndexVec, +} + +struct Appearance { + point_index: PointIndex, + next: Option, +} + +newtype_index! { + pub struct AppearanceIndex { .. } +} + +impl vll::LinkElem for Appearance { + type LinkIndex = AppearanceIndex; + + fn next(elem: &Self) -> Option { + elem.next + } +} + +impl LocalUseMap<'me> { + crate fn build( + liveness_map: &'me NllLivenessMap, + elements: &RegionValueElements, + mir: &Mir<'_>, + ) -> Self { + let nones = IndexVec::from_elem_n(None, liveness_map.num_variables()); + let mut local_use_map = LocalUseMap { + liveness_map, + first_def_at: nones.clone(), + first_use_at: nones.clone(), + first_drop_at: nones, + appearances: IndexVec::new(), + }; + + LocalUseMapBuild { + local_use_map: &mut local_use_map, + elements, + }.visit_mir(mir); + + local_use_map + } + + crate fn defs(&self, local: LiveVar) -> impl Iterator + '_ { + vll::iter(self.first_def_at[local], &self.appearances) + .map(move |aa| self.appearances[aa].point_index) + } + + crate fn uses(&self, local: LiveVar) -> impl Iterator + '_ { + vll::iter(self.first_use_at[local], &self.appearances) + .map(move |aa| self.appearances[aa].point_index) + } + + crate fn drops(&self, local: LiveVar) -> impl Iterator + '_ { + vll::iter(self.first_drop_at[local], &self.appearances) + .map(move |aa| self.appearances[aa].point_index) + } +} + +struct LocalUseMapBuild<'me, 'map: 'me> { + local_use_map: &'me mut LocalUseMap<'map>, + elements: &'me RegionValueElements, +} + +impl LocalUseMapBuild<'_, '_> { + fn insert_def(&mut self, local: LiveVar, location: Location) { + Self::insert( + self.elements, + &mut self.local_use_map.first_def_at[local], + &mut self.local_use_map.appearances, + location, + ); + } + + fn insert_use(&mut self, local: LiveVar, location: Location) { + Self::insert( + self.elements, + &mut self.local_use_map.first_use_at[local], + &mut self.local_use_map.appearances, + location, + ); + } + + fn insert_drop(&mut self, local: LiveVar, location: Location) { + Self::insert( + self.elements, + &mut self.local_use_map.first_drop_at[local], + &mut self.local_use_map.appearances, + location, + ); + } + + fn insert( + elements: &RegionValueElements, + first_appearance: &mut Option, + appearances: &mut IndexVec, + location: Location, + ) { + let point_index = elements.point_from_location(location); + let appearance_index = appearances.push(Appearance { + point_index, + next: *first_appearance, + }); + *first_appearance = Some(appearance_index); + } +} + +impl Visitor<'tcx> for LocalUseMapBuild<'_, '_> { + fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, location: Location) { + if let Some(local_with_region) = self.local_use_map.liveness_map.from_local(local) { + match categorize(context) { + Some(DefUse::Def) => self.insert_def(local_with_region, location), + Some(DefUse::Use) => self.insert_use(local_with_region, location), + Some(DefUse::Drop) => self.insert_drop(local_with_region, location), + _ => (), + } + } + } +} diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs new file mode 100644 index 0000000000..357e9ee721 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -0,0 +1,95 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use borrow_check::nll::region_infer::values::RegionValueElements; +use borrow_check::nll::constraints::ConstraintSet; +use borrow_check::nll::NllLivenessMap; +use borrow_check::nll::universal_regions::UniversalRegions; +use dataflow::move_paths::MoveData; +use dataflow::MaybeInitializedPlaces; +use dataflow::FlowAtLocation; +use rustc::mir::Mir; +use rustc::ty::RegionVid; +use rustc_data_structures::fx::FxHashSet; +use std::rc::Rc; + +use super::TypeChecker; + +crate mod liveness_map; +mod local_use_map; +mod trace; + +/// Combines liveness analysis with initialization analysis to +/// determine which variables are live at which points, both due to +/// ordinary uses and drops. Returns a set of (ty, location) pairs +/// that indicate which types must be live at which point in the CFG. +/// This vector is consumed by `constraint_generation`. +/// +/// NB. This computation requires normalization; therefore, it must be +/// performed before +pub(super) fn generate<'gcx, 'tcx>( + typeck: &mut TypeChecker<'_, 'gcx, 'tcx>, + mir: &Mir<'tcx>, + elements: &Rc, + flow_inits: &mut FlowAtLocation>, + move_data: &MoveData<'tcx>, +) { + debug!("liveness::generate"); + let free_regions = { + let borrowck_context = typeck.borrowck_context.as_ref().unwrap(); + regions_that_outlive_free_regions( + typeck.infcx.num_region_vars(), + &borrowck_context.universal_regions, + &borrowck_context.constraints.outlives_constraints, + ) + }; + let liveness_map = NllLivenessMap::compute(typeck.tcx(), &free_regions, mir); + trace::trace(typeck, mir, elements, flow_inits, move_data, &liveness_map); +} + +/// Compute all regions that are (currently) known to outlive free +/// regions. For these regions, we do not need to compute +/// liveness, since the outlives constraints will ensure that they +/// are live over the whole fn body anyhow. +fn regions_that_outlive_free_regions( + num_region_vars: usize, + universal_regions: &UniversalRegions<'tcx>, + constraint_set: &ConstraintSet, +) -> FxHashSet { + // Build a graph of the outlives constraints thus far. This is + // a reverse graph, so for each constraint `R1: R2` we have an + // edge `R2 -> R1`. Therefore, if we find all regions + // reachable from each free region, we will have all the + // regions that are forced to outlive some free region. + let rev_constraint_graph = constraint_set.reverse_graph(num_region_vars); + let fr_static = universal_regions.fr_static; + let rev_region_graph = rev_constraint_graph.region_graph(constraint_set, fr_static); + + // Stack for the depth-first search. Start out with all the free regions. + let mut stack: Vec<_> = universal_regions.universal_regions().collect(); + + // Set of all free regions, plus anything that outlives them. Initially + // just contains the free regions. + let mut outlives_free_region: FxHashSet<_> = stack.iter().cloned().collect(); + + // Do the DFS -- for each thing in the stack, find all things + // that outlive it and add them to the set. If they are not, + // push them onto the stack for later. + while let Some(sub_region) = stack.pop() { + stack.extend( + rev_region_graph + .outgoing_regions(sub_region) + .filter(|&r| outlives_free_region.insert(r)), + ); + } + + // Return the final set of things we visited. + outlives_free_region +} diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs new file mode 100644 index 0000000000..79589ce973 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -0,0 +1,553 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements}; +use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap}; +use borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap; +use borrow_check::nll::type_check::AtLocation; +use borrow_check::nll::type_check::TypeChecker; +use dataflow::move_paths::indexes::MovePathIndex; +use dataflow::move_paths::MoveData; +use dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces}; +use rustc::infer::canonical::QueryRegionConstraint; +use rustc::mir::{BasicBlock, Local, Location, Mir}; +use rustc::traits::query::dropck_outlives::DropckOutlivesResult; +use rustc::traits::query::type_op::outlives::DropckOutlives; +use rustc::traits::query::type_op::TypeOp; +use rustc::ty::{Ty, TypeFoldable}; +use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::fx::FxHashMap; +use std::rc::Rc; +use util::liveness::LiveVariableMap; + +/// This is the heart of the liveness computation. For each variable X +/// that requires a liveness computation, it walks over all the uses +/// of X and does a reverse depth-first search ("trace") through the +/// MIR. This search stops when we find a definition of that variable. +/// The points visited in this search is the USE-LIVE set for the variable; +/// of those points is added to all the regions that appear in the variable's +/// type. +/// +/// We then also walks through each *drop* of those variables and does +/// another search, stopping when we reach a use or definition. This +/// is the DROP-LIVE set of points. Each of the points in the +/// DROP-LIVE set are to the liveness sets for regions found in the +/// `dropck_outlives` result of the variable's type (in particular, +/// this respects `#[may_dangle]` annotations). +pub(super) fn trace( + typeck: &mut TypeChecker<'_, 'gcx, 'tcx>, + mir: &Mir<'tcx>, + elements: &Rc, + flow_inits: &mut FlowAtLocation>, + move_data: &MoveData<'tcx>, + liveness_map: &NllLivenessMap, +) { + debug!("trace()"); + + if liveness_map.is_empty() { + return; + } + + let local_use_map = &LocalUseMap::build(liveness_map, elements, mir); + + let cx = LivenessContext { + typeck, + mir, + flow_inits, + elements, + local_use_map, + move_data, + liveness_map, + drop_data: FxHashMap::default(), + }; + + LivenessResults::new(cx).compute_for_all_locals(); +} + +/// Contextual state for the type-liveness generator. +struct LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx> +where + 'typeck: 'me, + 'flow: 'me, + 'tcx: 'typeck + 'flow, + 'gcx: 'tcx, +{ + /// Current type-checker, giving us our inference context etc. + typeck: &'me mut TypeChecker<'typeck, 'gcx, 'tcx>, + + /// Defines the `PointIndex` mapping + elements: &'me RegionValueElements, + + /// MIR we are analyzing. + mir: &'me Mir<'tcx>, + + /// Mapping to/from the various indices used for initialization tracking. + move_data: &'me MoveData<'tcx>, + + /// Cache for the results of `dropck_outlives` query. + drop_data: FxHashMap, DropData<'tcx>>, + + /// Results of dataflow tracking which variables (and paths) have been + /// initialized. + flow_inits: &'me mut FlowAtLocation>, + + /// Index indicating where each variable is assigned, used, or + /// dropped. + local_use_map: &'me LocalUseMap<'me>, + + /// Map tracking which variables need liveness computation. + liveness_map: &'me NllLivenessMap, +} + +struct DropData<'tcx> { + dropck_result: DropckOutlivesResult<'tcx>, + region_constraint_data: Option>>>, +} + +struct LivenessResults<'me, 'typeck, 'flow, 'gcx, 'tcx> +where + 'typeck: 'me, + 'flow: 'me, + 'tcx: 'typeck + 'flow, + 'gcx: 'tcx, +{ + cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>, + + /// Set of points that define the current local. + defs: BitArray, + + /// Points where the current variable is "use live" -- meaning + /// that there is a future "full use" that may use its value. + use_live_at: BitArray, + + /// Points where the current variable is "drop live" -- meaning + /// that there is no future "full use" that may use its value, but + /// there is a future drop. + drop_live_at: BitArray, + + /// Locations where drops may occur. + drop_locations: Vec, + + /// Stack used when doing (reverse) DFS. + stack: Vec, +} + +impl LivenessResults<'me, 'typeck, 'flow, 'gcx, 'tcx> { + fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'gcx, 'tcx>) -> Self { + let num_points = cx.elements.num_points(); + LivenessResults { + cx, + defs: BitArray::new(num_points), + use_live_at: BitArray::new(num_points), + drop_live_at: BitArray::new(num_points), + drop_locations: vec![], + stack: vec![], + } + } + + fn compute_for_all_locals(&mut self) { + for live_local in self.cx.liveness_map.to_local.indices() { + let local = self.cx.liveness_map.from_live_var(live_local); + debug!("local={:?} live_local={:?}", local, live_local); + + self.reset_local_state(); + self.add_defs_for(live_local); + self.compute_use_live_points_for(live_local); + self.compute_drop_live_points_for(live_local); + + let local_ty = self.cx.mir.local_decls[local].ty; + + if !self.use_live_at.is_empty() { + self.cx.add_use_live_facts_for(local_ty, &self.use_live_at); + } + + if !self.drop_live_at.is_empty() { + self.cx.add_drop_live_facts_for( + local, + local_ty, + &self.drop_locations, + &self.drop_live_at, + ); + } + } + } + + /// Clear the value of fields that are "per local variable". + fn reset_local_state(&mut self) { + self.defs.clear(); + self.use_live_at.clear(); + self.drop_live_at.clear(); + self.drop_locations.clear(); + assert!(self.stack.is_empty()); + } + + /// Adds the definitions of `local` into `self.defs`. + fn add_defs_for(&mut self, live_local: LiveVar) { + for def in self.cx.local_use_map.defs(live_local) { + debug!("- defined at {:?}", def); + self.defs.insert(def); + } + } + + /// Compute all points where local is "use live" -- meaning its + /// current value may be used later (except by a drop). This is + /// done by walking backwards from each use of `live_local` until we + /// find a `def` of local. + /// + /// Requires `add_defs_for(live_local)` to have been executed. + fn compute_use_live_points_for(&mut self, live_local: LiveVar) { + debug!("compute_use_live_points_for(live_local={:?})", live_local); + + self.stack.extend(self.cx.local_use_map.uses(live_local)); + while let Some(p) = self.stack.pop() { + if self.defs.contains(p) { + continue; + } + + if self.use_live_at.insert(p) { + self.cx + .elements + .push_predecessors(self.cx.mir, p, &mut self.stack) + } + } + } + + /// Compute all points where local is "drop live" -- meaning its + /// current value may be dropped later (but not used). This is + /// done by iterating over the drops of `local` where `local` (or + /// some subpart of `local`) is initialized. For each such drop, + /// we walk backwards until we find a point where `local` is + /// either defined or use-live. + /// + /// Requires `compute_use_live_points_for` and `add_defs_for` to + /// have been executed. + fn compute_drop_live_points_for(&mut self, live_local: LiveVar) { + debug!("compute_drop_live_points_for(live_local={:?})", live_local); + + let local = self.cx.liveness_map.from_live_var(live_local); + let mpi = self.cx.move_data.rev_lookup.find_local(local); + debug!("compute_drop_live_points_for: mpi = {:?}", mpi); + + // Find the drops where `local` is initialized. + for drop_point in self.cx.local_use_map.drops(live_local) { + let location = self.cx.elements.to_location(drop_point); + debug_assert_eq!(self.cx.mir.terminator_loc(location.block), location,); + + if self.cx.initialized_at_terminator(location.block, mpi) { + if self.drop_live_at.insert(drop_point) { + self.drop_locations.push(location); + self.stack.push(drop_point); + } + } + } + + debug!( + "compute_drop_live_points_for: drop_locations={:?}", + self.drop_locations + ); + + // Reverse DFS. But for drops, we do it a bit differently. + // The stack only ever stores *terminators of blocks*. Within + // a block, we walk back the statements in an inner loop. + 'next_block: while let Some(term_point) = self.stack.pop() { + self.compute_drop_live_points_for_block(mpi, term_point); + } + } + + /// Executes one iteration of the drop-live analysis loop. + /// + /// The parameter `mpi` is the `MovePathIndex` of the local variable + /// we are currently analyzing. + /// + /// The point `term_point` represents some terminator in the MIR, + /// where the local `mpi` is drop-live on entry to that terminator. + /// + /// This method adds all drop-live points within the block and -- + /// where applicable -- pushes the terminators of preceding blocks + /// onto `self.stack`. + fn compute_drop_live_points_for_block(&mut self, mpi: MovePathIndex, term_point: PointIndex) { + debug!( + "compute_drop_live_points_for_block(mpi={:?}, term_point={:?})", + self.cx.move_data.move_paths[mpi].place, + self.cx.elements.to_location(term_point), + ); + + // We are only invoked with terminators where `mpi` is + // drop-live on entry. + debug_assert!(self.drop_live_at.contains(term_point)); + + // Otherwise, scan backwards through the statements in the + // block. One of them may be either a definition or use + // live point. + let term_location = self.cx.elements.to_location(term_point); + debug_assert_eq!( + self.cx.mir.terminator_loc(term_location.block), + term_location, + ); + let block = term_location.block; + let entry_point = self.cx.elements.entry_point(term_location.block); + for p in (entry_point..term_point).rev() { + debug!( + "compute_drop_live_points_for_block: p = {:?}", + self.cx.elements.to_location(p), + ); + + if self.defs.contains(p) { + debug!("compute_drop_live_points_for_block: def site"); + return; + } + + if self.use_live_at.contains(p) { + debug!("compute_drop_live_points_for_block: use-live at {:?}", p); + return; + } + + if !self.drop_live_at.insert(p) { + debug!("compute_drop_live_points_for_block: already drop-live"); + return; + } + } + + for &pred_block in self.cx.mir.predecessors_for(block).iter() { + debug!( + "compute_drop_live_points_for_block: pred_block = {:?}", + pred_block, + ); + + // Check whether the variable is (at least partially) + // initialized at the exit of this predecessor. If so, we + // want to enqueue it on our list. If not, go check the + // next block. + // + // Note that we only need to check whether `live_local` + // became de-initialized at basic block boundaries. If it + // were to become de-initialized within the block, that + // would have been a "use-live" transition in the earlier + // loop, and we'd have returned already. + // + // NB. It's possible that the pred-block ends in a call + // which stores to the variable; in that case, the + // variable may be uninitialized "at exit" because this + // call only considers the *unconditional effects* of the + // terminator. *But*, in that case, the terminator is also + // a *definition* of the variable, in which case we want + // to stop the search anyhow. (But see Note 1 below.) + if !self.cx.initialized_at_exit(pred_block, mpi) { + debug!("compute_drop_live_points_for_block: not initialized"); + continue; + } + + let pred_term_loc = self.cx.mir.terminator_loc(pred_block); + let pred_term_point = self.cx.elements.point_from_location(pred_term_loc); + + // If the terminator of this predecessor either *assigns* + // our value or is a "normal use", then stop. + if self.defs.contains(pred_term_point) { + debug!( + "compute_drop_live_points_for_block: defined at {:?}", + pred_term_loc + ); + continue; + } + + if self.use_live_at.contains(pred_term_point) { + debug!( + "compute_drop_live_points_for_block: use-live at {:?}", + pred_term_loc + ); + continue; + } + + // Otherwise, we are drop-live on entry to the terminator, + // so walk it. + if self.drop_live_at.insert(pred_term_point) { + debug!("compute_drop_live_points_for_block: pushed to stack"); + self.stack.push(pred_term_point); + } + } + + // Note 1. There is a weird scenario that you might imagine + // being problematic here, but which actually cannot happen. + // The problem would be if we had a variable that *is* initialized + // (but dead) on entry to the terminator, and where the current value + // will be dropped in the case of unwind. In that case, we ought to + // consider `X` to be drop-live in between the last use and call. + // Here is the example: + // + // ``` + // BB0 { + // X = ... + // use(X); // last use + // ... // <-- X ought to be drop-live here + // X = call() goto BB1 unwind BB2 + // } + // + // BB1 { + // DROP(X) + // } + // + // BB2 { + // DROP(X) + // } + // ``` + // + // However, the current code would, when walking back from BB2, + // simply stop and never explore BB0. This seems bad! But it turns + // out this code is flawed anyway -- note that the existing value of + // `X` would leak in the case where unwinding did *not* occur. + // + // What we *actually* generate is a store to a temporary + // for the call (`TMP = call()...`) and then a + // `DropAndReplace` to swap that with `X` + // (`DropAndReplace` has very particular semantics). + } +} + +impl LivenessContext<'_, '_, '_, '_, 'tcx> { + /// True if the local variable (or some part of it) is initialized in + /// the terminator of `block`. We need to check this to determine if a + /// DROP of some local variable will have an effect -- note that + /// drops, as they may unwind, are always terminators. + fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool { + // Compute the set of initialized paths at terminator of block + // by resetting to the start of the block and then applying + // the effects of all statements. This is the only way to get + // "just ahead" of a terminator. + self.flow_inits.reset_to_entry_of(block); + for statement_index in 0..self.mir[block].statements.len() { + let location = Location { + block, + statement_index, + }; + self.flow_inits.reconstruct_statement_effect(location); + self.flow_inits.apply_local_effect(location); + } + + self.flow_inits.has_any_child_of(mpi).is_some() + } + + /// True if the path `mpi` (or some part of it) is initialized at + /// the exit of `block`. + /// + /// **Warning:** Does not account for the result of `Call` + /// instructions. + fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool { + self.flow_inits.reset_to_exit_of(block); + self.flow_inits.has_any_child_of(mpi).is_some() + } + + /// Store the result that all regions in `value` are live for the + /// points `live_at`. + fn add_use_live_facts_for( + &mut self, + value: impl TypeFoldable<'tcx>, + live_at: &BitArray, + ) { + debug!("add_use_live_facts_for(value={:?})", value); + + Self::make_all_regions_live(self.elements, &mut self.typeck, value, live_at) + } + + /// Some variable with type `live_ty` is "drop live" at `location` + /// -- i.e., it may be dropped later. This means that *some* of + /// the regions in its type must be live at `location`. The + /// precise set will depend on the dropck constraints, and in + /// particular this takes `#[may_dangle]` into account. + fn add_drop_live_facts_for( + &mut self, + dropped_local: Local, + dropped_ty: Ty<'tcx>, + drop_locations: &[Location], + live_at: &BitArray, + ) { + debug!( + "add_drop_live_constraint(\ + dropped_local={:?}, \ + dropped_ty={:?}, \ + drop_locations={:?}, \ + live_at={:?})", + dropped_local, + dropped_ty, + drop_locations, + values::location_set_str(self.elements, live_at.iter()), + ); + + let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({ + let typeck = &mut self.typeck; + move || Self::compute_drop_data(typeck, dropped_ty) + }); + + if let Some(data) = &drop_data.region_constraint_data { + for &drop_location in drop_locations { + self.typeck + .push_region_constraints(drop_location.boring(), data); + } + } + + drop_data.dropck_result.report_overflows( + self.typeck.infcx.tcx, + self.mir.source_info(*drop_locations.first().unwrap()).span, + dropped_ty, + ); + + // All things in the `outlives` array may be touched by + // the destructor and must be live at this point. + for &kind in &drop_data.dropck_result.kinds { + Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at); + } + } + + fn make_all_regions_live( + elements: &RegionValueElements, + typeck: &mut TypeChecker<'_, '_, 'tcx>, + value: impl TypeFoldable<'tcx>, + live_at: &BitArray, + ) { + debug!("make_all_regions_live(value={:?})", value); + debug!( + "make_all_regions_live: live_at={}", + values::location_set_str(elements, live_at.iter()), + ); + + let tcx = typeck.tcx(); + tcx.for_each_free_region(&value, |live_region| { + let borrowck_context = typeck.borrowck_context.as_mut().unwrap(); + let live_region_vid = borrowck_context + .universal_regions + .to_region_vid(live_region); + borrowck_context + .constraints + .liveness_constraints + .add_elements(live_region_vid, live_at); + + if let Some(_) = borrowck_context.all_facts { + bug!("polonius liveness facts not implemented yet") + } + }); + } + + fn compute_drop_data( + typeck: &mut TypeChecker<'_, 'gcx, 'tcx>, + dropped_ty: Ty<'tcx>, + ) -> DropData<'tcx> { + debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,); + + let param_env = typeck.param_env; + let (dropck_result, region_constraint_data) = param_env + .and(DropckOutlives::new(dropped_ty)) + .fully_perform(typeck.infcx) + .unwrap(); + + DropData { + dropck_result, + region_constraint_data, + } + } +} diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a18e2368bf..de96539ec3 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -15,11 +15,12 @@ use borrow_check::borrow_set::BorrowSet; use borrow_check::location::LocationTable; use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint}; use borrow_check::nll::facts::AllFacts; -use borrow_check::nll::region_infer::values::{RegionValueElements, LivenessValues}; +use borrow_check::nll::region_infer::values::{LivenessValues, RegionValueElements}; use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; -use borrow_check::nll::type_check::free_region_relations::{CreateResult, UniversalRegionRelations}; +use borrow_check::nll::type_check::free_region_relations::{ + CreateResult, UniversalRegionRelations, +}; use borrow_check::nll::universal_regions::UniversalRegions; -use borrow_check::nll::LocalWithRegion; use borrow_check::nll::ToRegionVid; use dataflow::move_paths::MoveData; use dataflow::FlowAtLocation; @@ -36,16 +37,13 @@ use rustc::mir::*; use rustc::traits::query::type_op; use rustc::traits::query::{Fallible, NoSolution}; use rustc::ty::fold::TypeFoldable; -use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TypeVariants}; -use rustc_errors::Diagnostic; +use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; use std::fmt; use std::rc::Rc; use syntax_pos::{Span, DUMMY_SP}; use transform::{MirPass, MirSource}; -use util::liveness::LivenessResults; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::indexed_vec::Idx; macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ @@ -74,7 +72,7 @@ macro_rules! span_mirbug_and_err { mod constraint_conversion; pub mod free_region_relations; mod input_output; -mod liveness; +crate mod liveness; mod relate_tys; /// Type checks the given `mir` in the context of the inference @@ -105,8 +103,7 @@ mod relate_tys; /// - `liveness` -- results of a liveness computation on the MIR; used to create liveness /// constraints for the regions in the types of variables /// - `flow_inits` -- results of a maybe-init dataflow analysis -/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis -/// - `errors_buffer` -- errors are sent here for future reporting +/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysiss pub(crate) fn type_check<'gcx, 'tcx>( infcx: &InferCtxt<'_, 'gcx, 'tcx>, param_env: ty::ParamEnv<'gcx>, @@ -115,16 +112,11 @@ pub(crate) fn type_check<'gcx, 'tcx>( universal_regions: &Rc>, location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, - liveness: &LivenessResults, all_facts: &mut Option, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, elements: &Rc, - errors_buffer: &mut Vec, -) -> ( - MirTypeckRegionConstraints<'tcx>, - Rc>, -) { +) -> MirTypeckResults<'tcx> { let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body)); let mut constraints = MirTypeckRegionConstraints { liveness_constraints: LivenessValues::new(elements), @@ -138,7 +130,6 @@ pub(crate) fn type_check<'gcx, 'tcx>( normalized_inputs_and_output, } = free_region_relations::create( infcx, - mir_def_id, param_env, location_table, Some(implicit_region_bound), @@ -164,9 +155,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( ®ion_bound_pairs, Some(implicit_region_bound), Some(&mut borrowck_context), - Some(errors_buffer), |cx| { - liveness::generate(cx, mir, liveness, flow_inits, move_data); cx.equate_inputs_and_outputs( mir, mir_def_id, @@ -174,14 +163,18 @@ pub(crate) fn type_check<'gcx, 'tcx>( &universal_region_relations, &normalized_inputs_and_output, ); + liveness::generate(cx, mir, elements, flow_inits, move_data); }, ); } - (constraints, universal_region_relations) + MirTypeckResults { + constraints, + universal_region_relations, + } } -fn type_check_internal<'a, 'gcx, 'tcx, F>( +fn type_check_internal<'a, 'gcx, 'tcx, R>( infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'gcx>, @@ -189,11 +182,8 @@ fn type_check_internal<'a, 'gcx, 'tcx, F>( region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)], implicit_region_bound: Option>, borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>, - errors_buffer: Option<&mut Vec>, - mut extra: F, -) where - F: FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>), -{ + mut extra: impl FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>) -> R, +) -> R where { let mut checker = TypeChecker::new( infcx, mir, @@ -211,10 +201,10 @@ fn type_check_internal<'a, 'gcx, 'tcx, F>( if !errors_reported { // if verifier failed, don't do further checks to avoid ICEs - checker.typeck_mir(mir, errors_buffer); + checker.typeck_mir(mir); } - extra(&mut checker); + extra(&mut checker) } fn mirbug(tcx: TyCtxt, span: Span, msg: &str) { @@ -256,6 +246,24 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.super_constant(constant, location); self.sanitize_constant(constant, location); self.sanitize_type(constant, constant.ty); + + if let Some(user_ty) = constant.user_ty { + if let Err(terr) = self.cx.relate_type_and_user_type( + constant.ty, + ty::Variance::Invariant, + user_ty, + location.boring(), + ) { + span_mirbug!( + self, + constant, + "bad constant user type {:?} vs {:?}: {:?}", + user_ty, + constant.ty, + terr, + ); + } + } } fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { @@ -267,6 +275,25 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { self.super_local_decl(local, local_decl); self.sanitize_type(local_decl, local_decl.ty); + + if let Some(user_ty) = local_decl.user_ty { + if let Err(terr) = self.cx.relate_type_and_user_type( + local_decl.ty, + ty::Variance::Invariant, + user_ty, + Locations::All, + ) { + span_mirbug!( + self, + local, + "bad user type on variable {:?}: {:?} != {:?} ({:?})", + local, + local_decl.ty, + local_decl.user_ty, + terr, + ); + } + } } fn visit_mir(&mut self, mir: &Mir<'tcx>) { @@ -320,7 +347,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { // constraints on `'a` and `'b`. These constraints // would be lost if we just look at the normalized // value. - if let ty::TyFnDef(def_id, substs) = constant.literal.ty.sty { + if let ty::FnDef(def_id, substs) = constant.literal.ty.sty { let tcx = self.tcx(); let type_checker = &mut self.cx; @@ -343,8 +370,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { debug!("sanitize_constant: expected_ty={:?}", constant.literal.ty); - if let Err(terr) = self - .cx + if let Err(terr) = self.cx .eq_types(constant.literal.ty, constant.ty, location.boring()) { span_mirbug!( @@ -483,7 +509,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } ProjectionElem::Subslice { from, to } => PlaceTy::Ty { ty: match base_ty.sty { - ty::TyArray(inner, size) => { + ty::Array(inner, size) => { let size = size.unwrap_usize(tcx); let min_size = (from as u64) + (to as u64); if let Some(rest_size) = size.checked_sub(min_size) { @@ -497,12 +523,12 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { ) } } - ty::TySlice(..) => base_ty, + ty::Slice(..) => base_ty, _ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty), }, }, ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty { - ty::TyAdt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => { + ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => { if index >= adt_def.variants.len() { PlaceTy::Ty { ty: span_mirbug_and_err!( @@ -578,8 +604,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { variant_index, } => (&adt_def.variants[variant_index], substs), PlaceTy::Ty { ty } => match ty.sty { - ty::TyAdt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs), - ty::TyClosure(def_id, substs) => { + ty::Adt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs), + ty::Closure(def_id, substs) => { return match substs.upvar_tys(def_id, tcx).nth(field.index()) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { @@ -587,7 +613,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { }), } } - ty::TyGenerator(def_id, substs, _) => { + ty::Generator(def_id, substs, _) => { // Try pre-transform fields first (upvars and current state) if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field.index()) { return Ok(ty); @@ -602,7 +628,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { }), }; } - ty::TyTuple(tys) => { + ty::Tuple(tys) => { return match tys.get(field.index()) { Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { @@ -655,6 +681,11 @@ struct BorrowCheckContext<'a, 'tcx: 'a> { constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } +crate struct MirTypeckResults<'tcx> { + crate constraints: MirTypeckRegionConstraints<'tcx>, + crate universal_region_relations: Rc>, +} + /// A collection of region constraints that must be satisfied for the /// program to be considered well-typed. crate struct MirTypeckRegionConstraints<'tcx> { @@ -776,7 +807,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { /// predicates, or otherwise uses the inference context, executes /// `op` and then executes all the further obligations that `op` /// returns. This will yield a set of outlives constraints amongst - /// regions which are extracted and stored as having occured at + /// regions which are extracted and stored as having occurred at /// `locations`. /// /// **Any `rustc::infer` operations that might generate region @@ -842,15 +873,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ) } - fn eq_canonical_type_and_type( + fn relate_type_and_user_type( &mut self, - a: CanonicalTy<'tcx>, - b: Ty<'tcx>, + a: Ty<'tcx>, + v: ty::Variance, + b: CanonicalTy<'tcx>, locations: Locations, ) -> Fallible<()> { - relate_tys::eq_canonical_type_and_type( + relate_tys::relate_type_and_user_type( self.infcx, a, + v, b, locations, self.borrowck_context.as_mut().map(|x| &mut **x), @@ -870,8 +903,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // they are not caused by the user, but rather artifacts // of lowering. Assignments to other sorts of places *are* interesting // though. - let is_temp = if let Place::Local(l) = place { - !mir.local_decls[*l].is_user_variable.is_some() + let is_temp = if let Place::Local(l) = *place { + l != RETURN_PLACE && !mir.local_decls[l].is_user_variable.is_some() } else { false }; @@ -894,12 +927,33 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { terr ); } + + if let Some(user_ty) = self.rvalue_user_ty(rv) { + if let Err(terr) = self.relate_type_and_user_type( + rv_ty, + ty::Variance::Invariant, + user_ty, + location.boring(), + ) { + span_mirbug!( + self, + stmt, + "bad user type on rvalue ({:?} = {:?}): {:?}", + user_ty, + rv_ty, + terr + ); + } + } + self.check_rvalue(mir, rv, location); - let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().sized_trait().unwrap(), - substs: tcx.mk_substs_trait(place_ty, &[]), - }; - self.prove_trait_ref(trait_ref, location.interesting()); + if !self.tcx().features().unsized_locals { + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().sized_trait().unwrap(), + substs: tcx.mk_substs_trait(place_ty, &[]), + }; + self.prove_trait_ref(trait_ref, location.interesting()); + } } StatementKind::SetDiscriminant { ref place, @@ -907,7 +961,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } => { let place_type = place.ty(mir, tcx).to_ty(tcx); let adt = match place_type.sty { - TypeVariants::TyAdt(adt, _) if adt.is_enum() => adt, + TyKind::Adt(adt, _) if adt.is_enum() => adt, _ => { span_bug!( stmt.source_info.span, @@ -926,15 +980,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); }; } - StatementKind::UserAssertTy(c_ty, local) => { - let local_ty = mir.local_decls()[local].ty; - if let Err(terr) = self.eq_canonical_type_and_type(c_ty, local_ty, Locations::All) { + StatementKind::AscribeUserType(ref place, variance, c_ty) => { + let place_ty = place.ty(mir, tcx).to_ty(tcx); + if let Err(terr) = + self.relate_type_and_user_type(place_ty, variance, c_ty, Locations::All) + { span_mirbug!( self, stmt, - "bad type assert ({:?} = {:?}): {:?}", + "bad type assert ({:?} <: {:?}): {:?}", + place_ty, c_ty, - local_ty, terr ); } @@ -1021,7 +1077,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let func_ty = func.ty(mir, tcx); debug!("check_terminator: call, func_ty={:?}", func_ty); let sig = match func_ty.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx), + ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx), _ => { span_mirbug!(self, term, "call to non-function {:?}", func_ty); return; @@ -1112,7 +1168,18 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { match *destination { Some((ref dest, _target_block)) => { let dest_ty = dest.ty(mir, tcx).to_ty(tcx); - let locations = term_location.interesting(); + let is_temp = if let Place::Local(l) = *dest { + l != RETURN_PLACE && !mir.local_decls[l].is_user_variable.is_some() + } else { + false + }; + + let locations = if is_temp { + term_location.boring() + } else { + term_location.interesting() + }; + if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations) { span_mirbug!( self, @@ -1123,6 +1190,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { terr ); } + + // When `#![feature(unsized_locals)]` is not enabled, + // this check is done at `check_local`. + if self.tcx().features().unsized_locals { + let span = term.source_info.span; + self.ensure_place_sized(dest_ty, span); + } } None => { // FIXME(canndrew): This is_never should probably be an is_uninhabited @@ -1274,7 +1348,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { mir: &Mir<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>, - errors_buffer: &mut Option<&mut Vec>, ) { match mir.local_kind(local) { LocalKind::ReturnPointer | LocalKind::Arg => { @@ -1289,14 +1362,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { LocalKind::Var | LocalKind::Temp => {} } - let span = local_decl.source_info.span; - let ty = local_decl.ty; + // When `#![feature(unsized_locals)]` is enabled, only function calls + // and nullary ops are checked in `check_call_dest`. + if !self.tcx().features().unsized_locals { + let span = local_decl.source_info.span; + let ty = local_decl.ty; + self.ensure_place_sized(ty, span); + } + } + + fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) { + let tcx = self.tcx(); // Erase the regions from `ty` to get a global type. The // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. - let gcx = self.tcx().global_tcx(); - let erased_ty = gcx.lift(&self.tcx().erase_regions(&ty)).unwrap(); + let gcx = tcx.global_tcx(); + let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap(); if !erased_ty.is_sized(gcx.at(span), self.param_env) { // in current MIR construction, all non-control-flow rvalue // expressions evaluate through `as_temp` or `into` a return @@ -1311,15 +1393,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { cannot be statically determined", ty ); - if let Some(ref mut errors_buffer) = *errors_buffer { - diag.buffer(errors_buffer); - } else { - // we're allowed to use emit() here because the - // NLL migration will be turned on (and thus - // errors will need to be buffered) *only if* - // errors_buffer is Some. - diag.emit(); - } + + // While this is located in `nll::typeck` this error is not + // an NLL error, it's a required check to prevent creation + // of unsized rvalues in certain cases: + // * operand of a box expression + // * callee in a call expression + diag.emit(); } } } @@ -1333,7 +1413,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let tcx = self.tcx(); match *ak { - AggregateKind::Adt(def, variant_index, substs, active_field_index) => { + AggregateKind::Adt(def, variant_index, substs, _, active_field_index) => { let variant = &def.variants[variant_index]; let adj_field_index = active_field_index.unwrap_or(field_index); if let Some(field) = variant.fields.get(adj_field_index) { @@ -1394,6 +1474,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { }, Rvalue::NullaryOp(_, ty) => { + // Even with unsized locals cannot box an unsized value. + if self.tcx().features().unsized_locals { + let span = mir.source_info(location).span; + self.ensure_place_sized(ty, span); + } + let trait_ref = ty::TraitRef { def_id: tcx.lang_items().sized_trait().unwrap(), substs: tcx.mk_substs_trait(ty, &[]), @@ -1429,7 +1515,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { CastKind::ClosureFnPointer => { let sig = match op.ty(mir, tcx).sty { - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { substs.closure_sig_ty(def_id, tcx).fn_sig(tcx) } _ => bug!(), @@ -1499,6 +1585,32 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } + /// If this rvalue supports a user-given type annotation, then + /// extract and return it. This represents the final type of the + /// rvalue and will be unified with the inferred type. + fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option> { + match rvalue { + Rvalue::Use(_) + | Rvalue::Repeat(..) + | Rvalue::Ref(..) + | Rvalue::Len(..) + | Rvalue::Cast(..) + | Rvalue::BinaryOp(..) + | Rvalue::CheckedBinaryOp(..) + | Rvalue::NullaryOp(..) + | Rvalue::UnaryOp(..) + | Rvalue::Discriminant(..) => None, + + Rvalue::Aggregate(aggregate, _) => match **aggregate { + AggregateKind::Adt(_, _, _, user_ty, _) => user_ty, + AggregateKind::Array(_) => None, + AggregateKind::Tuple => None, + AggregateKind::Closure(_, _) => None, + AggregateKind::Generator(_, _, _) => None, + }, + } + } + fn check_aggregate_rvalue( &mut self, mir: &Mir<'tcx>, @@ -1607,7 +1719,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { debug!("add_reborrow_constraint - base_ty = {:?}", base_ty); match base_ty.sty { - ty::TyRef(ref_region, _, mutbl) => { + ty::Ref(ref_region, _, mutbl) => { constraints.outlives_constraints.push(OutlivesConstraint { sup: ref_region.to_region_vid(), sub: borrow_region.to_region_vid(), @@ -1654,11 +1766,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } } - ty::TyRawPtr(..) => { + ty::RawPtr(..) => { // deref of raw pointer, guaranteed to be valid break; } - ty::TyAdt(def, _) if def.is_box() => { + ty::Adt(def, _) if def.is_box() => { // deref of `Box`, need the base to be valid - propagate } _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place), @@ -1692,7 +1804,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); let instantiated_predicates = match aggregate_kind { - AggregateKind::Adt(def, _, substs, _) => { + AggregateKind::Adt(def, _, substs, _, _) => { tcx.predicates_of(def.did).instantiate(tcx, substs) } @@ -1797,12 +1909,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { }) } - fn typeck_mir(&mut self, mir: &Mir<'tcx>, mut errors_buffer: Option<&mut Vec>) { + fn typeck_mir(&mut self, mir: &Mir<'tcx>) { self.last_span = mir.span; debug!("run_on_mir: {:?}", mir.span); for (local, local_decl) in mir.local_decls.iter_enumerated() { - self.check_local(mir, local, local_decl, &mut errors_buffer); + self.check_local(mir, local, local_decl); } for (block, block_data) in mir.basic_blocks().iter_enumerated() { @@ -1875,7 +1987,6 @@ impl MirPass for TypeckMir { &[], None, None, - None, |_| (), ); diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs index ac9bf65b61..06cb44ac97 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs @@ -20,9 +20,9 @@ use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc::ty::subst::Kind; use rustc::ty::{self, CanonicalTy, CanonicalVar, RegionVid, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use std::mem; +use rustc_data_structures::indexed_vec::IndexVec; +/// Adds sufficient constraints to ensure that `a <: b`. pub(super) fn sub_types<'tcx>( infcx: &InferCtxt<'_, '_, 'tcx>, a: Ty<'tcx>, @@ -36,11 +36,12 @@ pub(super) fn sub_types<'tcx>( ty::Variance::Covariant, locations, borrowck_context, - ty::Slice::empty(), + ty::List::empty(), ).relate(&a, &b)?; Ok(()) } +/// Adds sufficient constraints to ensure that `a == b`. pub(super) fn eq_types<'tcx>( infcx: &InferCtxt<'_, '_, 'tcx>, a: Ty<'tcx>, @@ -54,33 +55,43 @@ pub(super) fn eq_types<'tcx>( ty::Variance::Invariant, locations, borrowck_context, - ty::Slice::empty(), + ty::List::empty(), ).relate(&a, &b)?; Ok(()) } -pub(super) fn eq_canonical_type_and_type<'tcx>( +/// Adds sufficient constraints to ensure that `a <: b`, where `b` is +/// a user-given type (which means it may have canonical variables +/// encoding things like `_`). +pub(super) fn relate_type_and_user_type<'tcx>( infcx: &InferCtxt<'_, '_, 'tcx>, - a: CanonicalTy<'tcx>, - b: Ty<'tcx>, + a: Ty<'tcx>, + v: ty::Variance, + b: CanonicalTy<'tcx>, locations: Locations, borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, ) -> Fallible<()> { debug!( - "eq_canonical_type_and_type(a={:?}, b={:?}, locations={:?})", + "sub_type_and_user_type(a={:?}, b={:?}, locations={:?})", a, b, locations ); let Canonical { - variables: a_variables, - value: a_value, - } = a; + variables: b_variables, + value: b_value, + } = b; + + // The `TypeRelating` code assumes that the "canonical variables" + // appear in the "a" side, so flip `Contravariant` ambient + // variance to get the right relationship. + let v1 = ty::Contravariant.xform(v); + TypeRelating::new( infcx, - ty::Variance::Invariant, + v1, locations, borrowck_context, - a_variables, - ).relate(&a_value, &b)?; + b_variables, + ).relate(&b_value, &a)?; Ok(()) } @@ -128,7 +139,7 @@ struct TypeRelating<'cx, 'bccx: 'cx, 'gcx: 'tcx, 'tcx: 'bccx> { /// how can we enforce that? I guess I could add some kind of /// "minimum universe constraint" that we can feed to the NLL checker. /// --> also, we know this doesn't happen - canonical_var_values: IndexVec>>, + canonical_var_values: IndexVec>>, } #[derive(Clone, Debug)] @@ -194,23 +205,44 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> { scope } + /// When we encounter binders during the type traversal, we record + /// the value to substitute for each of the things contained in + /// that binder. (This will be either a universal placeholder or + /// an existential inference variable.) Given the debruijn index + /// `debruijn` (and name `br`) of some binder we have now + /// encountered, this routine finds the value that we instantiated + /// the region with; to do so, it indexes backwards into the list + /// of ambient scopes `scopes`. + fn lookup_bound_region( + debruijn: ty::DebruijnIndex, + br: &ty::BoundRegion, + first_free_index: ty::DebruijnIndex, + scopes: &[BoundRegionScope], + ) -> RegionVid { + // The debruijn index is a "reverse index" into the + // scopes listing. So when we have INNERMOST (0), we + // want the *last* scope pushed, and so forth. + let debruijn_index = debruijn.index() - first_free_index.index(); + let scope = &scopes[scopes.len() - debruijn_index - 1]; + + // Find this bound region in that scope to map to a + // particular region. + scope.map[br] + } + + /// If `r` is a bound region, find the scope in which it is bound + /// (from `scopes`) and return the value that we instantiated it + /// with. Otherwise just return `r`. fn replace_bound_region( &self, universal_regions: &UniversalRegions<'tcx>, r: ty::Region<'tcx>, + first_free_index: ty::DebruijnIndex, scopes: &[BoundRegionScope], ) -> RegionVid { match r { ty::ReLateBound(debruijn, br) => { - // The debruijn index is a "reverse index" into the - // scopes listing. So when we have INNERMOST (0), we - // want the *last* scope pushed, and so forth. - let debruijn_index = debruijn.index() - ty::INNERMOST.index(); - let scope = &scopes[scopes.len() - debruijn_index - 1]; - - // Find this bound region in that scope to map to a - // particular region. - scope.map[br] + Self::lookup_bound_region(*debruijn, br, first_free_index, scopes) } ty::ReVar(v) => *v, @@ -219,6 +251,8 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> { } } + /// Push a new outlives requirement into our output set of + /// constraints. fn push_outlives(&mut self, sup: RegionVid, sub: RegionVid) { debug!("push_outlives({:?}: {:?})", sup, sub); @@ -236,46 +270,55 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> { } } - fn equate_var( + /// When we encounter a canonical variable `var` in the output, + /// equate it with `kind`. If the variable has been previously + /// equated, then equate it again. + fn relate_var( &mut self, var: CanonicalVar, b_kind: Kind<'tcx>, ) -> RelateResult<'tcx, Kind<'tcx>> { debug!("equate_var(var={:?}, b_kind={:?})", var, b_kind); - // We only encounter canonical variables when equating. - assert_eq!(self.ambient_variance, ty::Variance::Invariant); - - // The canonical variable already had a value. Equate that - // value with `b`. - let old_value = self.canonical_var_values[var].clone(); - if let Some(ScopesAndKind { scopes, kind }) = old_value { - debug!("equate_var: installing kind={:?} scopes={:?}", kind, scopes); - let old_a_scopes = mem::replace(&mut self.a_scopes, scopes); - let result = self.relate(&kind, &b_kind); - self.a_scopes = old_a_scopes; - debug!("equate_var: complete, result = {:?}", result); - return result; - } + let generalized_kind = match self.canonical_var_values[var] { + Some(v) => v, + None => { + let generalized_kind = self.generalize_value(b_kind); + self.canonical_var_values[var] = Some(generalized_kind); + generalized_kind + } + }; - // Not yet. Capture the value from the RHS and carry on. - self.canonical_var_values[var] = Some(ScopesAndKind { - scopes: self.b_scopes.clone(), - kind: b_kind, - }); - debug!( - "equate_var: capturing value {:?}", - self.canonical_var_values[var] - ); + // The generalized values we extract from `canonical_var_values` have + // been fully instantiated and hence the set of scopes we have + // doesn't matter -- just to be sure, put an empty vector + // in there. + let old_a_scopes = ::std::mem::replace(&mut self.a_scopes, vec![]); + + // Relate the generalized kind to the original one. + let result = self.relate(&generalized_kind, &b_kind); + + // Restore the old scopes now. + self.a_scopes = old_a_scopes; + + debug!("equate_var: complete, result = {:?}", result); + return result; + } - // FIXME -- technically, we should add some sort of - // assertion that this value can be named in the universe - // of the canonical variable. But in practice these - // canonical variables only arise presently in cases where - // they are in the root universe and the main typeck has - // ensured there are no universe errors. So we just kind - // of over look this right now. - Ok(b_kind) + fn generalize_value( + &self, + kind: Kind<'tcx>, + ) -> Kind<'tcx> { + TypeGeneralizer { + type_rel: self, + first_free_index: ty::INNERMOST, + ambient_variance: self.ambient_variance, + + // These always correspond to an `_` or `'_` written by + // user, and those are always in the root universe. + universe: ty::UniverseIndex::ROOT, + }.relate(&kind, &kind) + .unwrap() } } @@ -325,8 +368,8 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { // Watch out for the case that we are matching a `?T` against the // right-hand side. - if let ty::TyInfer(ty::CanonicalTy(var)) = a.sty { - self.equate_var(var, b.into())?; + if let ty::Infer(ty::CanonicalTy(var)) = a.sty { + self.relate_var(var, b.into())?; Ok(a) } else { debug!( @@ -348,7 +391,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> }) = self.borrowck_context { if let ty::ReCanonical(var) = a { - self.equate_var(*var, b.into())?; + self.relate_var(*var, b.into())?; return Ok(a); } @@ -357,8 +400,10 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> a, b, self.ambient_variance ); - let v_a = self.replace_bound_region(universal_regions, a, &self.a_scopes); - let v_b = self.replace_bound_region(universal_regions, b, &self.b_scopes); + let v_a = + self.replace_bound_region(universal_regions, a, ty::INNERMOST, &self.a_scopes); + let v_b = + self.replace_bound_region(universal_regions, b, ty::INNERMOST, &self.b_scopes); debug!("regions: v_a = {:?}", v_a); debug!("regions: v_b = {:?}", v_b); @@ -425,19 +470,30 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> self.b_scopes.push(b_scope); self.a_scopes.push(a_scope); - // FIXME -- to be fully correct, we would set the ambient - // variance to Covariant here. As is, we will sometimes - // propagate down an ambient variance of Equal -- this in - // turn causes us to report errors in some cases where - // types perhaps *ought* to be equal. See the - // `hr-fn-aau-eq-abu.rs` test for an example. Fixing this - // though is a bit nontrivial: in particular, it would - // require a more involved handling of canonical - // variables, since we would no longer be able to rely on - // having an `==` relationship for canonical variables. + // Reset the ambient variance to covariant. This is needed + // to correctly handle cases like + // + // for<'a> fn(&'a u32, &'a u3) == for<'b, 'c> fn(&'b u32, &'c u32) + // + // Somewhat surprisingly, these two types are actually + // **equal**, even though the one on the right looks more + // polymorphic. The reason is due to subtyping. To see it, + // consider that each function can call the other: + // + // - The left function can call the right with `'b` and + // `'c` both equal to `'a` + // + // - The right function can call the left with `'a` set to + // `{P}`, where P is the point in the CFG where the call + // itself occurs. Note that `'b` and `'c` must both + // include P. At the point, the call works because of + // subtyping (i.e., `&'b u32 <: &{P} u32`). + let variance = ::std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant); self.relate(a.skip_binder(), b.skip_binder())?; + self.ambient_variance = variance; + self.b_scopes.pop().unwrap(); self.a_scopes.pop().unwrap(); } @@ -458,8 +514,17 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> self.a_scopes.push(a_scope); self.b_scopes.push(b_scope); + // Reset ambient variance to contravariance. See the + // covariant case above for an explanation. + let variance = ::std::mem::replace( + &mut self.ambient_variance, + ty::Variance::Contravariant, + ); + self.relate(a.skip_binder(), b.skip_binder())?; + self.ambient_variance = variance; + self.b_scopes.pop().unwrap(); self.a_scopes.pop().unwrap(); } @@ -468,7 +533,14 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> } } -struct ScopeInstantiator<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> { +/// When we encounter a binder like `for<..> fn(..)`, we actually have +/// to walk the `fn` value to find all the values bound by the `for` +/// (these are not explicitly present in the ty representation right +/// now). This visitor handles that: it descends the type, tracking +/// binder depth, and finds late-bound regions targeting the +/// `for<..`>. For each of those, it creates an entry in +/// `bound_region_scope`. +struct ScopeInstantiator<'cx, 'gcx: 'tcx, 'tcx: 'cx> { infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, // The debruijn index of the scope we are instantiating. target_index: ty::DebruijnIndex, @@ -510,3 +582,143 @@ impl<'cx, 'gcx, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'cx, 'gcx, 'tcx> { false } } + +/// The "type generalize" is used when handling inference variables. +/// +/// The basic strategy for handling a constraint like `?A <: B` is to +/// apply a "generalization strategy" to the type `B` -- this replaces +/// all the lifetimes in the type `B` with fresh inference +/// variables. (You can read more about the strategy in this [blog +/// post].) +/// +/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x +/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the +/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which +/// establishes `'0: 'x` as a constraint. +/// +/// As a side-effect of this generalization procedure, we also replace +/// all the bound regions that we have traversed with concrete values, +/// so that the resulting generalized type is independent from the +/// scopes. +/// +/// [blog post]: https://is.gd/0hKvIr +struct TypeGeneralizer<'me, 'bccx: 'me, 'gcx: 'tcx, 'tcx: 'bccx> { + type_rel: &'me TypeRelating<'me, 'bccx, 'gcx, 'tcx>, + + /// After we generalize this type, we are going to relative it to + /// some other type. What will be the variance at this point? + ambient_variance: ty::Variance, + + first_free_index: ty::DebruijnIndex, + + universe: ty::UniverseIndex, +} + +impl TypeRelation<'me, 'gcx, 'tcx> for TypeGeneralizer<'me, 'bbcx, 'gcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> { + self.type_rel.infcx.tcx + } + + fn tag(&self) -> &'static str { + "nll::generalizer" + } + + fn a_is_expected(&self) -> bool { + true + } + + fn relate_with_variance>( + &mut self, + variance: ty::Variance, + a: &T, + b: &T, + ) -> RelateResult<'tcx, T> { + debug!( + "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})", + variance, a, b + ); + + let old_ambient_variance = self.ambient_variance; + self.ambient_variance = self.ambient_variance.xform(variance); + + debug!( + "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}", + self.ambient_variance + ); + + let r = self.relate(a, b)?; + + self.ambient_variance = old_ambient_variance; + + debug!("TypeGeneralizer::relate_with_variance: r={:?}", r); + + Ok(r) + } + + fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + debug!("TypeGeneralizer::tys(a={:?})", a,); + + match a.sty { + ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) => { + bug!( + "unexpected inference variable encountered in NLL generalization: {:?}", + a + ); + } + + _ => relate::super_relate_tys(self, a, a), + } + } + + fn regions( + &mut self, + a: ty::Region<'tcx>, + _: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { + debug!("TypeGeneralizer::regions(a={:?})", a,); + + if let ty::ReLateBound(debruijn, _) = a { + if *debruijn < self.first_free_index { + return Ok(a); + } + } + + // For now, we just always create a fresh region variable to + // replace all the regions in the source type. In the main + // type checker, we special case the case where the ambient + // variance is `Invariant` and try to avoid creating a fresh + // region variable, but since this comes up so much less in + // NLL (only when users use `_` etc) it is much less + // important. + // + // As an aside, since these new variables are created in + // `self.universe` universe, this also serves to enforce the + // universe scoping rules. + // + // FIXME(#54105) -- if the ambient variance is bivariant, + // though, we may however need to check well-formedness or + // risk a problem like #41677 again. + + let replacement_region_vid = self.type_rel + .infcx + .next_nll_region_var_in_universe(NLLRegionVariableOrigin::Existential, self.universe); + + Ok(replacement_region_vid) + } + + fn binders( + &mut self, + a: &ty::Binder, + _: &ty::Binder, + ) -> RelateResult<'tcx, ty::Binder> + where + T: Relate<'tcx>, + { + debug!("TypeGeneralizer::binders(a={:?})", a,); + + self.first_free_index.shift_in(1); + let result = self.relate(a.skip_binder(), a.skip_binder())?; + self.first_free_index.shift_out(1); + Ok(ty::Binder::bind(result)) + } +} diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index 765c4cf906..eb6f1a0677 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -31,6 +31,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_errors::DiagnosticBuilder; use std::iter; use syntax::ast; @@ -64,7 +65,7 @@ pub struct UniversalRegions<'tcx> { /// The "defining" type for this function, with all universal /// regions instantiated. For a closure or generator, this is the - /// closure type, but for a top-level function it's the `TyFnDef`. + /// closure type, but for a top-level function it's the `FnDef`. pub defining_ty: DefiningTy<'tcx>, /// The return type of this function, with all regions replaced by @@ -241,8 +242,9 @@ impl<'tcx> UniversalRegions<'tcx> { region_mapping.push(fr); }); - for_each_late_bound_region_defined_on( - tcx, closure_base_def_id, |r| { region_mapping.push(r); }); + for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| { + region_mapping.push(r); + }); assert_eq!( region_mapping.len(), @@ -309,6 +311,69 @@ impl<'tcx> UniversalRegions<'tcx> { pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { self.indices.to_region_vid(r) } + + /// As part of the NLL unit tests, you can annotate a function with + /// `#[rustc_regions]`, and we will emit information about the region + /// inference context and -- in particular -- the external constraints + /// that this region imposes on others. The methods in this file + /// handle the part about dumping the inference context internal + /// state. + crate fn annotate(&self, tcx: TyCtxt<'_, '_, 'tcx>, err: &mut DiagnosticBuilder<'_>) { + match self.defining_ty { + DefiningTy::Closure(def_id, substs) => { + err.note(&format!( + "defining type: {:?} with closure substs {:#?}", + def_id, + &substs.substs[..] + )); + + // FIXME: It'd be nice to print the late-bound regions + // here, but unfortunately these wind up stored into + // tests, and the resulting print-outs include def-ids + // and other things that are not stable across tests! + // So we just include the region-vid. Annoying. + let closure_base_def_id = tcx.closure_base_def_id(def_id); + for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| { + err.note(&format!( + "late-bound region is {:?}", + self.to_region_vid(r), + )); + }); + } + DefiningTy::Generator(def_id, substs, _) => { + err.note(&format!( + "defining type: {:?} with generator substs {:#?}", + def_id, + &substs.substs[..] + )); + + // FIXME: As above, we'd like to print out the region + // `r` but doing so is not stable across architectures + // and so forth. + let closure_base_def_id = tcx.closure_base_def_id(def_id); + for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| { + err.note(&format!( + "late-bound region is {:?}", + self.to_region_vid(r), + )); + }); + } + DefiningTy::FnDef(def_id, substs) => { + err.note(&format!( + "defining type: {:?} with substs {:#?}", + def_id, + &substs[..] + )); + } + DefiningTy::Const(def_id, substs) => { + err.note(&format!( + "defining constant type: {:?} with substs {:#?}", + def_id, + &substs[..] + )); + } + } + } } struct UniversalRegionsBuilder<'cx, 'gcx: 'tcx, 'tcx: 'cx> { @@ -352,9 +417,8 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { // let c = || { let x: &'a u32 = ...; } // } if self.mir_def_id != closure_base_def_id { - self.infcx.replace_late_bound_regions_with_nll_infer_vars( - self.mir_def_id, - &mut indices) + self.infcx + .replace_late_bound_regions_with_nll_infer_vars(self.mir_def_id, &mut indices) } let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty); @@ -371,9 +435,8 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { // Converse of above, if this is a function then the late-bound regions declared on its // signature are local to the fn. if self.mir_def_id == closure_base_def_id { - self.infcx.replace_late_bound_regions_with_nll_infer_vars( - self.mir_def_id, - &mut indices); + self.infcx + .replace_late_bound_regions_with_nll_infer_vars(self.mir_def_id, &mut indices); } let fr_fn_body = self.infcx.next_nll_region_var(FR).to_region_vid(); @@ -437,11 +500,11 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { .replace_free_regions_with_nll_infer_vars(FR, &defining_ty); match defining_ty.sty { - ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs), - ty::TyGenerator(def_id, substs, movability) => { + ty::Closure(def_id, substs) => DefiningTy::Closure(def_id, substs), + ty::Generator(def_id, substs, movability) => { DefiningTy::Generator(def_id, substs, movability) } - ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs), + ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs), _ => span_bug!( tcx.def_span(self.mir_def_id), "expected defining type for `{:?}`: `{:?}`", @@ -506,7 +569,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { &self, indices: &UniversalRegionIndices<'tcx>, defining_ty: DefiningTy<'tcx>, - ) -> ty::Binder<&'tcx ty::Slice>> { + ) -> ty::Binder<&'tcx ty::List>> { let tcx = self.infcx.tcx; match defining_ty { DefiningTy::Closure(def_id, substs) => { @@ -524,7 +587,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap(); assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); let inputs = match tuplized_inputs[0].sty { - ty::TyTuple(inputs) => inputs, + ty::Tuple(inputs) => inputs, _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), }; @@ -582,11 +645,10 @@ trait InferCtxtExt<'tcx> { where T: TypeFoldable<'tcx>; - fn replace_late_bound_regions_with_nll_infer_vars( &self, mir_def_id: DefId, - indices: &mut UniversalRegionIndices<'tcx> + indices: &mut UniversalRegionIndices<'tcx>, ); } @@ -619,6 +681,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> { value, all_outlive_scope, ); let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| { + debug!("replace_bound_regions_with_nll_infer_vars: br={:?}", br); let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: all_outlive_scope, bound_region: br, @@ -626,7 +689,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> { let region_vid = self.next_nll_region_var(origin); indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid()); debug!( - "liberated_region={:?} => {:?}", + "replace_bound_regions_with_nll_infer_vars: liberated_region={:?} => {:?}", liberated_region, region_vid ); region_vid @@ -648,12 +711,18 @@ impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> { mir_def_id: DefId, indices: &mut UniversalRegionIndices<'tcx>, ) { + debug!( + "replace_late_bound_regions_with_nll_infer_vars(mir_def_id={:?})", + mir_def_id + ); let closure_base_def_id = self.tcx.closure_base_def_id(mir_def_id); for_each_late_bound_region_defined_on(self.tcx, closure_base_def_id, |r| { + debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r); if !indices.indices.contains_key(&r) { let region_vid = self.next_nll_region_var(FR); indices.insert_late_bound_region(r, region_vid.to_region_vid()); - }}); + } + }); } } @@ -703,11 +772,14 @@ impl<'tcx> UniversalRegionIndices<'tcx> { fn for_each_late_bound_region_defined_on<'tcx>( tcx: TyCtxt<'_, '_, 'tcx>, fn_def_id: DefId, - mut f: impl FnMut(ty::Region<'tcx>) - ) { + mut f: impl FnMut(ty::Region<'tcx>), +) { if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.index) { for late_bound in late_bounds.iter() { - let hir_id = HirId{ owner: fn_def_id.index, local_id: *late_bound }; + let hir_id = HirId { + owner: fn_def_id.index, + local_id: *late_bound, + }; let region_node_id = tcx.hir.hir_to_node_id(hir_id); let name = tcx.hir.name(region_node_id).as_interned_str(); let region_def_id = tcx.hir.local_def_id(region_node_id); diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index b0517c5e61..740cc64598 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -10,13 +10,22 @@ use rustc::hir; use rustc::mir::ProjectionElem; -use rustc::mir::{Local, Mir, Place}; +use rustc::mir::{Local, Mir, Place, Mutability}; use rustc::ty::{self, TyCtxt}; +use borrow_check::borrow_set::LocalsStateAtExit; /// Extension methods for the `Place` type. crate trait PlaceExt<'tcx> { - /// True if this is a deref of a raw pointer. - fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool; + /// Returns true if we can safely ignore borrows of this place. + /// This is true whenever there is no action that the user can do + /// to the place `self` that would invalidate the borrow. This is true + /// for borrows of raw pointer dereferents as well as shared references. + fn ignore_borrow( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + locals_state_at_exit: &LocalsStateAtExit, + ) -> bool; /// If this is a place like `x.f.g`, returns the local /// `x`. Returns `None` if this is based in a static. @@ -24,10 +33,34 @@ crate trait PlaceExt<'tcx> { } impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { - fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool { + fn ignore_borrow( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + locals_state_at_exit: &LocalsStateAtExit, + ) -> bool { match self { - Place::Promoted(_) | - Place::Local(_) => false, + Place::Promoted(_) => false, + + // If a local variable is immutable, then we only need to track borrows to guard + // against two kinds of errors: + // * The variable being dropped while still borrowed (e.g., because the fn returns + // a reference to a local variable) + // * The variable being moved while still borrowed + // + // In particular, the variable cannot be mutated -- the "access checks" will fail -- + // so we don't have to worry about mutation while borrowed. + Place::Local(index) => { + match locals_state_at_exit { + LocalsStateAtExit::AllAreInvalidated => false, + LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => { + let ignore = !has_storage_dead_or_moved.contains(*index) && + mir.local_decls[*index].mutability == Mutability::Not; + debug!("ignore_borrow: local {:?} => {:?}", index, ignore); + ignore + } + } + } Place::Static(static_) => { tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable) } @@ -36,12 +69,24 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { | ProjectionElem::Downcast(..) | ProjectionElem::Subslice { .. } | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Index(_) => proj.base.is_unsafe_place(tcx, mir), + | ProjectionElem::Index(_) => proj.base.ignore_borrow( + tcx, mir, locals_state_at_exit), + ProjectionElem::Deref => { let ty = proj.base.ty(mir, tcx).to_ty(tcx); match ty.sty { - ty::TyRawPtr(..) => true, - _ => proj.base.is_unsafe_place(tcx, mir), + // For both derefs of raw pointers and `&T` + // references, the original path is `Copy` and + // therefore not significant. In particular, + // there is nothing the user can do to the + // original path that would invalidate the + // newly created reference -- and if there + // were, then the user could have copied the + // original path into a new variable and + // borrowed *that* one, leaving the original + // path unborrowed. + ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) => true, + _ => proj.base.ignore_borrow(tcx, mir, locals_state_at_exit), } } }, diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index c44af00365..3f055283e0 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -29,6 +29,14 @@ pub(super) fn places_conflict<'gcx, 'tcx>( borrow_place, access_place, access ); + // This Local/Local case is handled by the more general code below, but + // it's so common that it's a speed win to check for it first. + if let Place::Local(l1) = borrow_place { + if let Place::Local(l2) = access_place { + return l1 == l2; + } + } + unroll_place(borrow_place, None, |borrow_components| { unroll_place(access_place, None, |access_components| { place_components_conflict(tcx, mir, borrow_components, access_components, access) @@ -83,7 +91,7 @@ fn place_components_conflict<'gcx, 'tcx>( // Our invariant is, that at each step of the iteration: // - If we didn't run out of access to match, our borrow and access are comparable // and either equal or disjoint. - // - If we did run out of accesss, the borrow can access a part of it. + // - If we did run out of access, the borrow can access a part of it. loop { // loop invariant: borrow_c is always either equal to access_c or disjoint from it. if let Some(borrow_c) = borrow_components.next() { @@ -170,7 +178,7 @@ fn place_components_conflict<'gcx, 'tcx>( debug!("places_conflict: shallow access behind ptr"); return false; } - (ProjectionElem::Deref, ty::TyRef(_, _, hir::MutImmutable), _) => { + (ProjectionElem::Deref, ty::Ref(_, _, hir::MutImmutable), _) => { // the borrow goes through a dereference of a shared reference. // // I'm not sure why we are tracking these borrows - shared @@ -329,6 +337,13 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( } (Place::Promoted(p1), Place::Promoted(p2)) => { if p1.0 == p2.0 { + if let ty::Array(_, size) = p1.1.sty { + if size.unwrap_usize(tcx) == 0 { + // Ignore conflicts with promoted [T; 0]. + debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED"); + return Overlap::Disjoint; + } + } // the same promoted - base case, equal debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED"); Overlap::EqualOrDisjoint @@ -359,7 +374,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( } else { let ty = pi1.base.ty(mir, tcx).to_ty(tcx); match ty.sty { - ty::TyAdt(def, _) if def.is_union() => { + ty::Adt(def, _) if def.is_union() => { // Different fields of a union, we are basically stuck. debug!("place_element_conflict: STUCK-UNION"); Overlap::Arbitrary diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 9b16130d25..8dcc114330 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -155,8 +155,8 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> { let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); match ty.sty { - ty::TyRawPtr(_) | - ty::TyRef( + ty::RawPtr(_) | + ty::Ref( _, /*rgn*/ _, /*ty*/ hir::MutImmutable @@ -166,7 +166,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> { return Some(cursor); } - ty::TyRef( + ty::Ref( _, /*rgn*/ _, /*ty*/ hir::MutMutable, @@ -175,7 +175,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> { return Some(cursor); } - ty::TyAdt(..) if ty.is_box() => { + ty::Adt(..) if ty.is_box() => { self.next = Some(&proj.base); return Some(cursor); } diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index c3637a5abe..c4cb7958fd 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -106,7 +106,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { remainder_scope, init_scope, pattern, - ty, initializer, lint_level } => { @@ -136,7 +135,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { opt_destruction_scope.map(|de|(de, source_info)), block, |this| { let scope = (init_scope, source_info); this.in_scope(scope, lint_level, block, |this| { - this.expr_into_pattern(block, ty, pattern, init) + this.expr_into_pattern(block, pattern, init) }) })); } else { @@ -144,16 +143,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { None, remainder_span, lint_level, slice::from_ref(&pattern), ArmHasGuard(false), None); - // FIXME(#47184): We currently only insert `UserAssertTy` statements for - // patterns that are bindings, this is as we do not want to deconstruct - // the type being assertion to match the pattern. - if let PatternKind::Binding { var, .. } = *pattern.kind { - if let Some(ty) = ty { - this.user_assert_ty(block, ty, var, span); - } - } - - this.visit_bindings(&pattern, &mut |this, _, _, _, node, span, _| { + this.visit_bindings(&pattern, None, &mut |this, _, _, _, node, span, _, _| { this.storage_live_binding(block, node, span, OutsideGuard); this.schedule_drop_for_binding(node, span, OutsideGuard); }) @@ -177,7 +167,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // the case of `!`, no return value is required, as the block will never return. let tcx = this.hir.tcx(); let ty = destination.ty(&this.local_decls, tcx).to_ty(tcx); - if ty.is_nil() { + if ty.is_unit() { // We only want to assign an implicit `()` as the return value of the block if the // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.) this.cfg.push_assign_unit(block, source_info, destination); diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 1ed8289d44..8e40fd1994 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -51,7 +51,7 @@ impl<'tcx> CFG<'tcx> { source_info: SourceInfo, region_scope: region::Scope) { if tcx.emit_end_regions() { - if let region::ScopeData::CallSite(_) = region_scope.data() { + if let region::ScopeData::CallSite = region_scope.data { // The CallSite scope (aka the root scope) is sort of weird, in that it is // supposed to "separate" the "interior" and "exterior" of a closure. Being // that, it is not really a part of the region hierarchy, but for some diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index a57f1b9549..606bd2978b 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -18,7 +18,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! pub fn as_constant(&mut self, expr: M) -> Constant<'tcx> - where M: Mirror<'tcx, Output=Expr<'tcx>> + where + M: Mirror<'tcx, Output = Expr<'tcx>>, { let expr = self.hir.mirror(expr); self.expr_as_constant(expr) @@ -26,18 +27,25 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> { let this = self; - let Expr { ty, temp_lifetime: _, span, kind } - = expr; + let Expr { + ty, + temp_lifetime: _, + span, + kind, + } = expr; match kind { - ExprKind::Scope { region_scope: _, lint_level: _, value } => - this.as_constant(value), - ExprKind::Literal { literal } => - Constant { span: span, ty: ty, literal: literal }, - _ => - span_bug!( - span, - "expression is not a valid constant {:?}", - kind), + ExprKind::Scope { + region_scope: _, + lint_level: _, + value, + } => this.as_constant(value), + ExprKind::Literal { literal, user_ty } => Constant { + span, + ty, + user_ty, + literal, + }, + _ => span_bug!(span, "expression is not a valid constant {:?}", kind), } } } diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index 7eae414a39..8046d898e0 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -10,8 +10,8 @@ //! See docs in build/expr/mod.rs -use build::{BlockAnd, BlockAndExtension, Builder}; use build::expr::category::Category; +use build::{BlockAnd, BlockAndExtension, Builder}; use hair::*; use rustc::middle::region; use rustc::mir::*; @@ -23,9 +23,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. - pub fn as_local_operand(&mut self, block: BasicBlock, expr: M) - -> BlockAnd> - where M: Mirror<'tcx, Output = Expr<'tcx>> + pub fn as_local_operand(&mut self, block: BasicBlock, expr: M) -> BlockAnd> + where + M: Mirror<'tcx, Output = Expr<'tcx>>, { let local_scope = self.local_scope(); self.as_operand(block, local_scope, expr) @@ -37,25 +37,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// this time. /// /// The operand is known to be live until the end of `scope`. - pub fn as_operand(&mut self, - block: BasicBlock, - scope: Option, - expr: M) -> BlockAnd> - where M: Mirror<'tcx, Output = Expr<'tcx>> + pub fn as_operand( + &mut self, + block: BasicBlock, + scope: Option, + expr: M, + ) -> BlockAnd> + where + M: Mirror<'tcx, Output = Expr<'tcx>>, { let expr = self.hir.mirror(expr); self.expr_as_operand(block, scope, expr) } - fn expr_as_operand(&mut self, - mut block: BasicBlock, - scope: Option, - expr: Expr<'tcx>) - -> BlockAnd> { + fn expr_as_operand( + &mut self, + mut block: BasicBlock, + scope: Option, + expr: Expr<'tcx>, + ) -> BlockAnd> { debug!("expr_as_operand(block={:?}, expr={:?})", block, expr); let this = self; - if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { + if let ExprKind::Scope { + region_scope, + lint_level, + value, + } = expr.kind + { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); return this.in_scope(region_scope, lint_level, block, |this| { @@ -64,16 +73,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } let category = Category::of(&expr.kind).unwrap(); - debug!("expr_as_operand: category={:?} for={:?}", category, expr.kind); + debug!( + "expr_as_operand: category={:?} for={:?}", + category, expr.kind + ); match category { Category::Constant => { let constant = this.as_constant(expr); block.and(Operand::Constant(box constant)) } - Category::Place | - Category::Rvalue(..) => { - let operand = - unpack!(block = this.as_temp(block, scope, expr)); + Category::Place | Category::Rvalue(..) => { + let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut)); block.and(Operand::Move(Place::Local(operand))) } } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index a38ca7ae5b..5688ea9d26 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -10,42 +10,64 @@ //! See docs in build/expr/mod.rs -use build::{BlockAnd, BlockAndExtension, Builder}; -use build::ForGuard::{OutsideGuard, RefWithinGuard}; use build::expr::category::Category; +use build::ForGuard::{OutsideGuard, RefWithinGuard}; +use build::{BlockAnd, BlockAndExtension, Builder}; use hair::*; -use rustc::mir::*; use rustc::mir::interpret::EvalErrorKind::BoundsCheck; +use rustc::mir::*; use rustc_data_structures::indexed_vec::Idx; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr`, yielding a place that we can move from etc. - pub fn as_place(&mut self, - block: BasicBlock, - expr: M) - -> BlockAnd> - where M: Mirror<'tcx, Output=Expr<'tcx>> + pub fn as_place(&mut self, block: BasicBlock, expr: M) -> BlockAnd> + where + M: Mirror<'tcx, Output = Expr<'tcx>>, { let expr = self.hir.mirror(expr); - self.expr_as_place(block, expr) + self.expr_as_place(block, expr, Mutability::Mut) } - fn expr_as_place(&mut self, - mut block: BasicBlock, - expr: Expr<'tcx>) - -> BlockAnd> { - debug!("expr_as_place(block={:?}, expr={:?})", block, expr); + /// Compile `expr`, yielding a place that we can move from etc. + /// Mutability note: The caller of this method promises only to read from the resulting + /// place. The place itself may or may not be mutable: + /// * If this expr is a place expr like a.b, then we will return that place. + /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary. + pub fn as_read_only_place(&mut self, block: BasicBlock, expr: M) -> BlockAnd> + where + M: Mirror<'tcx, Output = Expr<'tcx>>, + { + let expr = self.hir.mirror(expr); + self.expr_as_place(block, expr, Mutability::Not) + } + + fn expr_as_place( + &mut self, + mut block: BasicBlock, + expr: Expr<'tcx>, + mutability: Mutability, + ) -> BlockAnd> { + debug!( + "expr_as_place(block={:?}, expr={:?}, mutability={:?})", + block, expr, mutability + ); let this = self; let expr_span = expr.span; let source_info = this.source_info(expr_span); match expr.kind { - ExprKind::Scope { region_scope, lint_level, value } => { - this.in_scope((region_scope, source_info), lint_level, block, |this| { + ExprKind::Scope { + region_scope, + lint_level, + value, + } => this.in_scope((region_scope, source_info), lint_level, block, |this| { + if mutability == Mutability::Not { + this.as_read_only_place(block, value) + } else { this.as_place(block, value) - }) - } + } + }), ExprKind::Field { lhs, name } => { let place = unpack!(block = this.as_place(block, lhs)); let place = place.field(name, expr.ty); @@ -63,32 +85,43 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // region_scope=None so place indexes live forever. They are scalars so they // do not need storage annotations, and they are often copied between // places. - let idx = unpack!(block = this.as_temp(block, None, index)); + let idx = unpack!(block = this.as_temp(block, None, index, Mutability::Mut)); // bounds check: - let (len, lt) = (this.temp(usize_ty.clone(), expr_span), - this.temp(bool_ty, expr_span)); - this.cfg.push_assign(block, source_info, // len = len(slice) - &len, Rvalue::Len(slice.clone())); - this.cfg.push_assign(block, source_info, // lt = idx < len - <, Rvalue::BinaryOp(BinOp::Lt, - Operand::Copy(Place::Local(idx)), - Operand::Copy(len.clone()))); + let (len, lt) = ( + this.temp(usize_ty.clone(), expr_span), + this.temp(bool_ty, expr_span), + ); + this.cfg.push_assign( + block, + source_info, // len = len(slice) + &len, + Rvalue::Len(slice.clone()), + ); + this.cfg.push_assign( + block, + source_info, // lt = idx < len + <, + Rvalue::BinaryOp( + BinOp::Lt, + Operand::Copy(Place::Local(idx)), + Operand::Copy(len.clone()), + ), + ); let msg = BoundsCheck { len: Operand::Move(len), - index: Operand::Copy(Place::Local(idx)) + index: Operand::Copy(Place::Local(idx)), }; - let success = this.assert(block, Operand::Move(lt), true, - msg, expr_span); + let success = this.assert(block, Operand::Move(lt), true, msg, expr_span); success.and(slice.index(idx)) } - ExprKind::SelfRef => { - block.and(Place::Local(Local::new(1))) - } + ExprKind::SelfRef => block.and(Place::Local(Local::new(1))), ExprKind::VarRef { id } => { - let place = if this.is_bound_var_in_guard(id) && - this.hir.tcx().all_pat_vars_are_implicit_refs_within_guards() + let place = if this.is_bound_var_in_guard(id) && this + .hir + .tcx() + .all_pat_vars_are_implicit_refs_within_guards() { let index = this.var_local_id(id, RefWithinGuard); Place::Local(index).deref() @@ -98,46 +131,48 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; block.and(place) } - ExprKind::StaticRef { id } => { - block.and(Place::Static(Box::new(Static { def_id: id, ty: expr.ty }))) - } + ExprKind::StaticRef { id } => block.and(Place::Static(Box::new(Static { + def_id: id, + ty: expr.ty, + }))), - ExprKind::Array { .. } | - ExprKind::Tuple { .. } | - ExprKind::Adt { .. } | - ExprKind::Closure { .. } | - ExprKind::Unary { .. } | - ExprKind::Binary { .. } | - ExprKind::LogicalOp { .. } | - ExprKind::Box { .. } | - ExprKind::Cast { .. } | - ExprKind::Use { .. } | - ExprKind::NeverToAny { .. } | - ExprKind::ReifyFnPointer { .. } | - ExprKind::ClosureFnPointer { .. } | - ExprKind::UnsafeFnPointer { .. } | - ExprKind::Unsize { .. } | - ExprKind::Repeat { .. } | - ExprKind::Borrow { .. } | - ExprKind::If { .. } | - ExprKind::Match { .. } | - ExprKind::Loop { .. } | - ExprKind::Block { .. } | - ExprKind::Assign { .. } | - ExprKind::AssignOp { .. } | - ExprKind::Break { .. } | - ExprKind::Continue { .. } | - ExprKind::Return { .. } | - ExprKind::Literal { .. } | - ExprKind::InlineAsm { .. } | - ExprKind::Yield { .. } | - ExprKind::Call { .. } => { + ExprKind::Array { .. } + | ExprKind::Tuple { .. } + | ExprKind::Adt { .. } + | ExprKind::Closure { .. } + | ExprKind::Unary { .. } + | ExprKind::Binary { .. } + | ExprKind::LogicalOp { .. } + | ExprKind::Box { .. } + | ExprKind::Cast { .. } + | ExprKind::Use { .. } + | ExprKind::NeverToAny { .. } + | ExprKind::ReifyFnPointer { .. } + | ExprKind::ClosureFnPointer { .. } + | ExprKind::UnsafeFnPointer { .. } + | ExprKind::Unsize { .. } + | ExprKind::Repeat { .. } + | ExprKind::Borrow { .. } + | ExprKind::If { .. } + | ExprKind::Match { .. } + | ExprKind::Loop { .. } + | ExprKind::Block { .. } + | ExprKind::Assign { .. } + | ExprKind::AssignOp { .. } + | ExprKind::Break { .. } + | ExprKind::Continue { .. } + | ExprKind::Return { .. } + | ExprKind::Literal { .. } + | ExprKind::InlineAsm { .. } + | ExprKind::Yield { .. } + | ExprKind::Call { .. } => { // these are not places, so we need to make a temporary. debug_assert!(match Category::of(&expr.kind) { Some(Category::Place) => false, _ => true, }); - let temp = unpack!(block = this.as_temp(block, expr.temp_lifetime, expr)); + let temp = + unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability)); block.and(Place::Local(temp)) } } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 68009e962a..b721120f74 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -13,64 +13,84 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; -use build::{BlockAnd, BlockAndExtension, Builder}; use build::expr::category::{Category, RvalueFunc}; +use build::{BlockAnd, BlockAndExtension, Builder}; use hair::*; use rustc::middle::region; -use rustc::ty::{self, Ty, UpvarSubsts}; -use rustc::mir::*; use rustc::mir::interpret::EvalErrorKind; +use rustc::mir::*; +use rustc::ty::{self, Ty, UpvarSubsts}; use syntax_pos::Span; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// See comment on `as_local_operand` - pub fn as_local_rvalue(&mut self, block: BasicBlock, expr: M) - -> BlockAnd> - where M: Mirror<'tcx, Output = Expr<'tcx>> + pub fn as_local_rvalue(&mut self, block: BasicBlock, expr: M) -> BlockAnd> + where + M: Mirror<'tcx, Output = Expr<'tcx>>, { let local_scope = self.local_scope(); self.as_rvalue(block, local_scope, expr) } /// Compile `expr`, yielding an rvalue. - pub fn as_rvalue(&mut self, block: BasicBlock, scope: Option, expr: M) - -> BlockAnd> - where M: Mirror<'tcx, Output = Expr<'tcx>> + pub fn as_rvalue( + &mut self, + block: BasicBlock, + scope: Option, + expr: M, + ) -> BlockAnd> + where + M: Mirror<'tcx, Output = Expr<'tcx>>, { let expr = self.hir.mirror(expr); self.expr_as_rvalue(block, scope, expr) } - fn expr_as_rvalue(&mut self, - mut block: BasicBlock, - scope: Option, - expr: Expr<'tcx>) - -> BlockAnd> { - debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr); + fn expr_as_rvalue( + &mut self, + mut block: BasicBlock, + scope: Option, + expr: Expr<'tcx>, + ) -> BlockAnd> { + debug!( + "expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", + block, scope, expr + ); let this = self; let expr_span = expr.span; let source_info = this.source_info(expr_span); match expr.kind { - ExprKind::Scope { region_scope, lint_level, value } => { + ExprKind::Scope { + region_scope, + lint_level, + value, + } => { let region_scope = (region_scope, source_info); - this.in_scope(region_scope, lint_level, block, - |this| this.as_rvalue(block, scope, value)) + this.in_scope(region_scope, lint_level, block, |this| { + this.as_rvalue(block, scope, value) + }) } ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, scope, value)); block.and(Rvalue::Repeat(value_operand, count)) } - ExprKind::Borrow { region, borrow_kind, arg } => { - let arg_place = unpack!(block = this.as_place(block, arg)); + ExprKind::Borrow { + region, + borrow_kind, + arg, + } => { + let arg_place = match borrow_kind { + BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, arg)), + _ => unpack!(block = this.as_place(block, arg)), + }; block.and(Rvalue::Ref(region, borrow_kind, arg_place)) } ExprKind::Binary { op, lhs, rhs } => { let lhs = unpack!(block = this.as_operand(block, scope, lhs)); let rhs = unpack!(block = this.as_operand(block, scope, rhs)); - this.build_binary_op(block, op, expr_span, expr.ty, - lhs, rhs) + this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs) } ExprKind::Unary { op, arg } => { let arg = unpack!(block = this.as_operand(block, scope, arg)); @@ -81,11 +101,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let minval = this.minval_literal(expr_span, expr.ty); let is_min = this.temp(bool_ty, expr_span); - this.cfg.push_assign(block, source_info, &is_min, - Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval)); + this.cfg.push_assign( + block, + source_info, + &is_min, + Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval), + ); - block = this.assert(block, Operand::Move(is_min), false, - EvalErrorKind::OverflowNeg, expr_span); + block = this.assert( + block, + Operand::Move(is_min), + false, + EvalErrorKind::OverflowNeg, + expr_span, + ); } block.and(Rvalue::UnaryOp(op, arg)) } @@ -94,22 +123,30 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // The `Box` temporary created here is not a part of the HIR, // and therefore is not considered during generator OIBIT // determination. See the comment about `box` at `yield_in_scope`. - let result = this.local_decls.push( - LocalDecl::new_internal(expr.ty, expr_span)); - this.cfg.push(block, Statement { - source_info, - kind: StatementKind::StorageLive(result) - }); + let result = this + .local_decls + .push(LocalDecl::new_internal(expr.ty, expr_span)); + this.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::StorageLive(result), + }, + ); if let Some(scope) = scope { // schedule a shallow free of that memory, lest we unwind: this.schedule_drop_storage_and_value( - expr_span, scope, &Place::Local(result), value.ty, + expr_span, + scope, + &Place::Local(result), + value.ty, ); } // malloc some memory of suitable type (thus far, uninitialized): let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); - this.cfg.push_assign(block, source_info, &Place::Local(result), box_); + this.cfg + .push_assign(block, source_info, &Place::Local(result), box_); // initialize the box contents: unpack!(block = this.into(&Place::Local(result).deref(), block, value)); @@ -170,23 +207,29 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // first process the set of fields let el_ty = expr.ty.sequence_element_type(this.hir.tcx()); - let fields: Vec<_> = - fields.into_iter() - .map(|f| unpack!(block = this.as_operand(block, scope, f))) - .collect(); + let fields: Vec<_> = fields + .into_iter() + .map(|f| unpack!(block = this.as_operand(block, scope, f))) + .collect(); block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields)) } - ExprKind::Tuple { fields } => { // see (*) above + ExprKind::Tuple { fields } => { + // see (*) above // first process the set of fields - let fields: Vec<_> = - fields.into_iter() - .map(|f| unpack!(block = this.as_operand(block, scope, f))) - .collect(); + let fields: Vec<_> = fields + .into_iter() + .map(|f| unpack!(block = this.as_operand(block, scope, f))) + .collect(); block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields)) } - ExprKind::Closure { closure_id, substs, upvars, movability } => { + ExprKind::Closure { + closure_id, + substs, + upvars, + movability, + } => { // see (*) above let mut operands: Vec<_> = upvars .into_iter() @@ -212,25 +255,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // that caused the capture will cause an error. match upvar.kind { ExprKind::Borrow { - borrow_kind: BorrowKind::Mut { - allow_two_phase_borrow: false - }, + borrow_kind: + BorrowKind::Mut { + allow_two_phase_borrow: false, + }, region, arg, - } => unpack!(block = this.limit_capture_mutability( - upvar.span, - upvar.ty, - scope, - block, - arg, - region, - )), + } => unpack!( + block = this.limit_capture_mutability( + upvar.span, upvar.ty, scope, block, arg, region, + ) + ), _ => unpack!(block = this.as_operand(block, scope, upvar)), } } } - }) - .collect(); + }).collect(); let result = match substs { UpvarSubsts::Generator(substs) => { let movability = movability.unwrap(); @@ -239,6 +279,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { operands.push(Operand::Constant(box Constant { span: expr_span, ty: this.hir.tcx().types.u32, + user_ty: None, literal: ty::Const::from_bits( this.hir.tcx(), 0, @@ -247,23 +288,36 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { })); box AggregateKind::Generator(closure_id, substs, movability) } - UpvarSubsts::Closure(substs) => { - box AggregateKind::Closure(closure_id, substs) - } + UpvarSubsts::Closure(substs) => box AggregateKind::Closure(closure_id, substs), }; block.and(Rvalue::Aggregate(result, operands)) } ExprKind::Adt { - adt_def, variant_index, substs, fields, base - } => { // see (*) above + adt_def, + variant_index, + substs, + user_ty, + fields, + base, + } => { + // see (*) above let is_union = adt_def.is_union(); - let active_field_index = if is_union { Some(fields[0].name.index()) } else { None }; + let active_field_index = if is_union { + Some(fields[0].name.index()) + } else { + None + }; // first process the set of fields that were provided // (evaluating them in order given by user) - let fields_map: FxHashMap<_, _> = fields.into_iter() - .map(|f| (f.name, unpack!(block = this.as_operand(block, scope, f.expr)))) - .collect(); + let fields_map: FxHashMap<_, _> = fields + .into_iter() + .map(|f| { + ( + f.name, + unpack!(block = this.as_operand(block, scope, f.expr)), + ) + }).collect(); let field_names = this.hir.all_fields(adt_def, variant_index); @@ -273,23 +327,30 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // MIR does not natively support FRU, so for each // base-supplied field, generate an operand that // reads it from the base. - field_names.into_iter() + field_names + .into_iter() .zip(field_types.into_iter()) .map(|(n, ty)| match fields_map.get(&n) { Some(v) => v.clone(), - None => this.consume_by_copy_or_move(base.clone().field(n, ty)) - }) - .collect() + None => this.consume_by_copy_or_move(base.clone().field(n, ty)), + }).collect() } else { - field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect() + field_names + .iter() + .filter_map(|n| fields_map.get(n).cloned()) + .collect() }; - let adt = - box AggregateKind::Adt(adt_def, variant_index, substs, active_field_index); + let adt = box AggregateKind::Adt( + adt_def, + variant_index, + substs, + user_ty, + active_field_index, + ); block.and(Rvalue::Aggregate(adt, fields)) } - ExprKind::Assign { .. } | - ExprKind::AssignOp { .. } => { + ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { block = unpack!(this.stmt_expr(block, expr)); block.and(this.unit_rvalue()) } @@ -297,31 +358,35 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let value = unpack!(block = this.as_operand(block, scope, value)); let resume = this.cfg.start_new_block(); let cleanup = this.generator_drop_cleanup(); - this.cfg.terminate(block, source_info, TerminatorKind::Yield { - value: value, - resume: resume, - drop: cleanup, - }); + this.cfg.terminate( + block, + source_info, + TerminatorKind::Yield { + value: value, + resume: resume, + drop: cleanup, + }, + ); resume.and(this.unit_rvalue()) } - ExprKind::Literal { .. } | - ExprKind::Block { .. } | - ExprKind::Match { .. } | - ExprKind::If { .. } | - ExprKind::NeverToAny { .. } | - ExprKind::Loop { .. } | - ExprKind::LogicalOp { .. } | - ExprKind::Call { .. } | - ExprKind::Field { .. } | - ExprKind::Deref { .. } | - ExprKind::Index { .. } | - ExprKind::VarRef { .. } | - ExprKind::SelfRef | - ExprKind::Break { .. } | - ExprKind::Continue { .. } | - ExprKind::Return { .. } | - ExprKind::InlineAsm { .. } | - ExprKind::StaticRef { .. } => { + ExprKind::Literal { .. } + | ExprKind::Block { .. } + | ExprKind::Match { .. } + | ExprKind::If { .. } + | ExprKind::NeverToAny { .. } + | ExprKind::Loop { .. } + | ExprKind::LogicalOp { .. } + | ExprKind::Call { .. } + | ExprKind::Field { .. } + | ExprKind::Deref { .. } + | ExprKind::Index { .. } + | ExprKind::VarRef { .. } + | ExprKind::SelfRef + | ExprKind::Break { .. } + | ExprKind::Continue { .. } + | ExprKind::Return { .. } + | ExprKind::InlineAsm { .. } + | ExprKind::StaticRef { .. } => { // these do not have corresponding `Rvalue` variants, // so make an operand and then return that debug_assert!(match Category::of(&expr.kind) { @@ -334,19 +399,27 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - pub fn build_binary_op(&mut self, mut block: BasicBlock, - op: BinOp, span: Span, ty: Ty<'tcx>, - lhs: Operand<'tcx>, rhs: Operand<'tcx>) -> BlockAnd> { + pub fn build_binary_op( + &mut self, + mut block: BasicBlock, + op: BinOp, + span: Span, + ty: Ty<'tcx>, + lhs: Operand<'tcx>, + rhs: Operand<'tcx>, + ) -> BlockAnd> { let source_info = self.source_info(span); let bool_ty = self.hir.bool_ty(); if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() { let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]); let result_value = self.temp(result_tup, span); - self.cfg.push_assign(block, source_info, - &result_value, Rvalue::CheckedBinaryOp(op, - lhs, - rhs)); + self.cfg.push_assign( + block, + source_info, + &result_value, + Rvalue::CheckedBinaryOp(op, lhs, rhs), + ); let val_fld = Field::new(0); let of_fld = Field::new(1); @@ -355,8 +428,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let err = EvalErrorKind::Overflow(op); - block = self.assert(block, Operand::Move(of), false, - err, span); + block = self.assert(block, Operand::Move(of), false, err, span); block.and(Rvalue::Use(Operand::Move(val))) } else { @@ -365,21 +437,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // and 2. there are two possible failure cases, divide-by-zero and overflow. let (zero_err, overflow_err) = if op == BinOp::Div { - (EvalErrorKind::DivisionByZero, - EvalErrorKind::Overflow(op)) + (EvalErrorKind::DivisionByZero, EvalErrorKind::Overflow(op)) } else { - (EvalErrorKind::RemainderByZero, - EvalErrorKind::Overflow(op)) + (EvalErrorKind::RemainderByZero, EvalErrorKind::Overflow(op)) }; // Check for / 0 let is_zero = self.temp(bool_ty, span); let zero = self.zero_literal(span, ty); - self.cfg.push_assign(block, source_info, &is_zero, - Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), zero)); + self.cfg.push_assign( + block, + source_info, + &is_zero, + Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), zero), + ); - block = self.assert(block, Operand::Move(is_zero), false, - zero_err, span); + block = self.assert(block, Operand::Move(is_zero), false, zero_err, span); // We only need to check for the overflow in one case: // MIN / -1, and only for signed values. @@ -388,23 +461,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let min = self.minval_literal(span, ty); let is_neg_1 = self.temp(bool_ty, span); - let is_min = self.temp(bool_ty, span); - let of = self.temp(bool_ty, span); + let is_min = self.temp(bool_ty, span); + let of = self.temp(bool_ty, span); // this does (rhs == -1) & (lhs == MIN). It could short-circuit instead - self.cfg.push_assign(block, source_info, &is_neg_1, - Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), neg_1)); - self.cfg.push_assign(block, source_info, &is_min, - Rvalue::BinaryOp(BinOp::Eq, lhs.to_copy(), min)); + self.cfg.push_assign( + block, + source_info, + &is_neg_1, + Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), neg_1), + ); + self.cfg.push_assign( + block, + source_info, + &is_min, + Rvalue::BinaryOp(BinOp::Eq, lhs.to_copy(), min), + ); let is_neg_1 = Operand::Move(is_neg_1); let is_min = Operand::Move(is_min); - self.cfg.push_assign(block, source_info, &of, - Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min)); + self.cfg.push_assign( + block, + source_info, + &of, + Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min), + ); - block = self.assert(block, Operand::Move(of), false, - overflow_err, span); + block = self.assert(block, Operand::Move(of), false, overflow_err, span); } } @@ -424,12 +508,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let this = self; let source_info = this.source_info(upvar_span); - let temp = this.local_decls.push(LocalDecl::new_temp(upvar_ty, upvar_span)); + let temp = this + .local_decls + .push(LocalDecl::new_temp(upvar_ty, upvar_span)); - this.cfg.push(block, Statement { - source_info, - kind: StatementKind::StorageLive(temp) - }); + this.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::StorageLive(temp), + }, + ); let arg_place = unpack!(block = this.as_place(block, arg)); @@ -440,8 +529,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { elem: ProjectionElem::Deref, }) => { debug_assert!( - if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) - = this.local_decls[local].is_user_variable { + if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) = + this.local_decls[local].is_user_variable + { true } else { false @@ -455,10 +545,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { elem: ProjectionElem::Field(upvar_index, _), }) | Place::Projection(box Projection { - base: Place::Projection(box Projection { - ref base, - elem: ProjectionElem::Field(upvar_index, _), - }), + base: + Place::Projection(box Projection { + ref base, + elem: ProjectionElem::Field(upvar_index, _), + }), elem: ProjectionElem::Deref, }) => { // Not projected from the implicit `self` in a closure. @@ -485,7 +576,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let borrow_kind = match mutability { Mutability::Not => BorrowKind::Unique, - Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false }, + Mutability::Mut => BorrowKind::Mut { + allow_two_phase_borrow: false, + }, }; this.cfg.push_assign( @@ -500,7 +593,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // a constant at this time, even if the type may need dropping. if let Some(temp_lifetime) = temp_lifetime { this.schedule_drop_storage_and_value( - upvar_span, temp_lifetime, &Place::Local(temp), upvar_ty, + upvar_span, + temp_lifetime, + &Place::Local(temp), + upvar_ty, ); } diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index f66fe763b7..a2dcce6adc 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -18,42 +18,63 @@ use rustc::mir::*; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr` into a fresh temporary. This is used when building /// up rvalues so as to freeze the value that will be consumed. - pub fn as_temp(&mut self, - block: BasicBlock, - temp_lifetime: Option, - expr: M) - -> BlockAnd - where M: Mirror<'tcx, Output = Expr<'tcx>> + pub fn as_temp( + &mut self, + block: BasicBlock, + temp_lifetime: Option, + expr: M, + mutability: Mutability, + ) -> BlockAnd + where + M: Mirror<'tcx, Output = Expr<'tcx>>, { let expr = self.hir.mirror(expr); - self.expr_as_temp(block, temp_lifetime, expr) + self.expr_as_temp(block, temp_lifetime, expr, mutability) } - fn expr_as_temp(&mut self, - mut block: BasicBlock, - temp_lifetime: Option, - expr: Expr<'tcx>) - -> BlockAnd { - debug!("expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?})", - block, temp_lifetime, expr); + fn expr_as_temp( + &mut self, + mut block: BasicBlock, + temp_lifetime: Option, + expr: Expr<'tcx>, + mutability: Mutability, + ) -> BlockAnd { + debug!( + "expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})", + block, temp_lifetime, expr, mutability + ); let this = self; let expr_span = expr.span; let source_info = this.source_info(expr_span); - if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { + if let ExprKind::Scope { + region_scope, + lint_level, + value, + } = expr.kind + { return this.in_scope((region_scope, source_info), lint_level, block, |this| { - this.as_temp(block, temp_lifetime, value) + this.as_temp(block, temp_lifetime, value, mutability) }); } let expr_ty = expr.ty; - let temp = this.local_decls.push(LocalDecl::new_temp(expr_ty, expr_span)); + let temp = if mutability == Mutability::Not { + this.local_decls + .push(LocalDecl::new_immutable_temp(expr_ty, expr_span)) + } else { + this.local_decls + .push(LocalDecl::new_temp(expr_ty, expr_span)) + }; if !expr_ty.is_never() { - this.cfg.push(block, Statement { - source_info, - kind: StatementKind::StorageLive(temp) - }); + this.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::StorageLive(temp), + }, + ); } unpack!(block = this.into(&Place::Local(temp), block, expr)); @@ -63,7 +84,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // a constant at this time, even if the type may need dropping. if let Some(temp_lifetime) = temp_lifetime { this.schedule_drop_storage_and_value( - expr_span, temp_lifetime, &Place::Local(temp), expr_ty, + expr_span, + temp_lifetime, + &Place::Local(temp), + expr_ty, ); } diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index bce8e97d48..601fe2d01f 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -45,53 +45,51 @@ impl Category { match *ek { ExprKind::Scope { .. } => None, - ExprKind::Field { .. } | - ExprKind::Deref { .. } | - ExprKind::Index { .. } | - ExprKind::SelfRef | - ExprKind::VarRef { .. } | - ExprKind::StaticRef { .. } => - Some(Category::Place), + ExprKind::Field { .. } + | ExprKind::Deref { .. } + | ExprKind::Index { .. } + | ExprKind::SelfRef + | ExprKind::VarRef { .. } + | ExprKind::StaticRef { .. } => Some(Category::Place), - ExprKind::LogicalOp { .. } | - ExprKind::If { .. } | - ExprKind::Match { .. } | - ExprKind::NeverToAny { .. } | - ExprKind::Call { .. } => - Some(Category::Rvalue(RvalueFunc::Into)), + ExprKind::LogicalOp { .. } + | ExprKind::If { .. } + | ExprKind::Match { .. } + | ExprKind::NeverToAny { .. } + | ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)), - ExprKind::Array { .. } | - ExprKind::Tuple { .. } | - ExprKind::Adt { .. } | - ExprKind::Closure { .. } | - ExprKind::Unary { .. } | - ExprKind::Binary { .. } | - ExprKind::Box { .. } | - ExprKind::Cast { .. } | - ExprKind::Use { .. } | - ExprKind::ReifyFnPointer { .. } | - ExprKind::ClosureFnPointer { .. } | - ExprKind::UnsafeFnPointer { .. } | - ExprKind::Unsize { .. } | - ExprKind::Repeat { .. } | - ExprKind::Borrow { .. } | - ExprKind::Assign { .. } | - ExprKind::AssignOp { .. } | - ExprKind::Yield { .. } | - ExprKind::InlineAsm { .. } => - Some(Category::Rvalue(RvalueFunc::AsRvalue)), + ExprKind::Array { .. } + | ExprKind::Tuple { .. } + | ExprKind::Adt { .. } + | ExprKind::Closure { .. } + | ExprKind::Unary { .. } + | ExprKind::Binary { .. } + | ExprKind::Box { .. } + | ExprKind::Cast { .. } + | ExprKind::Use { .. } + | ExprKind::ReifyFnPointer { .. } + | ExprKind::ClosureFnPointer { .. } + | ExprKind::UnsafeFnPointer { .. } + | ExprKind::Unsize { .. } + | ExprKind::Repeat { .. } + | ExprKind::Borrow { .. } + | ExprKind::Assign { .. } + | ExprKind::AssignOp { .. } + | ExprKind::Yield { .. } + | ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)), - ExprKind::Literal { .. } => - Some(Category::Constant), + ExprKind::Literal { .. } => Some(Category::Constant), - ExprKind::Loop { .. } | - ExprKind::Block { .. } | - ExprKind::Break { .. } | - ExprKind::Continue { .. } | - ExprKind::Return { .. } => - // FIXME(#27840) these probably want their own - // category, like "nonterminating" - Some(Category::Rvalue(RvalueFunc::Into)), + ExprKind::Loop { .. } + | ExprKind::Block { .. } + | ExprKind::Break { .. } + | ExprKind::Continue { .. } + | ExprKind::Return { .. } => + // FIXME(#27840) these probably want their own + // category, like "nonterminating" + { + Some(Category::Rvalue(RvalueFunc::Into)) + } } } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 59a7f49af8..5708ac4e6b 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -10,25 +10,27 @@ //! See docs in build/expr/mod.rs -use build::{BlockAnd, BlockAndExtension, Builder}; use build::expr::category::{Category, RvalueFunc}; +use build::{BlockAnd, BlockAndExtension, Builder}; use hair::*; -use rustc::ty; use rustc::mir::*; +use rustc::ty; use rustc_target::spec::abi::Abi; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Compile `expr`, storing the result into `destination`, which /// is assumed to be uninitialized. - pub fn into_expr(&mut self, - destination: &Place<'tcx>, - mut block: BasicBlock, - expr: Expr<'tcx>) - -> BlockAnd<()> - { - debug!("into_expr(destination={:?}, block={:?}, expr={:?})", - destination, block, expr); + pub fn into_expr( + &mut self, + destination: &Place<'tcx>, + mut block: BasicBlock, + expr: Expr<'tcx>, + ) -> BlockAnd<()> { + debug!( + "into_expr(destination={:?}, block={:?}, expr={:?})", + destination, block, expr + ); // since we frequently have to reference `self` from within a // closure, where `self` would be shadowed, it's easier to @@ -38,10 +40,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = this.source_info(expr_span); match expr.kind { - ExprKind::Scope { region_scope, lint_level, value } => { + ExprKind::Scope { + region_scope, + lint_level, + value, + } => { let region_scope = (region_scope, source_info); - this.in_scope(region_scope, lint_level, block, - |this| this.into(destination, block, value)) + this.in_scope(region_scope, lint_level, block, |this| { + this.into(destination, block, value) + }) } ExprKind::Block { body: ast_block } => { this.ast_block(destination, block, ast_block, source_info) @@ -63,12 +70,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if is_call { block.unit() } else { - this.cfg.terminate(block, source_info, TerminatorKind::Unreachable); + this.cfg + .terminate(block, source_info, TerminatorKind::Unreachable); let end_block = this.cfg.start_new_block(); end_block.unit() } } - ExprKind::If { condition: cond_expr, then: then_expr, otherwise: else_expr } => { + ExprKind::If { + condition: cond_expr, + then: then_expr, + otherwise: else_expr, + } => { let operand = unpack!(block = this.as_local_operand(block, cond_expr)); let mut then_block = this.cfg.start_new_block(); @@ -82,15 +94,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } else { // Body of the `if` expression without an `else` clause must return `()`, thus // we implicitly generate a `else {}` if it is not specified. - this.cfg.push_assign_unit(else_block, source_info, destination); + this.cfg + .push_assign_unit(else_block, source_info, destination); else_block }; let join_block = this.cfg.start_new_block(); - this.cfg.terminate(then_block, source_info, - TerminatorKind::Goto { target: join_block }); - this.cfg.terminate(else_block, source_info, - TerminatorKind::Goto { target: join_block }); + this.cfg.terminate( + then_block, + source_info, + TerminatorKind::Goto { target: join_block }, + ); + this.cfg.terminate( + else_block, + source_info, + TerminatorKind::Goto { target: join_block }, + ); join_block.unit() } @@ -107,9 +126,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // | (true) | (false) // [true_block] [false_block] - let (true_block, false_block, mut else_block, join_block) = - (this.cfg.start_new_block(), this.cfg.start_new_block(), - this.cfg.start_new_block(), this.cfg.start_new_block()); + let (true_block, false_block, mut else_block, join_block) = ( + this.cfg.start_new_block(), + this.cfg.start_new_block(), + this.cfg.start_new_block(), + this.cfg.start_new_block(), + ); let lhs = unpack!(block = this.as_local_operand(block, lhs)); let blocks = match op { @@ -124,29 +146,46 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.cfg.terminate(else_block, source_info, term); this.cfg.push_assign_constant( - true_block, source_info, destination, + true_block, + source_info, + destination, Constant { span: expr_span, ty: this.hir.bool_ty(), + user_ty: None, literal: this.hir.true_literal(), - }); + }, + ); this.cfg.push_assign_constant( - false_block, source_info, destination, + false_block, + source_info, + destination, Constant { span: expr_span, ty: this.hir.bool_ty(), + user_ty: None, literal: this.hir.false_literal(), - }); + }, + ); - this.cfg.terminate(true_block, source_info, - TerminatorKind::Goto { target: join_block }); - this.cfg.terminate(false_block, source_info, - TerminatorKind::Goto { target: join_block }); + this.cfg.terminate( + true_block, + source_info, + TerminatorKind::Goto { target: join_block }, + ); + this.cfg.terminate( + false_block, + source_info, + TerminatorKind::Goto { target: join_block }, + ); join_block.unit() } - ExprKind::Loop { condition: opt_cond_expr, body } => { + ExprKind::Loop { + condition: opt_cond_expr, + body, + } => { // [block] --> [loop_block] -/eval. cond./-> [loop_block_end] -1-> [exit_block] // ^ | // | 0 @@ -170,35 +209,45 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let exit_block = this.cfg.start_new_block(); // start the loop - this.cfg.terminate(block, source_info, - TerminatorKind::Goto { target: loop_block }); + this.cfg.terminate( + block, + source_info, + TerminatorKind::Goto { target: loop_block }, + ); this.in_breakable_scope( - Some(loop_block), exit_block, destination.clone(), + Some(loop_block), + exit_block, + destination.clone(), move |this| { // conduct the test, if necessary let body_block; if let Some(cond_expr) = opt_cond_expr { let loop_block_end; let cond = unpack!( - loop_block_end = this.as_local_operand(loop_block, cond_expr)); + loop_block_end = this.as_local_operand(loop_block, cond_expr) + ); body_block = this.cfg.start_new_block(); - let term = TerminatorKind::if_(this.hir.tcx(), cond, - body_block, exit_block); + let term = + TerminatorKind::if_(this.hir.tcx(), cond, body_block, exit_block); this.cfg.terminate(loop_block_end, source_info, term); // if the test is false, there's no `break` to assign `destination`, so // we have to do it; this overwrites any `break`-assigned value but it's // always `()` anyway - this.cfg.push_assign_unit(exit_block, source_info, destination); + this.cfg + .push_assign_unit(exit_block, source_info, destination); } else { body_block = this.cfg.start_new_block(); let diverge_cleanup = this.diverge_cleanup(); - this.cfg.terminate(loop_block, source_info, - TerminatorKind::FalseUnwind { - real_target: body_block, - unwind: Some(diverge_cleanup) - }) + this.cfg.terminate( + loop_block, + source_info, + TerminatorKind::FalseUnwind { + real_target: body_block, + unwind: Some(diverge_cleanup), + }, + ) } // The “return” value of the loop body must always be an unit. We therefore @@ -206,9 +255,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let tmp = this.get_unit_temp(); // Execute the body, branching back to the test. let body_block_end = unpack!(this.into(&tmp, body_block, body)); - this.cfg.terminate(body_block_end, source_info, - TerminatorKind::Goto { target: loop_block }); - } + this.cfg.terminate( + body_block_end, + source_info, + TerminatorKind::Goto { target: loop_block }, + ); + }, ); exit_block.unit() } @@ -216,16 +268,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // FIXME(canndrew): This is_never should probably be an is_uninhabited let diverges = expr.ty.is_never(); let intrinsic = match ty.sty { - ty::TyFnDef(def_id, _) => { + ty::FnDef(def_id, _) => { let f = ty.fn_sig(this.hir.tcx()); - if f.abi() == Abi::RustIntrinsic || - f.abi() == Abi::PlatformIntrinsic { + if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { Some(this.hir.tcx().item_name(def_id).as_str()) } else { None } } - _ => None + _ => None, }; let intrinsic = intrinsic.as_ref().map(|s| &s[..]); let fun = unpack!(block = this.as_local_operand(block, fun)); @@ -245,6 +296,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let ptr_temp = this.local_decls.push(LocalDecl { mutability: Mutability::Mut, ty: ptr_ty, + user_ty: None, name: None, source_info, visibility_scope: source_info.scope, @@ -255,95 +307,99 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let block = unpack!(this.into(&ptr_temp, block, ptr)); this.into(&ptr_temp.deref(), block, val) } else { - let args: Vec<_> = - args.into_iter() - .map(|arg| unpack!(block = this.as_local_operand(block, arg))) - .collect(); + let args: Vec<_> = args + .into_iter() + .map(|arg| unpack!(block = this.as_local_operand(block, arg))) + .collect(); let success = this.cfg.start_new_block(); let cleanup = this.diverge_cleanup(); - this.cfg.terminate(block, source_info, TerminatorKind::Call { - func: fun, - args, - cleanup: Some(cleanup), - destination: if diverges { - None - } else { - Some ((destination.clone(), success)) - } - }); + this.cfg.terminate( + block, + source_info, + TerminatorKind::Call { + func: fun, + args, + cleanup: Some(cleanup), + destination: if diverges { + None + } else { + Some((destination.clone(), success)) + }, + }, + ); success.unit() } } // These cases don't actually need a destination - ExprKind::Assign { .. } | - ExprKind::AssignOp { .. } | - ExprKind::Continue { .. } | - ExprKind::Break { .. } | - ExprKind::InlineAsm { .. } | - ExprKind::Return { .. } => { + ExprKind::Assign { .. } + | ExprKind::AssignOp { .. } + | ExprKind::Continue { .. } + | ExprKind::Break { .. } + | ExprKind::InlineAsm { .. } + | ExprKind::Return { .. } => { unpack!(block = this.stmt_expr(block, expr)); this.cfg.push_assign_unit(block, source_info, destination); block.unit() } // Avoid creating a temporary - ExprKind::VarRef { .. } | - ExprKind::SelfRef | - ExprKind::StaticRef { .. } => { + ExprKind::VarRef { .. } | ExprKind::SelfRef | ExprKind::StaticRef { .. } => { debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); let place = unpack!(block = this.as_place(block, expr)); let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); - this.cfg.push_assign(block, source_info, destination, rvalue); + this.cfg + .push_assign(block, source_info, destination, rvalue); block.unit() } - ExprKind::Index { .. } | - ExprKind::Deref { .. } | - ExprKind::Field { .. } => { + ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => { debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); // Create a "fake" temporary variable so that we check that the // value is Sized. Usually, this is caught in type checking, but // in the case of box expr there is no such check. if let Place::Projection(..) = destination { - this.local_decls.push(LocalDecl::new_temp(expr.ty, expr.span)); + this.local_decls + .push(LocalDecl::new_temp(expr.ty, expr.span)); } debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); let place = unpack!(block = this.as_place(block, expr)); let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); - this.cfg.push_assign(block, source_info, destination, rvalue); + this.cfg + .push_assign(block, source_info, destination, rvalue); block.unit() } // these are the cases that are more naturally handled by some other mode - ExprKind::Unary { .. } | - ExprKind::Binary { .. } | - ExprKind::Box { .. } | - ExprKind::Cast { .. } | - ExprKind::Use { .. } | - ExprKind::ReifyFnPointer { .. } | - ExprKind::ClosureFnPointer { .. } | - ExprKind::UnsafeFnPointer { .. } | - ExprKind::Unsize { .. } | - ExprKind::Repeat { .. } | - ExprKind::Borrow { .. } | - ExprKind::Array { .. } | - ExprKind::Tuple { .. } | - ExprKind::Adt { .. } | - ExprKind::Closure { .. } | - ExprKind::Literal { .. } | - ExprKind::Yield { .. } => { + ExprKind::Unary { .. } + | ExprKind::Binary { .. } + | ExprKind::Box { .. } + | ExprKind::Cast { .. } + | ExprKind::Use { .. } + | ExprKind::ReifyFnPointer { .. } + | ExprKind::ClosureFnPointer { .. } + | ExprKind::UnsafeFnPointer { .. } + | ExprKind::Unsize { .. } + | ExprKind::Repeat { .. } + | ExprKind::Borrow { .. } + | ExprKind::Array { .. } + | ExprKind::Tuple { .. } + | ExprKind::Adt { .. } + | ExprKind::Closure { .. } + | ExprKind::Literal { .. } + | ExprKind::Yield { .. } => { debug_assert!(match Category::of(&expr.kind).unwrap() { Category::Rvalue(RvalueFunc::Into) => false, _ => true, }); let rvalue = unpack!(block = this.as_local_rvalue(block, expr)); - this.cfg.push_assign(block, source_info, destination, rvalue); + this.cfg + .push_assign(block, source_info, destination, rvalue); block.unit() } } diff --git a/src/librustc_mir/build/expr/mod.rs b/src/librustc_mir/build/expr/mod.rs index a63cf41f06..6442ba34da 100644 --- a/src/librustc_mir/build/expr/mod.rs +++ b/src/librustc_mir/build/expr/mod.rs @@ -71,9 +71,9 @@ //! over to the "by reference" mode (`as_place`). mod as_constant; +mod as_operand; mod as_place; mod as_rvalue; -mod as_operand; mod as_temp; mod category; mod into; diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 6f1fe83357..0086cff46e 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use build::{BlockAnd, BlockAndExtension, Builder}; use build::scope::BreakableScope; +use build::{BlockAnd, BlockAndExtension, Builder}; use hair::*; use rustc::mir::*; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { - pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<()> { let this = self; let expr_span = expr.span; @@ -22,7 +21,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Handle a number of expressions that don't need a destination at all. This // avoids needing a mountain of temporary `()` variables. match expr.kind { - ExprKind::Scope { region_scope, lint_level, value } => { + ExprKind::Scope { + region_scope, + lint_level, + value, + } => { let value = this.hir.mirror(value); this.in_scope((region_scope, source_info), lint_level, block, |this| { this.stmt_expr(block, value) @@ -42,9 +45,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if this.hir.needs_drop(lhs.ty) { let rhs = unpack!(block = this.as_local_operand(block, rhs)); let lhs = unpack!(block = this.as_place(block, lhs)); - unpack!(block = this.build_drop_and_replace( - block, lhs_span, lhs, rhs - )); + unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs)); block.unit() } else { let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); @@ -72,18 +73,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // we don't have to drop prior contents or anything // because AssignOp is only legal for Copy types // (overloaded ops should be desugared into a call). - let result = unpack!(block = this.build_binary_op(block, op, expr_span, lhs_ty, - Operand::Copy(lhs.clone()), rhs)); + let result = unpack!( + block = this.build_binary_op( + block, + op, + expr_span, + lhs_ty, + Operand::Copy(lhs.clone()), + rhs + ) + ); this.cfg.push_assign(block, source_info, &lhs, result); block.unit() } ExprKind::Continue { label } => { - let BreakableScope { continue_block, region_scope, .. } = - *this.find_breakable_scope(expr_span, label); - let continue_block = continue_block.expect( - "Attempted to continue in non-continuable breakable block"); - this.exit_scope(expr_span, (region_scope, source_info), block, continue_block); + let BreakableScope { + continue_block, + region_scope, + .. + } = *this.find_breakable_scope(expr_span, label); + let continue_block = continue_block + .expect("Attempted to continue in non-continuable breakable block"); + this.exit_scope( + expr_span, + (region_scope, source_info), + block, + continue_block, + ); this.cfg.start_new_block().unit() } ExprKind::Break { label, value } => { @@ -106,13 +123,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } ExprKind::Return { value } => { block = match value { - Some(value) => { - unpack!(this.into(&Place::Local(RETURN_PLACE), block, value)) - } + Some(value) => unpack!(this.into(&Place::Local(RETURN_PLACE), block, value)), None => { - this.cfg.push_assign_unit(block, - source_info, - &Place::Local(RETURN_PLACE)); + this.cfg + .push_assign_unit(block, source_info, &Place::Local(RETURN_PLACE)); block } }; @@ -121,21 +135,30 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.exit_scope(expr_span, (region_scope, source_info), block, return_block); this.cfg.start_new_block().unit() } - ExprKind::InlineAsm { asm, outputs, inputs } => { - let outputs = outputs.into_iter().map(|output| { - unpack!(block = this.as_place(block, output)) - }).collect(); - let inputs = inputs.into_iter().map(|input| { - unpack!(block = this.as_local_operand(block, input)) - }).collect(); - this.cfg.push(block, Statement { - source_info, - kind: StatementKind::InlineAsm { - asm: box asm.clone(), - outputs, - inputs, + ExprKind::InlineAsm { + asm, + outputs, + inputs, + } => { + let outputs = outputs + .into_iter() + .map(|output| unpack!(block = this.as_place(block, output))) + .collect(); + let inputs = inputs + .into_iter() + .map(|input| unpack!(block = this.as_local_operand(block, input))) + .collect(); + this.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::InlineAsm { + asm: box asm.clone(), + outputs, + inputs, + }, }, - }); + ); block.unit() } _ => { @@ -147,5 +170,4 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } } - } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index a509ec08a1..cef1fb77e5 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -13,16 +13,16 @@ //! includes the high-level algorithm, the submodules contain the //! details. +use build::scope::{CachedBlock, DropKind}; +use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard}; use build::{BlockAnd, BlockAndExtension, Builder}; use build::{GuardFrame, GuardFrameLocal, LocalsForNode}; -use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard}; -use build::scope::{CachedBlock, DropKind}; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::bitvec::BitVector; -use rustc::ty::{self, Ty}; -use rustc::mir::*; -use rustc::hir; use hair::*; +use rustc::hir; +use rustc::mir::*; +use rustc::ty::{self, CanonicalTy, Ty}; +use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::fx::FxHashMap; use syntax::ast::{Name, NodeId}; use syntax_pos::Span; @@ -37,13 +37,14 @@ mod util; pub(crate) struct ArmHasGuard(pub bool); impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { - pub fn match_expr(&mut self, - destination: &Place<'tcx>, - span: Span, - mut block: BasicBlock, - discriminant: ExprRef<'tcx>, - arms: Vec>) - -> BlockAnd<()> { + pub fn match_expr( + &mut self, + destination: &Place<'tcx>, + span: Span, + mut block: BasicBlock, + discriminant: ExprRef<'tcx>, + arms: Vec>, + ) -> BlockAnd<()> { let tcx = self.hir.tcx(); let discriminant_span = discriminant.span(); let discriminant_place = unpack!(block = self.as_place(block, discriminant)); @@ -67,7 +68,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let dummy_access = Rvalue::Discriminant(discriminant_place.clone()); let dummy_ty = dummy_access.ty(&self.local_decls, tcx); let dummy_temp = self.temp(dummy_ty, dummy_source_info.span); - self.cfg.push_assign(block, dummy_source_info, &dummy_temp, dummy_access); + self.cfg + .push_assign(block, dummy_source_info, &dummy_temp, dummy_access); let source_info = self.source_info(discriminant_span); let borrowed_input_temp = if tcx.generate_borrow_of_any_match_input() { @@ -75,38 +77,46 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // inference to find an appropriate one. Therefore you can // only use this when NLL is turned on. assert!(tcx.use_mir_borrowck()); - let borrowed_input = - Rvalue::Ref(tcx.types.re_empty, BorrowKind::Shared, discriminant_place.clone()); + let borrowed_input = Rvalue::Ref( + tcx.types.re_empty, + BorrowKind::Shared, + discriminant_place.clone(), + ); let borrowed_input_ty = borrowed_input.ty(&self.local_decls, tcx); let borrowed_input_temp = self.temp(borrowed_input_ty, span); - self.cfg.push_assign(block, source_info, &borrowed_input_temp, borrowed_input); + self.cfg + .push_assign(block, source_info, &borrowed_input_temp, borrowed_input); Some(borrowed_input_temp) } else { None }; let mut arm_blocks = ArmBlocks { - blocks: arms.iter() - .map(|_| self.cfg.start_new_block()) - .collect(), + blocks: arms.iter().map(|_| self.cfg.start_new_block()).collect(), }; // Get the arm bodies and their scopes, while declaring bindings. - let arm_bodies: Vec<_> = arms.iter().map(|arm| { - // BUG: use arm lint level - let body = self.hir.mirror(arm.body.clone()); - let scope = self.declare_bindings(None, body.span, - LintLevel::Inherited, - &arm.patterns[..], - ArmHasGuard(arm.guard.is_some()), - Some((Some(&discriminant_place), discriminant_span))); - (body, scope.unwrap_or(self.source_scope)) - }).collect(); + let arm_bodies: Vec<_> = arms.iter() + .map(|arm| { + // BUG: use arm lint level + let body = self.hir.mirror(arm.body.clone()); + let scope = self.declare_bindings( + None, + body.span, + LintLevel::Inherited, + &arm.patterns[..], + ArmHasGuard(arm.guard.is_some()), + Some((Some(&discriminant_place), discriminant_span)), + ); + (body, scope.unwrap_or(self.source_scope)) + }) + .collect(); // create binding start block for link them by false edges let candidate_count = arms.iter().fold(0, |ac, c| ac + c.patterns.len()); let pre_binding_blocks: Vec<_> = (0..candidate_count + 1) - .map(|_| self.cfg.start_new_block()).collect(); + .map(|_| self.cfg.start_new_block()) + .collect(); // assemble a list of candidates: there is one candidate per // pattern, which means there may be more than one candidate @@ -114,21 +124,27 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // highest priority candidate comes first in the list. // (i.e. same order as in source) - let candidates: Vec<_> = - arms.iter() - .enumerate() - .flat_map(|(arm_index, arm)| { - arm.patterns.iter().enumerate() - .map(move |(pat_index, pat)| { - (arm_index, pat_index, pat, arm.guard.clone()) - }) - }) - .zip(pre_binding_blocks.iter().zip(pre_binding_blocks.iter().skip(1))) - .map(|((arm_index, pat_index, pattern, guard), - (pre_binding_block, next_candidate_pre_binding_block))| { - - if let (true, Some(borrow_temp)) = (tcx.emit_read_for_match(), - borrowed_input_temp.clone()) { + let candidates: Vec<_> = arms.iter() + .enumerate() + .flat_map(|(arm_index, arm)| { + arm.patterns + .iter() + .enumerate() + .map(move |(pat_index, pat)| (arm_index, pat_index, pat, arm.guard.clone())) + }) + .zip( + pre_binding_blocks + .iter() + .zip(pre_binding_blocks.iter().skip(1)), + ) + .map( + |( + (arm_index, pat_index, pattern, guard), + (pre_binding_block, next_candidate_pre_binding_block), + )| { + if let (true, Some(borrow_temp)) = + (tcx.emit_read_for_match(), borrowed_input_temp.clone()) + { // inject a fake read of the borrowed input at // the start of each arm's pattern testing // code. @@ -137,10 +153,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // the variant for an enum while you are in // the midst of matching on it. let pattern_source_info = self.source_info(pattern.span); - self.cfg.push(*pre_binding_block, Statement { - source_info: pattern_source_info, - kind: StatementKind::ReadForMatch(borrow_temp.clone()), - }); + self.cfg.push( + *pre_binding_block, + Statement { + source_info: pattern_source_info, + kind: StatementKind::ReadForMatch(borrow_temp.clone()), + }, + ); } // One might ask: why not build up the match pair such that it @@ -168,18 +187,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: pattern.span, match_pairs: vec![MatchPair::new(discriminant_place.clone(), pattern)], bindings: vec![], + ascriptions: vec![], guard, arm_index, pat_index, pre_binding_block: *pre_binding_block, next_candidate_pre_binding_block: *next_candidate_pre_binding_block, } - }) - .collect(); + }, + ) + .collect(); let outer_source_info = self.source_info(span); - self.cfg.terminate(*pre_binding_blocks.last().unwrap(), - outer_source_info, TerminatorKind::Unreachable); + self.cfg.terminate( + *pre_binding_blocks.last().unwrap(), + outer_source_info, + TerminatorKind::Unreachable, + ); // this will generate code to test discriminant_place and // branch to the appropriate arm block @@ -198,7 +222,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { otherwise.sort(); otherwise.dedup(); // variant switches can introduce duplicate target blocks for block in otherwise { - self.cfg.terminate(block, source_info, TerminatorKind::Unreachable); + self.cfg + .terminate(block, source_info, TerminatorKind::Unreachable); } } @@ -211,50 +236,75 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Re-enter the source scope we created the bindings in. self.source_scope = source_scope; unpack!(arm_block = self.into(destination, arm_block, body)); - self.cfg.terminate(arm_block, outer_source_info, - TerminatorKind::Goto { target: end_block }); + self.cfg.terminate( + arm_block, + outer_source_info, + TerminatorKind::Goto { target: end_block }, + ); } self.source_scope = outer_source_info.scope; end_block.unit() } - pub fn user_assert_ty(&mut self, block: BasicBlock, hir_id: hir::HirId, - var: NodeId, span: Span) { - if self.hir.tcx().sess.opts.debugging_opts.disable_nll_user_type_assert { return; } - - let local_id = self.var_local_id(var, OutsideGuard); - let source_info = self.source_info(span); - - debug!("user_assert_ty: local_id={:?}", hir_id.local_id); - if let Some(c_ty) = self.hir.tables.user_provided_tys().get(hir_id) { - debug!("user_assert_ty: c_ty={:?}", c_ty); - self.cfg.push(block, Statement { - source_info, - kind: StatementKind::UserAssertTy(*c_ty, local_id), - }); - } - } - - pub fn expr_into_pattern(&mut self, - mut block: BasicBlock, - ty: Option, - irrefutable_pat: Pattern<'tcx>, - initializer: ExprRef<'tcx>) - -> BlockAnd<()> { - // optimize the case of `let x = ...` + pub fn expr_into_pattern( + &mut self, + mut block: BasicBlock, + irrefutable_pat: Pattern<'tcx>, + initializer: ExprRef<'tcx>, + ) -> BlockAnd<()> { match *irrefutable_pat.kind { - PatternKind::Binding { mode: BindingMode::ByValue, - var, - subpattern: None, .. } => { - let place = self.storage_live_binding(block, var, irrefutable_pat.span, - OutsideGuard); - - if let Some(ty) = ty { - self.user_assert_ty(block, ty, var, irrefutable_pat.span); - } + // Optimize the case of `let x = ...` to write directly into `x` + PatternKind::Binding { + mode: BindingMode::ByValue, + var, + subpattern: None, + .. + } => { + let place = + self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); + unpack!(block = self.into(&place, block, initializer)); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); + block.unit() + } + // Optimize the case of `let x: T = ...` to write directly + // into `x` and then require that `T == typeof(x)`. + // + // Weirdly, this is needed to prevent the + // `intrinsic-move-val.rs` test case from crashing. That + // test works with uninitialized values in a rather + // dubious way, so it may be that the test is kind of + // broken. + PatternKind::AscribeUserType { + subpattern: Pattern { + kind: box PatternKind::Binding { + mode: BindingMode::ByValue, + var, + subpattern: None, + .. + }, + .. + }, + user_ty: ascription_user_ty, + } => { + let place = + self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); unpack!(block = self.into(&place, block, initializer)); + + let source_info = self.source_info(irrefutable_pat.span); + self.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::AscribeUserType( + place.clone(), + ty::Variance::Invariant, + ascription_user_ty, + ), + }, + ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } @@ -265,24 +315,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - pub fn place_into_pattern(&mut self, - mut block: BasicBlock, - irrefutable_pat: Pattern<'tcx>, - initializer: &Place<'tcx>, - set_match_place: bool) - -> BlockAnd<()> { + pub fn place_into_pattern( + &mut self, + mut block: BasicBlock, + irrefutable_pat: Pattern<'tcx>, + initializer: &Place<'tcx>, + set_match_place: bool, + ) -> BlockAnd<()> { // create a dummy candidate let mut candidate = Candidate { span: irrefutable_pat.span, match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)], bindings: vec![], + ascriptions: vec![], guard: None, // since we don't call `match_candidates`, next fields is unused arm_index: 0, pat_index: 0, pre_binding_block: block, - next_candidate_pre_binding_block: block + next_candidate_pre_binding_block: block, }; // Simplify the candidate. Since the pattern is irrefutable, this should @@ -290,10 +342,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { unpack!(block = self.simplify_candidate(block, &mut candidate)); if !candidate.match_pairs.is_empty() { - span_bug!(candidate.match_pairs[0].pattern.span, - "match pairs {:?} remaining after simplifying \ - irrefutable pattern", - candidate.match_pairs); + span_bug!( + candidate.match_pairs[0].pattern.span, + "match pairs {:?} remaining after simplifying \ + irrefutable pattern", + candidate.match_pairs + ); } // for matches and function arguments, the place that is being matched @@ -304,9 +358,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { for binding in &candidate.bindings { let local = self.var_local_id(binding.var_id, OutsideGuard); - if let Some(ClearCrossCrate::Set(BindingForm::Var( - VarBindingForm {opt_match_place: Some((ref mut match_place, _)), .. } - ))) = self.local_decls[local].is_user_variable + if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + opt_match_place: Some((ref mut match_place, _)), + .. + }))) = self.local_decls[local].is_user_variable { *match_place = Some(initializer.clone()); } else { @@ -315,124 +370,195 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } + self.ascribe_types(block, &candidate.ascriptions); + // now apply the bindings, which will also declare the variables self.bind_matched_candidate_for_arm_body(block, &candidate.bindings); block.unit() } - /// Declares the bindings of the given pattern and returns the visibility scope - /// for the bindings in this patterns, if such a scope had to be created. - /// NOTE: Declaring the bindings should always be done in their drop scope. - pub fn declare_bindings(&mut self, - mut visibility_scope: Option, - scope_span: Span, - lint_level: LintLevel, - patterns: &[Pattern<'tcx>], - has_guard: ArmHasGuard, - opt_match_place: Option<(Option<&Place<'tcx>>, Span)>) - -> Option { - assert!(!(visibility_scope.is_some() && lint_level.is_explicit()), - "can't have both a visibility and a lint scope at the same time"); + /// Declares the bindings of the given patterns and returns the visibility + /// scope for the bindings in these patterns, if such a scope had to be + /// created. NOTE: Declaring the bindings should always be done in their + /// drop scope. + pub fn declare_bindings( + &mut self, + mut visibility_scope: Option, + scope_span: Span, + lint_level: LintLevel, + patterns: &[Pattern<'tcx>], + has_guard: ArmHasGuard, + opt_match_place: Option<(Option<&Place<'tcx>>, Span)>, + ) -> Option { + assert!( + !(visibility_scope.is_some() && lint_level.is_explicit()), + "can't have both a visibility and a lint scope at the same time" + ); let mut scope = self.source_scope; let num_patterns = patterns.len(); - self.visit_bindings(&patterns[0], &mut |this, mutability, name, mode, var, span, ty| { - if visibility_scope.is_none() { - visibility_scope = Some(this.new_source_scope(scope_span, - LintLevel::Inherited, - None)); - // If we have lints, create a new source scope - // that marks the lints for the locals. See the comment - // on the `source_info` field for why this is needed. - if lint_level.is_explicit() { - scope = - this.new_source_scope(scope_span, lint_level, None); + self.visit_bindings( + &patterns[0], + None, + &mut |this, mutability, name, mode, var, span, ty, user_ty| { + if visibility_scope.is_none() { + visibility_scope = + Some(this.new_source_scope(scope_span, LintLevel::Inherited, None)); + // If we have lints, create a new source scope + // that marks the lints for the locals. See the comment + // on the `source_info` field for why this is needed. + if lint_level.is_explicit() { + scope = this.new_source_scope(scope_span, lint_level, None); + } } - } - let source_info = SourceInfo { - span, - scope, - }; - let visibility_scope = visibility_scope.unwrap(); - this.declare_binding(source_info, visibility_scope, mutability, name, mode, - num_patterns, var, ty, has_guard, - opt_match_place.map(|(x, y)| (x.cloned(), y))); - }); + let source_info = SourceInfo { span, scope }; + let visibility_scope = visibility_scope.unwrap(); + this.declare_binding( + source_info, + visibility_scope, + mutability, + name, + mode, + num_patterns, + var, + ty, + user_ty, + has_guard, + opt_match_place.map(|(x, y)| (x.cloned(), y)), + patterns[0].span, + ); + }, + ); visibility_scope } - pub fn storage_live_binding(&mut self, - block: BasicBlock, - var: NodeId, - span: Span, - for_guard: ForGuard) - -> Place<'tcx> - { + pub fn storage_live_binding( + &mut self, + block: BasicBlock, + var: NodeId, + span: Span, + for_guard: ForGuard, + ) -> Place<'tcx> { let local_id = self.var_local_id(var, for_guard); let source_info = self.source_info(span); - self.cfg.push(block, Statement { - source_info, - kind: StatementKind::StorageLive(local_id) - }); + self.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::StorageLive(local_id), + }, + ); let place = Place::Local(local_id); let var_ty = self.local_decls[local_id].ty; let hir_id = self.hir.tcx().hir.node_to_hir_id(var); let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id); - self.schedule_drop( - span, region_scope, &place, var_ty, - DropKind::Storage, - ); + self.schedule_drop(span, region_scope, &place, var_ty, DropKind::Storage); place } - pub fn schedule_drop_for_binding(&mut self, - var: NodeId, - span: Span, - for_guard: ForGuard) { + pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span, for_guard: ForGuard) { let local_id = self.var_local_id(var, for_guard); let var_ty = self.local_decls[local_id].ty; let hir_id = self.hir.tcx().hir.node_to_hir_id(var); let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id); self.schedule_drop( - span, region_scope, &Place::Local(local_id), var_ty, + span, + region_scope, + &Place::Local(local_id), + var_ty, DropKind::Value { cached_block: CachedBlock::default(), }, ); } - pub fn visit_bindings(&mut self, pattern: &Pattern<'tcx>, f: &mut F) - where F: FnMut(&mut Self, Mutability, Name, BindingMode, NodeId, Span, Ty<'tcx>) - { + pub fn visit_bindings( + &mut self, + pattern: &Pattern<'tcx>, + mut pattern_user_ty: Option>, + f: &mut impl FnMut( + &mut Self, + Mutability, + Name, + BindingMode, + NodeId, + Span, + Ty<'tcx>, + Option>, + ), + ) { match *pattern.kind { - PatternKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => { - f(self, mutability, name, mode, var, pattern.span, ty); + PatternKind::Binding { + mutability, + name, + mode, + var, + ty, + ref subpattern, + .. + } => { + match mode { + BindingMode::ByValue => { } + BindingMode::ByRef(..) => { + // If this is a `ref` binding (e.g., `let ref + // x: T = ..`), then the type of `x` is not + // `T` but rather `&T`, so ignore + // `pattern_user_ty` for now. + // + // FIXME(#47184): extract or handle `pattern_user_ty` somehow + pattern_user_ty = None; + } + } + + f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty); if let Some(subpattern) = subpattern.as_ref() { - self.visit_bindings(subpattern, f); + self.visit_bindings(subpattern, pattern_user_ty, f); } } - PatternKind::Array { ref prefix, ref slice, ref suffix } | - PatternKind::Slice { ref prefix, ref slice, ref suffix } => { + PatternKind::Array { + ref prefix, + ref slice, + ref suffix, + } + | PatternKind::Slice { + ref prefix, + ref slice, + ref suffix, + } => { + // FIXME(#47184): extract or handle `pattern_user_ty` somehow for subpattern in prefix.iter().chain(slice).chain(suffix) { - self.visit_bindings(subpattern, f); + self.visit_bindings(subpattern, None, f); } } - PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => { - } + PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {} PatternKind::Deref { ref subpattern } => { - self.visit_bindings(subpattern, f); + // FIXME(#47184): extract or handle `pattern_user_ty` somehow + self.visit_bindings(subpattern, None, f); } - PatternKind::Leaf { ref subpatterns } | - PatternKind::Variant { ref subpatterns, .. } => { + PatternKind::AscribeUserType { ref subpattern, user_ty } => { + // This corresponds to something like + // + // ``` + // let (p1: T1): T2 = ...; + // ``` + // + // Not presently possible, though maybe someday. + assert!(pattern_user_ty.is_none()); + self.visit_bindings(subpattern, Some(user_ty), f) + } + PatternKind::Leaf { ref subpatterns } + | PatternKind::Variant { + ref subpatterns, .. + } => { + // FIXME(#47184): extract or handle `pattern_user_ty` somehow for subpattern in subpatterns { - self.visit_bindings(&subpattern.pattern, f); + self.visit_bindings(&subpattern.pattern, None, f); } } } } } - /// List of blocks for each arm (and potentially other metadata in the /// future). struct ArmBlocks { @@ -440,7 +566,7 @@ struct ArmBlocks { } #[derive(Clone, Debug)] -pub struct Candidate<'pat, 'tcx:'pat> { +pub struct Candidate<'pat, 'tcx: 'pat> { // span of the original pattern that gave rise to this candidate span: Span, @@ -450,8 +576,11 @@ pub struct Candidate<'pat, 'tcx:'pat> { // ...these bindings established... bindings: Vec>, + // ...these types asserted... + ascriptions: Vec>, + // ...and the guard must be evaluated... - guard: Option>, + guard: Option>, // ...and then we branch to arm with this index. arm_index: usize, @@ -475,8 +604,18 @@ struct Binding<'tcx> { binding_mode: BindingMode<'tcx>, } +/// Indicates that the type of `source` must be a subtype of the +/// user-given type `user_ty`; this is basically a no-op but can +/// influence region inference. +#[derive(Clone, Debug)] +struct Ascription<'tcx> { + span: Span, + source: Place<'tcx>, + user_ty: CanonicalTy<'tcx>, +} + #[derive(Clone, Debug)] -pub struct MatchPair<'pat, 'tcx:'pat> { +pub struct MatchPair<'pat, 'tcx: 'pat> { // this place... place: Place<'tcx>, @@ -488,7 +627,7 @@ pub struct MatchPair<'pat, 'tcx:'pat> { // the "rest" part of the pattern right now has type &[T] and // as such, it requires an Rvalue::Slice to be generated. // See RFC 495 / issue #23121 for the eventual (proper) solution. - slice_len_checked: bool + slice_len_checked: bool, } #[derive(Clone, Debug, PartialEq)] @@ -496,7 +635,7 @@ enum TestKind<'tcx> { // test the branches of enum Switch { adt_def: &'tcx ty::AdtDef, - variants: BitVector, + variants: BitArray, }, // test the branches of enum @@ -557,15 +696,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// up the list of candidates and recurse with a non-exhaustive /// list. This is important to keep the size of the generated code /// under control. See `test_candidates` for more details. - fn match_candidates<'pat>(&mut self, - span: Span, - arm_blocks: &mut ArmBlocks, - mut candidates: Vec>, - mut block: BasicBlock) - -> Vec - { - debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})", - span, block, candidates); + fn match_candidates<'pat>( + &mut self, + span: Span, + arm_blocks: &mut ArmBlocks, + mut candidates: Vec>, + mut block: BasicBlock, + ) -> Vec { + debug!( + "matched_candidate(span={:?}, block={:?}, candidates={:?})", + span, block, candidates + ); // Start by simplifying candidates. Once this process is // complete, all the match pairs which remain require some @@ -578,13 +719,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // whether the higher priority candidates (and hence at // the front of the vec) have satisfied all their match // pairs. - let fully_matched = - candidates.iter().take_while(|c| c.match_pairs.is_empty()).count(); - debug!("match_candidates: {:?} candidates fully matched", fully_matched); + let fully_matched = candidates + .iter() + .take_while(|c| c.match_pairs.is_empty()) + .count(); + debug!( + "match_candidates: {:?} candidates fully matched", + fully_matched + ); let mut unmatched_candidates = candidates.split_off(fully_matched); - let fully_matched_with_guard = - candidates.iter().take_while(|c| c.guard.is_some()).count(); + let fully_matched_with_guard = candidates.iter().take_while(|c| c.guard.is_some()).count(); let unreachable_candidates = if fully_matched_with_guard + 1 < candidates.len() { candidates.split_off(fully_matched_with_guard + 1) @@ -601,20 +746,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // if None is returned, then any remaining candidates // are unreachable (at least not through this path). // Link them with false edges. - debug!("match_candidates: add false edges for unreachable {:?} and unmatched {:?}", - unreachable_candidates, unmatched_candidates); + debug!( + "match_candidates: add false edges for unreachable {:?} and unmatched {:?}", + unreachable_candidates, unmatched_candidates + ); for candidate in unreachable_candidates { let source_info = self.source_info(candidate.span); let target = self.cfg.start_new_block(); - if let Some(otherwise) = self.bind_and_guard_matched_candidate(target, - arm_blocks, - candidate) { - self.cfg.terminate(otherwise, source_info, TerminatorKind::Unreachable); + if let Some(otherwise) = + self.bind_and_guard_matched_candidate(target, arm_blocks, candidate) + { + self.cfg + .terminate(otherwise, source_info, TerminatorKind::Unreachable); } } if unmatched_candidates.is_empty() { - return vec![] + return vec![]; } else { let target = self.cfg.start_new_block(); return self.match_candidates(span, arm_blocks, unmatched_candidates, target); @@ -647,11 +795,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.match_candidates(span, arm_blocks, untested_candidates, join_block) } - fn join_otherwise_blocks(&mut self, - span: Span, - mut otherwise: Vec) - -> BasicBlock - { + fn join_otherwise_blocks(&mut self, span: Span, mut otherwise: Vec) -> BasicBlock { let source_info = self.source_info(span); otherwise.sort(); otherwise.dedup(); // variant switches can introduce duplicate target blocks @@ -660,8 +804,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } else { let join_block = self.cfg.start_new_block(); for block in otherwise { - self.cfg.terminate(block, source_info, - TerminatorKind::Goto { target: join_block }); + self.cfg.terminate( + block, + source_info, + TerminatorKind::Goto { target: join_block }, + ); } join_block } @@ -779,13 +926,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// In addition to avoiding exponential-time blowups, this algorithm /// also has nice property that each guard and arm is only generated /// once. - fn test_candidates<'pat>(&mut self, - span: Span, - arm_blocks: &mut ArmBlocks, - candidates: &[Candidate<'pat, 'tcx>], - block: BasicBlock) - -> (Vec, usize) - { + fn test_candidates<'pat>( + &mut self, + span: Span, + arm_blocks: &mut ArmBlocks, + candidates: &[Candidate<'pat, 'tcx>], + block: BasicBlock, + ) -> (Vec, usize) { // extract the match-pair from the highest priority candidate let match_pair = &candidates.first().unwrap().match_pairs[0]; let mut test = self.test(match_pair); @@ -795,34 +942,44 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // may want to add cases based on the candidates that are // available match test.kind { - TestKind::SwitchInt { switch_ty, ref mut options, ref mut indices } => { + TestKind::SwitchInt { + switch_ty, + ref mut options, + ref mut indices, + } => { for candidate in candidates.iter() { - if !self.add_cases_to_switch(&match_pair.place, - candidate, - switch_ty, - options, - indices) { + if !self.add_cases_to_switch( + &match_pair.place, + candidate, + switch_ty, + options, + indices, + ) { break; } } } - TestKind::Switch { adt_def: _, ref mut variants} => { + TestKind::Switch { + adt_def: _, + ref mut variants, + } => { for candidate in candidates.iter() { - if !self.add_variants_to_switch(&match_pair.place, - candidate, - variants) { + if !self.add_variants_to_switch(&match_pair.place, candidate, variants) { break; } } } - _ => { } + _ => {} } // perform the test, branching to one of N blocks. For each of // those N possible outcomes, create a (initially empty) // vector of candidates. Those are the candidates that still // apply if the test has that particular outcome. - debug!("match_candidates: test={:?} match_pair={:?}", test, match_pair); + debug!( + "match_candidates: test={:?} match_pair={:?}", + test, match_pair + ); let target_blocks = self.perform_test(block, &match_pair.place, &test); let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect(); @@ -830,31 +987,30 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // `target_candidates`. Note that at some point we may // encounter a candidate where the test is not relevant; at // that point, we stop sorting. - let tested_candidates = - candidates.iter() - .take_while(|c| self.sort_candidate(&match_pair.place, - &test, - c, - &mut target_candidates)) - .count(); + let tested_candidates = candidates + .iter() + .take_while(|c| { + self.sort_candidate(&match_pair.place, &test, c, &mut target_candidates) + }) + .count(); assert!(tested_candidates > 0); // at least the last candidate ought to be tested debug!("tested_candidates: {}", tested_candidates); - debug!("untested_candidates: {}", candidates.len() - tested_candidates); + debug!( + "untested_candidates: {}", + candidates.len() - tested_candidates + ); // For each outcome of test, process the candidates that still // apply. Collect a list of blocks where control flow will // branch if one of the `target_candidate` sets is not // exhaustive. - let otherwise: Vec<_> = - target_blocks.into_iter() - .zip(target_candidates) - .flat_map(|(target_block, target_candidates)| { - self.match_candidates(span, - arm_blocks, - target_candidates, - target_block) - }) - .collect(); + let otherwise: Vec<_> = target_blocks + .into_iter() + .zip(target_candidates) + .flat_map(|(target_block, target_candidates)| { + self.match_candidates(span, arm_blocks, target_candidates, target_block) + }) + .collect(); (otherwise, tested_candidates) } @@ -871,30 +1027,41 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// bindings, further tests would be a use-after-move (which would /// in turn be detected by the borrowck code that runs on the /// MIR). - fn bind_and_guard_matched_candidate<'pat>(&mut self, - mut block: BasicBlock, - arm_blocks: &mut ArmBlocks, - candidate: Candidate<'pat, 'tcx>) - -> Option { - debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})", - block, candidate); + fn bind_and_guard_matched_candidate<'pat>( + &mut self, + mut block: BasicBlock, + arm_blocks: &mut ArmBlocks, + candidate: Candidate<'pat, 'tcx>, + ) -> Option { + debug!( + "bind_and_guard_matched_candidate(block={:?}, candidate={:?})", + block, candidate + ); debug_assert!(candidate.match_pairs.is_empty()); + self.ascribe_types(block, &candidate.ascriptions); + let arm_block = arm_blocks.blocks[candidate.arm_index]; let candidate_source_info = self.source_info(candidate.span); - self.cfg.terminate(block, candidate_source_info, - TerminatorKind::Goto { target: candidate.pre_binding_block }); + self.cfg.terminate( + block, + candidate_source_info, + TerminatorKind::Goto { + target: candidate.pre_binding_block, + }, + ); block = self.cfg.start_new_block(); - self.cfg.terminate(candidate.pre_binding_block, candidate_source_info, - TerminatorKind::FalseEdges { - real_target: block, - imaginary_targets: - vec![candidate.next_candidate_pre_binding_block], - }); - + self.cfg.terminate( + candidate.pre_binding_block, + candidate_source_info, + TerminatorKind::FalseEdges { + real_target: block, + imaginary_targets: vec![candidate.next_candidate_pre_binding_block], + }, + ); // rust-lang/rust#27282: The `autoref` business deserves some // explanation here. @@ -978,13 +1145,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // match input itself; it is up to us to create a place // holding a `&` or `&mut` that we can then borrow). - let autoref = self.hir.tcx().all_pat_vars_are_implicit_refs_within_guards(); + let autoref = self.hir + .tcx() + .all_pat_vars_are_implicit_refs_within_guards(); if let Some(guard) = candidate.guard { if autoref { self.bind_matched_candidate_for_guard( - block, candidate.pat_index, &candidate.bindings); + block, + candidate.pat_index, + &candidate.bindings, + ); let guard_frame = GuardFrame { - locals: candidate.bindings.iter() + locals: candidate + .bindings + .iter() .map(|b| GuardFrameLocal::new(b.var_id, b.binding_mode)) .collect(), }; @@ -996,12 +1170,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // the block to branch to if the guard fails; if there is no // guard, this block is simply unreachable - let guard = self.hir.mirror(guard); + let guard = match guard { + Guard::If(e) => self.hir.mirror(e), + }; let source_info = self.source_info(guard.span); let cond = unpack!(block = self.as_local_operand(block, guard)); if autoref { let guard_frame = self.guard_context.pop().unwrap(); - debug!("Exiting guard building context with locals: {:?}", guard_frame); + debug!( + "Exiting guard building context with locals: {:?}", + guard_frame + ); } let false_edge_block = self.cfg.start_new_block(); @@ -1033,45 +1212,82 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // // and that is clearly not correct. let post_guard_block = self.cfg.start_new_block(); - self.cfg.terminate(block, source_info, - TerminatorKind::if_(self.hir.tcx(), cond, post_guard_block, - false_edge_block)); + self.cfg.terminate( + block, + source_info, + TerminatorKind::if_(self.hir.tcx(), cond, post_guard_block, false_edge_block), + ); if autoref { self.bind_matched_candidate_for_arm_body(post_guard_block, &candidate.bindings); } - self.cfg.terminate(post_guard_block, source_info, - TerminatorKind::Goto { target: arm_block }); + self.cfg.terminate( + post_guard_block, + source_info, + TerminatorKind::Goto { target: arm_block }, + ); let otherwise = self.cfg.start_new_block(); - self.cfg.terminate(false_edge_block, source_info, - TerminatorKind::FalseEdges { - real_target: otherwise, - imaginary_targets: - vec![candidate.next_candidate_pre_binding_block], - }); + self.cfg.terminate( + false_edge_block, + source_info, + TerminatorKind::FalseEdges { + real_target: otherwise, + imaginary_targets: vec![candidate.next_candidate_pre_binding_block], + }, + ); Some(otherwise) } else { // (Here, it is not too early to bind the matched // candidate on `block`, because there is no guard result // that we have to inspect before we bind them.) self.bind_matched_candidate_for_arm_body(block, &candidate.bindings); - self.cfg.terminate(block, candidate_source_info, - TerminatorKind::Goto { target: arm_block }); + self.cfg.terminate( + block, + candidate_source_info, + TerminatorKind::Goto { target: arm_block }, + ); None } } + /// Append `AscribeUserType` statements onto the end of `block` + /// for each ascription + fn ascribe_types<'pat>( + &mut self, + block: BasicBlock, + ascriptions: &[Ascription<'tcx>], + ) { + for ascription in ascriptions { + let source_info = self.source_info(ascription.span); + self.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::AscribeUserType( + ascription.source.clone(), + ty::Variance::Covariant, + ascription.user_ty, + ), + }, + ); + } + } + // Only called when all_pat_vars_are_implicit_refs_within_guards, // and thus all code/comments assume we are in that context. - fn bind_matched_candidate_for_guard(&mut self, - block: BasicBlock, - pat_index: usize, - bindings: &[Binding<'tcx>]) { - debug!("bind_matched_candidate_for_guard(block={:?}, pat_index={:?}, bindings={:?})", - block, pat_index, bindings); + fn bind_matched_candidate_for_guard( + &mut self, + block: BasicBlock, + pat_index: usize, + bindings: &[Binding<'tcx>], + ) { + debug!( + "bind_matched_candidate_for_guard(block={:?}, pat_index={:?}, bindings={:?})", + block, pat_index, bindings + ); // Assign each of the bindings. Since we are binding for a // guard expression, this will never trigger moves out of the @@ -1084,8 +1300,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // a reference R: &T pointing to the location matched by // the pattern, and every occurrence of P within a guard // denotes *R. - let ref_for_guard = self.storage_live_binding( - block, binding.var_id, binding.span, RefWithinGuard); + let ref_for_guard = + self.storage_live_binding(block, binding.var_id, binding.span, RefWithinGuard); // Question: Why schedule drops if bindings are all // shared-&'s? Answer: Because schedule_drop_for_binding // also emits StorageDead's for those locals. @@ -1093,7 +1309,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match binding.binding_mode { BindingMode::ByValue => { let rvalue = Rvalue::Ref(re_empty, BorrowKind::Shared, binding.source.clone()); - self.cfg.push_assign(block, source_info, &ref_for_guard, rvalue); + self.cfg + .push_assign(block, source_info, &ref_for_guard, rvalue); } BindingMode::ByRef(region, borrow_kind) => { // Tricky business: For `ref id` and `ref mut id` @@ -1110,9 +1327,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // used by the arm body itself. This eases // observing two-phase borrow restrictions. let val_for_guard = self.storage_live_binding( - block, binding.var_id, binding.span, ValWithinGuard(pat_index)); + block, + binding.var_id, + binding.span, + ValWithinGuard(pat_index), + ); self.schedule_drop_for_binding( - binding.var_id, binding.span, ValWithinGuard(pat_index)); + binding.var_id, + binding.span, + ValWithinGuard(pat_index), + ); // rust-lang/rust#27282: We reuse the two-phase // borrow infrastructure so that the mutable @@ -1122,27 +1346,36 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // discussion on rust-lang/rust#49870. let borrow_kind = match borrow_kind { BorrowKind::Shared | BorrowKind::Unique => borrow_kind, - BorrowKind::Mut { .. } => BorrowKind::Mut { allow_two_phase_borrow: true }, + BorrowKind::Mut { .. } => BorrowKind::Mut { + allow_two_phase_borrow: true, + }, }; let rvalue = Rvalue::Ref(region, borrow_kind, binding.source.clone()); - self.cfg.push_assign(block, source_info, &val_for_guard, rvalue); + self.cfg + .push_assign(block, source_info, &val_for_guard, rvalue); let rvalue = Rvalue::Ref(region, BorrowKind::Shared, val_for_guard); - self.cfg.push_assign(block, source_info, &ref_for_guard, rvalue); + self.cfg + .push_assign(block, source_info, &ref_for_guard, rvalue); } } } } - fn bind_matched_candidate_for_arm_body(&mut self, - block: BasicBlock, - bindings: &[Binding<'tcx>]) { - debug!("bind_matched_candidate_for_arm_body(block={:?}, bindings={:?}", block, bindings); + fn bind_matched_candidate_for_arm_body( + &mut self, + block: BasicBlock, + bindings: &[Binding<'tcx>], + ) { + debug!( + "bind_matched_candidate_for_arm_body(block={:?}, bindings={:?}", + block, bindings + ); // Assign each of the bindings. This may trigger moves out of the candidate. for binding in bindings { let source_info = self.source_info(binding.span); - let local = self.storage_live_binding(block, binding.var_id, binding.span, - OutsideGuard); + let local = + self.storage_live_binding(block, binding.var_id, binding.span, OutsideGuard); self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard); let rvalue = match binding.binding_mode { BindingMode::ByValue => { @@ -1171,21 +1404,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// parts of the matched data, and we want them to be distinct /// temps in order to simplify checks performed by our internal /// leveraging of two-phase borrows). - fn declare_binding(&mut self, - source_info: SourceInfo, - visibility_scope: SourceScope, - mutability: Mutability, - name: Name, - mode: BindingMode, - num_patterns: usize, - var_id: NodeId, - var_ty: Ty<'tcx>, - has_guard: ArmHasGuard, - opt_match_place: Option<(Option>, Span)>) - { - debug!("declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \ - visibility_scope={:?}, source_info={:?})", - var_id, name, mode, var_ty, visibility_scope, source_info); + fn declare_binding( + &mut self, + source_info: SourceInfo, + visibility_scope: SourceScope, + mutability: Mutability, + name: Name, + mode: BindingMode, + num_patterns: usize, + var_id: NodeId, + var_ty: Ty<'tcx>, + user_var_ty: Option>, + has_guard: ArmHasGuard, + opt_match_place: Option<(Option>, Span)>, + pat_span: Span, + ) { + debug!( + "declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \ + visibility_scope={:?}, source_info={:?})", + var_id, name, mode, var_ty, visibility_scope, source_info + ); let tcx = self.hir.tcx(); let binding_mode = match mode { @@ -1194,7 +1432,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; let local = LocalDecl::<'tcx> { mutability, - ty: var_ty.clone(), + ty: var_ty, + user_ty: user_var_ty, name: Some(name), source_info, visibility_scope, @@ -1207,18 +1446,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Instead, just abandon providing diagnostic info. opt_ty_info: None, opt_match_place, + pat_span, }))), }; let for_arm_body = self.local_decls.push(local.clone()); let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() { let mut vals_for_guard = Vec::with_capacity(num_patterns); for _ in 0..num_patterns { - let val_for_guard_idx = self.local_decls.push(local.clone()); + let val_for_guard_idx = self.local_decls.push(LocalDecl { + // This variable isn't mutated but has a name, so has to be + // immutable to avoid the unused mut lint. + mutability: Mutability::Not, + ..local.clone() + }); vals_for_guard.push(val_for_guard_idx); } let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> { - mutability, + // See previous comment. + mutability: Mutability::Not, ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty), + user_ty: None, name: Some(name), source_info, visibility_scope, @@ -1226,7 +1473,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { internal: false, is_user_variable: Some(ClearCrossCrate::Set(BindingForm::RefForGuard)), }); - LocalsForNode::ForGuard { vals_for_guard, ref_for_guard, for_arm_body } + LocalsForNode::ForGuard { + vals_for_guard, + ref_for_guard, + for_arm_body, + } } else { LocalsForNode::One(for_arm_body) }; diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 147b8cc217..14da8e9083 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -23,7 +23,7 @@ //! testing a value against a constant. use build::{BlockAnd, BlockAndExtension, Builder}; -use build::matches::{Binding, MatchPair, Candidate}; +use build::matches::{Ascription, Binding, MatchPair, Candidate}; use hair::*; use rustc::mir::*; @@ -63,6 +63,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { candidate: &mut Candidate<'pat, 'tcx>) -> Result<(), MatchPair<'pat, 'tcx>> { match *match_pair.pattern.kind { + PatternKind::AscribeUserType { ref subpattern, user_ty } => { + candidate.ascriptions.push(Ascription { + span: match_pair.pattern.span, + user_ty, + source: match_pair.place.clone(), + }); + + candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern)); + + Ok(()) + } + PatternKind::Wild => { // nothing left to do Ok(()) diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index f8bfb5b48b..373c8e039f 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -19,7 +19,7 @@ use build::Builder; use build::matches::{Candidate, MatchPair, Test, TestKind}; use hair::*; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc::ty::{self, Ty}; use rustc::ty::util::IntTypeExt; use rustc::mir::*; @@ -38,7 +38,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: match_pair.pattern.span, kind: TestKind::Switch { adt_def: adt_def.clone(), - variants: BitVector::new(adt_def.variants.len()), + variants: BitArray::new(adt_def.variants.len()), }, } } @@ -70,13 +70,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - PatternKind::Range { lo, hi, end } => { + PatternKind::Range { lo, hi, ty, end } => { + assert!(ty == match_pair.pattern.ty); Test { span: match_pair.pattern.span, kind: TestKind::Range { lo, hi, - ty: match_pair.pattern.ty.clone(), + ty, end, }, } @@ -96,6 +97,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } + PatternKind::AscribeUserType { .. } | PatternKind::Array { .. } | PatternKind::Slice { .. } | PatternKind::Wild | @@ -138,6 +140,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Array { .. } | PatternKind::Wild | PatternKind::Binding { .. } | + PatternKind::AscribeUserType { .. } | PatternKind::Leaf { .. } | PatternKind::Deref { .. } => { // don't know how to add these patterns to a switch @@ -149,7 +152,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn add_variants_to_switch<'pat>(&mut self, test_place: &Place<'tcx>, candidate: &Candidate<'pat, 'tcx>, - variants: &mut BitVector) + variants: &mut BitArray) -> bool { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { @@ -227,7 +230,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } TestKind::SwitchInt { switch_ty, ref options, indices: _ } => { - let (ret, terminator) = if switch_ty.sty == ty::TyBool { + let (ret, terminator) = if switch_ty.sty == ty::Bool { assert!(options.len() > 0 && options.len() <= 2); let (true_bb, false_bb) = (self.cfg.start_new_block(), self.cfg.start_new_block()); @@ -272,8 +275,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // array, so we can call `<[u8]>::eq` rather than having to find an // `<[u8; N]>::eq`. let unsize = |ty: Ty<'tcx>| match ty.sty { - ty::TyRef(region, rty, _) => match rty.sty { - ty::TyArray(inner_ty, n) => Some((region, inner_ty, n)), + ty::Ref(region, rty, _) => match rty.sty { + ty::Array(inner_ty, n) => Some((region, inner_ty, n)), _ => None, }, _ => None, @@ -344,7 +347,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { func: Operand::Constant(box Constant { span: test.span, ty: mty, - literal: method + + // FIXME(#47184): This constant comes from user + // input (a constant in a pattern). Are + // there forms where users can add type + // annotations here? For example, an + // associated constant? Need to + // experiment. + user_ty: None, + + literal: method, }), args: vec![val, expect], destination: Some((eq_result.clone(), eq_block)), @@ -629,6 +641,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: candidate.span, match_pairs: other_match_pairs, bindings: candidate.bindings.clone(), + ascriptions: candidate.ascriptions.clone(), guard: candidate.guard.clone(), arm_index: candidate.arm_index, pat_index: candidate.pat_index, @@ -693,6 +706,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: candidate.span, match_pairs: all_match_pairs, bindings: candidate.bindings.clone(), + ascriptions: candidate.ascriptions.clone(), guard: candidate.guard.clone(), arm_index: candidate.arm_index, pat_index: candidate.pat_index, diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index ae8070698c..9405f43c05 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -32,6 +32,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { place } + /// Convenience function for creating a literal operand, one + /// without any user type annotation. pub fn literal_operand(&mut self, span: Span, ty: Ty<'tcx>, @@ -40,6 +42,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let constant = box Constant { span, ty, + user_ty: None, literal, }; Operand::Constant(constant) @@ -69,6 +72,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Constant { span: source_info.span, ty: self.hir.usize_ty(), + user_ty: None, literal: self.hir.usize_literal(value), }); temp diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 054bd69c36..d2061d8eec 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -14,6 +14,7 @@ use build::scope::{CachedBlock, DropKind}; use hair::cx::Cx; use hair::{LintLevel, BindingMode, PatternKind}; use rustc::hir; +use rustc::hir::Node; use rustc::hir::def_id::{DefId, LocalDefId}; use rustc::middle::region; use rustc::mir::*; @@ -37,20 +38,17 @@ use util as mir_util; /// Construct the MIR for a given def-id. pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> { let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let unsupported = || { - span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id); - }; // Figure out what primary body this item has. let body_id = match tcx.hir.get(id) { - hir::map::NodeVariant(variant) => + Node::Variant(variant) => return create_constructor_shim(tcx, id, &variant.node.data), - hir::map::NodeStructCtor(ctor) => + Node::StructCtor(ctor) => return create_constructor_shim(tcx, id, ctor), _ => match tcx.hir.maybe_body_owned_by(id) { Some(body) => body, - None => unsupported(), + None => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id), }, }; @@ -67,13 +65,13 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t let ty = tcx.type_of(tcx.hir.local_def_id(id)); let mut abi = fn_sig.abi; let implicit_argument = match ty.sty { - ty::TyClosure(..) => { + ty::Closure(..) => { // HACK(eddyb) Avoid having RustCall on closures, // as it adds unnecessary (and wrong) auto-tupling. abi = Abi::Rust; Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)) } - ty::TyGenerator(..) => { + ty::Generator(..) => { let gen_ty = tcx.body_tables(body_id).node_id_to_type(fn_hir_id); Some(ArgInfo(gen_ty, None, None, None)) } @@ -115,7 +113,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t let (yield_ty, return_ty) = if body.is_generator { let gen_sig = match ty.sty { - ty::TyGenerator(gen_def_id, gen_substs, ..) => + ty::Generator(gen_def_id, gen_substs, ..) => gen_substs.sig(gen_def_id, tcx), _ => span_bug!(tcx.hir.span(id), "generator w/o generator type: {:?}", ty), @@ -241,7 +239,7 @@ fn liberated_closure_env_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id); let (closure_def_id, closure_substs) = match closure_ty.sty { - ty::TyClosure(closure_def_id, closure_substs) => (closure_def_id, closure_substs), + ty::Closure(closure_def_id, closure_substs) => (closure_def_id, closure_substs), _ => bug!("closure expr does not have closure type: {:?}", closure_ty) }; @@ -404,7 +402,9 @@ struct CFG<'tcx> { basic_blocks: IndexVec>, } -newtype_index!(ScopeId); +newtype_index! { + pub struct ScopeId { .. } +} /////////////////////////////////////////////////////////////////////////// /// The `BlockAnd` "monad" packages up the new basic block along with a @@ -523,7 +523,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, by_ref, mutability: Mutability::Not, }; - if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_id) { + if let Some(Node::Binding(pat)) = tcx.hir.find(var_id) { if let hir::PatKind::Binding(_, _, ident, _) = pat.node { decl.debug_name = ident.name; @@ -550,8 +550,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, upvar_decls); let fn_def_id = tcx.hir.local_def_id(fn_id); - let call_site_scope = region::Scope::CallSite(body.value.hir_id.local_id); - let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id); + let call_site_scope = region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite + }; + let arg_scope = region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Arguments + }; let mut block = START_BLOCK; let source_info = builder.source_info(span); let call_site_s = (call_site_scope, source_info); @@ -730,6 +736,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.local_decls.push(LocalDecl { mutability: Mutability::Mut, ty, + user_ty: None, source_info, visibility_scope: source_info.scope, name, @@ -763,6 +770,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { binding_mode, opt_ty_info, opt_match_place: Some((Some(place.clone()), span)), + pat_span: span, }))) }; self.var_indices.insert(var, LocalsForNode::One(local)); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 2dc5138c6f..cc5b08f2a9 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -95,7 +95,6 @@ use rustc::hir; use rustc::hir::def_id::LOCAL_CRATE; use rustc::mir::*; use syntax_pos::{Span}; -use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::fx::FxHashMap; #[derive(Debug)] @@ -566,8 +565,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // The outermost scope (`scopes[0]`) will be the `CallSiteScope`. // We want `scopes[1]`, which is the `ParameterScope`. assert!(self.scopes.len() >= 2); - assert!(match self.scopes[1].region_scope.data() { - region::ScopeData::Arguments(_) => true, + assert!(match self.scopes[1].region_scope.data { + region::ScopeData::Arguments => true, _ => false, }); self.scopes[1].region_scope @@ -732,7 +731,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let region_scope_span = region_scope.span(self.hir.tcx(), &self.hir.region_scope_tree); // Attribute scope exit drops to scope's closing brace. - let scope_end = self.hir.tcx().sess.codemap().end_point(region_scope_span); + let scope_end = self.hir.tcx().sess.source_map().end_point(region_scope_span); scope.drops.push(DropData { span: scope_end, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs new file mode 100644 index 0000000000..82cc1b7f66 --- /dev/null +++ b/src/librustc_mir/const_eval.rs @@ -0,0 +1,448 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Not in interpret to make sure we do not use private implementation details + +use std::fmt; +use std::error::Error; + +use rustc::hir::{self, def_id::DefId}; +use rustc::mir::interpret::ConstEvalErr; +use rustc::mir; +use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt}; +use rustc::ty::layout::{LayoutOf, TyLayout}; +use rustc::ty::subst::Subst; +use rustc_data_structures::indexed_vec::IndexVec; + +use syntax::ast::Mutability; +use syntax::source_map::Span; + +use rustc::mir::interpret::{ + EvalResult, EvalError, EvalErrorKind, GlobalId, + Scalar, Allocation, ConstValue, +}; +use interpret::{self, + Place, PlaceTy, MemPlace, OpTy, Operand, Value, + EvalContext, StackPopCleanup, MemoryKind, +}; + +pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + instance: Instance<'tcx>, + mir: &'mir mir::Mir<'tcx>, + span: Span, +) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> { + debug!("mk_borrowck_eval_cx: {:?}", instance); + let param_env = tcx.param_env(instance.def_id()); + let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ()); + // insert a stack frame so any queries have the correct substs + ecx.stack.push(interpret::Frame { + block: mir::START_BLOCK, + locals: IndexVec::new(), + instance, + span, + mir, + return_place: Place::null(tcx), + return_to_block: StackPopCleanup::Goto(None), // never pop + stmt: 0, + }); + Ok(ecx) +} + +pub fn mk_eval_cx<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + instance: Instance<'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> EvalResult<'tcx, EvalContext<'a, 'tcx, 'tcx, CompileTimeEvaluator>> { + debug!("mk_eval_cx: {:?}, {:?}", instance, param_env); + let span = tcx.def_span(instance.def_id()); + let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ()); + let mir = ecx.load_mir(instance.def)?; + // insert a stack frame so any queries have the correct substs + ecx.push_stack_frame( + instance, + mir.span, + mir, + Place::null(tcx), + StackPopCleanup::Goto(None), // never pop + )?; + Ok(ecx) +} + +pub fn eval_promoted<'a, 'mir, 'tcx>( + ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>, + cid: GlobalId<'tcx>, + mir: &'mir mir::Mir<'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> EvalResult<'tcx, OpTy<'tcx>> { + ecx.with_fresh_body(|ecx| { + eval_body_using_ecx(ecx, cid, Some(mir), param_env) + }) +} + +pub fn op_to_const<'tcx>( + ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>, + op: OpTy<'tcx>, + normalize: bool, +) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> { + let normalized_op = if normalize { + ecx.try_read_value(op)? + } else { + match op.op { + Operand::Indirect(mplace) => Err(mplace), + Operand::Immediate(val) => Ok(val) + } + }; + let val = match normalized_op { + Err(MemPlace { ptr, align, extra }) => { + // extract alloc-offset pair + assert!(extra.is_none()); + let ptr = ptr.to_ptr()?; + let alloc = ecx.memory.get(ptr.alloc_id)?; + assert!(alloc.align.abi() >= align.abi()); + assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes()); + let mut alloc = alloc.clone(); + alloc.align = align; + // FIXME shouldnt it be the case that `mark_static_initialized` has already + // interned this? I thought that is the entire point of that `FinishStatic` stuff? + let alloc = ecx.tcx.intern_const_alloc(alloc); + ConstValue::ByRef(ptr.alloc_id, alloc, ptr.offset) + }, + Ok(Value::Scalar(x)) => + ConstValue::Scalar(x.not_undef()?), + Ok(Value::ScalarPair(a, b)) => + ConstValue::ScalarPair(a.not_undef()?, b), + }; + Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty)) +} + +fn eval_body_and_ecx<'a, 'mir, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + cid: GlobalId<'tcx>, + mir: Option<&'mir mir::Mir<'tcx>>, + param_env: ty::ParamEnv<'tcx>, +) -> (EvalResult<'tcx, OpTy<'tcx>>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) { + // we start out with the best span we have + // and try improving it down the road when more information is available + let span = tcx.def_span(cid.instance.def_id()); + let span = mir.map(|mir| mir.span).unwrap_or(span); + let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ()); + let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env); + (r, ecx) +} + +// Returns a pointer to where the result lives +fn eval_body_using_ecx<'a, 'mir, 'tcx>( + ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>, + cid: GlobalId<'tcx>, + mir: Option<&'mir mir::Mir<'tcx>>, + param_env: ty::ParamEnv<'tcx>, +) -> EvalResult<'tcx, OpTy<'tcx>> { + debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env); + let tcx = ecx.tcx.tcx; + let mut mir = match mir { + Some(mir) => mir, + None => ecx.load_mir(cid.instance.def)?, + }; + if let Some(index) = cid.promoted { + mir = &mir.promoted[index]; + } + let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; + assert!(!layout.is_unsized()); + let ret = ecx.allocate(layout, MemoryKind::Stack)?; + + let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id())); + let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); + trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom); + assert!(mir.arg_count == 0); + ecx.push_stack_frame( + cid.instance, + mir.span, + mir, + Place::Ptr(*ret), + StackPopCleanup::None { cleanup: false }, + )?; + + // The main interpreter loop. + ecx.run()?; + + // Intern the result + let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span); + let is_static = tcx.is_static(cid.instance.def_id()); + let mutability = if is_static == Some(hir::Mutability::MutMutable) || internally_mutable { + Mutability::Mutable + } else { + Mutability::Immutable + }; + ecx.memory.intern_static(ret.ptr.to_ptr()?.alloc_id, mutability)?; + + debug!("eval_body_using_ecx done: {:?}", *ret); + Ok(ret.into()) +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct CompileTimeEvaluator; + +impl<'tcx> Into> for ConstEvalError { + fn into(self) -> EvalError<'tcx> { + EvalErrorKind::MachineError(self.to_string()).into() + } +} + +impl_stable_hash_for!(struct CompileTimeEvaluator {}); + +#[derive(Clone, Debug)] +enum ConstEvalError { + NeedsRfc(String), + NotConst(String), +} + +impl fmt::Display for ConstEvalError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::ConstEvalError::*; + match *self { + NeedsRfc(ref msg) => { + write!( + f, + "\"{}\" needs an rfc before being allowed inside constants", + msg + ) + } + NotConst(ref msg) => write!(f, "{}", msg), + } + } +} + +impl Error for ConstEvalError { + fn description(&self) -> &str { + use self::ConstEvalError::*; + match *self { + NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants", + NotConst(_) => "this feature is not compatible with constant evaluation", + } + } + + fn cause(&self) -> Option<&dyn Error> { + None + } +} + +impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator { + type MemoryData = (); + type MemoryKinds = !; + + const MUT_STATIC_KIND: Option = None; // no mutating of statics allowed + const DETECT_LOOPS: bool = true; + + fn find_fn<'a>( + ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + instance: ty::Instance<'tcx>, + args: &[OpTy<'tcx>], + dest: Option>, + ret: Option, + ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> { + debug!("eval_fn_call: {:?}", instance); + if !ecx.tcx.is_const_fn(instance.def_id()) { + // Some functions we support even if they are non-const -- but avoid testing + // that for const fn! + if ecx.hook_fn(instance, args, dest)? { + ecx.goto_block(ret)?; // fully evaluated and done + return Ok(None); + } + return Err( + ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into(), + ); + } + // This is a const fn. Call it. + Ok(Some(match ecx.load_mir(instance.def) { + Ok(mir) => mir, + Err(err) => { + if let EvalErrorKind::NoMirFor(ref path) = err.kind { + return Err( + ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path)) + .into(), + ); + } + return Err(err); + } + })) + } + + fn call_intrinsic<'a>( + ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + instance: ty::Instance<'tcx>, + args: &[OpTy<'tcx>], + dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + if ecx.emulate_intrinsic(instance, args, dest)? { + return Ok(()); + } + // An intrinsic that we do not support + let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..]; + Err( + ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into() + ) + } + + fn ptr_op<'a>( + _ecx: &EvalContext<'a, 'mir, 'tcx, Self>, + _bin_op: mir::BinOp, + _left: Scalar, + _left_layout: TyLayout<'tcx>, + _right: Scalar, + _right_layout: TyLayout<'tcx>, + ) -> EvalResult<'tcx, (Scalar, bool)> { + Err( + ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(), + ) + } + + fn find_foreign_static<'a>( + _tcx: TyCtxtAt<'a, 'tcx, 'tcx>, + _def_id: DefId, + ) -> EvalResult<'tcx, &'tcx Allocation> { + err!(ReadForeignStatic) + } + + fn box_alloc<'a>( + _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, + _dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + Err( + ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into(), + ) + } +} + +/// Project to a field of a (variant of a) const +pub fn const_field<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + instance: ty::Instance<'tcx>, + variant: Option, + field: mir::Field, + value: &'tcx ty::Const<'tcx>, +) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { + trace!("const_field: {:?}, {:?}, {:?}", instance, field, value); + let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); + let result = (|| { + // get the operand again + let op = ecx.const_to_op(value)?; + // downcast + let down = match variant { + None => op, + Some(variant) => ecx.operand_downcast(op, variant)? + }; + // then project + let field = ecx.operand_field(down, field.index() as u64)?; + // and finally move back to the const world, always normalizing because + // this is not called for statics. + op_to_const(&ecx, field, true) + })(); + result.map_err(|err| { + let (trace, span) = ecx.generate_stacktrace(None); + ConstEvalErr { + error: err, + stacktrace: trace, + span, + }.into() + }) +} + +pub fn const_variant_index<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + instance: ty::Instance<'tcx>, + val: &'tcx ty::Const<'tcx>, +) -> EvalResult<'tcx, usize> { + trace!("const_variant_index: {:?}, {:?}", instance, val); + let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); + let op = ecx.const_to_op(val)?; + Ok(ecx.read_discriminant(op)?.1) +} + +pub fn const_to_allocation_provider<'a, 'tcx>( + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + val: &'tcx ty::Const<'tcx>, +) -> &'tcx Allocation { + // FIXME: This really does not need to be a query. Instead, we should have a query for statics + // that returns an allocation directly (or an `AllocId`?), after doing a sanity check of the + // value and centralizing error reporting. + match val.val { + ConstValue::ByRef(_, alloc, offset) => { + assert_eq!(offset.bytes(), 0); + return alloc; + }, + _ => bug!("const_to_allocation called on non-static"), + } +} + +pub fn const_eval_provider<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, +) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { + trace!("const eval: {:?}", key); + let cid = key.value; + let def_id = cid.instance.def.def_id(); + + if let Some(id) = tcx.hir.as_local_node_id(def_id) { + let tables = tcx.typeck_tables_of(def_id); + let span = tcx.def_span(def_id); + + // Do match-check before building MIR + if tcx.check_match(def_id).is_err() { + return Err(ConstEvalErr { + error: EvalErrorKind::CheckMatchError.into(), + stacktrace: vec![], + span, + }.into()); + } + + if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) { + tcx.mir_const_qualif(def_id); + } + + // Do not continue into miri if typeck errors occurred; it will fail horribly + if tables.tainted_by_errors { + return Err(ConstEvalErr { + error: EvalErrorKind::CheckMatchError.into(), + stacktrace: vec![], + span, + }.into()); + } + }; + + let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env); + res.and_then(|op| { + let normalize = tcx.is_static(def_id).is_none() && cid.promoted.is_none(); + if !normalize { + // Sanity check: These must always be a MemPlace + match op.op { + Operand::Indirect(_) => { /* all is good */ }, + Operand::Immediate(_) => bug!("const eval gave us an Immediate"), + } + } + op_to_const(&ecx, op, normalize) + }).map_err(|err| { + let (trace, span) = ecx.generate_stacktrace(None); + let err = ConstEvalErr { + error: err, + stacktrace: trace, + span, + }; + if tcx.is_static(def_id).is_some() { + err.report_as_error(ecx.tcx, "could not evaluate static initializer"); + if tcx.sess.err_count() == 0 { + span_bug!(span, "static eval failure didn't emit an error: {:#?}", err); + } + } + err.into() + }) +} diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index 05453bd58c..39643af77a 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -12,8 +12,8 @@ //! locations. use rustc::mir::{BasicBlock, Location}; -use rustc_data_structures::indexed_set::{IdxSetBuf, Iter}; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::bitvec::BitIter; +use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet}; use dataflow::{BitDenotation, BlockSets, DataflowResults}; use dataflow::move_paths::{HasMoveData, MovePathIndex}; @@ -28,6 +28,15 @@ pub trait FlowsAtLocation { /// Reset the state bitvector to represent the entry to block `bb`. fn reset_to_entry_of(&mut self, bb: BasicBlock); + /// Reset the state bitvector to represent the exit of the + /// terminator of block `bb`. + /// + /// **Important:** In the case of a `Call` terminator, these + /// effects do *not* include the result of storing the destination + /// of the call, since that is edge-dependent (in other words, the + /// effects don't apply to the unwind edge). + fn reset_to_exit_of(&mut self, bb: BasicBlock); + /// Build gen + kill sets for statement at `loc`. /// /// Note that invoking this method alone does not change the @@ -67,9 +76,9 @@ where BD: BitDenotation, { base_results: DataflowResults, - curr_state: IdxSetBuf, - stmt_gen: IdxSetBuf, - stmt_kill: IdxSetBuf, + curr_state: IdxSet, + stmt_gen: HybridIdxSet, + stmt_kill: HybridIdxSet, } impl FlowAtLocation @@ -96,9 +105,9 @@ where pub fn new(results: DataflowResults) -> Self { let bits_per_block = results.sets().bits_per_block(); - let curr_state = IdxSetBuf::new_empty(bits_per_block); - let stmt_gen = IdxSetBuf::new_empty(bits_per_block); - let stmt_kill = IdxSetBuf::new_empty(bits_per_block); + let curr_state = IdxSet::new_empty(bits_per_block); + let stmt_gen = HybridIdxSet::new_empty(bits_per_block); + let stmt_kill = HybridIdxSet::new_empty(bits_per_block); FlowAtLocation { base_results: results, curr_state: curr_state, @@ -117,7 +126,7 @@ where } /// Returns an iterator over the elements present in the current state. - pub fn iter_incoming(&self) -> iter::Peekable> { + pub fn iter_incoming(&self) -> iter::Peekable> { self.curr_state.iter().peekable() } @@ -126,7 +135,7 @@ where /// Invokes `f` with an iterator over the resulting state. pub fn with_iter_outgoing(&self, f: F) where - F: FnOnce(Iter), + F: FnOnce(BitIter), { let mut curr_state = self.curr_state.clone(); curr_state.union(&self.stmt_gen); @@ -142,6 +151,12 @@ impl FlowsAtLocation for FlowAtLocation self.curr_state.overwrite(self.base_results.sets().on_entry_set_for(bb.index())); } + fn reset_to_exit_of(&mut self, bb: BasicBlock) { + self.reset_to_entry_of(bb); + self.curr_state.union(self.base_results.sets().gen_set_for(bb.index())); + self.curr_state.subtract(self.base_results.sets().kill_set_for(bb.index())); + } + fn reconstruct_statement_effect(&mut self, loc: Location) { self.stmt_gen.clear(); self.stmt_kill.clear(); diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs index 1cbe0dcc01..7af1daae4c 100644 --- a/src/librustc_mir/dataflow/drop_flag_effects.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -61,17 +61,17 @@ fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, place: &mir::Place<'tcx>) -> bool { let ty = place.ty(mir, tcx).to_ty(tcx); match ty.sty { - ty::TyArray(..) => { + ty::Array(..) => { debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false", place, ty); false } - ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => { + ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => { debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true", place, ty); true } - ty::TyAdt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => { + ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => { debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true", place, ty); true diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index 7475b4d82f..9487147ea9 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -12,8 +12,7 @@ use syntax::ast::NodeId; use rustc::mir::{BasicBlock, Mir}; -use rustc_data_structures::bitslice::bits_to_string; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::bitvec::bits_to_string; use dot; use dot::IntoCow; @@ -168,13 +167,13 @@ where MWF: MirWithFlowState<'tcx>, let i = n.index(); macro_rules! dump_set_for { - ($set:ident) => { + ($set:ident, $interpret:ident) => { write!(w, "")?; let flow = self.mbcx.flow_state(); - let entry_interp = flow.interpret_set(&flow.operator, - flow.sets.$set(i), - &self.render_idx); + let entry_interp = flow.$interpret(&flow.operator, + flow.sets.$set(i), + &self.render_idx); for e in &entry_interp { write!(w, "{:?}
", e)?; } @@ -184,7 +183,7 @@ where MWF: MirWithFlowState<'tcx>, write!(w, "")?; // Entry - dump_set_for!(on_entry_set_for); + dump_set_for!(on_entry_set_for, interpret_set); // MIR statements write!(w, "")?; @@ -198,10 +197,10 @@ where MWF: MirWithFlowState<'tcx>, write!(w, "")?; // Gen - dump_set_for!(gen_set_for); + dump_set_for!(gen_set_for, interpret_hybrid_set); // Kill - dump_set_for!(kill_set_for); + dump_set_for!(kill_set_for, interpret_hybrid_set); write!(w, "")?; @@ -217,19 +216,14 @@ where MWF: MirWithFlowState<'tcx>, -> io::Result<()> { let i = n.index(); - macro_rules! dump_set_for { - ($set:ident) => { - let flow = self.mbcx.flow_state(); - let bits_per_block = flow.sets.bits_per_block(); - let set = flow.sets.$set(i); - write!(w, "{:?}", - dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?; - } - } + let flow = self.mbcx.flow_state(); + let bits_per_block = flow.sets.bits_per_block(); write!(w, "")?; + // Entry - dump_set_for!(on_entry_set_for); + let set = flow.sets.on_entry_set_for(i); + write!(w, "{:?}", dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?; // Terminator write!(w, "")?; @@ -242,10 +236,12 @@ where MWF: MirWithFlowState<'tcx>, write!(w, "")?; // Gen - dump_set_for!(gen_set_for); + let set = flow.sets.gen_set_for(i); + write!(w, "{:?}", dot::escape_html(&format!("{:?}", set)))?; // Kill - dump_set_for!(kill_set_for); + let set = flow.sets.kill_set_for(i); + write!(w, "{:?}", dot::escape_html(&format!("{:?}", set)))?; write!(w, "")?; @@ -268,15 +264,12 @@ impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P> fn edges(&self) -> dot::Edges { let mir = self.mbcx.mir(); - // base initial capacity on assumption every block has at - // least one outgoing edge (Which should be true for all - // blocks but one, the exit-block). - let mut edges = Vec::with_capacity(mir.basic_blocks().len()); - for bb in mir.basic_blocks().indices() { - let outgoing = outgoing(mir, bb); - edges.extend(outgoing.into_iter()); - } - edges.into_cow() + + mir.basic_blocks() + .indices() + .flat_map(|bb| outgoing(mir, bb)) + .collect::>() + .into_cow() } fn source(&self, edge: &Edge) -> Node { diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 96f4c6b60f..c8c41c13b0 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -15,9 +15,9 @@ use rustc::mir::visit::Visitor; use dataflow::BitDenotation; /// This calculates if any part of a MIR local could have previously been borrowed. -/// This means that once a local has been borrowed, its bit will always be set -/// from that point and onwards, even if the borrow ends. You could also think of this -/// as computing the lifetimes of infinite borrows. +/// This means that once a local has been borrowed, its bit will be set +/// from that point and onwards, until we see a StorageDead statement for the local, +/// at which points there is no memory associated with the local, so it cannot be borrowed. /// This is used to compute which locals are live during a yield expression for /// immovable generators. #[derive(Copy, Clone)] @@ -50,9 +50,17 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { fn statement_effect(&self, sets: &mut BlockSets, loc: Location) { + let stmt = &self.mir[loc.block].statements[loc.statement_index]; + BorrowedLocalsVisitor { sets, - }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc); + }.visit_statement(loc.block, stmt, loc); + + // StorageDead invalidates all borrows and raw pointers to a local + match stmt.kind { + StatementKind::StorageDead(l) => sets.kill(&l), + _ => (), + } } fn terminator_effect(&self, diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index ea59e42fd4..93136a0fb8 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -20,8 +20,8 @@ use rustc::ty::TyCtxt; use rustc::ty::{RegionKind, RegionVid}; use rustc::ty::RegionKind::ReScope; -use rustc_data_structures::bitslice::{BitwiseOperator, Word}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::bitvec::{BitwiseOperator, Word}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_set::IdxSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::Lrc; @@ -53,6 +53,13 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { _nonlexical_regioncx: Rc>, } +struct StackEntry { + bb: mir::BasicBlock, + lo: usize, + hi: usize, + first_part_only: bool +} + fn precompute_borrows_out_of_scope<'tcx>( mir: &Mir<'tcx>, regioncx: &Rc>, @@ -61,48 +68,79 @@ fn precompute_borrows_out_of_scope<'tcx>( borrow_region: RegionVid, location: Location, ) { - // Keep track of places we've locations to check and locations that we have checked. - let mut stack = vec![ location ]; - let mut visited = FxHashSet(); - visited.insert(location); - - debug!( - "borrow {:?} has region {:?} with value {:?}", - borrow_index, - borrow_region, - regioncx.region_value_str(borrow_region), - ); - debug!("borrow {:?} starts at {:?}", borrow_index, location); - while let Some(location) = stack.pop() { - // If region does not contain a point at the location, then add to list and skip - // successor locations. - if !regioncx.region_contains(borrow_region, location) { - debug!("borrow {:?} gets killed at {:?}", borrow_index, location); - borrows_out_of_scope_at_location - .entry(location) - .or_insert(vec![]) - .push(borrow_index); - continue; + // We visit one BB at a time. The complication is that we may start in the + // middle of the first BB visited (the one containing `location`), in which + // case we may have to later on process the first part of that BB if there + // is a path back to its start. + + // For visited BBs, we record the index of the first statement processed. + // (In fully processed BBs this index is 0.) Note also that we add BBs to + // `visited` once they are added to `stack`, before they are actually + // processed, because this avoids the need to look them up again on + // completion. + let mut visited = FxHashMap(); + visited.insert(location.block, location.statement_index); + + let mut stack = vec![]; + stack.push(StackEntry { + bb: location.block, + lo: location.statement_index, + hi: mir[location.block].statements.len(), + first_part_only: false, + }); + + while let Some(StackEntry { bb, lo, hi, first_part_only }) = stack.pop() { + let mut finished_early = first_part_only; + for i in lo ..= hi { + let location = Location { block: bb, statement_index: i }; + // If region does not contain a point at the location, then add to list and skip + // successor locations. + if !regioncx.region_contains(borrow_region, location) { + debug!("borrow {:?} gets killed at {:?}", borrow_index, location); + borrows_out_of_scope_at_location + .entry(location) + .or_default() + .push(borrow_index); + finished_early = true; + break; + } } - let bb_data = &mir[location.block]; - // If this is the last statement in the block, then add the - // terminator successors next. - if location.statement_index == bb_data.statements.len() { - // Add successors to locations to visit, if not visited before. - if let Some(ref terminator) = bb_data.terminator { - for block in terminator.successors() { - let loc = block.start_location(); - if visited.insert(loc) { - stack.push(loc); - } - } - } - } else { - // Visit next statement in block. - let loc = location.successor_within_block(); - if visited.insert(loc) { - stack.push(loc); + if !finished_early { + // Add successor BBs to the work list, if necessary. + let bb_data = &mir[bb]; + assert!(hi == bb_data.statements.len()); + for &succ_bb in bb_data.terminator.as_ref().unwrap().successors() { + visited.entry(succ_bb) + .and_modify(|lo| { + // `succ_bb` has been seen before. If it wasn't + // fully processed, add its first part to `stack` + // for processing. + if *lo > 0 { + stack.push(StackEntry { + bb: succ_bb, + lo: 0, + hi: *lo - 1, + first_part_only: true, + }); + } + // And update this entry with 0, to represent the + // whole BB being processed. + *lo = 0; + }) + .or_insert_with(|| { + // succ_bb hasn't been seen before. Add it to + // `stack` for processing. + stack.push(StackEntry { + bb: succ_bb, + lo: 0, + hi: mir[succ_bb].statements.len(), + first_part_only: false, + }); + // Insert 0 for this BB, to represent the whole BB + // being processed. + 0 + }); } } } @@ -115,11 +153,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { nonlexical_regioncx: Rc>, def_id: DefId, body_id: Option, - borrow_set: &Rc> + borrow_set: &Rc>, ) -> Self { let scope_tree = tcx.region_scope_tree(def_id); let root_scope = body_id.map(|body_id| { - region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id) + region::Scope { + id: tcx.hir.body(body_id).value.hir_id.local_id, + data: region::ScopeData::CallSite + } }); let mut borrows_out_of_scope_at_location = FxHashMap(); @@ -168,9 +209,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { // region, then setting that gen-bit will override any // potential kill introduced here. if let Some(indices) = self.borrows_out_of_scope_at_location.get(&location) { - for index in indices { - sets.kill(&index); - } + sets.kill_all(indices); } } @@ -233,7 +272,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { // propagate_call_return method. if let mir::Rvalue::Ref(region, _, ref place) = *rhs { - if place.is_unsafe_place(self.tcx, self.mir) { return; } + if place.ignore_borrow( + self.tcx, + self.mir, + &self.borrow_set.locals_state_at_exit, + ) { + return; + } let index = self.borrow_set.location_map.get(&location).unwrap_or_else(|| { panic!("could not find BorrowIndex for location {:?}", location); }); @@ -296,7 +341,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { mir::StatementKind::SetDiscriminant { .. } | mir::StatementKind::StorageLive(..) | mir::StatementKind::Validate(..) | - mir::StatementKind::UserAssertTy(..) | + mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => {} } diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index ee3bba840c..c8f7047985 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -14,7 +14,7 @@ use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::bitslice::{BitwiseOperator, Word}; +use rustc_data_structures::bitvec::{BitwiseOperator, Word}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; @@ -22,13 +22,13 @@ use super::MoveDataParamEnv; use util::elaborate_drops::DropFlagState; -use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex, InitIndex}; +use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex}; use super::move_paths::{LookupResult, InitKind}; use super::{BitDenotation, BlockSets, InitialFlow}; use super::drop_flag_effects_for_function_entry; use super::drop_flag_effects_for_location; -use super::{on_lookup_result_bits, for_location_inits}; +use super::on_lookup_result_bits; mod storage_liveness; @@ -211,40 +211,6 @@ impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, ' fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `MovingOutStatements` tracks the statements that perform moves out -/// of particular places. More precisely, it tracks whether the -/// *effect* of such moves (namely, the uninitialization of the -/// place in question) can reach some point in the control-flow of -/// the function, or if that effect is "killed" by some intervening -/// operation reinitializing that place. -/// -/// The resulting dataflow is a more enriched version of -/// `MaybeUninitializedPlaces`. Both structures on their own only tell -/// you if a place *might* be uninitialized at a given point in the -/// control flow. But `MovingOutStatements` also includes the added -/// data of *which* particular statement causing the deinitialization -/// that the borrow checker's error message may need to report. -#[allow(dead_code)] -pub struct MovingOutStatements<'a, 'gcx: 'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, - mir: &'a Mir<'tcx>, - mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, -} - -impl<'a, 'gcx: 'tcx, 'tcx: 'a> MovingOutStatements<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, - mir: &'a Mir<'tcx>, - mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) - -> Self - { - MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe } - } -} - -impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'gcx, 'tcx> { - fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } -} - /// `EverInitializedPlaces` tracks all places that might have ever been /// initialized upon reaching a particular point in the control flow /// for a function, without an intervening `Storage Dead`. @@ -488,83 +454,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc } } -impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { - type Idx = MoveOutIndex; - fn name() -> &'static str { "moving_out" } - fn bits_per_block(&self) -> usize { - self.move_data().moves.len() - } - - fn start_block_effect(&self, _sets: &mut IdxSet) { - // no move-statements have been executed prior to function - // execution, so this method has no effect on `_sets`. - } - - fn statement_effect(&self, - sets: &mut BlockSets, - location: Location) { - let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data()); - let stmt = &mir[location.block].statements[location.statement_index]; - let loc_map = &move_data.loc_map; - let path_map = &move_data.path_map; - - match stmt.kind { - // this analysis only tries to find moves explicitly - // written by the user, so we ignore the move-outs - // created by `StorageDead` and at the beginning - // of a function. - mir::StatementKind::StorageDead(_) => {} - _ => { - debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", - stmt, location, &loc_map[location]); - // Every path deinitialized by a *particular move* - // has corresponding bit, "gen'ed" (i.e. set) - // here, in dataflow vector - sets.gen_all_and_assert_dead(&loc_map[location]); - } - } - - for_location_inits(tcx, mir, move_data, location, - |mpi| sets.kill_all(&path_map[mpi])); - } - - fn terminator_effect(&self, - sets: &mut BlockSets, - location: Location) - { - let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data()); - let term = mir[location.block].terminator(); - let loc_map = &move_data.loc_map; - let path_map = &move_data.path_map; - - debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", - term, location, &loc_map[location]); - sets.gen_all_and_assert_dead(&loc_map[location]); - - for_location_inits(tcx, mir, move_data, location, - |mpi| sets.kill_all(&path_map[mpi])); - } - - fn propagate_call_return(&self, - in_out: &mut IdxSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - dest_place: &mir::Place) { - let move_data = self.move_data(); - let bits_per_block = self.bits_per_block(); - - let path_map = &move_data.path_map; - on_lookup_result_bits(self.tcx, - self.mir, - move_data, - move_data.rev_lookup.find(dest_place), - |mpi| for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - in_out.remove(&moi); - }); - } -} - impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = InitIndex; fn name() -> &'static str { "ever_init" } @@ -682,13 +571,6 @@ impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedPlaces<'a, 'gcx, ' } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'gcx, 'tcx> { - #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 | pred2 // moves from both preds are in scope - } -} - impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: Word, pred2: Word) -> Word { @@ -727,13 +609,6 @@ impl<'a, 'gcx, 'tcx> InitialFlow for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> } } -impl<'a, 'gcx, 'tcx> InitialFlow for MovingOutStatements<'a, 'gcx, 'tcx> { - #[inline] - fn bottom_value() -> bool { - false // bottom = no loans in scope by default - } -} - impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 4227f0bcd3..49d75d31fc 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -10,9 +10,9 @@ use syntax::ast::{self, MetaItem}; -use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; +use rustc_data_structures::bitvec::{bitwise, BitwiseOperator}; +use rustc_data_structures::indexed_set::{HybridIdxSet, IdxSet}; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::bitslice::{bitwise, BitwiseOperator, Word}; use rustc_data_structures::work_queue::WorkQueue; use rustc::ty::{self, TyCtxt}; @@ -23,13 +23,12 @@ use rustc::session::Session; use std::borrow::Borrow; use std::fmt; use std::io; -use std::mem; use std::path::PathBuf; use std::usize; pub use self::impls::{MaybeStorageLive}; pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; -pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements}; +pub use self::impls::DefinitelyInitializedPlaces; pub use self::impls::EverInitializedPlaces; pub use self::impls::borrows::Borrows; pub use self::impls::HaveBeenBorrowedLocals; @@ -39,7 +38,7 @@ pub(crate) use self::drop_flag_effects::*; use self::move_paths::MoveData; mod at_location; -mod drop_flag_effects; +pub mod drop_flag_effects; mod graphviz; mod impls; pub mod move_paths; @@ -183,12 +182,11 @@ struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> where O: 'b + BitDenotation impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation { fn propagate(&mut self) { - let mut temp = IdxSetBuf::new_empty(self.flow_state.sets.bits_per_block); + let mut temp = IdxSet::new_empty(self.flow_state.sets.bits_per_block); let mut propcx = PropagationContext { builder: self, }; propcx.walk_cfg(&mut temp); - } fn build_sets(&mut self) { @@ -252,8 +250,7 @@ impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: Bi } } -fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf { - format!("{}_{}", context, prepost); +fn dataflow_path(context: &str, path: &str) -> PathBuf { let mut path = PathBuf::from(path); let new_file_name = { let orig_file_name = path.file_name().unwrap().to_str().unwrap(); @@ -269,7 +266,7 @@ impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation where P: Fn(&BD, BD::Idx) -> DebugFormatted { if let Some(ref path_str) = self.print_preflow_to { - let path = dataflow_path(BD::name(), "preflow", path_str); + let path = dataflow_path(BD::name(), path_str); graphviz::print_borrowck_graph_to(self, &path, p) } else { Ok(()) @@ -280,30 +277,14 @@ impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation where P: Fn(&BD, BD::Idx) -> DebugFormatted { if let Some(ref path_str) = self.print_postflow_to { - let path = dataflow_path(BD::name(), "postflow", path_str); + let path = dataflow_path(BD::name(), path_str); graphviz::print_borrowck_graph_to(self, &path, p) - } else{ + } else { Ok(()) } } } -/// Maps each block to a set of bits -#[derive(Debug)] -pub(crate) struct Bits { - bits: IdxSetBuf, -} - -impl Clone for Bits { - fn clone(&self) -> Self { Bits { bits: self.bits.clone() } } -} - -impl Bits { - fn new(bits: IdxSetBuf) -> Self { - Bits { bits: bits } - } -} - /// DataflowResultsConsumer abstracts over walking the MIR with some /// already constructed dataflow results. /// @@ -371,14 +352,16 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location, analysis: &T, result: &DataflowResults, mir: &Mir<'tcx>) - -> IdxSetBuf { - let mut entry = result.sets().on_entry_set_for(loc.block.index()).to_owned(); + -> IdxSet { + let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned(); + let mut kill_set = on_entry.to_hybrid(); + let mut gen_set = kill_set.clone(); { let mut sets = BlockSets { - on_entry: &mut entry.clone(), - kill_set: &mut entry.clone(), - gen_set: &mut entry, + on_entry: &mut on_entry, + kill_set: &mut kill_set, + gen_set: &mut gen_set, }; for stmt in 0..loc.statement_index { @@ -396,7 +379,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location, } } - entry + gen_set.to_dense() } pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation @@ -443,12 +426,22 @@ pub struct DataflowState impl DataflowState { pub(crate) fn interpret_set<'c, P>(&self, o: &'c O, - words: &IdxSet, + set: &IdxSet, render_idx: &P) -> Vec where P: Fn(&O, O::Idx) -> DebugFormatted { - words.iter().map(|i| render_idx(o, i)).collect() + set.iter().map(|i| render_idx(o, i)).collect() + } + + pub(crate) fn interpret_hybrid_set<'c, P>(&self, + o: &'c O, + set: &HybridIdxSet, + render_idx: &P) + -> Vec + where P: Fn(&O, O::Idx) -> DebugFormatted + { + set.iter().map(|i| render_idx(o, i)).collect() } } @@ -457,22 +450,22 @@ pub struct AllSets { /// Analysis bitwidth for each block. bits_per_block: usize, - /// Number of words associated with each block entry - /// equal to bits_per_block / (mem::size_of:: * 8), rounded up. - words_per_block: usize, - - /// For each block, bits generated by executing the statements in - /// the block. (For comparison, the Terminator for each block is - /// handled in a flow-specific manner during propagation.) - gen_sets: Bits, + /// For each block, bits valid on entry to the block. + on_entry_sets: Vec>, - /// For each block, bits killed by executing the statements in the - /// block. (For comparison, the Terminator for each block is - /// handled in a flow-specific manner during propagation.) - kill_sets: Bits, + /// For each block, bits generated by executing the statements + + /// terminator in the block -- with one caveat. In particular, for + /// *call terminators*, the effect of storing the destination is + /// not included, since that only takes effect on the **success** + /// edge (and not the unwind edge). + gen_sets: Vec>, - /// For each block, bits valid on entry to the block. - on_entry_sets: Bits, + /// For each block, bits killed by executing the statements + + /// terminator in the block -- with one caveat. In particular, for + /// *call terminators*, the effect of storing the destination is + /// not included, since that only takes effect on the **success** + /// edge (and not the unwind edge). + kill_sets: Vec>, } /// Triple of sets associated with a given block. @@ -494,11 +487,13 @@ pub struct BlockSets<'a, E: Idx> { /// Dataflow state immediately before control flow enters the given block. pub(crate) on_entry: &'a mut IdxSet, - /// Bits that are set to 1 by the time we exit the given block. - pub(crate) gen_set: &'a mut IdxSet, + /// Bits that are set to 1 by the time we exit the given block. Hybrid + /// because it usually contains only 0 or 1 elements. + pub(crate) gen_set: &'a mut HybridIdxSet, - /// Bits that are set to 0 by the time we exit the given block. - pub(crate) kill_set: &'a mut IdxSet, + /// Bits that are set to 0 by the time we exit the given block. Hybrid + /// because it usually contains only 0 or 1 elements. + pub(crate) kill_set: &'a mut HybridIdxSet, } impl<'a, E:Idx> BlockSets<'a, E> { @@ -515,18 +510,6 @@ impl<'a, E:Idx> BlockSets<'a, E> { } } - fn gen_all_and_assert_dead(&mut self, i: I) - where I: IntoIterator, - I::Item: Borrow - { - for j in i { - let j = j.borrow(); - let retval = self.gen_set.add(j); - self.kill_set.remove(j); - assert!(retval); - } - } - fn kill(&mut self, e: &E) { self.gen_set.remove(e); self.kill_set.add(e); @@ -542,36 +525,29 @@ impl<'a, E:Idx> BlockSets<'a, E> { } fn apply_local_effect(&mut self) { - self.on_entry.union(&self.gen_set); - self.on_entry.subtract(&self.kill_set); + self.on_entry.union(self.gen_set); + self.on_entry.subtract(self.kill_set); } } impl AllSets { pub fn bits_per_block(&self) -> usize { self.bits_per_block } pub fn for_block(&mut self, block_idx: usize) -> BlockSets { - let offset = self.words_per_block * block_idx; - let range = E::new(offset)..E::new(offset + self.words_per_block); BlockSets { - on_entry: self.on_entry_sets.bits.range_mut(&range), - gen_set: self.gen_sets.bits.range_mut(&range), - kill_set: self.kill_sets.bits.range_mut(&range), + on_entry: &mut self.on_entry_sets[block_idx], + gen_set: &mut self.gen_sets[block_idx], + kill_set: &mut self.kill_sets[block_idx], } } - fn lookup_set_for<'a>(&self, sets: &'a Bits, block_idx: usize) -> &'a IdxSet { - let offset = self.words_per_block * block_idx; - let range = E::new(offset)..E::new(offset + self.words_per_block); - sets.bits.range(&range) + pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet { + &self.on_entry_sets[block_idx] } - pub fn gen_set_for(&self, block_idx: usize) -> &IdxSet { - self.lookup_set_for(&self.gen_sets, block_idx) + pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSet { + &self.gen_sets[block_idx] } - pub fn kill_set_for(&self, block_idx: usize) -> &IdxSet { - self.lookup_set_for(&self.kill_sets, block_idx) - } - pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet { - self.lookup_set_for(&self.on_entry_sets, block_idx) + pub fn kill_set_for(&self, block_idx: usize) -> &HybridIdxSet { + &self.kill_sets[block_idx] } } @@ -599,7 +575,7 @@ pub trait BitDenotation: BitwiseOperator { /// `sets.on_entry` to that local clone into `statement_effect` and /// `terminator_effect`). /// - /// When its false, no local clone is constucted; instead a + /// When it's false, no local clone is constructed; instead a /// reference directly into `on_entry` is passed along via /// `sets.on_entry` instead, which represents the flow state at /// the block's start, not necessarily the state immediately prior @@ -725,18 +701,15 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation dead_unwinds: &'a IdxSet, denotation: D) -> Self where D: InitialFlow { let bits_per_block = denotation.bits_per_block(); - let bits_per_word = mem::size_of::() * 8; - let words_per_block = (bits_per_block + bits_per_word - 1) / bits_per_word; - let bits_per_block_rounded_up = words_per_block * bits_per_word; // a multiple of word size let num_blocks = mir.basic_blocks().len(); - let num_overall = num_blocks * bits_per_block_rounded_up; - let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall)); - let on_entry = Bits::new(if D::bottom_value() { - IdxSetBuf::new_filled(num_overall) + let on_entry_sets = if D::bottom_value() { + vec![IdxSet::new_filled(bits_per_block); num_blocks] } else { - IdxSetBuf::new_empty(num_overall) - }); + vec![IdxSet::new_empty(bits_per_block); num_blocks] + }; + let gen_sets = vec![HybridIdxSet::new_empty(bits_per_block); num_blocks]; + let kill_sets = gen_sets.clone(); DataflowAnalysis { mir, @@ -744,10 +717,9 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation flow_state: DataflowState { sets: AllSets { bits_per_block, - words_per_block, - gen_sets: zeroes.clone(), - kill_sets: zeroes, - on_entry_sets: on_entry, + on_entry_sets, + gen_sets, + kill_sets, }, operator: denotation, } @@ -867,5 +839,4 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation dirty_queue.insert(bb); } } - } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 44e46e9054..5451d27082 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -20,14 +20,14 @@ use std::mem; use super::abs_domain::Lift; use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex}; -use super::{MoveError, InitIndex, Init, LookupResult, InitKind}; +use super::{MoveError, InitIndex, Init, InitLocation, LookupResult, InitKind}; use super::IllegalMoveOriginKind::*; struct MoveDataBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> { mir: &'a Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>, data: MoveData<'tcx>, - errors: Vec>, + errors: Vec<(Place<'tcx>, MoveError<'tcx>)>, } impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> { @@ -134,19 +134,19 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { let tcx = self.builder.tcx; let place_ty = proj.base.ty(mir, tcx).to_ty(tcx); match place_ty.sty { - ty::TyRef(..) | ty::TyRawPtr(..) => + ty::Ref(..) | ty::RawPtr(..) => return Err(MoveError::cannot_move_out_of( self.loc, BorrowedContent { target_place: place.clone() })), - ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => + ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => return Err(MoveError::cannot_move_out_of(self.loc, InteriorOfTypeWithDestructor { container_ty: place_ty })), // move out of union - always move the entire union - ty::TyAdt(adt, _) if adt.is_union() => + ty::Adt(adt, _) if adt.is_union() => return Err(MoveError::UnionMove { path: base }), - ty::TySlice(_) => + ty::Slice(_) => return Err(MoveError::cannot_move_out_of( self.loc, InteriorOfSliceOrArray { @@ -155,7 +155,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { _ => false }, })), - ty::TyArray(..) => match proj.elem { + ty::Array(..) => match proj.elem { ProjectionElem::Index(..) => return Err(MoveError::cannot_move_out_of( self.loc, @@ -186,7 +186,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> { - fn finalize(self) -> Result, (MoveData<'tcx>, Vec>)> { + fn finalize( + self + ) -> Result, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> { debug!("{}", { debug!("moves for {:?}:", self.mir.span); for (j, mo) in self.data.moves.iter_enumerated() { @@ -199,7 +201,7 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> { "done dumping moves" }); - if self.errors.len() > 0 { + if !self.errors.is_empty() { Err((self.data, self.errors)) } else { Ok(self.data) @@ -207,9 +209,10 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> { } } -pub(super) fn gather_moves<'a, 'gcx, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) - -> Result, - (MoveData<'tcx>, Vec>)> { +pub(super) fn gather_moves<'a, 'gcx, 'tcx>( + mir: &Mir<'tcx>, + tcx: TyCtxt<'a, 'gcx, 'tcx> +) -> Result, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> { let mut builder = MoveDataBuilder::new(mir, tcx); builder.gather_args(); @@ -234,10 +237,9 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> { fn gather_args(&mut self) { for arg in self.mir.args_iter() { let path = self.data.rev_lookup.locals[arg]; - let span = self.mir.local_decls[arg].source_info.span; let init = self.data.inits.push(Init { - path, span, kind: InitKind::Deep + path, kind: InitKind::Deep, location: InitLocation::Argument(arg), }); debug!("gather_args: adding init {:?} of {:?} for argument {:?}", @@ -302,7 +304,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { } StatementKind::EndRegion(_) | StatementKind::Validate(..) | - StatementKind::UserAssertTy(..) | + StatementKind::AscribeUserType(..) | StatementKind::Nop => {} } } @@ -407,7 +409,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { let path = match self.move_path_for(place) { Ok(path) | Err(MoveError::UnionMove { path }) => path, Err(error @ MoveError::IllegalMove { .. }) => { - self.builder.errors.push(error); + self.builder.errors.push((place.clone(), error)); return; } }; @@ -425,7 +427,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place) { let init = self.builder.data.inits.push(Init { - span: self.builder.mir.source_info(self.loc).span, + location: InitLocation::Statement(self.loc), path, kind, }); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 64bfd36b7e..7d7da6c96e 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -196,12 +196,21 @@ impl fmt::Debug for MoveOut { pub struct Init { /// path being initialized pub path: MovePathIndex, - /// span of initialization - pub span: Span, + /// location of initialization + pub location: InitLocation, /// Extra information about this initialization pub kind: InitKind, } + +/// Initializations can be from an argument or from a statement. Arguments +/// do not have locations, in those cases the `Local` is kept.. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum InitLocation { + Argument(Local), + Statement(Location), +} + /// Additional information about the initialization. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum InitKind { @@ -215,7 +224,16 @@ pub enum InitKind { impl fmt::Debug for Init { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}@{:?} ({:?})", self.path, self.span, self.kind) + write!(fmt, "{:?}@{:?} ({:?})", self.path, self.location, self.kind) + } +} + +impl Init { + crate fn span<'gcx>(&self, mir: &Mir<'gcx>) -> Span { + match self.location { + InitLocation::Argument(local) => mir.local_decls[local].source_info.span, + InitLocation::Statement(location) => mir.source_info(location).span, + } } } @@ -313,7 +331,17 @@ impl<'tcx> MoveError<'tcx> { impl<'a, 'gcx, 'tcx> MoveData<'tcx> { pub fn gather_moves(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) - -> Result>)> { + -> Result, MoveError<'tcx>)>)> { builder::gather_moves(mir, tcx) } + + /// For the move path `mpi`, returns the root local variable (if any) that starts the path. + /// (e.g., for a path like `a.b.c` returns `Some(a)`) + pub fn base_local(&self, mut mpi: MovePathIndex) -> Option { + loop { + let path = &self.move_paths[mpi]; + if let Place::Local(l) = path.place { return Some(l); } + if let Some(parent) = path.parent { mpi = parent; continue } else { return None } + } + } } diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 3c751d52b0..ae4713a65d 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -619,38 +619,6 @@ If you really want global mutable state, try using `static mut` or a global `UnsafeCell`. "##, -E0018: r##" - -The value of static and constant integers must be known at compile time. You -can't cast a pointer to an integer because the address of a pointer can -vary. - -For example, if you write: - -```compile_fail,E0018 -static MY_STATIC: u32 = 42; -static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize; -static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR; -``` - -Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However, -the address can change when the program is linked, as well as change -between different executions due to ASLR, and many linkers would -not be able to calculate the value of `WHAT`. - -On the other hand, static and constant pointers can point either to -a known numeric address or to the address of a symbol. - -``` -static MY_STATIC: u32 = 42; -static MY_STATIC_ADDR: &'static u32 = &MY_STATIC; -const CONST_ADDR: *const u8 = 0x5f3759df as *const u8; -``` - -This does not pose a problem by itself because they can't be -accessed directly. -"##, - E0019: r##" 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 @@ -1145,36 +1113,6 @@ fn main() { ``` "##, -E0395: r##" -The value assigned to a constant scalar must be known at compile time, -which is not the case when comparing raw pointers. - -Erroneous code example: - -```compile_fail,E0395 -static FOO: i32 = 42; -static BAR: i32 = 42; - -static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; -// error: raw pointers cannot be compared in statics! -``` - -The address assigned by the linker to `FOO` and `BAR` may or may not -be identical, so the value of `BAZ` can't be determined. - -If you want to do the comparison, please do it at run-time. - -For example: - -``` -static FOO: i32 = 42; -static BAR: i32 = 42; - -let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; -// baz isn't a constant expression so it's ok -``` -"##, - E0161: r##" A value was moved. However, its size was not known at compile time, and only values of a known size can be moved. @@ -1208,29 +1146,6 @@ fn main() { ``` "##, -E0396: r##" -The value behind a raw pointer can't be determined at compile-time -(or even link-time), which means it can't be used in a constant -expression. Erroneous code example: - -```compile_fail,E0396 -const REG_ADDR: *const u8 = 0x5f3759df as *const u8; - -const VALUE: u8 = unsafe { *REG_ADDR }; -// error: raw pointers cannot be dereferenced in constants -``` - -A possible fix is to dereference your pointer at some point in run-time. - -For example: - -``` -const REG_ADDR: *const u8 = 0x5f3759df as *const u8; - -let reg_value = unsafe { *REG_ADDR }; -``` -"##, - E0492: r##" A borrow of a constant containing interior mutability was attempted. Erroneous code example: @@ -1281,9 +1196,7 @@ const F: &'static 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. In this -case, `StaticMutex` would work just fine, but it isn't stable yet: -https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html +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: @@ -2251,6 +2164,29 @@ unsafe { b.resume() }; ``` "##, +E0712: r##" +This error occurs because a borrow of a thread-local variable was made inside a +function which outlived the lifetime of the function. + +Example of erroneous code: + +```compile_fail,E0712 +#![feature(nll)] +#![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); + }); +} +``` +"##, + } register_diagnostics! { diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 6c8b5d97b6..2ab0a57a85 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -11,7 +11,7 @@ use hair::*; use hair::cx::Cx; use hair::cx::to_ref::ToRef; -use rustc::middle::region::{self, BlockRemainder}; +use rustc::middle::region; use rustc::hir; use rustc_data_structures::indexed_vec::Idx; @@ -27,7 +27,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id); Block { targeted_by_break: self.targeted_by_break, - region_scope: region::Scope::Node(self.hir_id.local_id), + region_scope: region::Scope { + id: self.hir_id.local_id, + data: region::ScopeData::Node + }, opt_destruction_scope, span: self.span, stmts, @@ -59,7 +62,10 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::StmtKind::Semi(ref expr, _) => { result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Expr { - scope: region::Scope::Node(hir_id.local_id), + scope: region::Scope { + id: hir_id.local_id, + data: region::ScopeData::Node + }, expr: expr.to_ref(), }, opt_destruction_scope: opt_dxn_ext, @@ -71,19 +77,35 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // ignore for purposes of the MIR } hir::DeclKind::Local(ref local) => { - let remainder_scope = region::Scope::Remainder(BlockRemainder { - block: block_id, - first_statement_index: region::FirstStatementIndex::new(index), - }); + let remainder_scope = region::Scope { + id: block_id, + data: region::ScopeData::Remainder( + region::FirstStatementIndex::new(index)), + }; + + let mut pattern = cx.pattern_from_hir(&local.pat); + + if let Some(ty) = &local.ty { + if let Some(user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) { + pattern = Pattern { + ty: pattern.ty, + span: pattern.span, + kind: Box::new(PatternKind::AscribeUserType { + user_ty: *user_ty, + subpattern: pattern + }) + }; + } + } - let ty = local.ty.clone().map(|ty| ty.hir_id); - let pattern = cx.pattern_from_hir(&local.pat); result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Let { remainder_scope: remainder_scope, - init_scope: region::Scope::Node(hir_id.local_id), + init_scope: region::Scope { + id: hir_id.local_id, + data: region::ScopeData::Node + }, pattern, - ty, initializer: local.init.to_ref(), lint_level: cx.lint_level_of(local.id), }, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index b60da286d9..3183f0f47e 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -27,7 +27,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> { let temp_lifetime = cx.region_scope_tree.temporary_scope(self.hir_id.local_id); - let expr_scope = region::Scope::Node(self.hir_id.local_id); + let expr_scope = region::Scope { + id: self.hir_id.local_id, + data: region::ScopeData::Node + }; debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); @@ -78,7 +81,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, mut expr: Expr<'tcx>, adjustment: &Adjustment<'tcx>) -> Expr<'tcx> { - let Expr { temp_lifetime, span, .. } = expr; + let Expr { temp_lifetime, mut span, .. } = expr; let kind = match adjustment.kind { Adjust::ReifyFnPointer => { ExprKind::ReifyFnPointer { source: expr.to_ref() } @@ -96,6 +99,25 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ExprKind::Cast { source: expr.to_ref() } } Adjust::Deref(None) => { + // Adjust the span from the block, to the last expression of the + // block. This is a better span when returning a mutable reference + // with too short a lifetime. The error message will use the span + // from the assignment to the return place, which should only point + // at the returned value, not the entire function body. + // + // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 { + // x + // // ^ error message points at this expression. + // } + // + // We don't need to do this adjustment in the next match arm since + // deref coercions always start with a built-in deref. + if let ExprKind::Block { body } = expr.kind { + if let Some(ref last_expr) = body.expr { + span = last_expr.span; + expr.span = span; + } + } ExprKind::Deref { arg: expr.to_ref() } } Adjust::Deref(Some(deref)) => { @@ -129,7 +151,10 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Convert this to a suitable `&foo` and // then an unsafe coercion. Limit the region to be just this // expression. - let region = ty::ReScope(region::Scope::Node(hir_expr.hir_id.local_id)); + let region = ty::ReScope(region::Scope { + id: hir_expr.hir_id.local_id, + data: region::ScopeData::Node + }); let region = cx.tcx.mk_region(region); expr = Expr { temp_lifetime, @@ -180,6 +205,13 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ExprKind::Use { source: cast_expr.to_ref() } } Adjust::Unsize => { + // See the above comment for Adjust::Deref + if let ExprKind::Block { body } = expr.kind { + if let Some(ref last_expr) = body.expr { + span = last_expr.span; + expr.span = span; + } + } ExprKind::Unsize { source: expr.to_ref() } } }; @@ -247,7 +279,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::VariantCtor(variant_id, CtorKind::Fn) => { Some((adt_def, adt_def.variant_index_with_id(variant_id))) } - Def::StructCtor(_, CtorKind::Fn) => Some((adt_def, 0)), + Def::StructCtor(_, CtorKind::Fn) | + Def::SelfCtor(..) => Some((adt_def, 0)), _ => None, } }) @@ -256,6 +289,16 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; if let Some((adt_def, index)) = adt_data { let substs = cx.tables().node_substs(fun.hir_id); + + let user_ty = cx.tables().user_substs(fun.hir_id) + .map(|user_substs| { + user_substs.unchecked_map(|user_substs| { + // Here, we just pair an `AdtDef` with the + // `user_substs`, so no new types etc are introduced. + cx.tcx().mk_adt(adt_def, user_substs) + }) + }); + let field_refs = args.iter() .enumerate() .map(|(idx, e)| { @@ -270,6 +313,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, substs, variant_index: index, fields: field_refs, + user_ty, base: None, } } else { @@ -284,7 +328,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::AddrOf(mutbl, ref expr) => { let region = match expr_ty.sty { - ty::TyRef(r, _, _) => r, + ty::Ref(r, _, _) => r, _ => span_bug!(expr.span, "type of & not region"), }; ExprKind::Borrow { @@ -317,6 +361,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Lit(ref lit) => ExprKind::Literal { literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false), + user_ty: None, }, hir::ExprKind::Binary(op, ref lhs, ref rhs) => { @@ -406,6 +451,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, if let hir::ExprKind::Lit(ref lit) = arg.node { ExprKind::Literal { literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true), + user_ty: None, } } else { ExprKind::Unary { @@ -418,13 +464,14 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Struct(ref qpath, ref fields, ref base) => { match expr_ty.sty { - ty::TyAdt(adt, substs) => { + ty::Adt(adt, substs) => { match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { ExprKind::Adt { adt_def: adt, variant_index: 0, substs, + user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt), fields: field_refs(cx, fields), base: base.as_ref().map(|base| { FruInfo { @@ -450,6 +497,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, adt_def: adt, variant_index: index, substs, + user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt), fields: field_refs(cx, fields), base: None, } @@ -472,8 +520,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Closure(..) => { let closure_ty = cx.tables().expr_ty(expr); let (def_id, substs, movability) = match closure_ty.sty { - ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None), - ty::TyGenerator(def_id, substs, movability) => { + ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None), + ty::Generator(def_id, substs, movability) => { (def_id, UpvarSubsts::Generator(substs), Some(movability)) } _ => { @@ -539,7 +587,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Break(dest, ref value) => { match dest.target_id { Ok(target_id) => ExprKind::Break { - label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(target_id).local_id), + label: region::Scope { + id: cx.tcx.hir.node_to_hir_id(target_id).local_id, + data: region::ScopeData::Node + }, value: value.to_ref(), }, Err(err) => bug!("invalid loop id for break: {}", err) @@ -548,7 +599,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Continue(dest) => { match dest.target_id { Ok(loop_id) => ExprKind::Continue { - label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(loop_id).local_id), + label: region::Scope { + id: cx.tcx.hir.node_to_hir_id(loop_id).local_id, + data: region::ScopeData::Node + }, }, Err(err) => bug!("invalid loop id for continue: {}", err) } @@ -631,7 +685,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, temp_lifetime, ty, span: expr.span, - kind: ExprKind::Literal { literal }, + kind: ExprKind::Literal { literal, user_ty: None }, }.to_ref(); let offset = mk_const(ty::Const::from_bits( cx.tcx, @@ -684,18 +738,96 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } -fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, - expr: &hir::Expr, - custom_callee: Option<(DefId, &'tcx Substs<'tcx>)>) - -> Expr<'tcx> { +fn user_annotated_ty_for_def( + cx: &mut Cx<'a, 'gcx, 'tcx>, + hir_id: hir::HirId, + def: &Def, +) -> Option> { + match def { + // A reference to something callable -- e.g., a fn, method, or + // a tuple-struct or tuple-variant. This has the type of a + // `Fn` but with the user-given substitutions. + Def::Fn(_) | + Def::Method(_) | + Def::StructCtor(_, CtorKind::Fn) | + Def::VariantCtor(_, CtorKind::Fn) => + Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| { + // Here, we just pair a `DefId` with the + // `user_substs`, so no new types etc are introduced. + cx.tcx().mk_fn_def(def.def_id(), user_substs) + })), + + Def::Const(_def_id) | + Def::AssociatedConst(_def_id) => + bug!("unimplemented"), + + // A unit struct/variant which is used as a value (e.g., + // `None`). This has the type of the enum/struct that defines + // this variant -- but with the substitutions given by the + // user. + Def::StructCtor(_def_id, CtorKind::Const) | + Def::VariantCtor(_def_id, CtorKind::Const) => + match &cx.tables().node_id_to_type(hir_id).sty { + ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def), + sty => bug!("unexpected sty: {:?}", sty), + }, + + // `Self` is used in expression as a tuple struct constructor or an unit struct constructor + Def::SelfCtor(_) => { + let sty = &cx.tables().node_id_to_type(hir_id).sty; + match sty { + ty::FnDef(ref def_id, _) => { + Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| { + // Here, we just pair a `DefId` with the + // `user_substs`, so no new types etc are introduced. + cx.tcx().mk_fn_def(*def_id, user_substs) + })) + } + ty::Adt(ref adt_def, _) => { + user_annotated_ty_for_adt(cx, hir_id, adt_def) + } + _ => { + bug!("unexpected sty: {:?}", sty) + } + } + } + _ => + bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id) + } +} + +fn user_annotated_ty_for_adt( + cx: &mut Cx<'a, 'gcx, 'tcx>, + hir_id: hir::HirId, + adt_def: &'tcx AdtDef, +) -> Option> { + let user_substs = cx.tables().user_substs(hir_id)?; + Some(user_substs.unchecked_map(|user_substs| { + // Here, we just pair an `AdtDef` with the + // `user_substs`, so no new types etc are introduced. + cx.tcx().mk_adt(adt_def, user_substs) + })) +} + +fn method_callee<'a, 'gcx, 'tcx>( + cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &hir::Expr, + overloaded_callee: Option<(DefId, &'tcx Substs<'tcx>)>, +) -> Expr<'tcx> { let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let (def_id, substs) = custom_callee.unwrap_or_else(|| { - if let Some(def) = cx.tables().type_dependent_defs().get(expr.hir_id) { - (def.def_id(), cx.tables().node_substs(expr.hir_id)) - } else { - span_bug!(expr.span, "no type-dependent def for method callee") + let (def_id, substs, user_ty) = match overloaded_callee { + Some((def_id, substs)) => (def_id, substs, None), + None => { + let type_dependent_defs = cx.tables().type_dependent_defs(); + let def = type_dependent_defs + .get(expr.hir_id) + .unwrap_or_else(|| { + span_bug!(expr.span, "no type-dependent def for method callee") + }); + let user_ty = user_annotated_ty_for_def(cx, expr.hir_id, def); + (def.def_id(), cx.tables().node_substs(expr.hir_id), user_ty) } - }); + }; let ty = cx.tcx().mk_fn_def(def_id, substs); Expr { temp_lifetime, @@ -703,6 +835,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, span: expr.span, kind: ExprKind::Literal { literal: ty::Const::zero_sized(cx.tcx(), ty), + user_ty, }, } } @@ -736,7 +869,10 @@ impl ToBorrowKind for hir::Mutability { fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { Arm { patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(), - guard: arm.guard.to_ref(), + guard: match arm.guard { + Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())), + _ => None, + }, body: arm.body.to_ref(), // BUG: fix this lint_level: LintLevel::Inherited, @@ -753,11 +889,16 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Fn(_) | Def::Method(_) | Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Fn) => ExprKind::Literal { - literal: ty::Const::zero_sized( - cx.tcx, - cx.tables().node_id_to_type(expr.hir_id), - ), + Def::VariantCtor(_, CtorKind::Fn) | + Def::SelfCtor(..) => { + let user_ty = user_annotated_ty_for_def(cx, expr.hir_id, &def); + ExprKind::Literal { + literal: ty::Const::zero_sized( + cx.tcx, + cx.tables().node_id_to_type(expr.hir_id), + ), + user_ty, + } }, Def::Const(def_id) | @@ -768,6 +909,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, substs, cx.tables().node_id_to_type(expr.hir_id), ), + user_ty: None, // FIXME(#47184) -- user given type annot on constants }, Def::StructCtor(def_id, CtorKind::Const) | @@ -775,11 +917,12 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, match cx.tables().node_id_to_type(expr.hir_id).sty { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. - ty::TyAdt(adt_def, substs) => { + ty::Adt(adt_def, substs) => { ExprKind::Adt { adt_def, variant_index: adt_def.variant_index_with_id(def_id), substs, + user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt_def), fields: vec![], base: None, } @@ -827,7 +970,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }); let region = cx.tcx.mk_region(region); - let self_expr = if let ty::TyClosure(_, closure_substs) = closure_ty.sty { + let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.sty { match cx.infcx.closure_kind(closure_def_id, closure_substs).unwrap() { ty::ClosureKind::Fn => { let ref_closure_ty = cx.tcx.mk_ref(region, @@ -958,12 +1101,13 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } -fn overloaded_place<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, - expr: &'tcx hir::Expr, - place_ty: Ty<'tcx>, - custom_callee: Option<(DefId, &'tcx Substs<'tcx>)>, - args: Vec>) - -> ExprKind<'tcx> { +fn overloaded_place<'a, 'gcx, 'tcx>( + cx: &mut Cx<'a, 'gcx, 'tcx>, + expr: &'tcx hir::Expr, + place_ty: Ty<'tcx>, + overloaded_callee: Option<(DefId, &'tcx Substs<'tcx>)>, + args: Vec>, +) -> ExprKind<'tcx> { // For an overloaded *x or x[y] expression of type T, the method // call returns an &T and we must add the deref so that the types // line up (this is because `*x` and `x[y]` represent places): @@ -977,7 +1121,7 @@ fn overloaded_place<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // same region and mutability as the receiver. This holds for // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. let (region, mutbl) = match recv_ty.sty { - ty::TyRef(region, _, mutbl) => (region, mutbl), + ty::Ref(region, _, mutbl) => (region, mutbl), _ => span_bug!(expr.span, "overloaded_place: receiver is not a reference"), }; let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { @@ -988,7 +1132,7 @@ fn overloaded_place<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // construct the complete expression `foo()` for the overloaded call, // which will yield the &T type let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let fun = method_callee(cx, expr, custom_callee); + let fun = method_callee(cx, expr, overloaded_callee); let ref_expr = Expr { temp_lifetime, ty: ref_ty, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 4a7225c3a7..4d4a89fca8 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -18,7 +18,7 @@ use hair::*; use rustc_data_structures::indexed_vec::Idx; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::hir::map::blocks::FnLikeNode; +use rustc::hir::Node; use rustc::middle::region; use rustc::infer::InferCtxt; use rustc::ty::subst::Subst; @@ -66,10 +66,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { let constness = match body_owner_kind { hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => hir::Constness::Const, - hir::BodyOwnerKind::Fn => { - let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(src_id)); - fn_like.map_or(hir::Constness::NotConst, |f| f.constness()) - } + hir::BodyOwnerKind::Fn => hir::Constness::NotConst, }; let attrs = tcx.hir.attrs(src_id); @@ -82,7 +79,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { // Respect -C overflow-checks. check_overflow |= tcx.sess.overflow_checks(); - // Constants and const fn's always need overflow checks. + // Constants always need overflow checks. check_overflow |= constness == hir::Constness::Const; let lint_level = lint_level_for_hir_id(tcx, src_id); @@ -121,7 +118,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn unit_ty(&mut self) -> Ty<'tcx> { - self.tcx.mk_nil() + self.tcx.mk_unit() } pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> { @@ -151,14 +148,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { let trunc = |n| { let param_ty = self.param_env.and(self.tcx.lift_to_global(&ty).unwrap()); - let bit_width = self.tcx.layout_of(param_ty).unwrap().size.bits(); - trace!("trunc {} with size {} and shift {}", n, bit_width, 128 - bit_width); - let shift = 128 - bit_width; + let width = self.tcx.layout_of(param_ty).unwrap().size; + trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); + let shift = 128 - width.bits(); let result = (n << shift) >> shift; trace!("trunc result: {}", result); ConstValue::Scalar(Scalar::Bits { bits: result, - defined: bit_width as u8, + size: width.bytes() as u8, }) }; @@ -167,8 +164,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { LitKind::Str(ref s, _) => { let s = s.as_str(); let id = self.tcx.allocate_bytes(s.as_bytes()); - let value = Scalar::Ptr(id.into()).to_value_with_len(s.len() as u64, self.tcx); - ConstValue::from_byval_value(value) + ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, self.tcx) }, LitKind::ByteStr(ref data) => { let id = self.tcx.allocate_bytes(data); @@ -176,7 +172,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { }, LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits { bits: n as u128, - defined: 8, + size: 1, }), LitKind::Int(n, _) if neg => { let n = n as i128; @@ -189,19 +185,13 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { - ty::TyFloat(fty) => fty, + ty::Float(fty) => fty, _ => bug!() }; parse_float(n, fty) } - LitKind::Bool(b) => ConstValue::Scalar(Scalar::Bits { - bits: b as u128, - defined: 8, - }), - LitKind::Char(c) => ConstValue::Scalar(Scalar::Bits { - bits: c as u128, - defined: 32, - }), + LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), + LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), }; ty::Const::from_const_value(self.tcx, lit, ty) } @@ -209,7 +199,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { pub fn pattern_from_hir(&mut self, p: &hir::Pat) -> Pattern<'tcx> { let tcx = self.tcx.global_tcx(); let p = match tcx.hir.get(p.id) { - hir::map::NodePat(p) | hir::map::NodeBinding(p) => p, + Node::Pat(p) | Node::Binding(p) => p, node => bug!("pattern became {:?}", node) }; Pattern::from_hir(tcx, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index c39aa9ca78..d86aee5431 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -18,7 +18,7 @@ use rustc::mir::{BinOp, BorrowKind, Field, UnOp}; use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::ty::subst::Substs; -use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const}; +use rustc::ty::{AdtDef, CanonicalTy, UpvarSubsts, Region, Ty, Const}; use rustc::hir; use syntax::ast; use syntax_pos::Span; @@ -93,12 +93,11 @@ pub enum StmtKind<'tcx> { /// lifetime of temporaries init_scope: region::Scope, - /// let : ty = ... + /// `let = ...` + /// + /// if a type is included, it is added as an ascription pattern pattern: Pattern<'tcx>, - /// let pat: = init ... - ty: Option, - /// let pat: ty = ... initializer: Option>, @@ -261,6 +260,11 @@ pub enum ExprKind<'tcx> { adt_def: &'tcx AdtDef, variant_index: usize, substs: &'tcx Substs<'tcx>, + + /// Optional user-given substs: for something like `let x = + /// Bar:: { ... }`. + user_ty: Option>, + fields: Vec>, base: Option> }, @@ -272,6 +276,13 @@ pub enum ExprKind<'tcx> { }, Literal { literal: &'tcx Const<'tcx>, + + /// Optional user-given type: for something like + /// `collect::>`, this would be present and would + /// indicate that `Vec<_>` was explicitly specified. + /// + /// Needed for NLL to impose user-given type constraints. + user_ty: Option>, }, InlineAsm { asm: &'tcx hir::InlineAsm, @@ -304,11 +315,16 @@ pub struct FruInfo<'tcx> { #[derive(Clone, Debug)] pub struct Arm<'tcx> { pub patterns: Vec>, - pub guard: Option>, + pub guard: Option>, pub body: ExprRef<'tcx>, pub lint_level: LintLevel, } +#[derive(Clone, Debug)] +pub enum Guard<'tcx> { + If(ExprRef<'tcx>), +} + #[derive(Copy, Clone, Debug)] pub enum LogicalOp { And, diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 5d45955771..aa1c6902dc 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -8,6 +8,164 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/// This file includes the logic for exhaustiveness and usefulness checking for +/// pattern-matching. Specifically, given a list of patterns for a type, we can +/// tell whether: +/// (a) the patterns cover every possible constructor for the type [exhaustiveness] +/// (b) each pattern is necessary [usefulness] +/// +/// The algorithm implemented here is a modified version of the one described in: +/// http://moscova.inria.fr/~maranget/papers/warn/index.html +/// However, to save future implementors from reading the original paper, I'm going +/// to summarise the algorithm here to hopefully save time and be a little clearer +/// (without being so rigorous). +/// +/// The core of the algorithm revolves about a "usefulness" check. In particular, we +/// are trying to compute a predicate `U(P, p_{m + 1})` where `P` is a list of patterns +/// of length `m` for a compound (product) type with `n` components (we refer to this as +/// a matrix). `U(P, p_{m + 1})` represents whether, given an existing list of patterns +/// `p_1 ..= p_m`, adding a new pattern will be "useful" (that is, cover previously- +/// uncovered values of the type). +/// +/// If we have this predicate, then we can easily compute both exhaustiveness of an +/// entire set of patterns and the individual usefulness of each one. +/// (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e. adding a wildcard +/// match doesn't increase the number of values we're matching) +/// (b) a pattern `p_i` is not useful if `U(P[0..=(i-1), p_i)` is false (i.e. adding a +/// pattern to those that have come before it doesn't increase the number of values +/// we're matching). +/// +/// For example, say we have the following: +/// ``` +/// // x: (Option, Result<()>) +/// match x { +/// (Some(true), _) => {} +/// (None, Err(())) => {} +/// (None, Err(_)) => {} +/// } +/// ``` +/// Here, the matrix `P` is 3 x 2 (rows x columns). +/// [ +/// [Some(true), _], +/// [None, Err(())], +/// [None, Err(_)], +/// ] +/// We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering +/// `[Some(false), _]`, for instance). In addition, row 3 is not useful, because +/// all the values it covers are already covered by row 2. +/// +/// To compute `U`, we must have two other concepts. +/// 1. `S(c, P)` is a "specialised matrix", where `c` is a constructor (like `Some` or +/// `None`). You can think of it as filtering `P` to just the rows whose *first* pattern +/// can cover `c` (and expanding OR-patterns into distinct patterns), and then expanding +/// the constructor into all of its components. +/// The specialisation of a row vector is computed by `specialize`. +/// +/// It is computed as follows. For each row `p_i` of P, we have four cases: +/// 1.1. `p_(i,1) = c(r_1, .., r_a)`. Then `S(c, P)` has a corresponding row: +/// r_1, .., r_a, p_(i,2), .., p_(i,n) +/// 1.2. `p_(i,1) = c'(r_1, .., r_a')` where `c ≠ c'`. Then `S(c, P)` has no +/// corresponding row. +/// 1.3. `p_(i,1) = _`. Then `S(c, P)` has a corresponding row: +/// _, .., _, p_(i,2), .., p_(i,n) +/// 1.4. `p_(i,1) = r_1 | r_2`. Then `S(c, P)` has corresponding rows inlined from: +/// S(c, (r_1, p_(i,2), .., p_(i,n))) +/// S(c, (r_2, p_(i,2), .., p_(i,n))) +/// +/// 2. `D(P)` is a "default matrix". This is used when we know there are missing +/// constructor cases, but there might be existing wildcard patterns, so to check the +/// usefulness of the matrix, we have to check all its *other* components. +/// The default matrix is computed inline in `is_useful`. +/// +/// It is computed as follows. For each row `p_i` of P, we have three cases: +/// 1.1. `p_(i,1) = c(r_1, .., r_a)`. Then `D(P)` has no corresponding row. +/// 1.2. `p_(i,1) = _`. Then `D(P)` has a corresponding row: +/// p_(i,2), .., p_(i,n) +/// 1.3. `p_(i,1) = r_1 | r_2`. Then `D(P)` has corresponding rows inlined from: +/// D((r_1, p_(i,2), .., p_(i,n))) +/// D((r_2, p_(i,2), .., p_(i,n))) +/// +/// Note that the OR-patterns are not always used directly in Rust, but are used to derive +/// the exhaustive integer matching rules, so they're written here for posterity. +/// +/// The algorithm for computing `U` +/// ------------------------------- +/// The algorithm is inductive (on the number of columns: i.e. components of tuple patterns). +/// That means we're going to check the components from left-to-right, so the algorithm +/// operates principally on the first component of the matrix and new pattern `p_{m + 1}`. +/// This algorithm is realised in the `is_useful` function. +/// +/// Base case. (`n = 0`, i.e. an empty tuple pattern) +/// - If `P` already contains an empty pattern (i.e. if the number of patterns `m > 0`), +/// then `U(P, p_{m + 1})` is false. +/// - Otherwise, `P` must be empty, so `U(P, p_{m + 1})` is true. +/// +/// Inductive step. (`n > 0`, i.e. whether there's at least one column +/// [which may then be expanded into further columns later]) +/// We're going to match on the new pattern, `p_{m + 1}`. +/// - If `p_{m + 1} == c(r_1, .., r_a)`, then we have a constructor pattern. +/// Thus, the usefulness of `p_{m + 1}` can be reduced to whether it is useful when +/// we ignore all the patterns in `P` that involve other constructors. This is where +/// `S(c, P)` comes in: +/// `U(P, p_{m + 1}) := U(S(c, P), S(c, p_{m + 1}))` +/// This special case is handled in `is_useful_specialized`. +/// - If `p_{m + 1} == _`, then we have two more cases: +/// + All the constructors of the first component of the type exist within +/// all the rows (after having expanded OR-patterns). In this case: +/// `U(P, p_{m + 1}) := ∨(k ϵ constructors) U(S(k, P), S(k, p_{m + 1}))` +/// I.e. the pattern `p_{m + 1}` is only useful when all the constructors are +/// present *if* its later components are useful for the respective constructors +/// covered by `p_{m + 1}` (usually a single constructor, but all in the case of `_`). +/// + Some constructors are not present in the existing rows (after having expanded +/// OR-patterns). However, there might be wildcard patterns (`_`) present. Thus, we +/// are only really concerned with the other patterns leading with wildcards. This is +/// where `D` comes in: +/// `U(P, p_{m + 1}) := U(D(P), p_({m + 1},2), .., p_({m + 1},n))` +/// - If `p_{m + 1} == r_1 | r_2`, then the usefulness depends on each separately: +/// `U(P, p_{m + 1}) := U(P, (r_1, p_({m + 1},2), .., p_({m + 1},n))) +/// || U(P, (r_2, p_({m + 1},2), .., p_({m + 1},n)))` +/// +/// Modifications to the algorithm +/// ------------------------------ +/// The algorithm in the paper doesn't cover some of the special cases that arise in Rust, for +/// example uninhabited types and variable-length slice patterns. These are drawn attention to +/// throughout the code below. I'll make a quick note here about how exhaustive integer matching +/// is accounted for, though. +/// +/// Exhaustive integer matching +/// --------------------------- +/// An integer type can be thought of as a (huge) sum type: 1 | 2 | 3 | ... +/// So to support exhaustive integer matching, we can make use of the logic in the paper for +/// OR-patterns. However, we obviously can't just treat ranges x..=y as individual sums, because +/// they are likely gigantic. So we instead treat ranges as constructors of the integers. This means +/// that we have a constructor *of* constructors (the integers themselves). We then need to work +/// through all the inductive step rules above, deriving how the ranges would be treated as +/// OR-patterns, and making sure that they're treated in the same way even when they're ranges. +/// There are really only four special cases here: +/// - When we match on a constructor that's actually a range, we have to treat it as if we would +/// an OR-pattern. +/// + It turns out that we can simply extend the case for single-value patterns in +/// `specialize` to either be *equal* to a value constructor, or *contained within* a range +/// constructor. +/// + When the pattern itself is a range, you just want to tell whether any of the values in +/// the pattern range coincide with values in the constructor range, which is precisely +/// intersection. +/// Since when encountering a range pattern for a value constructor, we also use inclusion, it +/// means that whenever the constructor is a value/range and the pattern is also a value/range, +/// we can simply use intersection to test usefulness. +/// - When we're testing for usefulness of a pattern and the pattern's first component is a +/// wildcard. +/// + If all the constructors appear in the matrix, we have a slight complication. By default, +/// the behaviour (i.e. a disjunction over specialised matrices for each constructor) is +/// invalid, because we want a disjunction over every *integer* in each range, not just a +/// disjunction over every range. This is a bit more tricky to deal with: essentially we need +/// to form equivalence classes of subranges of the constructor range for which the behaviour +/// of the matrix `P` and new pattern `p_{m + 1}` are the same. This is described in more +/// detail in `split_grouped_constructors`. +/// + If some constructors are missing from the matrix, it turns out we don't need to do +/// anything special (because we know none of the integers are actually wildcards: i.e. we +/// can't span wildcards using ranges). + use self::Constructor::*; use self::Usefulness::*; use self::WitnessPreference::*; @@ -21,18 +179,22 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals}; use rustc::hir::def_id::DefId; use rustc::hir::RangeEnd; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::layout::{Integer, IntegerExt}; use rustc::mir::Field; use rustc::mir::interpret::ConstValue; use rustc::util::common::ErrorReported; +use syntax::attr::{SignedInt, UnsignedInt}; use syntax_pos::{Span, DUMMY_SP}; use arena::TypedArena; -use std::cmp::{self, Ordering}; +use std::cmp::{self, Ordering, min, max}; use std::fmt; use std::iter::{FromIterator, IntoIterator}; +use std::ops::RangeInclusive; +use std::u128; pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>) -> &'a Pattern<'tcx> @@ -44,7 +206,7 @@ struct LiteralExpander; impl<'tcx> PatternFolder<'tcx> for LiteralExpander { fn fold_pattern(&mut self, pat: &Pattern<'tcx>) -> Pattern<'tcx> { match (&pat.ty.sty, &*pat.kind) { - (&ty::TyRef(_, rty, _), &PatternKind::Constant { ref value }) => { + (&ty::Ref(_, rty, _), &PatternKind::Constant { ref value }) => { Pattern { ty: pat.ty, span: pat.span, @@ -138,7 +300,6 @@ impl<'a, 'tcx> FromIterator>> for Matrix<'a, 'tcx> { } } -//NOTE: appears to be the only place other then InferCtxt to contain a ParamEnv pub struct MatchCheckCtxt<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, /// The module in which the match occurs. This is necessary for @@ -165,7 +326,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { tcx, module, pattern_arena: &pattern_arena, - byte_array_map: FxHashMap(), + byte_array_map: FxHashMap::default(), }) } @@ -220,14 +381,14 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { match ty.sty { - ty::TyAdt(adt_def, ..) => adt_def.is_enum() && adt_def.is_non_exhaustive(), + ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(), _ => false, } } fn is_local(&self, ty: Ty<'tcx>) -> bool { match ty.sty { - ty::TyAdt(adt_def, ..) => adt_def.did.is_local(), + ty::Adt(adt_def, ..) => adt_def.did.is_local(), _ => false, } } @@ -255,7 +416,7 @@ pub enum Constructor<'tcx> { /// Literal values. ConstantValue(&'tcx ty::Const<'tcx>), /// Ranges of literal values (`2...5` and `2..5`). - ConstantRange(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>, RangeEnd), + ConstantRange(u128, u128, Ty<'tcx>, RangeEnd), /// Array patterns of length n. Slice(u64), } @@ -273,7 +434,7 @@ impl<'tcx> Constructor<'tcx> { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Usefulness<'tcx> { Useful, UsefulWithWitness(Vec>), @@ -289,7 +450,7 @@ impl<'tcx> Usefulness<'tcx> { } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum WitnessPreference { ConstructWitness, LeaveOutWitness @@ -301,8 +462,39 @@ struct PatternContext<'tcx> { max_slice_length: u64, } -/// A stack of patterns in reverse order of construction -#[derive(Clone)] +/// A witness of non-exhaustiveness for error reporting, represented +/// as a list of patterns (in reverse order of construction) with +/// wildcards inside to represent elements that can take any inhabitant +/// of the type as a value. +/// +/// A witness against a list of patterns should have the same types +/// and length as the pattern matched against. Because Rust `match` +/// is always against a single pattern, at the end the witness will +/// have length 1, but in the middle of the algorithm, it can contain +/// multiple patterns. +/// +/// For example, if we are constructing a witness for the match against +/// ``` +/// struct Pair(Option<(u32, u32)>, bool); +/// +/// match (p: Pair) { +/// Pair(None, _) => {} +/// Pair(_, false) => {} +/// } +/// ``` +/// +/// We'll perform the following steps: +/// 1. Start with an empty witness +/// `Witness(vec![])` +/// 2. Push a witness `Some(_)` against the `None` +/// `Witness(vec![Some(_)])` +/// 3. Push a witness `true` against the `false` +/// `Witness(vec![Some(_), true])` +/// 4. Apply the `Pair` constructor to the witnesses +/// `Witness(vec![Pair(Some(_), true)])` +/// +/// The final `Pair(Some(_), true)` is then the resulting witness. +#[derive(Clone, Debug)] pub struct Witness<'tcx>(Vec>); impl<'tcx> Witness<'tcx> { @@ -353,11 +545,11 @@ impl<'tcx> Witness<'tcx> { let arity = constructor_arity(cx, ctor, ty); let pat = { let len = self.0.len() as u64; - let mut pats = self.0.drain((len-arity) as usize..).rev(); + let mut pats = self.0.drain((len - arity) as usize..).rev(); match ty.sty { - ty::TyAdt(..) | - ty::TyTuple(..) => { + ty::Adt(..) | + ty::Tuple(..) => { let pats = pats.enumerate().map(|(i, p)| { FieldPattern { field: Field::new(i), @@ -365,7 +557,7 @@ impl<'tcx> Witness<'tcx> { } }).collect(); - if let ty::TyAdt(adt, substs) = ty.sty { + if let ty::Adt(adt, substs) = ty.sty { if adt.is_enum() { PatternKind::Variant { adt_def: adt, @@ -381,11 +573,11 @@ impl<'tcx> Witness<'tcx> { } } - ty::TyRef(..) => { + ty::Ref(..) => { PatternKind::Deref { subpattern: pats.nth(0).unwrap() } } - ty::TySlice(_) | ty::TyArray(..) => { + ty::Slice(_) | ty::Array(..) => { PatternKind::Slice { prefix: pats.collect(), slice: None, @@ -396,6 +588,12 @@ impl<'tcx> Witness<'tcx> { _ => { match *ctor { ConstantValue(value) => PatternKind::Constant { value }, + ConstantRange(lo, hi, ty, end) => PatternKind::Range { + lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), + hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), + ty, + end, + }, _ => PatternKind::Wild, } } @@ -417,10 +615,6 @@ impl<'tcx> Witness<'tcx> { /// but is instead bounded by the maximum fixed length of slice patterns in /// the column of patterns being analyzed. /// -/// This intentionally does not list ConstantValue specializations for -/// non-booleans, because we currently assume that there is always a -/// "non-standard constant" that matches. See issue #12483. -/// /// We make sure to omit constructors that are statically impossible. eg for /// Option we do not include Some(_) in the returned list of constructors. fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, @@ -428,13 +622,14 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, -> Vec> { debug!("all_constructors({:?})", pcx.ty); - match pcx.ty.sty { - ty::TyBool => { + let exhaustive_integer_patterns = cx.tcx.features().exhaustive_integer_patterns; + let ctors = match pcx.ty.sty { + ty::Bool => { [true, false].iter().map(|&b| { ConstantValue(ty::Const::from_bool(cx.tcx, b)) }).collect() } - ty::TyArray(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => { + ty::Array(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => { let len = len.unwrap_usize(cx.tcx); if len != 0 && cx.is_uninhabited(sub_ty) { vec![] @@ -443,20 +638,48 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, } } // Treat arrays of a constant but unknown length like slices. - ty::TyArray(ref sub_ty, _) | - ty::TySlice(ref sub_ty) => { + ty::Array(ref sub_ty, _) | + ty::Slice(ref sub_ty) => { if cx.is_uninhabited(sub_ty) { vec![Slice(0)] } else { (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect() } } - ty::TyAdt(def, substs) if def.is_enum() => { + ty::Adt(def, substs) if def.is_enum() => { def.variants.iter() .filter(|v| !cx.is_variant_uninhabited(v, substs)) .map(|v| Variant(v.did)) .collect() } + ty::Char if exhaustive_integer_patterns => { + vec![ + // The valid Unicode Scalar Value ranges. + ConstantRange('\u{0000}' as u128, + '\u{D7FF}' as u128, + cx.tcx.types.char, + RangeEnd::Included + ), + ConstantRange('\u{E000}' as u128, + '\u{10FFFF}' as u128, + cx.tcx.types.char, + RangeEnd::Included + ), + ] + } + ty::Int(ity) if exhaustive_integer_patterns => { + // FIXME(49937): refactor these bit manipulations into interpret. + let bits = Integer::from_attr(cx.tcx, SignedInt(ity)).size().bits() as u128; + let min = 1u128 << (bits - 1); + let max = (1u128 << (bits - 1)) - 1; + vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included)] + } + ty::Uint(uty) if exhaustive_integer_patterns => { + // FIXME(49937): refactor these bit manipulations into interpret. + let bits = Integer::from_attr(cx.tcx, UnsignedInt(uty)).size().bits() as u128; + let max = !0u128 >> (128 - bits); + vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included)] + } _ => { if cx.is_uninhabited(pcx.ty) { vec![] @@ -464,7 +687,8 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, vec![Single] } } - } + }; + ctors } fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( @@ -497,7 +721,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( // `[true, ..]` // `[.., false]` // Then any slice of length ≥1 that matches one of these two - // patterns can be be trivially turned to a slice of any + // patterns can be trivially turned to a slice of any // other length ≥1 that matches them and vice-versa - for // but the slice from length 2 `[false, true]` that matches neither // of these patterns can't be turned to a slice from length 1 that @@ -569,6 +793,184 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( cmp::max(max_fixed_len + 1, max_prefix_len + max_suffix_len) } +/// An inclusive interval, used for precise integer exhaustiveness checking. +/// `IntRange`s always store a contiguous range. This means that values are +/// encoded such that `0` encodes the minimum value for the integer, +/// regardless of the signedness. +/// For example, the pattern `-128...127i8` is encoded as `0..=255`. +/// This makes comparisons and arithmetic on interval endpoints much more +/// straightforward. See `signed_bias` for details. +/// +/// `IntRange` is never used to encode an empty range or a "range" that wraps +/// around the (offset) space: i.e. `range.lo <= range.hi`. +#[derive(Clone)] +struct IntRange<'tcx> { + pub range: RangeInclusive, + pub ty: Ty<'tcx>, +} + +impl<'tcx> IntRange<'tcx> { + fn from_ctor(tcx: TyCtxt<'_, 'tcx, 'tcx>, + ctor: &Constructor<'tcx>) + -> Option> { + match ctor { + ConstantRange(lo, hi, ty, end) => { + // Perform a shift if the underlying types are signed, + // which makes the interval arithmetic simpler. + let bias = IntRange::signed_bias(tcx, ty); + let (lo, hi) = (lo ^ bias, hi ^ bias); + // Make sure the interval is well-formed. + if lo > hi || lo == hi && *end == RangeEnd::Excluded { + None + } else { + let offset = (*end == RangeEnd::Excluded) as u128; + Some(IntRange { range: lo..=(hi - offset), ty }) + } + } + ConstantValue(val) => { + let ty = val.ty; + if let Some(val) = val.assert_bits(tcx, ty::ParamEnv::empty().and(ty)) { + let bias = IntRange::signed_bias(tcx, ty); + let val = val ^ bias; + Some(IntRange { range: val..=val, ty }) + } else { + None + } + } + Single | Variant(_) | Slice(_) => { + None + } + } + } + + fn from_pat(tcx: TyCtxt<'_, 'tcx, 'tcx>, + pat: &Pattern<'tcx>) + -> Option> { + Self::from_ctor(tcx, &match pat.kind { + box PatternKind::Constant { value } => ConstantValue(value), + box PatternKind::Range { lo, hi, ty, end } => ConstantRange( + lo.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), + hi.to_bits(tcx, ty::ParamEnv::empty().and(ty)).unwrap(), + ty, + end, + ), + _ => return None, + }) + } + + // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it. + fn signed_bias(tcx: TyCtxt<'_, 'tcx, 'tcx>, ty: Ty<'tcx>) -> u128 { + match ty.sty { + ty::Int(ity) => { + let bits = Integer::from_attr(tcx, SignedInt(ity)).size().bits() as u128; + 1u128 << (bits - 1) + } + _ => 0 + } + } + + /// Convert a `RangeInclusive` to a `ConstantValue` or inclusive `ConstantRange`. + fn range_to_ctor( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + ty: Ty<'tcx>, + r: RangeInclusive, + ) -> Constructor<'tcx> { + let bias = IntRange::signed_bias(tcx, ty); + let (lo, hi) = r.into_inner(); + if lo == hi { + let ty = ty::ParamEnv::empty().and(ty); + ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty)) + } else { + ConstantRange(lo ^ bias, hi ^ bias, ty, RangeEnd::Included) + } + } + + /// Return a collection of ranges that spans the values covered by `ranges`, subtracted + /// by the values covered by `self`: i.e. `ranges \ self` (in set notation). + fn subtract_from(self, + tcx: TyCtxt<'_, 'tcx, 'tcx>, + ranges: Vec>) + -> Vec> { + let ranges = ranges.into_iter().filter_map(|r| { + IntRange::from_ctor(tcx, &r).map(|i| i.range) + }); + let mut remaining_ranges = vec![]; + let ty = self.ty; + let (lo, hi) = self.range.into_inner(); + for subrange in ranges { + let (subrange_lo, subrange_hi) = subrange.into_inner(); + if lo > subrange_hi || subrange_lo > hi { + // The pattern doesn't intersect with the subrange at all, + // so the subrange remains untouched. + remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=subrange_hi)); + } else { + if lo > subrange_lo { + // The pattern intersects an upper section of the + // subrange, so a lower section will remain. + remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=(lo - 1))); + } + if hi < subrange_hi { + // The pattern intersects a lower section of the + // subrange, so an upper section will remain. + remaining_ranges.push(Self::range_to_ctor(tcx, ty, (hi + 1)..=subrange_hi)); + } + } + } + remaining_ranges + } + + fn intersection(&self, other: &Self) -> Option { + let ty = self.ty; + let (lo, hi) = (*self.range.start(), *self.range.end()); + let (other_lo, other_hi) = (*other.range.start(), *other.range.end()); + if lo <= other_hi && other_lo <= hi { + Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty }) + } else { + None + } + } +} + +// Return a set of constructors equivalent to `all_ctors \ used_ctors`. +fn compute_missing_ctors<'a, 'tcx: 'a>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + all_ctors: &Vec>, + used_ctors: &Vec>, +) -> Vec> { + let mut missing_ctors = vec![]; + + for req_ctor in all_ctors { + let mut refined_ctors = vec![req_ctor.clone()]; + for used_ctor in used_ctors { + if used_ctor == req_ctor { + // If a constructor appears in a `match` arm, we can + // eliminate it straight away. + refined_ctors = vec![] + } else if tcx.features().exhaustive_integer_patterns { + if let Some(interval) = IntRange::from_ctor(tcx, used_ctor) { + // Refine the required constructors for the type by subtracting + // the range defined by the current constructor pattern. + refined_ctors = interval.subtract_from(tcx, refined_ctors); + } + } + + // If the constructor patterns that have been considered so far + // already cover the entire range of values, then we the + // constructor is not missing, and we can move on to the next one. + if refined_ctors.is_empty() { + break; + } + } + // If a constructor has not been matched, then it is missing. + // We add `refined_ctors` instead of `req_ctor`, because then we can + // provide more detailed error information about precisely which + // ranges have been omitted. + missing_ctors.extend(refined_ctors); + } + + missing_ctors +} + /// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html /// The algorithm from the paper has been modified to correctly handle empty /// types. The changes are: @@ -637,8 +1039,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // FIXME: this might lead to "unstable" behavior with macro hygiene // introducing uninhabited patterns for inaccessible fields. We // need to figure out how to model that. - ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error()) - .unwrap_or(v[0].ty), + ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error()).unwrap_or(v[0].ty), max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0]))) }; @@ -646,7 +1047,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, if let Some(constructors) = pat_constructors(cx, v[0], pcx) { debug!("is_useful - expanding constructors: {:#?}", constructors); - constructors.into_iter().map(|c| + split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c| is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) ).find(|result| result.is_useful()).unwrap_or(NotUseful) } else { @@ -656,11 +1057,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, pat_constructors(cx, row[0], pcx).unwrap_or(vec![]) }).collect(); debug!("used_ctors = {:#?}", used_ctors); + // `all_ctors` are all the constructors for the given type, which + // should all be represented (or caught with the wild pattern `_`). let all_ctors = all_constructors(cx, pcx); debug!("all_ctors = {:#?}", all_ctors); - let missing_ctors: Vec = all_ctors.iter().filter(|c| { - !used_ctors.contains(*c) - }).cloned().collect(); // `missing_ctors` is the set of constructors from the same type as the // first column of `matrix` that are matched only by wildcard patterns @@ -681,10 +1081,12 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // feature flag is not present, so this is only // needed for that case. - let is_privately_empty = - all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty); - let is_declared_nonexhaustive = - cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty); + // Find those constructors that are not matched by any non-wildcard patterns in the + // current column. + let missing_ctors = compute_missing_ctors(cx.tcx, &all_ctors, &used_ctors); + + let is_privately_empty = all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty); + let is_declared_nonexhaustive = cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty); debug!("missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}", missing_ctors, is_privately_empty, is_declared_nonexhaustive); @@ -693,7 +1095,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive; if missing_ctors.is_empty() && !is_non_exhaustive { - all_ctors.into_iter().map(|c| { + split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| { is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) }).find(|result| result.is_useful()).unwrap_or(NotUseful) } else { @@ -753,7 +1155,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // `used_ctors` is empty. let new_witnesses = if is_non_exhaustive || used_ctors.is_empty() { // All constructors are unused. Add wild patterns - // rather than each individual constructor + // rather than each individual constructor. pats.into_iter().map(|mut witness| { witness.0.push(Pattern { ty: pcx.ty, @@ -765,6 +1167,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, } else { pats.into_iter().flat_map(|witness| { missing_ctors.iter().map(move |ctor| { + // Extends the witness with a "wild" version of this + // constructor, that matches everything that can be built with + // it. For example, if `ctor` is a `Constructor::Variant` for + // `Option::Some`, this pushes the witness for `Some(_)`. witness.clone().push_wild_constructor(cx, ctor, pcx.ty) }) }).collect() @@ -777,14 +1183,16 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, } } +/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e. `is_useful` applied +/// to the specialised version of both the pattern matrix `P` and the new pattern `q`. fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>( cx: &mut MatchCheckCtxt<'a, 'tcx>, &Matrix(ref m): &Matrix<'p, 'tcx>, v: &[&'p Pattern<'tcx>], ctor: Constructor<'tcx>, lty: Ty<'tcx>, - witness: WitnessPreference) -> Usefulness<'tcx> -{ + witness: WitnessPreference, +) -> Usefulness<'tcx> { debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty); let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty); let wild_patterns_owned: Vec<_> = sub_pat_tys.iter().map(|ty| { @@ -806,7 +1214,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>( .collect() ), result => result - }, + } None => NotUseful } } @@ -819,24 +1227,29 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>( /// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on. /// /// Returns None in case of a catch-all, which can't be specialized. -fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt, +fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, pat: &Pattern<'tcx>, pcx: PatternContext) -> Option>> { match *pat.kind { - PatternKind::Binding { .. } | PatternKind::Wild => - None, - PatternKind::Leaf { .. } | PatternKind::Deref { .. } => - Some(vec![Single]), - PatternKind::Variant { adt_def, variant_index, .. } => - Some(vec![Variant(adt_def.variants[variant_index].did)]), - PatternKind::Constant { value } => - Some(vec![ConstantValue(value)]), - PatternKind::Range { lo, hi, end } => - Some(vec![ConstantRange(lo, hi, end)]), + PatternKind::AscribeUserType { ref subpattern, .. } => + pat_constructors(cx, subpattern, pcx), + PatternKind::Binding { .. } | PatternKind::Wild => None, + PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]), + PatternKind::Variant { adt_def, variant_index, .. } => { + Some(vec![Variant(adt_def.variants[variant_index].did)]) + } + PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), + PatternKind::Range { lo, hi, ty, end } => + Some(vec![ConstantRange( + lo.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), + hi.to_bits(cx.tcx, ty::ParamEnv::empty().and(ty)).unwrap(), + ty, + end, + )]), PatternKind::Array { .. } => match pcx.ty.sty { - ty::TyArray(_, length) => Some(vec![ + ty::Array(_, length) => Some(vec![ Slice(length.unwrap_usize(cx.tcx)) ]), _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty) @@ -860,14 +1273,14 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt, fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 { debug!("constructor_arity({:#?}, {:?})", ctor, ty); match ty.sty { - ty::TyTuple(ref fs) => fs.len() as u64, - ty::TySlice(..) | ty::TyArray(..) => match *ctor { + ty::Tuple(ref fs) => fs.len() as u64, + ty::Slice(..) | ty::Array(..) => match *ctor { Slice(length) => length, ConstantValue(_) => 0, _ => bug!("bad slice pattern {:?} {:?}", ctor, ty) }, - ty::TyRef(..) => 1, - ty::TyAdt(adt, _) => { + ty::Ref(..) => 1, + ty::Adt(adt, _) => { adt.variants[ctor.variant_index_for_adt(adt)].fields.len() as u64 } _ => 0 @@ -884,14 +1297,14 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, { debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty); match ty.sty { - ty::TyTuple(ref fs) => fs.into_iter().map(|t| *t).collect(), - ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor { + ty::Tuple(ref fs) => fs.into_iter().map(|t| *t).collect(), + ty::Slice(ty) | ty::Array(ty, _) => match *ctor { Slice(length) => (0..length).map(|_| ty).collect(), ConstantValue(_) => vec![], _ => bug!("bad slice pattern {:?} {:?}", ctor, ty) }, - ty::TyRef(_, rty, _) => vec![rty], - ty::TyAdt(adt, substs) => { + ty::Ref(_, rty, _) => vec![rty], + ty::Adt(adt, substs) => { if adt.is_box() { // Use T as the sub pattern type of Box. vec![substs.type_at(0)] @@ -970,13 +1383,170 @@ fn slice_pat_covered_by_constructor<'tcx>( Ok(true) } +// Whether to evaluate a constructor using exhaustive integer matching. This is true if the +// constructor is a range or constant with an integer type. +fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Constructor<'tcx>) -> bool { + if tcx.features().exhaustive_integer_patterns { + let ty = match ctor { + ConstantValue(value) => value.ty, + ConstantRange(_, _, ty, _) => ty, + _ => return false, + }; + if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.sty { + return true; + } + } + false +} + +/// For exhaustive integer matching, some constructors are grouped within other constructors +/// (namely integer typed values are grouped within ranges). However, when specialising these +/// constructors, we want to be specialising for the underlying constructors (the integers), not +/// the groups (the ranges). Thus we need to split the groups up. Splitting them up naïvely would +/// mean creating a separate constructor for every single value in the range, which is clearly +/// impractical. However, observe that for some ranges of integers, the specialisation will be +/// identical across all values in that range (i.e. there are equivalence classes of ranges of +/// constructors based on their `is_useful_specialised` outcome). These classes are grouped by +/// the patterns that apply to them (in the matrix `P`). We can split the range whenever the +/// patterns that apply to that range (specifically: the patterns that *intersect* with that range) +/// change. +/// Our solution, therefore, is to split the range constructor into subranges at every single point +/// the group of intersecting patterns changes (using the method described below). +/// And voilà! We're testing precisely those ranges that we need to, without any exhaustive matching +/// on actual integers. The nice thing about this is that the number of subranges is linear in the +/// number of rows in the matrix (i.e. the number of cases in the `match` statement), so we don't +/// need to be worried about matching over gargantuan ranges. +/// +/// Essentially, given the first column of a matrix representing ranges, looking like the following: +/// +/// |------| |----------| |-------| || +/// |-------| |-------| |----| || +/// |---------| +/// +/// We split the ranges up into equivalence classes so the ranges are no longer overlapping: +/// +/// |--|--|||-||||--||---|||-------| |-|||| || +/// +/// The logic for determining how to split the ranges is fairly straightforward: we calculate +/// boundaries for each interval range, sort them, then create constructors for each new interval +/// between every pair of boundary points. (This essentially sums up to performing the intuitive +/// merging operation depicted above.) +fn split_grouped_constructors<'p, 'a: 'p, 'tcx: 'a>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + ctors: Vec>, + &Matrix(ref m): &Matrix<'p, 'tcx>, + ty: Ty<'tcx>, +) -> Vec> { + let mut split_ctors = Vec::with_capacity(ctors.len()); + + for ctor in ctors.into_iter() { + match ctor { + // For now, only ranges may denote groups of "subconstructors", so we only need to + // special-case constant ranges. + ConstantRange(..) if should_treat_range_exhaustively(tcx, &ctor) => { + // We only care about finding all the subranges within the range of the constructor + // range. Anything else is irrelevant, because it is guaranteed to result in + // `NotUseful`, which is the default case anyway, and can be ignored. + let ctor_range = IntRange::from_ctor(tcx, &ctor).unwrap(); + + /// Represents a border between 2 integers. Because the intervals spanning borders + /// must be able to cover every integer, we need to be able to represent + /// 2^128 + 1 such borders. + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] + enum Border { + JustBefore(u128), + AfterMax, + } + + // A function for extracting the borders of an integer interval. + fn range_borders(r: IntRange<'_>) -> impl Iterator { + let (lo, hi) = r.range.into_inner(); + let from = Border::JustBefore(lo); + let to = match hi.checked_add(1) { + Some(m) => Border::JustBefore(m), + None => Border::AfterMax, + }; + vec![from, to].into_iter() + } + + // `borders` is the set of borders between equivalence classes: each equivalence + // class lies between 2 borders. + let row_borders = m.iter() + .flat_map(|row| IntRange::from_pat(tcx, row[0])) + .flat_map(|range| ctor_range.intersection(&range)) + .flat_map(|range| range_borders(range)); + let ctor_borders = range_borders(ctor_range.clone()); + let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect(); + borders.sort_unstable(); + + // We're going to iterate through every pair of borders, making sure that each + // represents an interval of nonnegative length, and convert each such interval + // into a constructor. + for IntRange { range, .. } in borders.windows(2).filter_map(|window| { + match (window[0], window[1]) { + (Border::JustBefore(n), Border::JustBefore(m)) => { + if n < m { + Some(IntRange { range: n..=(m - 1), ty }) + } else { + None + } + } + (Border::JustBefore(n), Border::AfterMax) => { + Some(IntRange { range: n..=u128::MAX, ty }) + } + (Border::AfterMax, _) => None, + } + }) { + split_ctors.push(IntRange::range_to_ctor(tcx, ty, range)); + } + } + // Any other constructor can be used unchanged. + _ => split_ctors.push(ctor), + } + } + + split_ctors +} + +/// Check whether there exists any shared value in either `ctor` or `pat` by intersecting them. +fn constructor_intersects_pattern<'p, 'a: 'p, 'tcx: 'a>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + ctor: &Constructor<'tcx>, + pat: &'p Pattern<'tcx>, +) -> Option>> { + if should_treat_range_exhaustively(tcx, ctor) { + match (IntRange::from_ctor(tcx, ctor), IntRange::from_pat(tcx, pat)) { + (Some(ctor), Some(pat)) => { + ctor.intersection(&pat).map(|_| { + let (pat_lo, pat_hi) = pat.range.into_inner(); + let (ctor_lo, ctor_hi) = ctor.range.into_inner(); + assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi); + vec![] + }) + } + _ => None, + } + } else { + // Fallback for non-ranges and ranges that involve floating-point numbers, which are not + // conveniently handled by `IntRange`. For these cases, the constructor may not be a range + // so intersection actually devolves into being covered by the pattern. + match constructor_covered_by_range(tcx, ctor, pat) { + Ok(true) => Some(vec![]), + Ok(false) | Err(ErrorReported) => None, + } + } +} + fn constructor_covered_by_range<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, ctor: &Constructor<'tcx>, - from: &'tcx ty::Const<'tcx>, to: &'tcx ty::Const<'tcx>, - end: RangeEnd, - ty: Ty<'tcx>, + pat: &Pattern<'tcx>, ) -> Result { + let (from, to, end, ty) = match pat.kind { + box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty), + box PatternKind::Range { lo, hi, ty, end } => (lo, hi, end, ty), + _ => bug!("`constructor_covered_by_range` called with {:?}", pat), + }; trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); let cmp_from = |c_from| compare_const_vals(tcx, c_from, from, ty::ParamEnv::empty().and(ty)) .map(|res| res != Ordering::Less); @@ -996,17 +1566,33 @@ fn constructor_covered_by_range<'a, 'tcx>( (end == RangeEnd::Included && to == Ordering::Equal); Ok(some_or_ok!(cmp_from(value)) && end) }, - ConstantRange(from, to, RangeEnd::Included) => { - let to = some_or_ok!(cmp_to(to)); + ConstantRange(from, to, ty, RangeEnd::Included) => { + let to = some_or_ok!(cmp_to(ty::Const::from_bits( + tcx, + to, + ty::ParamEnv::empty().and(ty), + ))); let end = (to == Ordering::Less) || (end == RangeEnd::Included && to == Ordering::Equal); - Ok(some_or_ok!(cmp_from(from)) && end) + Ok(some_or_ok!(cmp_from(ty::Const::from_bits( + tcx, + from, + ty::ParamEnv::empty().and(ty), + ))) && end) }, - ConstantRange(from, to, RangeEnd::Excluded) => { - let to = some_or_ok!(cmp_to(to)); + ConstantRange(from, to, ty, RangeEnd::Excluded) => { + let to = some_or_ok!(cmp_to(ty::Const::from_bits( + tcx, + to, + ty::ParamEnv::empty().and(ty) + ))); let end = (to == Ordering::Less) || (end == RangeEnd::Excluded && to == Ordering::Equal); - Ok(some_or_ok!(cmp_from(from)) && end) + Ok(some_or_ok!(cmp_from(ty::Const::from_bits( + tcx, + from, + ty::ParamEnv::empty().and(ty))) + ) && end) } Single => Ok(true), _ => bug!(), @@ -1040,15 +1626,17 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( cx: &mut MatchCheckCtxt<'a, 'tcx>, r: &[&'p Pattern<'tcx>], constructor: &Constructor<'tcx>, - wild_patterns: &[&'p Pattern<'tcx>]) - -> Option>> -{ + wild_patterns: &[&'p Pattern<'tcx>], +) -> Option>> { let pat = &r[0]; let head: Option> = match *pat.kind { + PatternKind::AscribeUserType { ref subpattern, .. } => + specialize(cx, ::std::slice::from_ref(&subpattern), constructor, wild_patterns), + PatternKind::Binding { .. } | PatternKind::Wild => { Some(wild_patterns.to_owned()) - }, + } PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { let ref variant = adt_def.variants[variant_index]; @@ -1062,6 +1650,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( PatternKind::Leaf { ref subpatterns } => { Some(patterns_for_variant(subpatterns, wild_patterns)) } + PatternKind::Deref { ref subpattern } => { Some(vec![subpattern]) } @@ -1090,30 +1679,21 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( span_bug!(pat.span, "unexpected const-val {:?} with ctor {:?}", value, constructor) } - }, + } _ => { - match constructor_covered_by_range( - cx.tcx, - constructor, value, value, RangeEnd::Included, - value.ty, - ) { - Ok(true) => Some(vec![]), - Ok(false) => None, - Err(ErrorReported) => None, - } + // If the constructor is a: + // Single value: add a row if the constructor equals the pattern. + // Range: add a row if the constructor contains the pattern. + constructor_intersects_pattern(cx.tcx, constructor, pat) } } } - PatternKind::Range { lo, hi, ref end } => { - match constructor_covered_by_range( - cx.tcx, - constructor, lo, hi, end.clone(), lo.ty, - ) { - Ok(true) => Some(vec![]), - Ok(false) => None, - Err(ErrorReported) => None, - } + PatternKind::Range { .. } => { + // If the constructor is a: + // Single value: add a row if the pattern contains the constructor. + // Range: add a row if the constructor intersects the pattern. + constructor_intersects_pattern(cx.tcx, constructor, pat) } PatternKind::Array { ref prefix, ref slice, ref suffix } | @@ -1123,14 +1703,12 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( let pat_len = prefix.len() + suffix.len(); if let Some(slice_count) = wild_patterns.len().checked_sub(pat_len) { if slice_count == 0 || slice.is_some() { - Some( - prefix.iter().chain( - wild_patterns.iter().map(|p| *p) - .skip(prefix.len()) - .take(slice_count) - .chain( - suffix.iter() - )).collect()) + Some(prefix.iter().chain( + wild_patterns.iter().map(|p| *p) + .skip(prefix.len()) + .take(slice_count) + .chain(suffix.iter()) + ).collect()) } else { None } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 35f9dcee99..bf878145e1 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -208,7 +208,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { } (pattern, &**pat) }).collect(), - arm.guard.as_ref().map(|e| &**e) + arm.guard.as_ref().map(|g| match g { + hir::Guard::If(ref e) => &**e, + }) )).collect(); // Bail out early if inlining failed. @@ -258,8 +260,8 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool { // "rustc-1.0-style" uncontentious uninhabitableness check match scrutinee_ty.sty { - ty::TyNever => true, - ty::TyAdt(def, _) => def.variants.is_empty(), + ty::Never => true, + ty::Adt(def, _) => def.variants.is_empty(), _ => false } } @@ -272,7 +274,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { self.tables); let pattern = patcx.lower_pattern(pat); let pattern_ty = pattern.ty; - let pats : Matrix = vec![vec![ + let pats: Matrix = vec![vec![ expand_pattern(cx, pattern) ]].into_iter().collect(); @@ -315,7 +317,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { return true; } let pat_ty = cx.tables.pat_ty(p); - if let ty::TyAdt(edef, _) = pat_ty.sty { + if let ty::Adt(edef, _) = pat_ty.sty { if edef.is_enum() && edef.variants.iter().any(|variant| { variant.name == ident.name && variant.ctor_kind == CtorKind::Const }) { @@ -391,7 +393,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, printed_if_let_err = true; } } - }, + } hir::MatchSource::WhileLetDesugar => { // check which arm we're on. @@ -540,12 +542,16 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, "cannot bind by-move into a pattern guard") .span_label(p.span, "moves value into pattern guard") .emit(); - } else if by_ref_span.is_some() { - struct_span_err!(cx.tcx.sess, p.span, E0009, - "cannot bind by-move and by-ref in the same pattern") - .span_label(p.span, "by-move pattern here") - .span_label(by_ref_span.unwrap(), "both by-ref and by-move used") - .emit(); + } else if let Some(by_ref_span) = by_ref_span { + struct_span_err!( + cx.tcx.sess, + p.span, + E0009, + "cannot bind by-move and by-ref in the same pattern", + ) + .span_label(p.span, "by-move pattern here") + .span_label(by_ref_span, "both by-ref and by-move used") + .emit(); } }; @@ -575,12 +581,19 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// assign. /// /// FIXME: this should be done by borrowck. -fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { +fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Guard) { let mut checker = MutationChecker { cx, }; - ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables, None) - .walk_expr(guard); + match guard { + hir::Guard::If(expr) => + ExprUseVisitor::new(&mut checker, + cx.tcx, + cx.param_env, + cx.region_scope_tree, + cx.tables, + None).walk_expr(expr), + }; } struct MutationChecker<'a, 'tcx: 'a> { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 53511c1c12..57519d6ad7 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -16,11 +16,11 @@ mod check_match; pub use self::check_match::check_crate; pub(crate) use self::check_match::check_match; -use interpret::{const_val_field, const_variant_index, self}; +use interpret::{const_field, const_variant_index}; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; -use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, Value}; -use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region}; +use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; +use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region}; use rustc::ty::subst::{Substs, Kind}; use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::def::{Def, CtorKind}; @@ -66,6 +66,11 @@ pub struct Pattern<'tcx> { pub enum PatternKind<'tcx> { Wild, + AscribeUserType { + user_ty: CanonicalTy<'tcx>, + subpattern: Pattern<'tcx>, + }, + /// x, ref x, x @ P, etc Binding { mutability: Mutability, @@ -101,6 +106,7 @@ pub enum PatternKind<'tcx> { Range { lo: &'tcx ty::Const<'tcx>, hi: &'tcx ty::Const<'tcx>, + ty: Ty<'tcx>, end: RangeEnd, }, @@ -125,6 +131,8 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self.kind { PatternKind::Wild => write!(f, "_"), + PatternKind::AscribeUserType { ref subpattern, .. } => + write!(f, "{}: _", subpattern), PatternKind::Binding { mutability, name, mode, ref subpattern, .. } => { let is_mut = match mode { BindingMode::ByValue => mutability == Mutability::Mut, @@ -148,7 +156,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Variant { adt_def, variant_index, .. } => { Some(&adt_def.variants[variant_index]) } - _ => if let ty::TyAdt(adt, _) = self.ty.sty { + _ => if let ty::Adt(adt, _) = self.ty.sty { if !adt.is_enum() { Some(&adt.variants[0]) } else { @@ -165,7 +173,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { if let Some(variant) = variant { write!(f, "{}", variant.name)?; - // Only for TyAdt we can have `S {...}`, + // Only for Adt we can have `S {...}`, // which we handle separately here. if variant.ctor_kind == CtorKind::Fictive { write!(f, " {{ ")?; @@ -216,8 +224,8 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { } PatternKind::Deref { ref subpattern } => { match self.ty.sty { - ty::TyAdt(def, _) if def.is_box() => write!(f, "box ")?, - ty::TyRef(_, _, mutbl) => { + ty::Adt(def, _) if def.is_box() => write!(f, "box ")?, + ty::Ref(_, _, mutbl) => { write!(f, "&")?; if mutbl == hir::MutMutable { write!(f, "mut ")?; @@ -230,10 +238,10 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Constant { value } => { fmt_const_val(f, value) } - PatternKind::Range { lo, hi, end } => { + PatternKind::Range { lo, hi, ty: _, end } => { fmt_const_val(f, lo)?; match end { - RangeEnd::Included => write!(f, "...")?, + RangeEnd::Included => write!(f, "..=")?, RangeEnd::Excluded => write!(f, "..")?, } fmt_const_val(f, hi) @@ -359,7 +367,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => - PatternKind::Range { lo, hi, end }, + PatternKind::Range { lo, hi, ty, end }, (RangeEnd::Excluded, _) => { span_err!( self.tcx.sess, @@ -368,9 +376,14 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { "lower range bound must be less than upper", ); PatternKind::Wild - }, - (RangeEnd::Included, None) | - (RangeEnd::Included, Some(Ordering::Greater)) => { + } + (RangeEnd::Included, Some(Ordering::Equal)) => { + PatternKind::Constant { value: lo } + } + (RangeEnd::Included, Some(Ordering::Less)) => { + PatternKind::Range { lo, hi, ty, end } + } + (RangeEnd::Included, _) => { let mut err = struct_span_err!( self.tcx.sess, lo_expr.span, @@ -390,8 +403,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } err.emit(); PatternKind::Wild - }, - (RangeEnd::Included, Some(_)) => PatternKind::Range { lo, hi, end }, + } } } _ => PatternKind::Wild @@ -409,7 +421,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatKind::Slice(ref prefix, ref slice, ref suffix) => { match ty.sty { - ty::TyRef(_, ty, _) => + ty::Ref(_, ty, _) => PatternKind::Deref { subpattern: Pattern { ty, @@ -418,10 +430,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { pat.span, ty, prefix, slice, suffix)) }, }, - ty::TySlice(..) | - ty::TyArray(..) => + ty::Slice(..) | + ty::Array(..) => self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix), - ty::TyError => { // Avoid ICE + ty::Error => { // Avoid ICE return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) }; } ref sty => @@ -434,7 +446,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatKind::Tuple(ref subpatterns, ddpos) => { match ty.sty { - ty::TyTuple(ref tys) => { + ty::Tuple(ref tys) => { let subpatterns = subpatterns.iter() .enumerate_and_adjust(tys.len(), ddpos) @@ -446,7 +458,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Leaf { subpatterns: subpatterns } } - ty::TyError => { // Avoid ICE (#50577) + ty::Error => { // Avoid ICE (#50577) return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) }; } ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty), @@ -456,8 +468,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatKind::Binding(_, id, ident, ref sub) => { let var_ty = self.tables.node_id_to_type(pat.hir_id); let region = match var_ty.sty { - ty::TyRef(r, _, _) => Some(r), - ty::TyError => { // Avoid ICE + ty::Ref(r, _, _) => Some(r), + ty::Error => { // Avoid ICE return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) }; } _ => None, @@ -480,7 +492,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { // A ref x pattern is the same node used for x, and as such it has // x's type, which is &T, where we want T (the type being matched). if let ty::BindByReference(_) = bm { - if let ty::TyRef(_, rty, _) = ty.sty { + if let ty::Ref(_, rty, _) = ty.sty { ty = rty; } else { bug!("`ref {}` has wrong type {}", ident, ty); @@ -500,8 +512,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => { let def = self.tables.qpath_def(qpath, pat.hir_id); let adt_def = match ty.sty { - ty::TyAdt(adt_def, _) => adt_def, - ty::TyError => { // Avoid ICE (#50585) + ty::Adt(adt_def, _) => adt_def, + ty::Error => { // Avoid ICE (#50585) return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) }; } _ => span_bug!(pat.span, @@ -604,12 +616,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { self.flatten_nested_slice_patterns(prefix, slice, suffix); match ty.sty { - ty::TySlice(..) => { + ty::Slice(..) => { // matching a slice or fixed-length array PatternKind::Slice { prefix: prefix, slice: slice, suffix: suffix } } - ty::TyArray(_, len) => { + ty::Array(_, len) => { // fixed-length array let len = len.unwrap_usize(self.tcx); assert!(len >= prefix.len() as u64 + suffix.len() as u64); @@ -636,9 +648,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let adt_def = self.tcx.adt_def(enum_id); if adt_def.is_enum() { let substs = match ty.sty { - ty::TyAdt(_, substs) | - ty::TyFnDef(_, substs) => substs, - ty::TyError => { // Avoid ICE (#50585) + ty::Adt(_, substs) | + ty::FnDef(_, substs) => substs, + ty::Error => { // Avoid ICE (#50585) return PatternKind::Wild; } _ => bug!("inappropriate type for def: {:?}", ty.sty), @@ -655,7 +667,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { + Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => { PatternKind::Leaf { subpatterns: subpatterns } } @@ -791,7 +803,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { debug!("const_to_pat: cv={:#?}", cv); let adt_subpattern = |i, variant_opt| { let field = Field::new(i); - let val = const_val_field( + let val = const_field( self.tcx, self.param_env, instance, variant_opt, field, cv, ).expect("field access failed"); @@ -807,7 +819,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }).collect::>() }; let kind = match cv.ty.sty { - ty::TyFloat(_) => { + ty::Float(_) => { let id = self.tcx.hir.hir_to_node_id(id); self.tcx.lint_node( ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, @@ -819,12 +831,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { value: cv, } }, - ty::TyAdt(adt_def, _) if adt_def.is_union() => { + ty::Adt(adt_def, _) if adt_def.is_union() => { // Matching on union fields is unsafe, we can't hide it in constants self.tcx.sess.span_err(span, "cannot use unions in constant patterns"); PatternKind::Wild } - ty::TyAdt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => { + ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => { let msg = format!("to use a constant of type `{}` in a pattern, \ `{}` must be annotated with `#[derive(PartialEq, Eq)]`", self.tcx.item_path_str(adt_def.did), @@ -832,7 +844,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { self.tcx.sess.span_err(span, &msg); PatternKind::Wild }, - ty::TyAdt(adt_def, substs) if adt_def.is_enum() => { + ty::Adt(adt_def, substs) if adt_def.is_enum() => { let variant_index = const_variant_index( self.tcx, self.param_env, instance, cv ).expect("const_variant_index failed"); @@ -847,18 +859,18 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { subpatterns, } }, - ty::TyAdt(adt_def, _) => { + ty::Adt(adt_def, _) => { let struct_var = adt_def.non_enum_variant(); PatternKind::Leaf { subpatterns: adt_subpatterns(struct_var.fields.len(), None), } } - ty::TyTuple(fields) => { + ty::Tuple(fields) => { PatternKind::Leaf { subpatterns: adt_subpatterns(fields.len(), None), } } - ty::TyArray(_, n) => { + ty::Array(_, n) => { PatternKind::Array { prefix: (0..n.unwrap_usize(self.tcx)) .map(|i| adt_subpattern(i as usize, None)) @@ -935,7 +947,7 @@ macro_rules! CloneImpls { CloneImpls!{ <'tcx> Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>, Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef, - &'tcx Substs<'tcx>, &'tcx Kind<'tcx> + &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, CanonicalTy<'tcx> } impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> { @@ -969,6 +981,13 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { match *self { PatternKind::Wild => PatternKind::Wild, + PatternKind::AscribeUserType { + ref subpattern, + user_ty, + } => PatternKind::AscribeUserType { + subpattern: subpattern.fold_with(folder), + user_ty: user_ty.fold_with(folder), + }, PatternKind::Binding { mutability, name, @@ -1013,10 +1032,12 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { PatternKind::Range { lo, hi, + ty, end, } => PatternKind::Range { lo: lo.fold_with(folder), hi: hi.fold_with(folder), + ty: ty.fold_with(folder), end, }, PatternKind::Slice { @@ -1069,38 +1090,47 @@ pub fn compare_const_vals<'a, 'tcx>( if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) { use ::rustc_apfloat::Float; return match ty.value.sty { - ty::TyFloat(ast::FloatTy::F32) => { + ty::Float(ast::FloatTy::F32) => { let l = ::rustc_apfloat::ieee::Single::from_bits(a); let r = ::rustc_apfloat::ieee::Single::from_bits(b); l.partial_cmp(&r) }, - ty::TyFloat(ast::FloatTy::F64) => { + ty::Float(ast::FloatTy::F64) => { let l = ::rustc_apfloat::ieee::Double::from_bits(a); let r = ::rustc_apfloat::ieee::Double::from_bits(b); l.partial_cmp(&r) }, - ty::TyInt(_) => { - let a = interpret::sign_extend(tcx, a, ty.value).expect("layout error for TyInt"); - let b = interpret::sign_extend(tcx, b, ty.value).expect("layout error for TyInt"); + ty::Int(_) => { + let layout = tcx.layout_of(ty).ok()?; + assert!(layout.abi.is_signed()); + let a = sign_extend(a, layout.size); + let b = sign_extend(b, layout.size); Some((a as i128).cmp(&(b as i128))) }, _ => Some(a.cmp(&b)), } } - if let ty::TyRef(_, rty, _) = ty.value.sty { - if let ty::TyStr = rty.sty { - match (a.to_byval_value(), b.to_byval_value()) { + if let ty::Ref(_, rty, _) = ty.value.sty { + if let ty::Str = rty.sty { + match (a.val, b.val) { ( - Some(Value::ScalarPair( + ConstValue::ScalarPair( Scalar::Ptr(ptr_a), len_a, - )), - Some(Value::ScalarPair( + ), + ConstValue::ScalarPair( Scalar::Ptr(ptr_b), len_b, - )) + ), ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => { + let len_a = len_a.not_undef().ok(); + let len_b = len_b.not_undef().ok(); + if len_a.is_none() || len_b.is_none() { + tcx.sess.struct_err("str slice len is undef").delay_as_bug(); + } + let len_a = len_a?; + let len_b = len_b?; if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) { if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) { if len_a == len_b { @@ -1141,8 +1171,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, LitKind::Str(ref s, _) => { let s = s.as_str(); let id = tcx.allocate_bytes(s.as_bytes()); - let value = Scalar::Ptr(id.into()).to_value_with_len(s.len() as u64, tcx); - ConstValue::from_byval_value(value) + ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, tcx) }, LitKind::ByteStr(ref data) => { let id = tcx.allocate_bytes(data); @@ -1150,7 +1179,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, }, LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits { bits: n as u128, - defined: 8, + size: 1, }), LitKind::Int(n, _) => { enum Int { @@ -1158,11 +1187,11 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, Unsigned(UintTy), } let ity = match ty.sty { - ty::TyInt(IntTy::Isize) => Int::Signed(tcx.sess.target.isize_ty), - ty::TyInt(other) => Int::Signed(other), - ty::TyUint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty), - ty::TyUint(other) => Int::Unsigned(other), - ty::TyError => { // Avoid ICE (#51963) + ty::Int(IntTy::Isize) => Int::Signed(tcx.sess.target.isize_ty), + ty::Int(other) => Int::Signed(other), + ty::Uint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty), + ty::Uint(other) => Int::Unsigned(other), + ty::Error => { // Avoid ICE (#51963) return Err(LitToConstError::Propagated); } _ => bug!("literal integer type with bad type ({:?})", ty.sty), @@ -1188,10 +1217,10 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, Int::Signed(IntTy::I128)| Int::Unsigned(UintTy::U128) => n, _ => bug!(), }; - let defined = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size.bits() as u8; + let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size.bytes() as u8; ConstValue::Scalar(Scalar::Bits { bits: n, - defined, + size, }) }, LitKind::Float(n, fty) => { @@ -1199,19 +1228,13 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { - ty::TyFloat(fty) => fty, + ty::Float(fty) => fty, _ => bug!() }; parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? } - LitKind::Bool(b) => ConstValue::Scalar(Scalar::Bits { - bits: b as u128, - defined: 8, - }), - LitKind::Char(c) => ConstValue::Scalar(Scalar::Bits { - bits: c as u128, - defined: 32, - }), + LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), + LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), }; Ok(ty::Const::from_const_value(tcx, lit, ty)) } @@ -1224,7 +1247,7 @@ pub fn parse_float<'tcx>( let num = num.as_str(); use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; - let (bits, defined) = match fty { + let (bits, size) = match fty { ast::FloatTy::F32 => { num.parse::().map_err(|_| ())?; let mut f = num.parse::().unwrap_or_else(|e| { @@ -1233,7 +1256,7 @@ pub fn parse_float<'tcx>( if neg { f = -f; } - (f.to_bits(), 32) + (f.to_bits(), 4) } ast::FloatTy::F64 => { num.parse::().map_err(|_| ())?; @@ -1243,9 +1266,9 @@ pub fn parse_float<'tcx>( if neg { f = -f; } - (f.to_bits(), 64) + (f.to_bits(), 8) } }; - Ok(ConstValue::Scalar(Scalar::Bits { bits, defined })) + Ok(ConstValue::Scalar(Scalar::Bits { bits, size })) } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 7bcf4ef658..83264acf76 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -1,93 +1,92 @@ -use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, LayoutOf}; +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::ty::{self, Ty, TypeAndMut}; +use rustc::ty::layout::{self, TyLayout, Size}; use syntax::ast::{FloatTy, IntTy, UintTy}; use rustc_apfloat::ieee::{Single, Double}; -use super::{EvalContext, Machine}; -use rustc::mir::interpret::{Scalar, EvalResult, Pointer, PointerArithmetic, Value, EvalErrorKind}; +use rustc::mir::interpret::{ + Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind, truncate +}; use rustc::mir::CastKind; use rustc_apfloat::Float; -use interpret::eval_context::ValTy; -use interpret::Place; + +use super::{EvalContext, Machine, PlaceTy, OpTy, Value}; impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { - crate fn cast( + fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::RawPtr(ty::TypeAndMut { ty, .. }) | + ty::Ref(_, ty, _) => !self.type_is_sized(ty), + ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()), + _ => false, + } + } + + pub fn cast( &mut self, - src: ValTy<'tcx>, + src: OpTy<'tcx>, kind: CastKind, - dest_ty: Ty<'tcx>, - dest: Place, + dest: PlaceTy<'tcx>, ) -> EvalResult<'tcx> { + let src_layout = src.layout; + let dst_layout = dest.layout; use rustc::mir::CastKind::*; match kind { Unsize => { - let src_layout = self.layout_of(src.ty)?; - let dst_layout = self.layout_of(dest_ty)?; - self.unsize_into(src.value, src_layout, dest, dst_layout)?; + self.unsize_into(src, dest)?; } Misc => { - if self.type_is_fat_ptr(src.ty) { - match (src.value, self.type_is_fat_ptr(dest_ty)) { - (Value::ByRef { .. }, _) | + let src = self.read_value(src)?; + if self.type_is_fat_ptr(src_layout.ty) { + match (*src, self.type_is_fat_ptr(dest.layout.ty)) { // pointers to extern types (Value::Scalar(_),_) | // slices and trait objects to other slices/trait objects (Value::ScalarPair(..), true) => { - let valty = ValTy { - value: src.value, - ty: dest_ty, - }; - self.write_value(valty, dest)?; + // No change to value + self.write_value(*src, dest)?; } // slices and trait objects to thin pointers (dropping the metadata) (Value::ScalarPair(data, _), false) => { - let valty = ValTy { - value: Value::Scalar(data), - ty: dest_ty, - }; - self.write_value(valty, dest)?; + self.write_scalar(data, dest)?; } } } else { - let src_layout = self.layout_of(src.ty)?; match src_layout.variants { layout::Variants::Single { index } => { - if let Some(def) = src.ty.ty_adt_def() { + if let Some(def) = src_layout.ty.ty_adt_def() { let discr_val = def .discriminant_for_variant(*self.tcx, index) .val; - let defined = self - .layout_of(dest_ty) - .unwrap() - .size - .bits() as u8; return self.write_scalar( - dest, - Scalar::Bits { - bits: discr_val, - defined, - }, - dest_ty); + Scalar::from_uint(discr_val, dst_layout.size), + dest); } } layout::Variants::Tagged { .. } | layout::Variants::NicheFilling { .. } => {}, } - let src_val = self.value_to_scalar(src)?; - let dest_val = self.cast_scalar(src_val, src.ty, dest_ty)?; - let valty = ValTy { - value: Value::Scalar(dest_val), - ty: dest_ty, - }; - self.write_value(valty, dest)?; + let src = src.to_scalar()?; + let dest_val = self.cast_scalar(src, src_layout, dest.layout)?; + self.write_scalar(dest_val, dest)?; } } ReifyFnPointer => { - match src.ty.sty { - ty::TyFnDef(def_id, substs) => { + // The src operand does not matter, just its type + match src_layout.ty.sty { + ty::FnDef(def_id, substs) => { if self.tcx.has_attr(def_id, "rustc_args_required_const") { bug!("reifying a fn ptr that requires \ const arguments"); @@ -99,30 +98,27 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { substs, ).ok_or_else(|| EvalErrorKind::TooGeneric.into()); let fn_ptr = self.memory.create_fn_alloc(instance?); - let valty = ValTy { - value: Value::Scalar(fn_ptr.into()), - ty: dest_ty, - }; - self.write_value(valty, dest)?; + self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?; } ref other => bug!("reify fn pointer on {:?}", other), } } UnsafeFnPointer => { - match dest_ty.sty { - ty::TyFnPtr(_) => { - let mut src = src; - src.ty = dest_ty; - self.write_value(src, dest)?; + let src = self.read_value(src)?; + match dest.layout.ty.sty { + ty::FnPtr(_) => { + // No change to value + self.write_value(*src, dest)?; } ref other => bug!("fn to unsafe fn cast on {:?}", other), } } ClosureFnPointer => { - match src.ty.sty { - ty::TyClosure(def_id, substs) => { + // The src operand does not matter, just its type + match src_layout.ty.sty { + ty::Closure(def_id, substs) => { let substs = self.tcx.subst_and_normalize_erasing_regions( self.substs(), ty::ParamEnv::reveal_all(), @@ -135,11 +131,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { ty::ClosureKind::FnOnce, ); let fn_ptr = self.memory.create_fn_alloc(instance); - let valty = ValTy { - value: Value::Scalar(fn_ptr.into()), - ty: dest_ty, - }; - self.write_value(valty, dest)?; + let val = Value::Scalar(Scalar::Ptr(fn_ptr.into()).into()); + self.write_value(val, dest)?; } ref other => bug!("closure fn pointer on {:?}", other), } @@ -151,21 +144,35 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { pub(super) fn cast_scalar( &self, val: Scalar, - src_ty: Ty<'tcx>, - dest_ty: Ty<'tcx>, + src_layout: TyLayout<'tcx>, + dest_layout: TyLayout<'tcx>, ) -> EvalResult<'tcx, Scalar> { - use rustc::ty::TypeVariants::*; - trace!("Casting {:?}: {:?} to {:?}", val, src_ty, dest_ty); + use rustc::ty::TyKind::*; + trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty); match val { - Scalar::Bits { defined: 0, .. } => Ok(val), - Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_ty), - Scalar::Bits { bits, .. } => { - // TODO(oli-obk): check defined bits here - match src_ty.sty { - TyFloat(fty) => self.cast_from_float(bits, fty, dest_ty), - _ => self.cast_from_int(bits, src_ty, dest_ty), + Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_layout.ty), + Scalar::Bits { bits, size } => { + debug_assert_eq!(size as u64, src_layout.size.bytes()); + debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits, + "Unexpected value of size {} before casting", size); + + let res = match src_layout.ty.sty { + Float(fty) => self.cast_from_float(bits, fty, dest_layout.ty)?, + _ => self.cast_from_int(bits, src_layout, dest_layout)?, + }; + + // Sanity check + match res { + Scalar::Ptr(_) => bug!("Fabricated a ptr value from an int...?"), + Scalar::Bits { bits, size } => { + debug_assert_eq!(size as u64, dest_layout.size.bytes()); + debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits, + "Unexpected value of size {} after casting", size); + } } + // Done + Ok(res) } } } @@ -173,127 +180,226 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { fn cast_from_int( &self, v: u128, - src_ty: Ty<'tcx>, - dest_ty: Ty<'tcx>, + src_layout: TyLayout<'tcx>, + dest_layout: TyLayout<'tcx>, ) -> EvalResult<'tcx, Scalar> { - let signed = self.layout_of(src_ty)?.abi.is_signed(); + let signed = src_layout.abi.is_signed(); let v = if signed { - self.sign_extend(v, src_ty)? + self.sign_extend(v, src_layout) } else { v }; - trace!("cast_from_int: {}, {}, {}", v, src_ty, dest_ty); - use rustc::ty::TypeVariants::*; - match dest_ty.sty { - TyInt(_) | TyUint(_) => { - let v = self.truncate(v, dest_ty)?; - Ok(Scalar::Bits { - bits: v, - defined: self.layout_of(dest_ty).unwrap().size.bits() as u8, - }) + trace!("cast_from_int: {}, {}, {}", v, src_layout.ty, dest_layout.ty); + use rustc::ty::TyKind::*; + match dest_layout.ty.sty { + Int(_) | Uint(_) => { + let v = self.truncate(v, dest_layout); + Ok(Scalar::from_uint(v, dest_layout.size)) } - TyFloat(FloatTy::F32) if signed => Ok(Scalar::Bits { - bits: Single::from_i128(v as i128).value.to_bits(), - defined: 32, - }), - TyFloat(FloatTy::F64) if signed => Ok(Scalar::Bits { - bits: Double::from_i128(v as i128).value.to_bits(), - defined: 64, - }), - TyFloat(FloatTy::F32) => Ok(Scalar::Bits { - bits: Single::from_u128(v).value.to_bits(), - defined: 32, - }), - TyFloat(FloatTy::F64) => Ok(Scalar::Bits { - bits: Double::from_u128(v).value.to_bits(), - defined: 64, - }), + Float(FloatTy::F32) if signed => Ok(Scalar::from_uint( + Single::from_i128(v as i128).value.to_bits(), + Size::from_bits(32) + )), + Float(FloatTy::F64) if signed => Ok(Scalar::from_uint( + Double::from_i128(v as i128).value.to_bits(), + Size::from_bits(64) + )), + Float(FloatTy::F32) => Ok(Scalar::from_uint( + Single::from_u128(v).value.to_bits(), + Size::from_bits(32) + )), + Float(FloatTy::F64) => Ok(Scalar::from_uint( + Double::from_u128(v).value.to_bits(), + Size::from_bits(64) + )), - TyChar if v as u8 as u128 == v => Ok(Scalar::Bits { bits: v, defined: 32 }), - TyChar => err!(InvalidChar(v)), + Char => { + // `u8` to `char` cast + debug_assert_eq!(v as u8 as u128, v); + Ok(Scalar::from_uint(v, Size::from_bytes(4))) + }, - // No alignment check needed for raw pointers. But we have to truncate to target ptr size. - TyRawPtr(_) => { - Ok(Scalar::Bits { - bits: self.memory.truncate_to_ptr(v).0 as u128, - defined: self.memory.pointer_size().bits() as u8, - }) + // No alignment check needed for raw pointers. + // But we have to truncate to target ptr size. + RawPtr(_) => { + Ok(Scalar::from_uint( + self.truncate_to_ptr(v).0, + self.pointer_size(), + )) }, // Casts to bool are not permitted by rustc, no need to handle them here. - _ => err!(Unimplemented(format!("int to {:?} cast", dest_ty))), + _ => err!(Unimplemented(format!("int to {:?} cast", dest_layout.ty))), } } - fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> { - use rustc::ty::TypeVariants::*; + fn cast_from_float( + &self, + bits: u128, + fty: FloatTy, + dest_ty: Ty<'tcx> + ) -> EvalResult<'tcx, Scalar> { + use rustc::ty::TyKind::*; use rustc_apfloat::FloatConvert; match dest_ty.sty { // float -> uint - TyUint(t) => { - let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize); - match fty { - FloatTy::F32 => Ok(Scalar::Bits { - bits: Single::from_bits(bits).to_u128(width).value, - defined: width as u8, - }), - FloatTy::F64 => Ok(Scalar::Bits { - bits: Double::from_bits(bits).to_u128(width).value, - defined: width as u8, - }), - } + Uint(t) => { + let width = t.bit_width().unwrap_or(self.pointer_size().bits() as usize); + let v = match fty { + FloatTy::F32 => Single::from_bits(bits).to_u128(width).value, + FloatTy::F64 => Double::from_bits(bits).to_u128(width).value, + }; + // This should already fit the bit width + Ok(Scalar::from_uint(v, Size::from_bits(width as u64))) }, // float -> int - TyInt(t) => { - let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize); - match fty { - FloatTy::F32 => Ok(Scalar::Bits { - bits: Single::from_bits(bits).to_i128(width).value as u128, - defined: width as u8, - }), - FloatTy::F64 => Ok(Scalar::Bits { - bits: Double::from_bits(bits).to_i128(width).value as u128, - defined: width as u8, - }), - } + Int(t) => { + let width = t.bit_width().unwrap_or(self.pointer_size().bits() as usize); + let v = match fty { + FloatTy::F32 => Single::from_bits(bits).to_i128(width).value, + FloatTy::F64 => Double::from_bits(bits).to_i128(width).value, + }; + Ok(Scalar::from_int(v, Size::from_bits(width as u64))) }, // f64 -> f32 - TyFloat(FloatTy::F32) if fty == FloatTy::F64 => { - Ok(Scalar::Bits { - bits: Single::to_bits(Double::from_bits(bits).convert(&mut false).value), - defined: 32, - }) + Float(FloatTy::F32) if fty == FloatTy::F64 => { + Ok(Scalar::from_uint( + Single::to_bits(Double::from_bits(bits).convert(&mut false).value), + Size::from_bits(32), + )) }, // f32 -> f64 - TyFloat(FloatTy::F64) if fty == FloatTy::F32 => { - Ok(Scalar::Bits { - bits: Double::to_bits(Single::from_bits(bits).convert(&mut false).value), - defined: 64, - }) + Float(FloatTy::F64) if fty == FloatTy::F32 => { + Ok(Scalar::from_uint( + Double::to_bits(Single::from_bits(bits).convert(&mut false).value), + Size::from_bits(64), + )) }, // identity cast - TyFloat(FloatTy:: F64) => Ok(Scalar::Bits { - bits, - defined: 64, - }), - TyFloat(FloatTy:: F32) => Ok(Scalar::Bits { - bits, - defined: 32, - }), + Float(FloatTy:: F64) => Ok(Scalar::from_uint(bits, Size::from_bits(64))), + Float(FloatTy:: F32) => Ok(Scalar::from_uint(bits, Size::from_bits(32))), _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))), } } fn cast_from_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Scalar> { - use rustc::ty::TypeVariants::*; + use rustc::ty::TyKind::*; match ty.sty { - // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here. - TyRawPtr(_) | - TyInt(IntTy::Isize) | - TyUint(UintTy::Usize) => Ok(ptr.into()), - TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes), + // Casting to a reference or fn pointer is not permitted by rustc, + // no need to support it here. + RawPtr(_) | + Int(IntTy::Isize) | + Uint(UintTy::Usize) => Ok(ptr.into()), + Int(_) | Uint(_) => err!(ReadPointerAsBytes), _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))), } } + + fn unsize_into_ptr( + &mut self, + src: OpTy<'tcx>, + dest: PlaceTy<'tcx>, + // The pointee types + sty: Ty<'tcx>, + dty: Ty<'tcx>, + ) -> EvalResult<'tcx> { + // A -> A conversion + let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(sty, dty); + + match (&src_pointee_ty.sty, &dest_pointee_ty.sty) { + (&ty::Array(_, length), &ty::Slice(_)) => { + let ptr = self.read_value(src)?.to_scalar_ptr()?; + // u64 cast is from usize to u64, which is always good + let val = Value::new_slice(ptr, length.unwrap_usize(self.tcx.tcx), self.tcx.tcx); + self.write_value(val, dest) + } + (&ty::Dynamic(..), &ty::Dynamic(..)) => { + // For now, upcasts are limited to changes in marker + // traits, and hence never actually require an actual + // change to the vtable. + self.copy_op(src, dest) + } + (_, &ty::Dynamic(ref data, _)) => { + // Initial cast from sized to dyn trait + let trait_ref = data.principal().unwrap().with_self_ty( + *self.tcx, + src_pointee_ty, + ); + let trait_ref = self.tcx.erase_regions(&trait_ref); + let vtable = self.get_vtable(src_pointee_ty, trait_ref)?; + let ptr = self.read_value(src)?.to_scalar_ptr()?; + let val = Value::new_dyn_trait(ptr, vtable); + self.write_value(val, dest) + } + + _ => bug!("invalid unsizing {:?} -> {:?}", src.layout.ty, dest.layout.ty), + } + } + + fn unsize_into( + &mut self, + src: OpTy<'tcx>, + dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + match (&src.layout.ty.sty, &dest.layout.ty.sty) { + (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) | + (&ty::Ref(_, s, _), &ty::RawPtr(TypeAndMut { ty: d, .. })) | + (&ty::RawPtr(TypeAndMut { ty: s, .. }), + &ty::RawPtr(TypeAndMut { ty: d, .. })) => { + self.unsize_into_ptr(src, dest, s, d) + } + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { + assert_eq!(def_a, def_b); + if def_a.is_box() || def_b.is_box() { + if !def_a.is_box() || !def_b.is_box() { + bug!("invalid unsizing between {:?} -> {:?}", src.layout, dest.layout); + } + return self.unsize_into_ptr( + src, + dest, + src.layout.ty.boxed_ty(), + dest.layout.ty.boxed_ty(), + ); + } + + // unsizing of generic struct with pointer fields + // Example: `Arc` -> `Arc` + // here we need to increase the size of every &T thin ptr field to a fat ptr + for i in 0..src.layout.fields.count() { + let dst_field = self.place_field(dest, i as u64)?; + if dst_field.layout.is_zst() { + continue; + } + let src_field = match src.try_as_mplace() { + Ok(mplace) => { + let src_field = self.mplace_field(mplace, i as u64)?; + src_field.into() + } + Err(..) => { + let src_field_layout = src.layout.field(&self, i)?; + // this must be a field covering the entire thing + assert_eq!(src.layout.fields.offset(i).bytes(), 0); + assert_eq!(src_field_layout.size, src.layout.size); + // just sawp out the layout + OpTy { op: src.op, layout: src_field_layout } + } + }; + if src_field.layout.ty == dst_field.layout.ty { + self.copy_op(src_field, dst_field)?; + } else { + self.unsize_into(src_field, dst_field)?; + } + } + Ok(()) + } + _ => { + bug!( + "unsize_into: invalid conversion: {:?} -> {:?}", + src.layout, + dest.layout + ) + } + } + } } diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs deleted file mode 100644 index 873fef75bb..0000000000 --- a/src/librustc_mir/interpret/const_eval.rs +++ /dev/null @@ -1,588 +0,0 @@ -use std::fmt; -use std::error::Error; - -use rustc::hir; -use rustc::mir::interpret::{ConstEvalErr}; -use rustc::mir; -use rustc::ty::{self, TyCtxt, Ty, Instance}; -use rustc::ty::layout::{self, LayoutOf, Primitive, TyLayout}; -use rustc::ty::subst::Subst; - -use syntax::ast::Mutability; -use syntax::codemap::Span; -use syntax::codemap::DUMMY_SP; - -use rustc::mir::interpret::{ - EvalResult, EvalError, EvalErrorKind, GlobalId, - Value, Scalar, AllocId, Allocation, ConstValue, -}; -use super::{Place, EvalContext, StackPopCleanup, ValTy, Memory, MemoryKind}; - -pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - instance: Instance<'tcx>, - mir: &'mir mir::Mir<'tcx>, - span: Span, -) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> { - debug!("mk_borrowck_eval_cx: {:?}", instance); - let param_env = tcx.param_env(instance.def_id()); - let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ()); - // insert a stack frame so any queries have the correct substs - ecx.push_stack_frame( - instance, - span, - mir, - Place::undef(), - StackPopCleanup::None, - )?; - Ok(ecx) -} - -pub fn mk_eval_cx<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - instance: Instance<'tcx>, - param_env: ty::ParamEnv<'tcx>, -) -> EvalResult<'tcx, EvalContext<'a, 'tcx, 'tcx, CompileTimeEvaluator>> { - debug!("mk_eval_cx: {:?}, {:?}", instance, param_env); - let span = tcx.def_span(instance.def_id()); - let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ()); - let mir = ecx.load_mir(instance.def)?; - // insert a stack frame so any queries have the correct substs - ecx.push_stack_frame( - instance, - mir.span, - mir, - Place::undef(), - StackPopCleanup::None, - )?; - Ok(ecx) -} - -pub fn eval_promoted<'a, 'mir, 'tcx>( - ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>, - cid: GlobalId<'tcx>, - mir: &'mir mir::Mir<'tcx>, - param_env: ty::ParamEnv<'tcx>, -) -> EvalResult<'tcx, (Value, Scalar, TyLayout<'tcx>)> { - ecx.with_fresh_body(|ecx| { - eval_body_using_ecx(ecx, cid, Some(mir), param_env) - }) -} - -pub fn value_to_const_value<'tcx>( - ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>, - val: Value, - ty: Ty<'tcx>, -) -> &'tcx ty::Const<'tcx> { - let layout = ecx.layout_of(ty).unwrap(); - match (val, &layout.abi) { - (Value::Scalar(Scalar::Bits { defined: 0, ..}), _) if layout.is_zst() => {}, - (Value::ByRef(..), _) | - (Value::Scalar(_), &layout::Abi::Scalar(_)) | - (Value::ScalarPair(..), &layout::Abi::ScalarPair(..)) => {}, - _ => bug!("bad value/layout combo: {:#?}, {:#?}", val, layout), - } - let val = (|| { - match val { - Value::Scalar(val) => Ok(ConstValue::Scalar(val)), - Value::ScalarPair(a, b) => Ok(ConstValue::ScalarPair(a, b)), - Value::ByRef(ptr, align) => { - let ptr = ptr.to_ptr().unwrap(); - let alloc = ecx.memory.get(ptr.alloc_id)?; - assert!(alloc.align.abi() >= align.abi()); - assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes()); - let mut alloc = alloc.clone(); - alloc.align = align; - let alloc = ecx.tcx.intern_const_alloc(alloc); - Ok(ConstValue::ByRef(alloc, ptr.offset)) - } - } - })(); - match val { - Ok(val) => ty::Const::from_const_value(ecx.tcx.tcx, val, ty), - Err(err) => { - let (frames, span) = ecx.generate_stacktrace(None); - let err = ConstEvalErr { - span, - error: err, - stacktrace: frames, - }; - err.report_as_error( - ecx.tcx, - "failed to convert Value to ConstValue, this is a bug", - ); - span_bug!(span, "miri error occured when converting Value to ConstValue") - } - } -} - -fn eval_body_and_ecx<'a, 'mir, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - cid: GlobalId<'tcx>, - mir: Option<&'mir mir::Mir<'tcx>>, - param_env: ty::ParamEnv<'tcx>, -) -> (EvalResult<'tcx, (Value, Scalar, TyLayout<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) { - debug!("eval_body_and_ecx: {:?}, {:?}", cid, param_env); - // we start out with the best span we have - // and try improving it down the road when more information is available - let span = tcx.def_span(cid.instance.def_id()); - let span = mir.map(|mir| mir.span).unwrap_or(span); - let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ()); - let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env); - (r, ecx) -} - -fn eval_body_using_ecx<'a, 'mir, 'tcx>( - ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>, - cid: GlobalId<'tcx>, - mir: Option<&'mir mir::Mir<'tcx>>, - param_env: ty::ParamEnv<'tcx>, -) -> EvalResult<'tcx, (Value, Scalar, TyLayout<'tcx>)> { - debug!("eval_body: {:?}, {:?}", cid, param_env); - let tcx = ecx.tcx.tcx; - let mut mir = match mir { - Some(mir) => mir, - None => ecx.load_mir(cid.instance.def)?, - }; - if let Some(index) = cid.promoted { - mir = &mir.promoted[index]; - } - let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; - assert!(!layout.is_unsized()); - let ptr = ecx.memory.allocate( - layout.size, - layout.align, - MemoryKind::Stack, - )?; - let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span); - let is_static = tcx.is_static(cid.instance.def_id()); - let mutability = if is_static == Some(hir::Mutability::MutMutable) || internally_mutable { - Mutability::Mutable - } else { - Mutability::Immutable - }; - let cleanup = StackPopCleanup::MarkStatic(mutability); - let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id())); - let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); - trace!("const_eval: pushing stack frame for global: {}{}", name, prom); - assert!(mir.arg_count == 0); - ecx.push_stack_frame( - cid.instance, - mir.span, - mir, - Place::from_ptr(ptr, layout.align), - cleanup, - )?; - - while ecx.step()? {} - let ptr = ptr.into(); - // always try to read the value and report errors - let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? { - Some(val) if is_static.is_none() && cid.promoted.is_none() => val, - // point at the allocation - _ => Value::ByRef(ptr, layout.align), - }; - Ok((value, ptr, layout)) -} - -#[derive(Debug, Clone, Eq, PartialEq, Hash)] -pub struct CompileTimeEvaluator; - -impl<'tcx> Into> for ConstEvalError { - fn into(self) -> EvalError<'tcx> { - EvalErrorKind::MachineError(self.to_string()).into() - } -} - -#[derive(Clone, Debug)] -enum ConstEvalError { - NeedsRfc(String), - NotConst(String), -} - -impl fmt::Display for ConstEvalError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::ConstEvalError::*; - match *self { - NeedsRfc(ref msg) => { - write!( - f, - "\"{}\" needs an rfc before being allowed inside constants", - msg - ) - } - NotConst(ref msg) => write!(f, "{}", msg), - } - } -} - -impl Error for ConstEvalError { - fn description(&self) -> &str { - use self::ConstEvalError::*; - match *self { - NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants", - NotConst(_) => "this feature is not compatible with constant evaluation", - } - } - - fn cause(&self) -> Option<&dyn Error> { - None - } -} - -impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator { - type MemoryData = (); - type MemoryKinds = !; - fn eval_fn_call<'a>( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - instance: ty::Instance<'tcx>, - destination: Option<(Place, mir::BasicBlock)>, - args: &[ValTy<'tcx>], - span: Span, - sig: ty::FnSig<'tcx>, - ) -> EvalResult<'tcx, bool> { - debug!("eval_fn_call: {:?}", instance); - if !ecx.tcx.is_const_fn(instance.def_id()) { - let def_id = instance.def_id(); - let (op, oflo) = if let Some(op) = ecx.tcx.is_binop_lang_item(def_id) { - op - } else { - return Err( - ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into(), - ); - }; - let (dest, bb) = destination.expect("128 lowerings can't diverge"); - let dest_ty = sig.output(); - if oflo { - ecx.intrinsic_with_overflow(op, args[0], args[1], dest, dest_ty)?; - } else { - ecx.intrinsic_overflowing(op, args[0], args[1], dest, dest_ty)?; - } - ecx.goto_block(bb); - return Ok(true); - } - let mir = match ecx.load_mir(instance.def) { - Ok(mir) => mir, - Err(err) => { - if let EvalErrorKind::NoMirFor(ref path) = err.kind { - return Err( - ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path)) - .into(), - ); - } - return Err(err); - } - }; - let (return_place, return_to_block) = match destination { - Some((place, block)) => (place, StackPopCleanup::Goto(block)), - None => (Place::undef(), StackPopCleanup::None), - }; - - ecx.push_stack_frame( - instance, - span, - mir, - return_place, - return_to_block, - )?; - - Ok(false) - } - - - fn call_intrinsic<'a>( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - instance: ty::Instance<'tcx>, - args: &[ValTy<'tcx>], - dest: Place, - dest_layout: layout::TyLayout<'tcx>, - target: mir::BasicBlock, - ) -> EvalResult<'tcx> { - let substs = instance.substs; - - let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..]; - match intrinsic_name { - "min_align_of" => { - let elem_ty = substs.type_at(0); - let elem_align = ecx.layout_of(elem_ty)?.align.abi(); - let align_val = Scalar::Bits { - bits: elem_align as u128, - defined: dest_layout.size.bits() as u8, - }; - ecx.write_scalar(dest, align_val, dest_layout.ty)?; - } - - "size_of" => { - let ty = substs.type_at(0); - let size = ecx.layout_of(ty)?.size.bytes() as u128; - let size_val = Scalar::Bits { - bits: size, - defined: dest_layout.size.bits() as u8, - }; - ecx.write_scalar(dest, size_val, dest_layout.ty)?; - } - - "type_id" => { - let ty = substs.type_at(0); - let type_id = ecx.tcx.type_id_hash(ty) as u128; - let id_val = Scalar::Bits { - bits: type_id, - defined: dest_layout.size.bits() as u8, - }; - ecx.write_scalar(dest, id_val, dest_layout.ty)?; - } - "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" | "bswap" => { - let ty = substs.type_at(0); - let layout_of = ecx.layout_of(ty)?; - let bits = ecx.value_to_scalar(args[0])?.to_bits(layout_of.size)?; - let kind = match layout_of.abi { - ty::layout::Abi::Scalar(ref scalar) => scalar.value, - _ => Err(::rustc::mir::interpret::EvalErrorKind::TypeNotPrimitive(ty))?, - }; - let out_val = if intrinsic_name.ends_with("_nonzero") { - if bits == 0 { - return err!(Intrinsic(format!("{} called on 0", intrinsic_name))); - } - numeric_intrinsic(intrinsic_name.trim_right_matches("_nonzero"), bits, kind)? - } else { - numeric_intrinsic(intrinsic_name, bits, kind)? - }; - ecx.write_scalar(dest, out_val, ty)?; - } - - name => return Err( - ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", name)).into() - ), - } - - ecx.goto_block(target); - - // Since we pushed no stack frame, the main loop will act - // as if the call just completed and it's returning to the - // current frame. - Ok(()) - } - - fn try_ptr_op<'a>( - _ecx: &EvalContext<'a, 'mir, 'tcx, Self>, - _bin_op: mir::BinOp, - left: Scalar, - _left_ty: Ty<'tcx>, - right: Scalar, - _right_ty: Ty<'tcx>, - ) -> EvalResult<'tcx, Option<(Scalar, bool)>> { - if left.is_bits() && right.is_bits() { - Ok(None) - } else { - Err( - ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(), - ) - } - } - - fn mark_static_initialized<'a>( - _mem: &mut Memory<'a, 'mir, 'tcx, Self>, - _id: AllocId, - _mutability: Mutability, - ) -> EvalResult<'tcx, bool> { - Ok(false) - } - - fn init_static<'a>( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - cid: GlobalId<'tcx>, - ) -> EvalResult<'tcx, AllocId> { - Ok(ecx - .tcx - .alloc_map - .lock() - .intern_static(cid.instance.def_id())) - } - - fn box_alloc<'a>( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - _ty: Ty<'tcx>, - _dest: Place, - ) -> EvalResult<'tcx> { - Err( - ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into(), - ) - } - - fn global_item_with_linkage<'a>( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - _instance: ty::Instance<'tcx>, - _mutability: Mutability, - ) -> EvalResult<'tcx> { - Err( - ConstEvalError::NotConst("statics with `linkage` attribute".to_string()).into(), - ) - } -} - -pub fn const_val_field<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - instance: ty::Instance<'tcx>, - variant: Option, - field: mir::Field, - value: &'tcx ty::Const<'tcx>, -) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { - trace!("const_val_field: {:?}, {:?}, {:?}", instance, field, value); - let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); - let result = (|| { - let ty = value.ty; - let value = ecx.const_to_value(value.val)?; - let layout = ecx.layout_of(ty)?; - let place = ecx.allocate_place_for_value(value, layout, variant)?; - let (place, layout) = ecx.place_field(place, field, layout)?; - let (ptr, align) = place.to_ptr_align(); - let mut new_value = Value::ByRef(ptr, align); - new_value = ecx.try_read_by_ref(new_value, layout.ty)?; - use rustc_data_structures::indexed_vec::Idx; - match (value, new_value) { - (Value::Scalar(_), Value::ByRef(..)) | - (Value::ScalarPair(..), Value::ByRef(..)) | - (Value::Scalar(_), Value::ScalarPair(..)) => bug!( - "field {} of {:?} yielded {:?}", - field.index(), - value, - new_value, - ), - _ => {}, - } - Ok(value_to_const_value(&ecx, new_value, layout.ty)) - })(); - result.map_err(|err| { - let (trace, span) = ecx.generate_stacktrace(None); - ConstEvalErr { - error: err, - stacktrace: trace, - span, - }.into() - }) -} - -pub fn const_variant_index<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - instance: ty::Instance<'tcx>, - val: &'tcx ty::Const<'tcx>, -) -> EvalResult<'tcx, usize> { - trace!("const_variant_index: {:?}, {:?}", instance, val); - let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); - let value = ecx.const_to_value(val.val)?; - let layout = ecx.layout_of(val.ty)?; - let (ptr, align) = match value { - Value::ScalarPair(..) | Value::Scalar(_) => { - let ptr = ecx.memory.allocate(layout.size, layout.align, MemoryKind::Stack)?.into(); - ecx.write_value_to_ptr(value, ptr, layout.align, val.ty)?; - (ptr, layout.align) - }, - Value::ByRef(ptr, align) => (ptr, align), - }; - let place = Place::from_scalar_ptr(ptr, align); - ecx.read_discriminant_as_variant_index(place, layout) -} - -pub fn const_value_to_allocation_provider<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - val: &'tcx ty::Const<'tcx>, -) -> &'tcx Allocation { - match val.val { - ConstValue::ByRef(alloc, offset) => { - assert_eq!(offset.bytes(), 0); - return alloc; - }, - _ => () - } - let result = || -> EvalResult<'tcx, &'tcx Allocation> { - let mut ecx = EvalContext::new( - tcx.at(DUMMY_SP), - ty::ParamEnv::reveal_all(), - CompileTimeEvaluator, - ()); - let value = ecx.const_to_value(val.val)?; - let layout = ecx.layout_of(val.ty)?; - let ptr = ecx.memory.allocate(layout.size, layout.align, MemoryKind::Stack)?; - ecx.write_value_to_ptr(value, ptr.into(), layout.align, val.ty)?; - let alloc = ecx.memory.get(ptr.alloc_id)?; - Ok(tcx.intern_const_alloc(alloc.clone())) - }; - result().expect("unable to convert ConstValue to Allocation") -} - -pub fn const_eval_provider<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, -) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { - trace!("const eval: {:?}", key); - let cid = key.value; - let def_id = cid.instance.def.def_id(); - - if let Some(id) = tcx.hir.as_local_node_id(def_id) { - let tables = tcx.typeck_tables_of(def_id); - let span = tcx.def_span(def_id); - - // Do match-check before building MIR - if tcx.check_match(def_id).is_err() { - return Err(ConstEvalErr { - error: EvalErrorKind::CheckMatchError.into(), - stacktrace: vec![], - span, - }.into()); - } - - if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) { - tcx.mir_const_qualif(def_id); - } - - // Do not continue into miri if typeck errors occurred; it will fail horribly - if tables.tainted_by_errors { - return Err(ConstEvalErr { - error: EvalErrorKind::CheckMatchError.into(), - stacktrace: vec![], - span, - }.into()); - } - }; - - let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env); - res.and_then(|(mut val, _, layout)| { - if tcx.is_static(def_id).is_none() && cid.promoted.is_none() { - val = ecx.try_read_by_ref(val, layout.ty)?; - } - Ok(value_to_const_value(&ecx, val, layout.ty)) - }).map_err(|err| { - let (trace, span) = ecx.generate_stacktrace(None); - let err = ConstEvalErr { - error: err, - stacktrace: trace, - span, - }; - if tcx.is_static(def_id).is_some() { - err.report_as_error(ecx.tcx, "could not evaluate static initializer"); - } - err.into() - }) -} - -fn numeric_intrinsic<'tcx>( - name: &str, - bits: u128, - kind: Primitive, -) -> EvalResult<'tcx, Scalar> { - let defined = match kind { - Primitive::Int(integer, _) => integer.size().bits() as u8, - _ => bug!("invalid `{}` argument: {:?}", name, bits), - }; - let extra = 128 - defined as u128; - let bits_out = match name { - "ctpop" => bits.count_ones() as u128, - "ctlz" => bits.leading_zeros() as u128 - extra, - "cttz" => (bits << extra).trailing_zeros() as u128 - extra, - "bswap" => (bits << extra).swap_bytes(), - _ => bug!("not a numeric intrinsic: {}", name), - }; - Ok(Scalar::Bits { bits: bits_out, defined }) -} diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 8c071ff723..740d4e038d 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1,53 +1,44 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use std::fmt::Write; -use std::hash::{Hash, Hasher}; use std::mem; use rustc::hir::def_id::DefId; use rustc::hir::def::Def; use rustc::hir::map::definitions::DefPathData; +use rustc::ich::StableHashingContext; use rustc::mir; -use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout, Primitive}; +use rustc::ty::layout::{ + self, Size, Align, HasDataLayout, LayoutOf, TyLayout +}; use rustc::ty::subst::{Subst, Substs}; -use rustc::ty::{self, Ty, TyCtxt, TypeAndMut}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::query::TyCtxtAt; -use rustc_data_structures::fx::{FxHashSet, FxHasher}; -use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use rustc::mir::interpret::{ - GlobalId, Value, Scalar, FrameInfo, AllocType, - EvalResult, EvalErrorKind, Pointer, ConstValue, + GlobalId, Scalar, FrameInfo, AllocId, + EvalResult, EvalErrorKind, + ScalarMaybeUndef, + truncate, sign_extend, }; -use syntax::codemap::{self, Span}; -use syntax::ast::Mutability; +use syntax::source_map::{self, Span}; -use super::{Place, PlaceExtra, Memory, - HasMemory, MemoryKind, - Machine}; +use super::{ + Value, Operand, MemPlace, MPlaceTy, Place, + Memory, Machine +}; -macro_rules! validation_failure{ - ($what:expr, $where:expr, $details:expr) => {{ - let where_ = if $where.is_empty() { - String::new() - } else { - format!(" at {}", $where) - }; - err!(ValidationFailure(format!( - "encountered {}{}, but expected {}", - $what, where_, $details, - ))) - }}; - ($what:expr, $where:expr) => {{ - let where_ = if $where.is_empty() { - String::new() - } else { - format!(" at {}", $where) - }; - err!(ValidationFailure(format!( - "encountered {}{}", - $what, where_, - ))) - }}; -} +use super::snapshot::InfiniteLoopDetector; pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { /// Stores the `Machine` instance. @@ -66,15 +57,17 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { pub(crate) stack: Vec>, /// The maximum number of stack frames allowed - pub(crate) stack_limit: usize, + pub(super) stack_limit: usize, /// When this value is negative, it indicates the number of interpreter /// steps *until* the loop detector is enabled. When it is positive, it is /// the number of steps after the detector has been enabled modulo the loop /// detector period. - pub(crate) steps_since_detector_enabled: isize, + pub(super) steps_since_detector_enabled: isize, - pub(crate) loop_detector: InfiniteLoopDetector<'a, 'mir, 'tcx, M>, + /// Extra state to detect loops. + /// FIXME: Move this to the CTFE machine's state, out of the general miri engine. + pub(super) loop_detector: InfiniteLoopDetector<'a, 'mir, 'tcx, M>, } /// A stack frame. @@ -90,24 +83,23 @@ pub struct Frame<'mir, 'tcx: 'mir> { pub instance: ty::Instance<'tcx>, /// The span of the call site. - pub span: codemap::Span, + pub span: source_map::Span, //////////////////////////////////////////////////////////////////////////////// // Return place and locals //////////////////////////////////////////////////////////////////////////////// - /// The block to return to when returning from the current stack frame + /// Work to perform when returning from this function pub return_to_block: StackPopCleanup, /// The location where the result of the current stack frame should be written to. pub return_place: Place, /// The list of locals for this stack frame, stored in order as - /// `[return_ptr, arguments..., variables..., temporaries...]`. The locals are stored as `Option`s. + /// `[return_ptr, arguments..., variables..., temporaries...]`. + /// The locals are stored as `Option`s. /// `None` represents a local that is currently dead, while a live local /// can either directly contain `Scalar` or refer to some part of an `Allocation`. - /// - /// Before being initialized, arguments are `Value::Scalar(Scalar::undef())` and other locals are `None`. - pub locals: IndexVec>, + pub locals: IndexVec>, //////////////////////////////////////////////////////////////////////////////// // Current position within the function @@ -120,38 +112,17 @@ pub struct Frame<'mir, 'tcx: 'mir> { pub stmt: usize, } -impl<'mir, 'tcx: 'mir> Eq for Frame<'mir, 'tcx> {} - -impl<'mir, 'tcx: 'mir> PartialEq for Frame<'mir, 'tcx> { - fn eq(&self, other: &Self) -> bool { - let Frame { - mir: _, - instance, - span: _, - return_to_block, - return_place, - locals, - block, - stmt, - } = self; - - // Some of these are constant during evaluation, but are included - // anyways for correctness. - *instance == other.instance - && *return_to_block == other.return_to_block - && *return_place == other.return_place - && *locals == other.locals - && *block == other.block - && *stmt == other.stmt - } -} +// Not using the macro because that does not support types depending on 'tcx +impl<'a, 'mir, 'tcx: 'mir> HashStable> for Frame<'mir, 'tcx> { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { -impl<'mir, 'tcx: 'mir> Hash for Frame<'mir, 'tcx> { - fn hash(&self, state: &mut H) { let Frame { - mir: _, + mir, instance, - span: _, + span, return_to_block, return_place, locals, @@ -159,114 +130,69 @@ impl<'mir, 'tcx: 'mir> Hash for Frame<'mir, 'tcx> { stmt, } = self; - instance.hash(state); - return_to_block.hash(state); - return_place.hash(state); - locals.hash(state); - block.hash(state); - stmt.hash(state); + (mir, instance, span, return_to_block).hash_stable(hcx, hasher); + (return_place, locals, block, stmt).hash_stable(hcx, hasher); } } -/// The virtual machine state during const-evaluation at a given point in time. -type EvalSnapshot<'a, 'mir, 'tcx, M> - = (M, Vec>, Memory<'a, 'mir, 'tcx, M>); - -pub(crate) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { - /// The set of all `EvalSnapshot` *hashes* observed by this detector. - /// - /// When a collision occurs in this table, we store the full snapshot in - /// `snapshots`. - hashes: FxHashSet, - - /// The set of all `EvalSnapshot`s observed by this detector. - /// - /// An `EvalSnapshot` will only be fully cloned once it has caused a - /// collision in `hashes`. As a result, the detector must observe at least - /// *two* full cycles of an infinite loop before it triggers. - snapshots: FxHashSet>, +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub enum StackPopCleanup { + /// Jump to the next block in the caller, or cause UB if None (that's a function + /// that may never return). + Goto(Option), + /// Just do nohing: Used by Main and for the box_alloc hook in miri. + /// `cleanup` says whether locals are deallocated. Static computation + /// wants them leaked to intern what they need (and just throw away + /// the entire `ecx` when it is done). + None { cleanup: bool }, } -impl<'a, 'mir, 'tcx, M> Default for InfiniteLoopDetector<'a, 'mir, 'tcx, M> - where M: Machine<'mir, 'tcx>, - 'tcx: 'a + 'mir, -{ - fn default() -> Self { - InfiniteLoopDetector { - hashes: FxHashSet::default(), - snapshots: FxHashSet::default(), +// Can't use the macro here because that does not support named enum fields. +impl<'a> HashStable> for StackPopCleanup { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) + { + mem::discriminant(self).hash_stable(hcx, hasher); + match self { + StackPopCleanup::Goto(ref block) => block.hash_stable(hcx, hasher), + StackPopCleanup::None { cleanup } => cleanup.hash_stable(hcx, hasher), } } } -impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M> - where M: Machine<'mir, 'tcx>, - 'tcx: 'a + 'mir, -{ - /// Returns `true` if the loop detector has not yet observed a snapshot. - pub fn is_empty(&self) -> bool { - self.hashes.is_empty() - } +// State of a local variable +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub enum LocalValue { + Dead, + // Mostly for convenience, we re-use the `Operand` type here. + // This is an optimization over just always having a pointer here; + // we can thus avoid doing an allocation when the local just stores + // immediate values *and* never has its address taken. + Live(Operand), +} - pub fn observe_and_analyze( - &mut self, - machine: &M, - stack: &Vec>, - memory: &Memory<'a, 'mir, 'tcx, M>, - ) -> EvalResult<'tcx, ()> { - let mut fx = FxHasher::default(); - // don't hash the memory, that takes too much time, just compare when you hit a collision - // should be rare enough - (machine, stack).hash(&mut fx); - let hash = fx.finish(); - - if self.hashes.insert(hash) { - // No collision - return Ok(()) +impl<'tcx> LocalValue { + pub fn access(&self) -> EvalResult<'tcx, &Operand> { + match self { + LocalValue::Dead => err!(DeadLocal), + LocalValue::Live(ref val) => Ok(val), } + } - if self.snapshots.insert((machine.clone(), stack.clone(), memory.clone())) { - // Spurious collision or first cycle - return Ok(()) + pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand> { + match self { + LocalValue::Dead => err!(DeadLocal), + LocalValue::Live(ref mut val) => Ok(val), } - - // Second cycle - Err(EvalErrorKind::InfiniteLoop.into()) } } -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub enum StackPopCleanup { - /// The stackframe existed to compute the initial value of a static/constant, make sure it - /// isn't modifyable afterwards in case of constants. - /// In case of `static mut`, mark the memory to ensure it's never marked as immutable through - /// references or deallocated - MarkStatic(Mutability), - /// A regular stackframe added due to a function call will need to get forwarded to the next - /// block - Goto(mir::BasicBlock), - /// The main function and diverging functions have nowhere to return to - None, -} - -#[derive(Copy, Clone, Debug)] -pub struct TyAndPacked<'tcx> { - pub ty: Ty<'tcx>, - pub packed: bool, -} - -#[derive(Copy, Clone, Debug)] -pub struct ValTy<'tcx> { - pub value: Value, - pub ty: Ty<'tcx>, -} - -impl<'tcx> ::std::ops::Deref for ValTy<'tcx> { - type Target = Value; - fn deref(&self) -> &Value { - &self.value - } -} +impl_stable_hash_for!(enum self::LocalValue { + Dead, + Live(x), +}); impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for &'a EvalContext<'a, 'mir, 'tcx, M> { #[inline] @@ -276,14 +202,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for &'a EvalContext<' } impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout - for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M> { + for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M> +{ #[inline] fn data_layout(&self) -> &layout::TargetDataLayout { &self.tcx.data_layout } } -impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasTyCtxt<'tcx> for &'a EvalContext<'a, 'mir, 'tcx, M> { +impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for &'a EvalContext<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx> +{ #[inline] fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { *self.tcx @@ -302,6 +231,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for &'a EvalContext<'a, 'm type Ty = Ty<'tcx>; type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>; + #[inline] fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { self.tcx.layout_of(self.param_env.and(ty)) .map_err(|layout| EvalErrorKind::Layout(layout).into()) @@ -342,19 +272,14 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M pub(crate) fn with_fresh_body R, R>(&mut self, f: F) -> R { let stack = mem::replace(&mut self.stack, Vec::new()); - let steps = mem::replace(&mut self.steps_since_detector_enabled, -STEPS_UNTIL_DETECTOR_ENABLED); + let steps = mem::replace(&mut self.steps_since_detector_enabled, + -STEPS_UNTIL_DETECTOR_ENABLED); let r = f(self); self.stack = stack; self.steps_since_detector_enabled = steps; r } - pub fn alloc_ptr(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Pointer> { - assert!(!layout.is_unsized(), "cannot alloc memory for unsized type"); - - self.memory.allocate(layout.size, layout.align, MemoryKind::Stack) - } - pub fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> { &self.memory } @@ -373,34 +298,35 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M self.stack.len() - 1 } - pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> { - let ptr = self.memory.allocate_bytes(s.as_bytes()); - Ok(Scalar::Ptr(ptr).to_value_with_len(s.len() as u64, self.tcx.tcx)) + /// Mark a storage as live, killing the previous content and returning it. + /// Remember to deallocate that! + pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, LocalValue> { + trace!("{:?} is now live", local); + + let layout = self.layout_of_local(self.cur_frame(), local)?; + let init = LocalValue::Live(self.uninit_operand(layout)?); + // StorageLive *always* kills the value that's currently stored + Ok(mem::replace(&mut self.frame_mut().locals[local], init)) } - pub fn const_to_value( - &mut self, - val: ConstValue<'tcx>, - ) -> EvalResult<'tcx, Value> { - match val { - ConstValue::Unevaluated(def_id, substs) => { - let instance = self.resolve(def_id, substs)?; - self.read_global_as_value(GlobalId { - instance, - promoted: None, - }) - } - ConstValue::ByRef(alloc, offset) => { - // FIXME: Allocate new AllocId for all constants inside - let id = self.memory.allocate_value(alloc.clone(), MemoryKind::Stack)?; - Ok(Value::ByRef(Pointer::new(id, offset).into(), alloc.align)) - }, - ConstValue::ScalarPair(a, b) => Ok(Value::ScalarPair(a, b)), - ConstValue::Scalar(val) => Ok(Value::Scalar(val)), - } + /// Returns the old value of the local. + /// Remember to deallocate that! + pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue { + trace!("{:?} is now dead", local); + + mem::replace(&mut self.frame_mut().locals[local], LocalValue::Dead) + } + + pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> { + let ptr = self.memory.allocate_static_bytes(s.as_bytes()); + Ok(Value::new_slice(Scalar::Ptr(ptr), s.len() as u64, self.tcx.tcx)) } - pub(super) fn resolve(&self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, ty::Instance<'tcx>> { + pub(super) fn resolve( + &self, + def_id: DefId, + substs: &'tcx Substs<'tcx> + ) -> EvalResult<'tcx, ty::Instance<'tcx>> { trace!("resolve: {:?}, {:#?}", def_id, substs); trace!("substs: {:#?}", self.substs()); trace!("param_env: {:#?}", self.param_env); @@ -427,7 +353,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M ) -> EvalResult<'tcx, &'tcx mir::Mir<'tcx>> { // do not continue if typeck errors occurred (can only occur in local crate) let did = instance.def_id(); - if did.is_local() && self.tcx.has_typeck_tables(did) && self.tcx.typeck_tables_of(did).tainted_by_errors { + if did.is_local() + && self.tcx.has_typeck_tables(did) + && self.tcx.typeck_tables_of(did).tainted_by_errors + { return err!(TypeckError); } trace!("load mir {:?}", instance); @@ -441,105 +370,153 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } } - pub fn monomorphize(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { + pub fn monomorphize + Subst<'tcx>>( + &self, + t: T, + substs: &'tcx Substs<'tcx> + ) -> T { // miri doesn't care about lifetimes, and will choke on some crazy ones // let's simply get rid of them - let substituted = ty.subst(*self.tcx, substs); + let substituted = t.subst(*self.tcx, substs); self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted) } - /// Return the size and aligment of the value at the given type. - /// Note that the value does not matter if the type is sized. For unsized types, - /// the value has to be a fat pointer, and we only care about the "extra" data in it. - pub fn size_and_align_of_dst( - &mut self, - ty: Ty<'tcx>, - value: Value, + pub fn layout_of_local( + &self, + frame: usize, + local: mir::Local + ) -> EvalResult<'tcx, TyLayout<'tcx>> { + let local_ty = self.stack[frame].mir.local_decls[local].ty; + let local_ty = self.monomorphize( + local_ty, + self.stack[frame].instance.substs + ); + self.layout_of(local_ty) + } + + /// Return the actual dynamic size and alignment of the place at the given type. + /// Only the "extra" (metadata) part of the place matters. + pub(super) fn size_and_align_of( + &self, + metadata: Option, + layout: TyLayout<'tcx>, ) -> EvalResult<'tcx, (Size, Align)> { - let layout = self.layout_of(ty)?; - if !layout.is_unsized() { - Ok(layout.size_and_align()) - } else { - match ty.sty { - ty::TyAdt(..) | ty::TyTuple(..) => { - // First get the size of all statically known fields. - // Don't use type_of::sizing_type_of because that expects t to be sized, - // and it also rounds up to alignment, which we want to avoid, - // as the unsized field's alignment could be smaller. - assert!(!ty.is_simd()); - debug!("DST {} layout: {:?}", ty, layout); - - let sized_size = layout.fields.offset(layout.fields.count() - 1); - let sized_align = layout.align; - debug!( - "DST {} statically sized prefix size: {:?} align: {:?}", - ty, - sized_size, - sized_align - ); - - // Recurse to get the size of the dynamically sized field (must be - // the last field). - let field_ty = layout.field(&self, layout.fields.count() - 1)?.ty; - let (unsized_size, unsized_align) = - self.size_and_align_of_dst(field_ty, value)?; - - // FIXME (#26403, #27023): We should be adding padding - // to `sized_size` (to accommodate the `unsized_align` - // required of the unsized field that follows) before - // summing it with `sized_size`. (Note that since #26403 - // is unfixed, we do not yet add the necessary padding - // here. But this is where the add would go.) - - // Return the sum of sizes and max of aligns. - let size = sized_size + unsized_size; - - // Choose max of two known alignments (combined value must - // be aligned according to more restrictive of the two). - let align = sized_align.max(unsized_align); - - // Issue #27023: must add any necessary padding to `size` - // (to make it a multiple of `align`) before returning it. - // - // Namely, the returned size should be, in C notation: - // - // `size + ((size & (align-1)) ? align : 0)` - // - // emulated via the semi-standard fast bit trick: - // - // `(size + (align-1)) & -align` - - Ok((size.abi_align(align), align)) - } - ty::TyDynamic(..) => { - let (_, vtable) = self.into_ptr_vtable_pair(value)?; - // the second entry in the vtable is the dynamic size of the object. - self.read_size_and_align_from_vtable(vtable) - } + let metadata = match metadata { + None => { + assert!(!layout.is_unsized()); + return Ok(layout.size_and_align()) + } + Some(metadata) => { + assert!(layout.is_unsized()); + metadata + } + }; + match layout.ty.sty { + ty::Adt(..) | ty::Tuple(..) => { + // First get the size of all statically known fields. + // Don't use type_of::sizing_type_of because that expects t to be sized, + // and it also rounds up to alignment, which we want to avoid, + // as the unsized field's alignment could be smaller. + assert!(!layout.ty.is_simd()); + debug!("DST layout: {:?}", layout); + + let sized_size = layout.fields.offset(layout.fields.count() - 1); + let sized_align = layout.align; + debug!( + "DST {} statically sized prefix size: {:?} align: {:?}", + layout.ty, + sized_size, + sized_align + ); - ty::TySlice(_) | ty::TyStr => { - let (elem_size, align) = layout.field(&self, 0)?.size_and_align(); - let (_, len) = self.into_slice(value)?; - Ok((elem_size * len, align)) - } + // Recurse to get the size of the dynamically sized field (must be + // the last field). + let field = layout.field(self, layout.fields.count() - 1)?; + let (unsized_size, unsized_align) = self.size_and_align_of(Some(metadata), field)?; + + // FIXME (#26403, #27023): We should be adding padding + // to `sized_size` (to accommodate the `unsized_align` + // required of the unsized field that follows) before + // summing it with `sized_size`. (Note that since #26403 + // is unfixed, we do not yet add the necessary padding + // here. But this is where the add would go.) + + // Return the sum of sizes and max of aligns. + let size = sized_size + unsized_size; + + // Choose max of two known alignments (combined value must + // be aligned according to more restrictive of the two). + let align = sized_align.max(unsized_align); + + // Issue #27023: must add any necessary padding to `size` + // (to make it a multiple of `align`) before returning it. + // + // Namely, the returned size should be, in C notation: + // + // `size + ((size & (align-1)) ? align : 0)` + // + // emulated via the semi-standard fast bit trick: + // + // `(size + (align-1)) & -align` - _ => bug!("size_of_val::<{:?}>", ty), + Ok((size.abi_align(align), align)) } + ty::Dynamic(..) => { + let vtable = metadata.to_ptr()?; + // the second entry in the vtable is the dynamic size of the object. + self.read_size_and_align_from_vtable(vtable) + } + + ty::Slice(_) | ty::Str => { + let len = metadata.to_usize(self)?; + let (elem_size, align) = layout.field(self, 0)?.size_and_align(); + Ok((elem_size * len, align)) + } + + _ => bug!("size_and_align_of::<{:?}> not supported", layout.ty), } } + #[inline] + pub fn size_and_align_of_mplace( + &self, + mplace: MPlaceTy<'tcx> + ) -> EvalResult<'tcx, (Size, Align)> { + self.size_and_align_of(mplace.extra, mplace.layout) + } pub fn push_stack_frame( &mut self, instance: ty::Instance<'tcx>, - span: codemap::Span, + span: source_map::Span, mir: &'mir mir::Mir<'tcx>, return_place: Place, return_to_block: StackPopCleanup, ) -> EvalResult<'tcx> { ::log_settings::settings().indentation += 1; - let locals = if mir.local_decls.len() > 1 { - let mut locals = IndexVec::from_elem(Some(Value::Scalar(Scalar::undef())), &mir.local_decls); + // first push a stack frame so we have access to the local substs + self.stack.push(Frame { + mir, + block: mir::START_BLOCK, + return_to_block, + return_place, + // empty local array, we fill it in below, after we are inside the stack frame and + // all methods actually know about the frame + locals: IndexVec::new(), + span, + instance, + stmt: 0, + }); + + // don't allocate at all for trivial constants + if mir.local_decls.len() > 1 { + // We put some marker value into the locals that we later want to initialize. + // This can be anything except for LocalValue::Dead -- because *that* is the + // value we use for things that we know are initially dead. + let dummy = + LocalValue::Live(Operand::Immediate(Value::Scalar(ScalarMaybeUndef::Undef))); + let mut locals = IndexVec::from_elem(dummy, &mir.local_decls); + // Now mark those locals as dead that we do not want to initialize match self.tcx.describe_def(instance.def_id()) { // statics and constants don't have `Storage*` statements, no need to look for them Some(Def::Static(..)) | Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {}, @@ -550,31 +527,31 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M use rustc::mir::StatementKind::{StorageDead, StorageLive}; match stmt.kind { StorageLive(local) | - StorageDead(local) => locals[local] = None, + StorageDead(local) => { + locals[local] = LocalValue::Dead; + } _ => {} } } } }, } - locals - } else { - // don't allocate at all for trivial constants - IndexVec::new() - }; - - self.stack.push(Frame { - mir, - block: mir::START_BLOCK, - return_to_block, - return_place, - locals, - span, - instance, - stmt: 0, - }); - - self.memory.cur_frame = self.cur_frame(); + // Finally, properly initialize all those that still have the dummy value + for (local, decl) in locals.iter_mut().zip(mir.local_decls.iter()) { + match *local { + LocalValue::Live(_) => { + // This needs to be peoperly initialized. + let layout = self.layout_of(self.monomorphize(decl.ty, instance.substs))?; + *local = LocalValue::Live(self.uninit_operand(layout)?); + } + LocalValue::Dead => { + // Nothing to do + } + } + } + // done + self.frame_mut().locals = locals; + } if self.stack.len() > self.stack_limit { err!(StackFrameLimitReached) @@ -585,28 +562,19 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { ::log_settings::settings().indentation -= 1; - M::end_region(self, None)?; let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", ); - if !self.stack.is_empty() { - // TODO: Is this the correct time to start considering these accesses as originating from the returned-to stack frame? - self.memory.cur_frame = self.cur_frame(); - } match frame.return_to_block { - StackPopCleanup::MarkStatic(mutable) => { - if let Place::Ptr { ptr, .. } = frame.return_place { - // FIXME: to_ptr()? might be too extreme here, static zsts might reach this under certain conditions - self.memory.mark_static_initialized( - ptr.to_ptr()?.alloc_id, - mutable, - )? - } else { - bug!("StackPopCleanup::MarkStatic on: {:?}", frame.return_place); + StackPopCleanup::Goto(block) => { + self.goto_block(block)?; + } + StackPopCleanup::None { cleanup } => { + if !cleanup { + // Leak the locals + return Ok(()); } } - StackPopCleanup::Goto(target) => self.goto_block(target), - StackPopCleanup::None => {} } // deallocate all locals that are backed by an allocation for local in frame.locals { @@ -616,8 +584,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M Ok(()) } - pub fn deallocate_local(&mut self, local: Option) -> EvalResult<'tcx> { - if let Some(Value::ByRef(ptr, _align)) = local { + pub(super) fn deallocate_local(&mut self, local: LocalValue) -> EvalResult<'tcx> { + // FIXME: should we tell the user that there was a local which was never written to? + if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local { trace!("deallocating local"); let ptr = ptr.to_ptr()?; self.memory.dump_alloc(ptr.alloc_id); @@ -626,942 +595,22 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M Ok(()) } - /// Evaluate an assignment statement. - /// - /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue - /// type writes its results directly into the memory specified by the place. - pub(super) fn eval_rvalue_into_place( - &mut self, - rvalue: &mir::Rvalue<'tcx>, - place: &mir::Place<'tcx>, - ) -> EvalResult<'tcx> { - let dest = self.eval_place(place)?; - let dest_ty = self.place_ty(place); - - use rustc::mir::Rvalue::*; - match *rvalue { - Use(ref operand) => { - let value = self.eval_operand(operand)?.value; - let valty = ValTy { - value, - ty: dest_ty, - }; - self.write_value(valty, dest)?; - } - - BinaryOp(bin_op, ref left, ref right) => { - let left = self.eval_operand(left)?; - let right = self.eval_operand(right)?; - self.intrinsic_overflowing( - bin_op, - left, - right, - dest, - dest_ty, - )?; - } - - CheckedBinaryOp(bin_op, ref left, ref right) => { - let left = self.eval_operand(left)?; - let right = self.eval_operand(right)?; - self.intrinsic_with_overflow( - bin_op, - left, - right, - dest, - dest_ty, - )?; - } - - UnaryOp(un_op, ref operand) => { - let val = self.eval_operand_to_scalar(operand)?; - let val = self.unary_op(un_op, val, dest_ty)?; - self.write_scalar( - dest, - val, - dest_ty, - )?; - } - - Aggregate(ref kind, ref operands) => { - let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => { - self.write_discriminant_value(dest_ty, dest, variant_index)?; - if adt_def.is_enum() { - (self.place_downcast(dest, variant_index)?, active_field_index) - } else { - (dest, active_field_index) - } - } - _ => (dest, None) - }; - - let layout = self.layout_of(dest_ty)?; - for (i, operand) in operands.iter().enumerate() { - let value = self.eval_operand(operand)?; - // Ignore zero-sized fields. - if !self.layout_of(value.ty)?.is_zst() { - let field_index = active_field_index.unwrap_or(i); - let (field_dest, _) = self.place_field(dest, mir::Field::new(field_index), layout)?; - self.write_value(value, field_dest)?; - } - } - } - - Repeat(ref operand, _) => { - let (elem_ty, length) = match dest_ty.sty { - ty::TyArray(elem_ty, n) => (elem_ty, n.unwrap_usize(self.tcx.tcx)), - _ => { - bug!( - "tried to assign array-repeat to non-array type {:?}", - dest_ty - ) - } - }; - let elem_size = self.layout_of(elem_ty)?.size; - let value = self.eval_operand(operand)?.value; - - let (dest, dest_align) = self.force_allocation(dest)?.to_ptr_align(); - - if length > 0 { - //write the first value - self.write_value_to_ptr(value, dest, dest_align, elem_ty)?; - - if length > 1 { - let rest = dest.ptr_offset(elem_size * 1 as u64, &self)?; - self.memory.copy_repeatedly(dest, dest_align, rest, dest_align, elem_size, length - 1, false)?; - } - } - } - - Len(ref place) => { - // FIXME(CTFE): don't allow computing the length of arrays in const eval - let src = self.eval_place(place)?; - let ty = self.place_ty(place); - let (_, len) = src.elem_ty_and_len(ty, self.tcx.tcx); - let defined = self.memory.pointer_size().bits() as u8; - self.write_scalar( - dest, - Scalar::Bits { - bits: len as u128, - defined, - }, - dest_ty, - )?; - } - - Ref(_, _, ref place) => { - let src = self.eval_place(place)?; - // We ignore the alignment of the place here -- special handling for packed structs ends - // at the `&` operator. - let (ptr, _align, extra) = self.force_allocation(src)?.to_ptr_align_extra(); - - let val = match extra { - PlaceExtra::None => ptr.to_value(), - PlaceExtra::Length(len) => ptr.to_value_with_len(len, self.tcx.tcx), - PlaceExtra::Vtable(vtable) => ptr.to_value_with_vtable(vtable), - PlaceExtra::DowncastVariant(..) => { - bug!("attempted to take a reference to an enum downcast place") - } - }; - let valty = ValTy { - value: val, - ty: dest_ty, - }; - self.write_value(valty, dest)?; - } - - NullaryOp(mir::NullOp::Box, ty) => { - let ty = self.monomorphize(ty, self.substs()); - M::box_alloc(self, ty, dest)?; - } - - NullaryOp(mir::NullOp::SizeOf, ty) => { - let ty = self.monomorphize(ty, self.substs()); - let layout = self.layout_of(ty)?; - assert!(!layout.is_unsized(), - "SizeOf nullary MIR operator called for unsized type"); - let defined = self.memory.pointer_size().bits() as u8; - self.write_scalar( - dest, - Scalar::Bits { - bits: layout.size.bytes() as u128, - defined, - }, - dest_ty, - )?; - } - - Cast(kind, ref operand, cast_ty) => { - debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest_ty); - let src = self.eval_operand(operand)?; - self.cast(src, kind, dest_ty, dest)?; - } - - Discriminant(ref place) => { - let ty = self.place_ty(place); - let layout = self.layout_of(ty)?; - let place = self.eval_place(place)?; - let discr_val = self.read_discriminant_value(place, layout)?; - let defined = self.layout_of(dest_ty).unwrap().size.bits() as u8; - self.write_scalar(dest, Scalar::Bits { - bits: discr_val, - defined, - }, dest_ty)?; - } - } - - self.dump_local(dest); - - Ok(()) - } - - pub(super) fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty::TyRawPtr(ty::TypeAndMut { ty, .. }) | - ty::TyRef(_, ty, _) => !self.type_is_sized(ty), - ty::TyAdt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()), - _ => false, - } - } - - pub(super) fn eval_operand_to_scalar( - &mut self, - op: &mir::Operand<'tcx>, - ) -> EvalResult<'tcx, Scalar> { - let valty = self.eval_operand(op)?; - self.value_to_scalar(valty) - } - - pub(crate) fn operands_to_args( - &mut self, - ops: &[mir::Operand<'tcx>], - ) -> EvalResult<'tcx, Vec>> { - ops.into_iter() - .map(|op| self.eval_operand(op)) - .collect() - } - - pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> { - use rustc::mir::Operand::*; - let ty = self.monomorphize(op.ty(self.mir(), *self.tcx), self.substs()); - match *op { - // FIXME: do some more logic on `move` to invalidate the old location - Copy(ref place) | - Move(ref place) => { - Ok(ValTy { - value: self.eval_and_read_place(place)?, - ty - }) - }, - - Constant(ref constant) => { - let value = self.const_to_value(constant.literal.val)?; - - Ok(ValTy { - value, - ty, - }) - } - } - } - - /// reads a tag and produces the corresponding variant index - pub fn read_discriminant_as_variant_index( - &self, - place: Place, - layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx, usize> { - match layout.variants { - ty::layout::Variants::Single { index } => Ok(index), - ty::layout::Variants::Tagged { .. } => { - let discr_val = self.read_discriminant_value(place, layout)?; - layout - .ty - .ty_adt_def() - .expect("tagged layout for non adt") - .discriminants(self.tcx.tcx) - .position(|var| var.val == discr_val) - .ok_or_else(|| EvalErrorKind::InvalidDiscriminant.into()) - } - ty::layout::Variants::NicheFilling { .. } => { - let discr_val = self.read_discriminant_value(place, layout)?; - assert_eq!(discr_val as usize as u128, discr_val); - Ok(discr_val as usize) - }, - } - } - - pub fn read_discriminant_value( - &self, - place: Place, - layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx, u128> { - trace!("read_discriminant_value {:#?}", layout); - if layout.abi == layout::Abi::Uninhabited { - return Ok(0); - } - - match layout.variants { - layout::Variants::Single { index } => { - let discr_val = layout.ty.ty_adt_def().map_or( - index as u128, - |def| def.discriminant_for_variant(*self.tcx, index).val); - return Ok(discr_val); - } - layout::Variants::Tagged { .. } | - layout::Variants::NicheFilling { .. } => {}, - } - let discr_place_val = self.read_place(place)?; - let (discr_val, discr) = self.read_field(discr_place_val, None, mir::Field::new(0), layout)?; - trace!("discr value: {:?}, {:?}", discr_val, discr); - let raw_discr = self.value_to_scalar(ValTy { - value: discr_val, - ty: discr.ty - })?; - let discr_val = match layout.variants { - layout::Variants::Single { .. } => bug!(), - // FIXME: should we catch invalid discriminants here? - layout::Variants::Tagged { .. } => { - if discr.ty.is_signed() { - let i = raw_discr.to_bits(discr.size)? as i128; - // going from layout tag type to typeck discriminant type - // requires first sign extending with the layout discriminant - let shift = 128 - discr.size.bits(); - let sexted = (i << shift) >> shift; - // and then zeroing with the typeck discriminant type - let discr_ty = layout - .ty - .ty_adt_def().expect("tagged layout corresponds to adt") - .repr - .discr_type(); - let discr_ty = layout::Integer::from_attr(self.tcx.tcx, discr_ty); - let shift = 128 - discr_ty.size().bits(); - let truncatee = sexted as u128; - (truncatee << shift) >> shift - } else { - raw_discr.to_bits(discr.size)? - } - }, - layout::Variants::NicheFilling { - dataful_variant, - ref niche_variants, - niche_start, - .. - } => { - let variants_start = *niche_variants.start() as u128; - let variants_end = *niche_variants.end() as u128; - match raw_discr { - Scalar::Ptr(_) => { - assert!(niche_start == 0); - assert!(variants_start == variants_end); - dataful_variant as u128 - }, - Scalar::Bits { bits: raw_discr, defined } => { - if defined < discr.size.bits() as u8 { - return err!(ReadUndefBytes); - } - let discr = raw_discr.wrapping_sub(niche_start) - .wrapping_add(variants_start); - if variants_start <= discr && discr <= variants_end { - discr - } else { - dataful_variant as u128 - } - }, - } - } - }; - - Ok(discr_val) - } - - - pub fn write_discriminant_value( - &mut self, - dest_ty: Ty<'tcx>, - dest: Place, - variant_index: usize, - ) -> EvalResult<'tcx> { - let layout = self.layout_of(dest_ty)?; - - match layout.variants { - layout::Variants::Single { index } => { - if index != variant_index { - // If the layout of an enum is `Single`, all - // other variants are necessarily uninhabited. - assert_eq!(layout.for_variant(&self, variant_index).abi, - layout::Abi::Uninhabited); - } - } - layout::Variants::Tagged { ref tag, .. } => { - let discr_val = dest_ty.ty_adt_def().unwrap() - .discriminant_for_variant(*self.tcx, variant_index) - .val; - - // raw discriminants for enums are isize or bigger during - // their computation, but the in-memory tag is the smallest possible - // representation - let size = tag.value.size(self.tcx.tcx).bits(); - let shift = 128 - size; - let discr_val = (discr_val << shift) >> shift; - - let (discr_dest, tag) = self.place_field(dest, mir::Field::new(0), layout)?; - self.write_scalar(discr_dest, Scalar::Bits { - bits: discr_val, - defined: size as u8, - }, tag.ty)?; - } - layout::Variants::NicheFilling { - dataful_variant, - ref niche_variants, - niche_start, - .. - } => { - if variant_index != dataful_variant { - let (niche_dest, niche) = - self.place_field(dest, mir::Field::new(0), layout)?; - let niche_value = ((variant_index - niche_variants.start()) as u128) - .wrapping_add(niche_start); - self.write_scalar(niche_dest, Scalar::Bits { - bits: niche_value, - defined: niche.size.bits() as u8, - }, niche.ty)?; - } - } - } - - Ok(()) - } - - pub fn read_global_as_value(&mut self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Value> { - let cv = self.const_eval(gid)?; - self.const_to_value(cv.val) - } - pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> { let param_env = if self.tcx.is_static(gid.instance.def_id()).is_some() { ty::ParamEnv::reveal_all() } else { self.param_env }; - self.tcx.const_eval(param_env.and(gid)).map_err(|err| EvalErrorKind::ReferencedConstant(err).into()) - } - - pub fn allocate_place_for_value( - &mut self, - value: Value, - layout: TyLayout<'tcx>, - variant: Option, - ) -> EvalResult<'tcx, Place> { - let (ptr, align) = match value { - Value::ByRef(ptr, align) => (ptr, align), - Value::ScalarPair(..) | Value::Scalar(_) => { - let ptr = self.alloc_ptr(layout)?.into(); - self.write_value_to_ptr(value, ptr, layout.align, layout.ty)?; - (ptr, layout.align) - }, - }; - Ok(Place::Ptr { - ptr, - align, - extra: variant.map_or(PlaceExtra::None, PlaceExtra::DowncastVariant), - }) - } - - pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> { - let new_place = match place { - Place::Local { frame, local } => { - match self.stack[frame].locals[local] { - None => return err!(DeadLocal), - Some(Value::ByRef(ptr, align)) => { - Place::Ptr { - ptr, - align, - extra: PlaceExtra::None, - } - } - Some(val) => { - let ty = self.stack[frame].mir.local_decls[local].ty; - let ty = self.monomorphize(ty, self.stack[frame].instance.substs); - let layout = self.layout_of(ty)?; - let ptr = self.alloc_ptr(layout)?; - self.stack[frame].locals[local] = - Some(Value::ByRef(ptr.into(), layout.align)); // it stays live - let place = Place::from_ptr(ptr, layout.align); - self.write_value(ValTy { value: val, ty }, place)?; - place - } - } - } - Place::Ptr { .. } => place, - }; - Ok(new_place) - } - - /// ensures this Value is not a ByRef - pub fn follow_by_ref_value( - &self, - value: Value, - ty: Ty<'tcx>, - ) -> EvalResult<'tcx, Value> { - match value { - Value::ByRef(ptr, align) => { - self.read_value(ptr, align, ty) - } - other => Ok(other), - } - } - - pub fn value_to_scalar( - &self, - ValTy { value, ty } : ValTy<'tcx>, - ) -> EvalResult<'tcx, Scalar> { - match self.follow_by_ref_value(value, ty)? { - Value::ByRef { .. } => bug!("follow_by_ref_value can't result in `ByRef`"), - - Value::Scalar(scalar) => Ok(scalar), - - Value::ScalarPair(..) => bug!("value_to_scalar can't work with fat pointers"), - } - } - - pub fn write_ptr(&mut self, dest: Place, val: Scalar, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> { - let valty = ValTy { - value: val.to_value(), - ty: dest_ty, - }; - self.write_value(valty, dest) - } - - pub fn write_scalar( - &mut self, - dest: Place, - val: Scalar, - dest_ty: Ty<'tcx>, - ) -> EvalResult<'tcx> { - let valty = ValTy { - value: Value::Scalar(val), - ty: dest_ty, - }; - self.write_value(valty, dest) - } - - pub fn write_value( - &mut self, - ValTy { value: src_val, ty: dest_ty } : ValTy<'tcx>, - dest: Place, - ) -> EvalResult<'tcx> { - //trace!("Writing {:?} to {:?} at type {:?}", src_val, dest, dest_ty); - // Note that it is really important that the type here is the right one, and matches the type things are read at. - // In case `src_val` is a `ScalarPair`, we don't do any magic here to handle padding properly, which is only - // correct if we never look at this data with the wrong type. - - match dest { - Place::Ptr { ptr, align, extra } => { - assert_eq!(extra, PlaceExtra::None); - self.write_value_to_ptr(src_val, ptr, align, dest_ty) - } - - Place::Local { frame, local } => { - let dest = self.stack[frame].get_local(local)?; - self.write_value_possibly_by_val( - src_val, - |this, val| this.stack[frame].set_local(local, val), - dest, - dest_ty, - ) - } - } - } - - // The cases here can be a bit subtle. Read carefully! - fn write_value_possibly_by_val EvalResult<'tcx>>( - &mut self, - src_val: Value, - write_dest: F, - old_dest_val: Value, - dest_ty: Ty<'tcx>, - ) -> EvalResult<'tcx> { - if let Value::ByRef(dest_ptr, align) = old_dest_val { - // If the value is already `ByRef` (that is, backed by an `Allocation`), - // then we must write the new value into this allocation, because there may be - // other pointers into the allocation. These other pointers are logically - // pointers into the local variable, and must be able to observe the change. - // - // Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we - // knew for certain that there were no outstanding pointers to this allocation. - self.write_value_to_ptr(src_val, dest_ptr, align, dest_ty)?; - } else if let Value::ByRef(src_ptr, align) = src_val { - // If the value is not `ByRef`, then we know there are no pointers to it - // and we can simply overwrite the `Value` in the locals array directly. - // - // In this specific case, where the source value is `ByRef`, we must duplicate - // the allocation, because this is a by-value operation. It would be incorrect - // if they referred to the same allocation, since then a change to one would - // implicitly change the other. - // - // It is a valid optimization to attempt reading a primitive value out of the - // source and write that into the destination without making an allocation, so - // we do so here. - if let Ok(Some(src_val)) = self.try_read_value(src_ptr, align, dest_ty) { - write_dest(self, src_val)?; - } else { - let layout = self.layout_of(dest_ty)?; - let dest_ptr = self.alloc_ptr(layout)?.into(); - self.memory.copy(src_ptr, align.min(layout.align), dest_ptr, layout.align, layout.size, false)?; - write_dest(self, Value::ByRef(dest_ptr, layout.align))?; - } - } else { - // Finally, we have the simple case where neither source nor destination are - // `ByRef`. We may simply copy the source value over the the destintion. - write_dest(self, src_val)?; - } - Ok(()) - } - - pub fn write_value_to_ptr( - &mut self, - value: Value, - dest: Scalar, - dest_align: Align, - dest_ty: Ty<'tcx>, - ) -> EvalResult<'tcx> { - let layout = self.layout_of(dest_ty)?; - trace!("write_value_to_ptr: {:#?}, {}, {:#?}", value, dest_ty, layout); - match value { - Value::ByRef(ptr, align) => { - self.memory.copy(ptr, align.min(layout.align), dest, dest_align.min(layout.align), layout.size, false) - } - Value::Scalar(scalar) => { - let signed = match layout.abi { - layout::Abi::Scalar(ref scal) => match scal.value { - layout::Primitive::Int(_, signed) => signed, - _ => false, - }, - _ => match scalar { - Scalar::Bits { defined: 0, .. } => false, - _ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout), - } - }; - self.memory.write_scalar(dest, dest_align, scalar, layout.size, signed) - } - Value::ScalarPair(a_val, b_val) => { - trace!("write_value_to_ptr valpair: {:#?}", layout); - let (a, b) = match layout.abi { - layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value), - _ => bug!("write_value_to_ptr: invalid ScalarPair layout: {:#?}", layout) - }; - let (a_size, b_size) = (a.size(&self), b.size(&self)); - let a_ptr = dest; - let b_offset = a_size.abi_align(b.align(&self)); - let b_ptr = dest.ptr_offset(b_offset, &self)?.into(); - // TODO: What about signedess? - self.memory.write_scalar(a_ptr, dest_align, a_val, a_size, false)?; - self.memory.write_scalar(b_ptr, dest_align, b_val, b_size, false) - } - } - } - - pub fn read_value(&self, ptr: Scalar, align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> { - if let Some(val) = self.try_read_value(ptr, align, ty)? { - Ok(val) - } else { - bug!("primitive read failed for type: {:?}", ty); - } - } - - pub(crate) fn read_ptr( - &self, - ptr: Pointer, - ptr_align: Align, - pointee_ty: Ty<'tcx>, - ) -> EvalResult<'tcx, Value> { - let ptr_size = self.memory.pointer_size(); - let p: Scalar = self.memory.read_ptr_sized(ptr, ptr_align)?.into(); - if self.type_is_sized(pointee_ty) { - Ok(p.to_value()) - } else { - trace!("reading fat pointer extra of type {}", pointee_ty); - let extra = ptr.offset(ptr_size, self)?; - match self.tcx.struct_tail(pointee_ty).sty { - ty::TyDynamic(..) => Ok(p.to_value_with_vtable( - self.memory.read_ptr_sized(extra, ptr_align)?.to_ptr()?, - )), - ty::TySlice(..) | ty::TyStr => { - let len = self - .memory - .read_ptr_sized(extra, ptr_align)? - .to_bits(ptr_size)?; - Ok(p.to_value_with_len(len as u64, self.tcx.tcx)) - }, - _ => bug!("unsized scalar ptr read from {:?}", pointee_ty), - } - } - } - - fn validate_scalar( - &self, - value: Scalar, - size: Size, - scalar: &layout::Scalar, - path: &str, - ty: Ty, - ) -> EvalResult<'tcx> { - trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty); - let (lo, hi) = scalar.valid_range.clone().into_inner(); - - let (bits, defined) = match value { - Scalar::Bits { bits, defined } => (bits, defined), - Scalar::Ptr(_) => { - let ptr_size = self.memory.pointer_size(); - let ptr_max = u128::max_value() >> (128 - ptr_size.bits()); - return if lo > hi { - if lo - hi == 1 { - // no gap, all values are ok - Ok(()) - } else if hi < ptr_max || lo > 1 { - let max = u128::max_value() >> (128 - size.bits()); - validation_failure!( - "pointer", - path, - format!("something in the range {:?} or {:?}", 0..=lo, hi..=max) - ) - } else { - Ok(()) - } - } else if hi < ptr_max || lo > 1 { - validation_failure!( - "pointer", - path, - format!("something in the range {:?}", scalar.valid_range) - ) - } else { - Ok(()) - }; - }, - }; - - // char gets a special treatment, because its number space is not contiguous so `TyLayout` - // has no special checks for chars - match ty.sty { - ty::TyChar => { - assert_eq!(size.bytes(), 4); - if ::std::char::from_u32(bits as u32).is_none() { - return err!(InvalidChar(bits)); - } - } - _ => {}, - } - - use std::ops::RangeInclusive; - let in_range = |bound: RangeInclusive| { - defined as u64 >= size.bits() && bound.contains(&bits) - }; - if lo > hi { - if in_range(0..=hi) || in_range(lo..=u128::max_value()) { - Ok(()) - } else if defined as u64 >= size.bits() { - validation_failure!( - bits, - path, - format!("something in the range {:?} or {:?}", ..=hi, lo..) - ) - } else { - validation_failure!("undefined bytes", path) - } - } else { - if in_range(scalar.valid_range.clone()) { - Ok(()) - } else if defined as u64 >= size.bits() { - validation_failure!( - bits, - path, - format!("something in the range {:?}", scalar.valid_range) - ) - } else { - validation_failure!("undefined bytes", path) - } - } - } - - /// This function checks the memory where `ptr` points to. - /// It will error if the bits at the destination do not match the ones described by the layout. - pub fn validate_ptr_target( - &self, - ptr: Pointer, - ptr_align: Align, - mut layout: TyLayout<'tcx>, - path: String, - seen: &mut FxHashSet<(Pointer, Ty<'tcx>)>, - todo: &mut Vec<(Pointer, Ty<'tcx>, String)>, - ) -> EvalResult<'tcx> { - self.memory.dump_alloc(ptr.alloc_id); - trace!("validate_ptr_target: {:?}, {:#?}", ptr, layout); - - let variant; - match layout.variants { - layout::Variants::NicheFilling { niche: ref tag, .. } | - layout::Variants::Tagged { ref tag, .. } => { - let size = tag.value.size(self); - let (tag_value, tag_layout) = self.read_field( - Value::ByRef(ptr.into(), ptr_align), - None, - mir::Field::new(0), - layout, - )?; - let tag_value = self.value_to_scalar(ValTy { - value: tag_value, - ty: tag_layout.ty, - })?; - let path = format!("{}.TAG", path); - self.validate_scalar(tag_value, size, tag, &path, tag_layout.ty)?; - let variant_index = self.read_discriminant_as_variant_index( - Place::from_ptr(ptr, ptr_align), - layout, - )?; - variant = variant_index; - layout = layout.for_variant(self, variant_index); - trace!("variant layout: {:#?}", layout); - }, - layout::Variants::Single { index } => variant = index, - } - match layout.fields { - // primitives are unions with zero fields - layout::FieldPlacement::Union(0) => { - match layout.abi { - // nothing to do, whatever the pointer points to, it is never going to be read - layout::Abi::Uninhabited => validation_failure!("a value of an uninhabited type", path), - // check that the scalar is a valid pointer or that its bit range matches the - // expectation. - layout::Abi::Scalar(ref scalar) => { - let size = scalar.value.size(self); - let value = self.memory.read_scalar(ptr, ptr_align, size)?; - self.validate_scalar(value, size, scalar, &path, layout.ty)?; - if scalar.value == Primitive::Pointer { - // ignore integer pointers, we can't reason about the final hardware - if let Scalar::Ptr(ptr) = value { - let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id); - if let Some(AllocType::Static(did)) = alloc_kind { - // statics from other crates are already checked - // extern statics should not be validated as they have no body - if !did.is_local() || self.tcx.is_foreign_item(did) { - return Ok(()); - } - } - if let Some(tam) = layout.ty.builtin_deref(false) { - // we have not encountered this pointer+layout combination before - if seen.insert((ptr, tam.ty)) { - todo.push((ptr, tam.ty, format!("(*{})", path))) - } - } - } - } - Ok(()) - }, - _ => bug!("bad abi for FieldPlacement::Union(0): {:#?}", layout.abi), - } - } - layout::FieldPlacement::Union(_) => { - // We can't check unions, their bits are allowed to be anything. - // The fields don't need to correspond to any bit pattern of the union's fields. - // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389 - Ok(()) - }, - layout::FieldPlacement::Array { stride, count } => { - let elem_layout = layout.field(self, 0)?; - for i in 0..count { - let mut path = path.clone(); - self.write_field_name(&mut path, layout.ty, i as usize, variant).unwrap(); - self.validate_ptr_target(ptr.offset(stride * i, self)?, ptr_align, elem_layout, path, seen, todo)?; - } - Ok(()) - }, - layout::FieldPlacement::Arbitrary { ref offsets, .. } => { - - // check length field and vtable field - match layout.ty.builtin_deref(false).map(|tam| &tam.ty.sty) { - | Some(ty::TyStr) - | Some(ty::TySlice(_)) => { - let (len, len_layout) = self.read_field( - Value::ByRef(ptr.into(), ptr_align), - None, - mir::Field::new(1), - layout, - )?; - let len = self.value_to_scalar(ValTy { value: len, ty: len_layout.ty })?; - if len.to_bits(len_layout.size).is_err() { - return validation_failure!("length is not a valid integer", path); - } - }, - Some(ty::TyDynamic(..)) => { - let (vtable, vtable_layout) = self.read_field( - Value::ByRef(ptr.into(), ptr_align), - None, - mir::Field::new(1), - layout, - )?; - let vtable = self.value_to_scalar(ValTy { value: vtable, ty: vtable_layout.ty })?; - if vtable.to_ptr().is_err() { - return validation_failure!("vtable address is not a pointer", path); - } - } - _ => {}, - } - for (i, &offset) in offsets.iter().enumerate() { - let field_layout = layout.field(self, i)?; - let mut path = path.clone(); - self.write_field_name(&mut path, layout.ty, i, variant).unwrap(); - self.validate_ptr_target(ptr.offset(offset, self)?, ptr_align, field_layout, path, seen, todo)?; - } - Ok(()) - } - } - } - - pub fn try_read_by_ref(&self, mut val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> { - // Convert to ByVal or ScalarPair if possible - if let Value::ByRef(ptr, align) = val { - if let Some(read_val) = self.try_read_value(ptr, align, ty)? { - val = read_val; - } - } - Ok(val) - } - - pub fn try_read_value(&self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option> { - let layout = self.layout_of(ty)?; - self.memory.check_align(ptr, ptr_align)?; - - if layout.size.bytes() == 0 { - return Ok(Some(Value::Scalar(Scalar::undef()))); - } - - let ptr = ptr.to_ptr()?; - - match layout.abi { - layout::Abi::Scalar(..) => { - let scalar = self.memory.read_scalar(ptr, ptr_align, layout.size)?; - Ok(Some(Value::Scalar(scalar))) - } - layout::Abi::ScalarPair(ref a, ref b) => { - let (a, b) = (&a.value, &b.value); - let (a_size, b_size) = (a.size(self), b.size(self)); - let a_ptr = ptr; - let b_offset = a_size.abi_align(b.align(self)); - let b_ptr = ptr.offset(b_offset, self)?.into(); - let a_val = self.memory.read_scalar(a_ptr, ptr_align, a_size)?; - let b_val = self.memory.read_scalar(b_ptr, ptr_align, b_size)?; - Ok(Some(Value::ScalarPair(a_val, b_val))) - } - _ => Ok(None), - } + self.tcx.const_eval(param_env.and(gid)) + .map_err(|err| EvalErrorKind::ReferencedConstant(err).into()) } + #[inline(always)] pub fn frame(&self) -> &Frame<'mir, 'tcx> { self.stack.last().expect("no call frames exist") } + #[inline(always)] pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx> { self.stack.last_mut().expect("no call frames exist") } @@ -1578,132 +627,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } } - fn unsize_into_ptr( - &mut self, - src: Value, - src_ty: Ty<'tcx>, - dest: Place, - dest_ty: Ty<'tcx>, - sty: Ty<'tcx>, - dty: Ty<'tcx>, - ) -> EvalResult<'tcx> { - // A -> A conversion - let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(sty, dty); - - match (&src_pointee_ty.sty, &dest_pointee_ty.sty) { - (&ty::TyArray(_, length), &ty::TySlice(_)) => { - let ptr = self.into_ptr(src)?; - // u64 cast is from usize to u64, which is always good - let valty = ValTy { - value: ptr.to_value_with_len(length.unwrap_usize(self.tcx.tcx), self.tcx.tcx), - ty: dest_ty, - }; - self.write_value(valty, dest) - } - (&ty::TyDynamic(..), &ty::TyDynamic(..)) => { - // For now, upcasts are limited to changes in marker - // traits, and hence never actually require an actual - // change to the vtable. - let valty = ValTy { - value: src, - ty: dest_ty, - }; - self.write_value(valty, dest) - } - (_, &ty::TyDynamic(ref data, _)) => { - let trait_ref = data.principal().unwrap().with_self_ty( - *self.tcx, - src_pointee_ty, - ); - let trait_ref = self.tcx.erase_regions(&trait_ref); - let vtable = self.get_vtable(src_pointee_ty, trait_ref)?; - let ptr = self.into_ptr(src)?; - let valty = ValTy { - value: ptr.to_value_with_vtable(vtable), - ty: dest_ty, - }; - self.write_value(valty, dest) - } - - _ => bug!("invalid unsizing {:?} -> {:?}", src_ty, dest_ty), - } - } - - crate fn unsize_into( - &mut self, - src: Value, - src_layout: TyLayout<'tcx>, - dst: Place, - dst_layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx> { - match (&src_layout.ty.sty, &dst_layout.ty.sty) { - (&ty::TyRef(_, s, _), &ty::TyRef(_, d, _)) | - (&ty::TyRef(_, s, _), &ty::TyRawPtr(TypeAndMut { ty: d, .. })) | - (&ty::TyRawPtr(TypeAndMut { ty: s, .. }), - &ty::TyRawPtr(TypeAndMut { ty: d, .. })) => { - self.unsize_into_ptr(src, src_layout.ty, dst, dst_layout.ty, s, d) - } - (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => { - assert_eq!(def_a, def_b); - if def_a.is_box() || def_b.is_box() { - if !def_a.is_box() || !def_b.is_box() { - bug!("invalid unsizing between {:?} -> {:?}", src_layout, dst_layout); - } - return self.unsize_into_ptr( - src, - src_layout.ty, - dst, - dst_layout.ty, - src_layout.ty.boxed_ty(), - dst_layout.ty.boxed_ty(), - ); - } - - // unsizing of generic struct with pointer fields - // Example: `Arc` -> `Arc` - // here we need to increase the size of every &T thin ptr field to a fat ptr - for i in 0..src_layout.fields.count() { - let (dst_f_place, dst_field) = - self.place_field(dst, mir::Field::new(i), dst_layout)?; - if dst_field.is_zst() { - continue; - } - let (src_f_value, src_field) = match src { - Value::ByRef(ptr, align) => { - let src_place = Place::from_scalar_ptr(ptr, align); - let (src_f_place, src_field) = - self.place_field(src_place, mir::Field::new(i), src_layout)?; - (self.read_place(src_f_place)?, src_field) - } - Value::Scalar(_) | Value::ScalarPair(..) => { - let src_field = src_layout.field(&self, i)?; - assert_eq!(src_layout.fields.offset(i).bytes(), 0); - assert_eq!(src_field.size, src_layout.size); - (src, src_field) - } - }; - if src_field.ty == dst_field.ty { - self.write_value(ValTy { - value: src_f_value, - ty: src_field.ty, - }, dst_f_place)?; - } else { - self.unsize_into(src_f_value, src_field, dst_f_place, dst_field)?; - } - } - Ok(()) - } - _ => { - bug!( - "unsize_into: invalid conversion: {:?} -> {:?}", - src_layout, - dst_layout - ) - } - } - } - - pub fn dump_local(&self, place: Place) { + pub fn dump_place(&self, place: Place) { // Debug output if !log_enabled!(::log::Level::Trace) { return; @@ -1717,7 +641,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } write!(msg, ":").unwrap(); - match self.stack[frame].get_local(local) { + match self.stack[frame].locals[local].access() { Err(err) => { if let EvalErrorKind::DeadLocal = err.kind { write!(msg, " is dead").unwrap(); @@ -1725,27 +649,28 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M panic!("Failed to access local: {:?}", err); } } - Ok(Value::ByRef(ptr, align)) => { + Ok(Operand::Indirect(mplace)) => { + let (ptr, align) = mplace.to_scalar_ptr_align(); match ptr { Scalar::Ptr(ptr) => { write!(msg, " by align({}) ref:", align.abi()).unwrap(); allocs.push(ptr.alloc_id); } - ptr => write!(msg, " integral by ref: {:?}", ptr).unwrap(), + ptr => write!(msg, " by integral ref: {:?}", ptr).unwrap(), } } - Ok(Value::Scalar(val)) => { + Ok(Operand::Immediate(Value::Scalar(val))) => { write!(msg, " {:?}", val).unwrap(); - if let Scalar::Ptr(ptr) = val { + if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val { allocs.push(ptr.alloc_id); } } - Ok(Value::ScalarPair(val1, val2)) => { + Ok(Operand::Immediate(Value::ScalarPair(val1, val2))) => { write!(msg, " ({:?}, {:?})", val1, val2).unwrap(); - if let Scalar::Ptr(ptr) = val1 { + if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val1 { allocs.push(ptr.alloc_id); } - if let Scalar::Ptr(ptr) = val2 { + if let ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) = val2 { allocs.push(ptr.alloc_id); } } @@ -1754,10 +679,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M trace!("{}", msg); self.memory.dump_allocs(allocs); } - Place::Ptr { ptr, align, .. } => { - match ptr { + Place::Ptr(mplace) => { + match mplace.ptr { Scalar::Ptr(ptr) => { - trace!("by align({}) ref:", align.abi()); + trace!("by align({}) ref:", mplace.align.abi()); self.memory.dump_alloc(ptr.alloc_id); } ptr => trace!(" integral by ref: {:?}", ptr), @@ -1766,21 +691,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } } - /// Convenience function to ensure correct usage of locals - pub fn modify_local(&mut self, frame: usize, local: mir::Local, f: F) -> EvalResult<'tcx> - where - F: FnOnce(&mut Self, Value) -> EvalResult<'tcx, Value>, - { - let val = self.stack[frame].get_local(local)?; - let new_val = f(self, val)?; - self.stack[frame].set_local(local, new_val)?; - // FIXME(solson): Run this when setting to Undef? (See previous version of this code.) - // if let Value::ByRef(ptr) = self.stack[frame].get_local(local) { - // self.memory.deallocate(ptr)?; - // } - Ok(()) - } - pub fn generate_stacktrace(&self, explicit_span: Option) -> (Vec, Span) { let mut last_span = None; let mut frames = Vec::new(); @@ -1798,7 +708,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } else { last_span = Some(span); } - let location = if self.tcx.def_key(instance.def_id()).disambiguated_data.data == DefPathData::ClosureExpr { + let location = if self.tcx.def_key(instance.def_id()).disambiguated_data.data + == DefPathData::ClosureExpr + { "closure".to_owned() } else { instance.to_string() @@ -1819,108 +731,15 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M (frames, self.tcx.span) } - pub fn sign_extend(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { - super::sign_extend(self.tcx.tcx, value, ty) - } - - pub fn truncate(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { - super::truncate(self.tcx.tcx, value, ty) + #[inline(always)] + pub fn sign_extend(&self, value: u128, ty: TyLayout<'_>) -> u128 { + assert!(ty.abi.is_signed()); + sign_extend(value, ty.size) } - fn write_field_name(&self, s: &mut String, ty: Ty<'tcx>, i: usize, variant: usize) -> ::std::fmt::Result { - match ty.sty { - ty::TyBool | - ty::TyChar | - ty::TyInt(_) | - ty::TyUint(_) | - ty::TyFloat(_) | - ty::TyFnPtr(_) | - ty::TyNever | - ty::TyFnDef(..) | - ty::TyGeneratorWitness(..) | - ty::TyForeign(..) | - ty::TyDynamic(..) => { - bug!("field_name({:?}): not applicable", ty) - } - - // Potentially-fat pointers. - ty::TyRef(_, pointee, _) | - ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => { - assert!(i < 2); - - // 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 { - return write!(s, ".data_ptr"); - } - - match self.tcx.struct_tail(pointee).sty { - ty::TySlice(_) | - ty::TyStr => write!(s, ".len"), - ty::TyDynamic(..) => write!(s, ".vtable_ptr"), - _ => bug!("field_name({:?}): not applicable", ty) - } - } - - // Arrays and slices. - ty::TyArray(_, _) | - ty::TySlice(_) | - ty::TyStr => write!(s, "[{}]", i), - - // generators and closures. - ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => { - let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); - let freevar = self.tcx.with_freevars(node_id, |fv| fv[i]); - write!(s, ".upvar({})", self.tcx.hir.name(freevar.var_id())) - } - - ty::TyTuple(_) => write!(s, ".{}", i), - - // enums - ty::TyAdt(def, ..) if def.is_enum() => { - let variant = &def.variants[variant]; - write!(s, ".{}::{}", variant.name, variant.fields[i].ident) - } - - // other ADTs. - ty::TyAdt(def, _) => write!(s, ".{}", def.non_enum_variant().fields[i].ident), - - ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) | - ty::TyInfer(_) | ty::TyError => { - bug!("write_field_name: unexpected type `{}`", ty) - } - } + #[inline(always)] + pub fn truncate(&self, value: u128, ty: TyLayout<'_>) -> u128 { + truncate(value, ty.size) } } -impl<'mir, 'tcx> Frame<'mir, 'tcx> { - pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> { - self.locals[local].ok_or_else(|| EvalErrorKind::DeadLocal.into()) - } - - fn set_local(&mut self, local: mir::Local, value: Value) -> EvalResult<'tcx> { - match self.locals[local] { - None => err!(DeadLocal), - Some(ref mut local) => { - *local = value; - Ok(()) - } - } - } - - pub fn storage_live(&mut self, local: mir::Local) -> Option { - trace!("{:?} is now live", local); - - // StorageLive *always* kills the value that's currently stored - mem::replace(&mut self.locals[local], Some(Value::Scalar(Scalar::undef()))) - } - - /// Returns the old value of the local - pub fn storage_dead(&mut self, local: mir::Local) -> Option { - trace!("{:?} is now dead", local); - - self.locals[local].take() - } -} diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs new file mode 100644 index 0000000000..48085c2145 --- /dev/null +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -0,0 +1,222 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Intrinsics and other functions that the miri engine executes without +//! looking at their MIR. Intrinsics/functions supported here are shared by CTFE +//! and miri. + +use syntax::symbol::Symbol; +use rustc::ty; +use rustc::ty::layout::{LayoutOf, Primitive}; +use rustc::mir::BinOp; +use rustc::mir::interpret::{ + EvalResult, EvalErrorKind, Scalar, +}; + +use super::{ + Machine, PlaceTy, OpTy, EvalContext, +}; + + +fn numeric_intrinsic<'tcx>( + name: &str, + bits: u128, + kind: Primitive, +) -> EvalResult<'tcx, Scalar> { + let size = match kind { + Primitive::Int(integer, _) => integer.size(), + _ => bug!("invalid `{}` argument: {:?}", name, bits), + }; + let extra = 128 - size.bits() as u128; + let bits_out = match name { + "ctpop" => bits.count_ones() as u128, + "ctlz" => bits.leading_zeros() as u128 - extra, + "cttz" => (bits << extra).trailing_zeros() as u128 - extra, + "bswap" => (bits << extra).swap_bytes(), + "bitreverse" => (bits << extra).reverse_bits(), + _ => bug!("not a numeric intrinsic: {}", name), + }; + Ok(Scalar::from_uint(bits_out, size)) +} + +impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { + /// Returns whether emulation happened. + pub fn emulate_intrinsic( + &mut self, + instance: ty::Instance<'tcx>, + args: &[OpTy<'tcx>], + dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx, bool> { + let substs = instance.substs; + + let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..]; + match intrinsic_name { + "min_align_of" => { + let elem_ty = substs.type_at(0); + let elem_align = self.layout_of(elem_ty)?.align.abi(); + let align_val = Scalar::from_uint(elem_align, dest.layout.size); + self.write_scalar(align_val, dest)?; + } + + "size_of" => { + let ty = substs.type_at(0); + let size = self.layout_of(ty)?.size.bytes() as u128; + let size_val = Scalar::from_uint(size, dest.layout.size); + self.write_scalar(size_val, dest)?; + } + + "type_id" => { + let ty = substs.type_at(0); + let type_id = self.tcx.type_id_hash(ty) as u128; + let id_val = Scalar::from_uint(type_id, dest.layout.size); + self.write_scalar(id_val, dest)?; + } + | "ctpop" + | "cttz" + | "cttz_nonzero" + | "ctlz" + | "ctlz_nonzero" + | "bswap" + | "bitreverse" => { + let ty = substs.type_at(0); + let layout_of = self.layout_of(ty)?; + let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?; + let kind = match layout_of.abi { + ty::layout::Abi::Scalar(ref scalar) => scalar.value, + _ => Err(::rustc::mir::interpret::EvalErrorKind::TypeNotPrimitive(ty))?, + }; + let out_val = if intrinsic_name.ends_with("_nonzero") { + if bits == 0 { + return err!(Intrinsic(format!("{} called on 0", intrinsic_name))); + } + numeric_intrinsic(intrinsic_name.trim_right_matches("_nonzero"), bits, kind)? + } else { + numeric_intrinsic(intrinsic_name, bits, kind)? + }; + self.write_scalar(out_val, dest)?; + } + | "overflowing_add" + | "overflowing_sub" + | "overflowing_mul" + | "add_with_overflow" + | "sub_with_overflow" + | "mul_with_overflow" => { + let lhs = self.read_value(args[0])?; + let rhs = self.read_value(args[1])?; + let (bin_op, ignore_overflow) = match intrinsic_name { + "overflowing_add" => (BinOp::Add, true), + "overflowing_sub" => (BinOp::Sub, true), + "overflowing_mul" => (BinOp::Mul, true), + "add_with_overflow" => (BinOp::Add, false), + "sub_with_overflow" => (BinOp::Sub, false), + "mul_with_overflow" => (BinOp::Mul, false), + _ => bug!("Already checked for int ops") + }; + if ignore_overflow { + self.binop_ignore_overflow(bin_op, lhs, rhs, dest)?; + } else { + self.binop_with_overflow(bin_op, lhs, rhs, dest)?; + } + } + "unchecked_shl" | "unchecked_shr" => { + let l = self.read_value(args[0])?; + let r = self.read_value(args[1])?; + let bin_op = match intrinsic_name { + "unchecked_shl" => BinOp::Shl, + "unchecked_shr" => BinOp::Shr, + _ => bug!("Already checked for int ops") + }; + let (val, overflowed) = self.binary_op_val(bin_op, l, r)?; + if overflowed { + let layout = self.layout_of(substs.type_at(0))?; + let r_val = r.to_scalar()?.to_bits(layout.size)?; + return err!(Intrinsic( + format!("Overflowing shift by {} in {}", r_val, intrinsic_name), + )); + } + self.write_scalar(val, dest)?; + } + "transmute" => { + // Go through an allocation, to make sure the completely different layouts + // do not pose a problem. (When the user transmutes through a union, + // there will not be a layout mismatch.) + let dest = self.force_allocation(dest)?; + self.copy_op(args[0], dest.into())?; + } + + _ => return Ok(false), + } + + Ok(true) + } + + /// "Intercept" a function call because we have something special to do for it. + /// Returns whether an intercept happened. + pub fn hook_fn( + &mut self, + instance: ty::Instance<'tcx>, + args: &[OpTy<'tcx>], + dest: Option>, + ) -> EvalResult<'tcx, bool> { + let def_id = instance.def_id(); + // Some fn calls are actually BinOp intrinsics + if let Some((op, oflo)) = self.tcx.is_binop_lang_item(def_id) { + let dest = dest.expect("128 lowerings can't diverge"); + let l = self.read_value(args[0])?; + let r = self.read_value(args[1])?; + if oflo { + self.binop_with_overflow(op, l, r, dest)?; + } else { + self.binop_ignore_overflow(op, l, r, dest)?; + } + return Ok(true); + } else if Some(def_id) == self.tcx.lang_items().panic_fn() { + assert!(args.len() == 1); + // &(&'static str, &'static str, u32, u32) + let ptr = self.read_value(args[0])?; + let place = self.ref_to_mplace(ptr)?; + let (msg, file, line, col) = ( + self.mplace_field(place, 0)?, + self.mplace_field(place, 1)?, + self.mplace_field(place, 2)?, + self.mplace_field(place, 3)?, + ); + + let msg_place = self.ref_to_mplace(self.read_value(msg.into())?)?; + let msg = Symbol::intern(self.read_str(msg_place)?); + let file_place = self.ref_to_mplace(self.read_value(file.into())?)?; + let file = Symbol::intern(self.read_str(file_place)?); + let line = self.read_scalar(line.into())?.to_u32()?; + let col = self.read_scalar(col.into())?.to_u32()?; + return Err(EvalErrorKind::Panic { msg, file, line, col }.into()); + } else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() { + assert!(args.len() == 2); + // &'static str, &(&'static str, u32, u32) + let msg = args[0]; + let ptr = self.read_value(args[1])?; + let place = self.ref_to_mplace(ptr)?; + let (file, line, col) = ( + self.mplace_field(place, 0)?, + self.mplace_field(place, 1)?, + self.mplace_field(place, 2)?, + ); + + let msg_place = self.ref_to_mplace(self.read_value(msg.into())?)?; + let msg = Symbol::intern(self.read_str(msg_place)?); + let file_place = self.ref_to_mplace(self.read_value(file.into())?)?; + let file = Symbol::intern(self.read_str(file_place)?); + let line = self.read_scalar(line.into())?.to_u32()?; + let col = self.read_scalar(col.into())?.to_u32()?; + return Err(EvalErrorKind::Panic { msg, file, line, col }.into()); + } else { + return Ok(false); + } + } +} diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index e2086c57c7..f33cb47910 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -1,126 +1,98 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! This module contains everything needed to instantiate an interpreter. //! This separation exists to ensure that no fancy miri features like //! interpreting common C functions leak into CTFE. -use std::hash::Hash; - -use rustc::mir::interpret::{AllocId, EvalResult, Scalar, Pointer, AccessKind, GlobalId}; -use super::{EvalContext, Place, ValTy, Memory}; - +use rustc::hir::def_id::DefId; +use rustc::mir::interpret::{Allocation, EvalResult, Scalar}; use rustc::mir; -use rustc::ty::{self, Ty}; -use rustc::ty::layout::Size; -use syntax::codemap::Span; -use syntax::ast::Mutability; +use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt}; + +use super::{EvalContext, PlaceTy, OpTy}; /// Methods of this trait signifies a point where CTFE evaluation would fail /// and some use case dependent behaviour can instead be applied -pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash { +pub trait Machine<'mir, 'tcx>: Clone + Eq { /// Additional data that can be accessed via the Memory - type MemoryData: Clone + Eq + Hash; + type MemoryData: Clone + Eq; /// Additional memory kinds a machine wishes to distinguish from the builtin ones - type MemoryKinds: ::std::fmt::Debug + PartialEq + Copy + Clone; + type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq; + + /// The memory kind to use for mutated statics -- or None if those are not supported. + const MUT_STATIC_KIND: Option; + + /// Whether to attempt to detect infinite loops (any kind of infinite + /// execution, really). + const DETECT_LOOPS: bool; /// Entry point to all function calls. /// - /// Returns Ok(true) when the function was handled completely - /// e.g. due to missing mir - /// - /// Returns Ok(false) if a new stack frame was pushed - fn eval_fn_call<'a>( + /// Returns either the mir to use for the call, or `None` if execution should + /// just proceed (which usually means this hook did all the work that the + /// called function should usually have done). In the latter case, it is + /// this hook's responsibility to call `goto_block(ret)` to advance the instruction pointer! + /// (This is to support functions like `__rust_maybe_catch_panic` that neither find a MIR + /// nor just jump to `ret`, but instead push their own stack frame.) + /// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them + /// was used. + fn find_fn<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, - destination: Option<(Place, mir::BasicBlock)>, - args: &[ValTy<'tcx>], - span: Span, - sig: ty::FnSig<'tcx>, - ) -> EvalResult<'tcx, bool>; + args: &[OpTy<'tcx>], + dest: Option>, + ret: Option, + ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>>; - /// directly process an intrinsic without pushing a stack frame. + /// Directly process an intrinsic without pushing a stack frame. + /// If this returns successfully, the engine will take care of jumping to the next block. fn call_intrinsic<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, - args: &[ValTy<'tcx>], - dest: Place, - dest_layout: ty::layout::TyLayout<'tcx>, - target: mir::BasicBlock, + args: &[OpTy<'tcx>], + dest: PlaceTy<'tcx>, ) -> EvalResult<'tcx>; - /// Called for all binary operations except on float types. - /// - /// Returns `None` if the operation should be handled by the integer - /// op code in order to share more code between machines + /// Called for read access to a foreign static item. + /// This can be called multiple times for the same static item and should return consistent + /// results. Once the item is *written* the first time, as usual for statics a copy is + /// made and this function is not called again. + fn find_foreign_static<'a>( + tcx: TyCtxtAt<'a, 'tcx, 'tcx>, + def_id: DefId, + ) -> EvalResult<'tcx, &'tcx Allocation>; + + /// Called for all binary operations on integer(-like) types when one operand is a pointer + /// value, and for the `Offset` operation that is inherently about pointers. /// /// Returns a (value, overflowed) pair if the operation succeeded - fn try_ptr_op<'a>( + fn ptr_op<'a>( ecx: &EvalContext<'a, 'mir, 'tcx, Self>, bin_op: mir::BinOp, left: Scalar, - left_ty: Ty<'tcx>, + left_layout: TyLayout<'tcx>, right: Scalar, - right_ty: Ty<'tcx>, - ) -> EvalResult<'tcx, Option<(Scalar, bool)>>; - - /// Called when trying to mark machine defined `MemoryKinds` as static - fn mark_static_initialized<'a>( - _mem: &mut Memory<'a, 'mir, 'tcx, Self>, - _id: AllocId, - _mutability: Mutability, - ) -> EvalResult<'tcx, bool>; - - /// Called when requiring a pointer to a static. Non const eval can - /// create a mutable memory location for `static mut` - fn init_static<'a>( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - cid: GlobalId<'tcx>, - ) -> EvalResult<'tcx, AllocId>; + right_layout: TyLayout<'tcx>, + ) -> EvalResult<'tcx, (Scalar, bool)>; /// Heap allocations via the `box` keyword /// /// Returns a pointer to the allocated memory fn box_alloc<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - ty: Ty<'tcx>, - dest: Place, - ) -> EvalResult<'tcx>; - - /// Called when trying to access a global declared with a `linkage` attribute - fn global_item_with_linkage<'a>( - ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - instance: ty::Instance<'tcx>, - mutability: Mutability, + dest: PlaceTy<'tcx>, ) -> EvalResult<'tcx>; - fn check_locks<'a>( - _mem: &Memory<'a, 'mir, 'tcx, Self>, - _ptr: Pointer, - _size: Size, - _access: AccessKind, - ) -> EvalResult<'tcx> { - Ok(()) - } - - fn add_lock<'a>( - _mem: &mut Memory<'a, 'mir, 'tcx, Self>, - _id: AllocId, - ) {} - - fn free_lock<'a>( - _mem: &mut Memory<'a, 'mir, 'tcx, Self>, - _id: AllocId, - _len: u64, - ) -> EvalResult<'tcx> { - Ok(()) - } - - fn end_region<'a>( - _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - _reg: Option<::rustc::middle::region::Scope>, - ) -> EvalResult<'tcx> { - Ok(()) - } - + /// Execute a validation operation fn validation_op<'a>( _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, _op: ::rustc::mir::ValidationOp, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 6e5cfe3bb3..fcb310f704 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -1,26 +1,37 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The memory subsystem. +//! +//! Generally, we use `Pointer` to denote memory addresses. However, some operations +//! have a "size"-like parameter, and they take `Scalar` for the address because +//! if the size is 0, then the pointer can also be a (properly aligned, non-NULL) +//! integer. It is crucial that these operations call `check_align` *before* +//! short-circuiting the empty case! + use std::collections::VecDeque; -use std::hash::{Hash, Hasher}; use std::ptr; -use rustc::hir::def_id::DefId; -use rustc::ty::Instance; -use rustc::ty::ParamEnv; -use rustc::ty::query::TyCtxtAt; -use rustc::ty::layout::{self, Align, TargetDataLayout, Size}; -use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value, - EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType}; -pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint}; -use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher}; +use rustc::ty::{self, Instance, query::TyCtxtAt}; +use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout}; +use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, ScalarMaybeUndef, GlobalId, + EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic, + truncate}; +pub use rustc::mir::interpret::{write_target_uint, read_target_uint}; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use syntax::ast::Mutability; -use super::{EvalContext, Machine}; - -//////////////////////////////////////////////////////////////////////////////// -// Allocations and pointers -//////////////////////////////////////////////////////////////////////////////// +use super::Machine; -#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub enum MemoryKind { /// Error if deallocated except during a stack pop Stack, @@ -28,82 +39,38 @@ pub enum MemoryKind { Machine(T), } -//////////////////////////////////////////////////////////////////////////////// -// Top-level interpreter memory -//////////////////////////////////////////////////////////////////////////////// - #[derive(Clone)] pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { /// Additional data required by the Machine pub data: M::MemoryData, - /// Helps guarantee that stack allocations aren't deallocated via `rust_deallocate` - alloc_kind: FxHashMap>, + /// Allocations local to this instance of the miri engine. The kind + /// helps ensure that the same mechanism is used for allocation and + /// deallocation. When an allocation is not found here, it is a + /// static and looked up in the `tcx` for read access. Writing to + /// a static creates a copy here, in the machine. + alloc_map: FxHashMap, Allocation)>, - /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations). - alloc_map: FxHashMap, - - /// The current stack frame. Used to check accesses against locks. - pub cur_frame: usize, + /// To be able to compare pointers with NULL, and to check alignment for accesses + /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations + /// that do not exist any more. + dead_alloc_map: FxHashMap, pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>, } -impl<'a, 'mir, 'tcx, M> Eq for Memory<'a, 'mir, 'tcx, M> - where M: Machine<'mir, 'tcx>, - 'tcx: 'a + 'mir, -{} - -impl<'a, 'mir, 'tcx, M> PartialEq for Memory<'a, 'mir, 'tcx, M> - where M: Machine<'mir, 'tcx>, - 'tcx: 'a + 'mir, -{ - fn eq(&self, other: &Self) -> bool { - let Memory { - data, - alloc_kind, - alloc_map, - cur_frame, - tcx: _, - } = self; - - *data == other.data - && *alloc_kind == other.alloc_kind - && *alloc_map == other.alloc_map - && *cur_frame == other.cur_frame +impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for &'a Memory<'a, 'mir, 'tcx, M> { + #[inline] + fn data_layout(&self) -> &TargetDataLayout { + &self.tcx.data_layout } } - -impl<'a, 'mir, 'tcx, M> Hash for Memory<'a, 'mir, 'tcx, M> - where M: Machine<'mir, 'tcx>, - 'tcx: 'a + 'mir, +impl<'a, 'b, 'c, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout + for &'b &'c mut Memory<'a, 'mir, 'tcx, M> { - fn hash(&self, state: &mut H) { - let Memory { - data, - alloc_kind: _, - alloc_map: _, - cur_frame, - tcx: _, - } = self; - - data.hash(state); - cur_frame.hash(state); - - // We ignore some fields which don't change between evaluation steps. - - // Since HashMaps which contain the same items may have different - // iteration orders, we use a commutative operation (in this case - // addition, but XOR would also work), to combine the hash of each - // `Allocation`. - self.allocations() - .map(|allocs| { - let mut h = FxHasher::default(); - allocs.hash(&mut h); - h.finish() - }) - .fold(0u64, |hash, x| hash.wrapping_add(x)) - .hash(state); + #[inline] + fn data_layout(&self) -> &TargetDataLayout { + &self.tcx.data_layout } } @@ -111,48 +78,37 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self { Memory { data, - alloc_kind: FxHashMap::default(), alloc_map: FxHashMap::default(), + dead_alloc_map: FxHashMap::default(), tcx, - cur_frame: usize::max_value(), } } - pub fn allocations<'x>( - &'x self, - ) -> impl Iterator { - self.alloc_map.iter().map(|(&id, alloc)| (id, alloc)) - } - pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer { self.tcx.alloc_map.lock().create_fn_alloc(instance).into() } - pub fn allocate_bytes(&mut self, bytes: &[u8]) -> Pointer { + pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer { self.tcx.allocate_bytes(bytes).into() } - /// kind is `None` for statics - pub fn allocate_value( + pub fn allocate_with( &mut self, alloc: Allocation, kind: MemoryKind, ) -> EvalResult<'tcx, AllocId> { let id = self.tcx.alloc_map.lock().reserve(); - M::add_lock(self, id); - self.alloc_map.insert(id, alloc); - self.alloc_kind.insert(id, kind); + self.alloc_map.insert(id, (kind, alloc)); Ok(id) } - /// kind is `None` for statics pub fn allocate( &mut self, size: Size, align: Align, kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { - self.allocate_value(Allocation::undef(size, align), kind).map(Pointer::from) + self.allocate_with(Allocation::undef(size, align), kind).map(Pointer::from) } pub fn reallocate( @@ -167,15 +123,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { if ptr.offset.bytes() != 0 { return err!(ReallocateNonBasePtr); } - if self.alloc_map.contains_key(&ptr.alloc_id) { - let alloc_kind = self.alloc_kind[&ptr.alloc_id]; - if alloc_kind != kind { - return err!(ReallocatedWrongMemoryKind( - format!("{:?}", alloc_kind), - format!("{:?}", kind), - )); - } - } // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc" let new_ptr = self.allocate(new_size, new_align, kind)?; @@ -185,20 +132,21 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_ptr.into(), new_align, old_size.min(new_size), - /*nonoverlapping*/ - true, + /*nonoverlapping*/ true, )?; self.deallocate(ptr, Some((old_size, old_align)), kind)?; Ok(new_ptr) } + /// Deallocate a local, or do nothing if that local has been made into a static pub fn deallocate_local(&mut self, ptr: Pointer) -> EvalResult<'tcx> { - match self.alloc_kind.get(&ptr.alloc_id).cloned() { - Some(MemoryKind::Stack) => self.deallocate(ptr, None, MemoryKind::Stack), - // Happens if the memory was interned into immutable memory - None => Ok(()), - other => bug!("local contained non-stack memory: {:?}", other), + // The allocation might be already removed by static interning. + // This can only really happen in the CTFE instance, not in miri. + if self.alloc_map.contains_key(&ptr.alloc_id) { + self.deallocate(ptr, None, MemoryKind::Stack) + } else { + Ok(()) } } @@ -208,13 +156,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { size_and_align: Option<(Size, Align)>, kind: MemoryKind, ) -> EvalResult<'tcx> { + debug!("deallocating: {}", ptr.alloc_id); + if ptr.offset.bytes() != 0 { return err!(DeallocateNonBasePtr); } - let alloc = match self.alloc_map.remove(&ptr.alloc_id) { + let (alloc_kind, alloc) = match self.alloc_map.remove(&ptr.alloc_id) { Some(alloc) => alloc, None => { + // Deallocating static memory -- always an error return match self.tcx.alloc_map.lock().get(ptr.alloc_id) { Some(AllocType::Function(..)) => err!(DeallocatedWrongMemoryKind( "function".to_string(), @@ -230,15 +181,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } }; - let alloc_kind = self.alloc_kind.remove(&ptr.alloc_id).expect("alloc_map out of sync with alloc_kind"); - - // It is okay for us to still holds locks on deallocation -- for example, we could store data we own - // in a local, and the local could be deallocated (from StorageDead) before the function returns. - // However, we should check *something*. For now, we make sure that there is no conflicting write - // lock by another frame. We *have* to permit deallocation if we hold a read lock. - // TODO: Figure out the exact rules here. - M::free_lock(self, ptr.alloc_id, alloc.bytes.len() as u64)?; - if alloc_kind != kind { return err!(DeallocatedWrongMemoryKind( format!("{:?}", alloc_kind), @@ -247,42 +189,54 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } if let Some((size, align)) = size_and_align { if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align { - return err!(IncorrectAllocationInformation(size, Size::from_bytes(alloc.bytes.len() as u64), align, alloc.align)); + let bytes = Size::from_bytes(alloc.bytes.len() as u64); + return err!(IncorrectAllocationInformation(size, + bytes, + align, + alloc.align)); } } - debug!("deallocated : {}", ptr.alloc_id); + // Don't forget to remember size and align of this now-dead allocation + let old = self.dead_alloc_map.insert( + ptr.alloc_id, + (Size::from_bytes(alloc.bytes.len() as u64), alloc.align) + ); + if old.is_some() { + bug!("Nothing can be deallocated twice"); + } Ok(()) } - pub fn pointer_size(&self) -> Size { - self.tcx.data_layout.pointer_size - } - - pub fn endianness(&self) -> layout::Endian { - self.tcx.data_layout.endian - } - - /// Check that the pointer is aligned AND non-NULL. + /// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways: + /// You can pass a scalar, and a `Pointer` does not have to actually still be allocated. pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx> { // Check non-NULL/Undef, extract offset let (offset, alloc_align) = match ptr { Scalar::Ptr(ptr) => { - let alloc = self.get(ptr.alloc_id)?; - (ptr.offset.bytes(), alloc.align) + let (size, align) = self.get_size_and_align(ptr.alloc_id)?; + // check this is not NULL -- which we can ensure only if this is in-bounds + // of some (potentially dead) allocation. + if ptr.offset > size { + return err!(PointerOutOfBounds { + ptr, + access: true, + allocation_size: size, + }); + }; + // keep data for alignment check + (ptr.offset.bytes(), align) } - Scalar::Bits { bits, defined } => { - if (defined as u64) < self.pointer_size().bits() { - return err!(ReadUndefBytes); - } - // FIXME: what on earth does this line do? docs or fix needed! - let v = ((bits as u128) % (1 << self.pointer_size().bytes())) as u64; - if v == 0 { + Scalar::Bits { bits, size } => { + assert_eq!(size as u64, self.pointer_size().bytes()); + assert!(bits < (1u128 << self.pointer_size().bits())); + // check this is not NULL + if bits == 0 { return err!(InvalidNullPointerUsage); } - // the base address if the "integer allocation" is 0 and hence always aligned - (v, required_align) + // the "base address" is 0 and hence always aligned + (bits as u64, required_align) } }; // Check alignment @@ -303,6 +257,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } } + /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end + /// of an allocation (i.e., at the first *inaccessible* location) *is* considered + /// in-bounds! This follows C's/LLVM's rules. The `access` boolean is just used + /// for the error message. + /// If you want to check bounds before doing a memory access, be sure to + /// check the pointer one past the end of your access, then everything will + /// work out exactly. pub fn check_bounds(&self, ptr: Pointer, access: bool) -> EvalResult<'tcx> { let alloc = self.get(ptr.alloc_id)?; let allocation_size = alloc.bytes.len() as u64; @@ -319,63 +280,94 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Allocation accessors impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { - fn const_eval_static(&self, def_id: DefId) -> EvalResult<'tcx, &'tcx Allocation> { - if self.tcx.is_foreign_item(def_id) { - return err!(ReadForeignStatic); + /// Helper function to obtain the global (tcx) allocation for a static + fn get_static_alloc( + tcx: TyCtxtAt<'a, 'tcx, 'tcx>, + id: AllocId, + ) -> EvalResult<'tcx, &'tcx Allocation> { + let alloc = tcx.alloc_map.lock().get(id); + let def_id = match alloc { + Some(AllocType::Memory(mem)) => { + return Ok(mem) + } + Some(AllocType::Function(..)) => { + return err!(DerefFunctionPointer) + } + Some(AllocType::Static(did)) => { + did + } + None => + return err!(DanglingPointerDeref), + }; + // We got a "lazy" static that has not been computed yet, do some work + trace!("static_alloc: Need to compute {:?}", def_id); + if tcx.is_foreign_item(def_id) { + return M::find_foreign_static(tcx, def_id); } - let instance = Instance::mono(self.tcx.tcx, def_id); + let instance = Instance::mono(tcx.tcx, def_id); let gid = GlobalId { instance, promoted: None, }; - self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| { + tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| { // no need to report anything, the const_eval call takes care of that for statics - assert!(self.tcx.is_static(def_id).is_some()); + assert!(tcx.is_static(def_id).is_some()); EvalErrorKind::ReferencedConstant(err).into() - }).map(|val| { - self.tcx.const_value_to_allocation(val) + }).map(|const_val| { + if let ConstValue::ByRef(_, allocation, _) = const_val.val { + allocation + } else { + bug!("Matching on non-ByRef static") + } }) } pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> { - // normal alloc? match self.alloc_map.get(&id) { - Some(alloc) => Ok(alloc), - // uninitialized static alloc? - None => { - // static alloc? - let alloc = self.tcx.alloc_map.lock().get(id); - match alloc { - Some(AllocType::Memory(mem)) => Ok(mem), - Some(AllocType::Function(..)) => { - Err(EvalErrorKind::DerefFunctionPointer.into()) - } - Some(AllocType::Static(did)) => { - self.const_eval_static(did) - } - None => Err(EvalErrorKind::DanglingPointerDeref.into()), - } - }, - } + // Normal alloc? + Some(alloc) => Ok(&alloc.1), + // Static. No need to make any copies, just provide read access to the global static + // memory in tcx. + None => Self::get_static_alloc(self.tcx, id), + } + } + + pub fn get_size_and_align(&self, id: AllocId) -> EvalResult<'tcx, (Size, Align)> { + Ok(match self.get(id) { + Ok(alloc) => (Size::from_bytes(alloc.bytes.len() as u64), alloc.align), + Err(err) => match err.kind { + EvalErrorKind::DanglingPointerDeref => + // This should be in the dead allocation map + *self.dead_alloc_map.get(&id).expect( + "allocation missing in dead_alloc_map" + ), + // E.g. a function ptr allocation + _ => return Err(err) + } + }) } - fn get_mut( + pub fn get_mut( &mut self, id: AllocId, ) -> EvalResult<'tcx, &mut Allocation> { - // normal alloc? - match self.alloc_map.get_mut(&id) { - Some(alloc) => Ok(alloc), - // uninitialized static alloc? - None => { - // no alloc or immutable alloc? produce an error - match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Memory(..)) | - Some(AllocType::Static(..)) => err!(ModifiedConstantMemory), - Some(AllocType::Function(..)) => err!(DerefFunctionPointer), - None => err!(DanglingPointerDeref), - } - }, + // Static? + if !self.alloc_map.contains_key(&id) { + // Ask the machine for what to do + if let Some(kind) = M::MUT_STATIC_KIND { + // The machine supports mutating statics. Make a copy, use that. + self.deep_copy_static(id, MemoryKind::Machine(kind))?; + } else { + return err!(ModifiedConstantMemory) + } + } + // If we come here, we know the allocation is in our map + let alloc = &mut self.alloc_map.get_mut(&id).unwrap().1; + // See if we are allowed to mutate this + if alloc.mutability == Mutability::Immutable { + err!(ModifiedConstantMemory) + } else { + Ok(alloc) } } @@ -383,17 +375,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { if ptr.offset.bytes() != 0 { return err!(InvalidFunctionPointer); } - debug!("reading fn ptr: {}", ptr.alloc_id); + trace!("reading fn ptr: {}", ptr.alloc_id); match self.tcx.alloc_map.lock().get(ptr.alloc_id) { Some(AllocType::Function(instance)) => Ok(instance), _ => Err(EvalErrorKind::ExecuteMemory.into()), } } - pub fn get_alloc_kind(&self, id: AllocId) -> Option> { - self.alloc_kind.get(&id).cloned() - } - /// For debugging, print an allocation and all allocations it points to, recursively. pub fn dump_alloc(&self, id: AllocId) { if !log_enabled!(::log::Level::Trace) { @@ -421,14 +409,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { let (alloc, immutable) = // normal alloc? match self.alloc_map.get(&id) { - Some(a) => (a, match self.alloc_kind[&id] { + Some((kind, alloc)) => (alloc, match kind { MemoryKind::Stack => " (stack)".to_owned(), MemoryKind::Machine(m) => format!(" ({:?})", m), }), None => { // static alloc? match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Memory(a)) => (a, "(immutable)".to_owned()), + Some(AllocType::Memory(a)) => (a, " (immutable)".to_owned()), Some(AllocType::Function(func)) => { trace!("{} {}", msg, func); continue; @@ -453,7 +441,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } relocations.push((i, target_id)); } - if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)) { + if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() { // this `as usize` is fine, since `i` came from a `usize` write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap(); } else { @@ -489,9 +477,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn leak_report(&self) -> usize { trace!("### LEAK REPORT ###"); + let mut_static_kind = M::MUT_STATIC_KIND.map(|k| MemoryKind::Machine(k)); let leaks: Vec<_> = self.alloc_map - .keys() - .cloned() + .iter() + .filter_map(|(&id, &(kind, _))| + // exclude mutable statics + if Some(kind) == mut_static_kind { None } else { Some(id) } ) .collect(); let n = leaks.len(); self.dump_allocs(leaks); @@ -501,19 +492,29 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Byte accessors impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { - fn get_bytes_unchecked( + /// The last argument controls whether we error out when there are undefined + /// or pointer bytes. You should never call this, call `get_bytes` or + /// `get_bytes_with_undef_and_ptr` instead, + fn get_bytes_internal( &self, ptr: Pointer, size: Size, align: Align, + check_defined_and_ptr: bool, ) -> EvalResult<'tcx, &[u8]> { - // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL + assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; - if size.bytes() == 0 { - return Ok(&[]); + // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) + self.check_bounds(ptr.offset(size, &*self)?, true)?; + + if check_defined_and_ptr { + self.check_defined(ptr, size)?; + self.check_relocations(ptr, size)?; + } else { + // We still don't want relocations on the *edges* + self.check_relocation_edges(ptr, size)?; } - M::check_locks(self, ptr, size, AccessKind::Read)?; - self.check_bounds(ptr.offset(size, self)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) + let alloc = self.get(ptr.alloc_id)?; assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); assert_eq!(size.bytes() as usize as u64, size.bytes()); @@ -521,66 +522,51 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(&alloc.bytes[offset..offset + size.bytes() as usize]) } - fn get_bytes_unchecked_mut( - &mut self, - ptr: Pointer, - size: Size, - align: Align, - ) -> EvalResult<'tcx, &mut [u8]> { - // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL - self.check_align(ptr.into(), align)?; - if size.bytes() == 0 { - return Ok(&mut []); - } - M::check_locks(self, ptr, size, AccessKind::Write)?; - self.check_bounds(ptr.offset(size, &*self)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) - let alloc = self.get_mut(ptr.alloc_id)?; - assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); - assert_eq!(size.bytes() as usize as u64, size.bytes()); - let offset = ptr.offset.bytes() as usize; - Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize]) + #[inline] + fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> { + self.get_bytes_internal(ptr, size, align, true) } - fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> { - assert_ne!(size.bytes(), 0); - if self.relocations(ptr, size)?.len() != 0 { - return err!(ReadPointerAsBytes); - } - self.check_defined(ptr, size)?; - self.get_bytes_unchecked(ptr, size, align) + /// It is the caller's responsibility to handle undefined and pointer bytes. + /// However, this still checks that there are no relocations on the egdes. + #[inline] + fn get_bytes_with_undef_and_ptr( + &self, + ptr: Pointer, + size: Size, + align: Align + ) -> EvalResult<'tcx, &[u8]> { + self.get_bytes_internal(ptr, size, align, false) } + /// Just calling this already marks everything as defined and removes relocations, + /// so be sure to actually put data there! fn get_bytes_mut( &mut self, ptr: Pointer, size: Size, align: Align, ) -> EvalResult<'tcx, &mut [u8]> { - assert_ne!(size.bytes(), 0); + assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); + self.check_align(ptr.into(), align)?; + // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) + self.check_bounds(ptr.offset(size, &self)?, true)?; + + self.mark_definedness(ptr, size, true)?; self.clear_relocations(ptr, size)?; - self.mark_definedness(ptr.into(), size, true)?; - self.get_bytes_unchecked_mut(ptr, size, align) + + let alloc = self.get_mut(ptr.alloc_id)?; + assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); + assert_eq!(size.bytes() as usize as u64, size.bytes()); + let offset = ptr.offset.bytes() as usize; + Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize]) } } /// Reading and writing impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { - /// mark an allocation pointed to by a static as static and initialized - fn mark_inner_allocation_initialized( - &mut self, - alloc: AllocId, - mutability: Mutability, - ) -> EvalResult<'tcx> { - match self.alloc_kind.get(&alloc) { - // do not go into statics - None => Ok(()), - // just locals and machine allocs - Some(_) => self.mark_static_initialized(alloc, mutability), - } - } - /// mark an allocation as static and initialized, either mutable or not - pub fn mark_static_initialized( + pub fn intern_static( &mut self, alloc_id: AllocId, mutability: Mutability, @@ -590,31 +576,48 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { alloc_id, mutability ); - // The machine handled it - if M::mark_static_initialized(self, alloc_id, mutability)? { - return Ok(()) - } - let alloc = self.alloc_map.remove(&alloc_id); - match self.alloc_kind.remove(&alloc_id) { - None => {}, - Some(MemoryKind::Machine(_)) => bug!("machine didn't handle machine alloc"), - Some(MemoryKind::Stack) => {}, - } - if let Some(mut alloc) = alloc { - // ensure llvm knows not to put this into immutable memroy - alloc.runtime_mutability = mutability; - let alloc = self.tcx.intern_const_alloc(alloc); - self.tcx.alloc_map.lock().set_id_memory(alloc_id, alloc); - // recurse into inner allocations - for &alloc in alloc.relocations.values() { - self.mark_inner_allocation_initialized(alloc, mutability)?; + // remove allocation + let (kind, mut alloc) = self.alloc_map.remove(&alloc_id).unwrap(); + match kind { + MemoryKind::Machine(_) => bug!("Static cannot refer to machine memory"), + MemoryKind::Stack => {}, + } + // ensure llvm knows not to put this into immutable memory + alloc.mutability = mutability; + let alloc = self.tcx.intern_const_alloc(alloc); + self.tcx.alloc_map.lock().set_id_memory(alloc_id, alloc); + // recurse into inner allocations + for &alloc in alloc.relocations.values() { + // FIXME: Reusing the mutability here is likely incorrect. It is originally + // determined via `is_freeze`, and data is considered frozen if there is no + // `UnsafeCell` *immediately* in that data -- however, this search stops + // at references. So whenever we follow a reference, we should likely + // assume immutability -- and we should make sure that the compiler + // does not permit code that would break this! + if self.alloc_map.contains_key(&alloc) { + // Not yet interned, so proceed recursively + self.intern_static(alloc, mutability)?; } - } else { - bug!("no allocation found for {:?}", alloc_id); } Ok(()) } + /// The alloc_id must refer to a (mutable) static; a deep copy of that + /// static is made into this memory. + fn deep_copy_static( + &mut self, + id: AllocId, + kind: MemoryKind, + ) -> EvalResult<'tcx> { + let alloc = Self::get_static_alloc(self.tcx, id)?; + if alloc.mutability == Mutability::Immutable { + return err!(ModifiedConstantMemory); + } + let old = self.alloc_map.insert(id, (kind, alloc.clone())); + assert!(old.is_none(), "deep_copy_static: must not overwrite existing memory"); + Ok(()) + } + pub fn copy( &mut self, src: Scalar, @@ -637,19 +640,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { length: u64, nonoverlapping: bool, ) -> EvalResult<'tcx> { - // Empty accesses don't need to be valid pointers, but they should still be aligned - self.check_align(src, src_align)?; - self.check_align(dest, dest_align)?; if size.bytes() == 0 { + // Nothing to do for ZST, other than checking alignment and non-NULLness. + self.check_align(src, src_align)?; + self.check_align(dest, dest_align)?; return Ok(()); } let src = src.to_ptr()?; let dest = dest.to_ptr()?; - self.check_relocation_edges(src, size)?; // first copy the relocations to a temporary buffer, because // `get_bytes_mut` will clear the relocations, which is correct, // since we don't want to keep any relocations at the target. + // (`get_bytes_with_undef_and_ptr` below checks that there are no + // relocations overlapping the edges; those would not be handled correctly). let relocations = { let relocations = self.relocations(src, size)?; let mut new_relocations = Vec::with_capacity(relocations.len() * (length as usize)); @@ -658,7 +662,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { relocations .iter() .map(|&(offset, alloc_id)| { - (offset + dest.offset - src.offset + (i * size * relocations.len() as u64), alloc_id) + (offset + dest.offset - src.offset + (i * size * relocations.len() as u64), + alloc_id) }) ); } @@ -666,7 +671,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations }; - let src_bytes = self.get_bytes_unchecked(src, size, src_align)?.as_ptr(); + // This also checks alignment, and relocation edges on the src. + let src_bytes = self.get_bytes_with_undef_and_ptr(src, size, src_align)?.as_ptr(); let dest_bytes = self.get_bytes_mut(dest, size * length, dest_align)?.as_mut_ptr(); // SAFE: The above indexing would have panicked if there weren't at least `size` bytes @@ -686,17 +692,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } for i in 0..length { - ptr::copy(src_bytes, dest_bytes.offset((size.bytes() * i) as isize), size.bytes() as usize); + ptr::copy(src_bytes, + dest_bytes.offset((size.bytes() * i) as isize), + size.bytes() as usize); } } else { for i in 0..length { - ptr::copy_nonoverlapping(src_bytes, dest_bytes.offset((size.bytes() * i) as isize), size.bytes() as usize); + ptr::copy_nonoverlapping(src_bytes, + dest_bytes.offset((size.bytes() * i) as isize), + size.bytes() as usize); } } } + // copy definedness to the destination self.copy_undef_mask(src, dest, size, length)?; - // copy back the relocations + // copy the relocations to the destination self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations); Ok(()) @@ -709,11 +720,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { match alloc.bytes[offset..].iter().position(|&c| c == 0) { Some(size) => { let p1 = Size::from_bytes((size + 1) as u64); - if self.relocations(ptr, p1)?.len() != 0 { - return err!(ReadPointerAsBytes); - } + self.check_relocations(ptr, p1)?; self.check_defined(ptr, p1)?; - M::check_locks(self, ptr, p1, AccessKind::Read)?; Ok(&alloc.bytes[offset..offset + size]) } None => err!(UnterminatedCString(ptr)), @@ -723,8 +731,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1, 1).unwrap(); - self.check_align(ptr, align)?; if size.bytes() == 0 { + self.check_align(ptr, align)?; return Ok(&[]); } self.get_bytes(ptr.to_ptr()?, size, align) @@ -733,8 +741,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1, 1).unwrap(); - self.check_align(ptr, align)?; if src.is_empty() { + self.check_align(ptr, align)?; return Ok(()); } let bytes = self.get_bytes_mut(ptr.to_ptr()?, Size::from_bytes(src.len() as u64), align)?; @@ -745,8 +753,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<'tcx> { // Empty accesses don't need to be valid pointers, but they should still be non-NULL let align = Align::from_bytes(1, 1).unwrap(); - self.check_align(ptr, align)?; if count.bytes() == 0 { + self.check_align(ptr, align)?; return Ok(()); } let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, align)?; @@ -756,69 +764,81 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } - pub fn read_scalar(&self, ptr: Pointer, ptr_align: Align, size: Size) -> EvalResult<'tcx, Scalar> { - self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer - let endianness = self.endianness(); - let bytes = self.get_bytes_unchecked(ptr, size, ptr_align.min(self.int_align(size)))?; + /// Read a *non-ZST* scalar + pub fn read_scalar( + &self, + ptr: Pointer, + ptr_align: Align, + size: Size + ) -> EvalResult<'tcx, ScalarMaybeUndef> { + // get_bytes_unchecked tests alignment and relocation edges + let bytes = self.get_bytes_with_undef_and_ptr( + ptr, size, ptr_align.min(self.int_align(size)) + )?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { - // this inflates undefined bytes to the entire scalar, even if only a few bytes are undefined - return Ok(Scalar::undef().into()); + // this inflates undefined bytes to the entire scalar, even if only a few + // bytes are undefined + return Ok(ScalarMaybeUndef::Undef); } // Now we do the actual reading - let bits = read_target_uint(endianness, bytes).unwrap(); + let bits = read_target_uint(self.tcx.data_layout.endian, bytes).unwrap(); // See if we got a pointer if size != self.pointer_size() { - if self.relocations(ptr, size)?.len() != 0 { - return err!(ReadPointerAsBytes); - } + // *Now* better make sure that the inside also is free of relocations. + self.check_relocations(ptr, size)?; } else { let alloc = self.get(ptr.alloc_id)?; match alloc.relocations.get(&ptr.offset) { - Some(&alloc_id) => return Ok(Pointer::new(alloc_id, Size::from_bytes(bits as u64)).into()), + Some(&alloc_id) => { + let ptr = Pointer::new(alloc_id, Size::from_bytes(bits as u64)); + return Ok(ScalarMaybeUndef::Scalar(ptr.into())) + } None => {}, } } // We don't. Just return the bits. - Ok(Scalar::Bits { - bits, - defined: size.bits() as u8, - }) + Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size))) } - pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align) -> EvalResult<'tcx, Scalar> { + pub fn read_ptr_sized(&self, ptr: Pointer, ptr_align: Align) + -> EvalResult<'tcx, ScalarMaybeUndef> { self.read_scalar(ptr, ptr_align, self.pointer_size()) } - pub fn write_scalar(&mut self, ptr: Scalar, ptr_align: Align, val: Scalar, size: Size, signed: bool) -> EvalResult<'tcx> { - let endianness = self.endianness(); + /// Write a *non-ZST* scalar + pub fn write_scalar( + &mut self, + ptr: Pointer, + ptr_align: Align, + val: ScalarMaybeUndef, + type_size: Size, + ) -> EvalResult<'tcx> { + let val = match val { + ScalarMaybeUndef::Scalar(scalar) => scalar, + ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false), + }; let bytes = match val { Scalar::Ptr(val) => { - assert_eq!(size, self.pointer_size()); + assert_eq!(type_size, self.pointer_size()); val.offset.bytes() as u128 } - Scalar::Bits { bits, defined } if defined as u64 >= size.bits() && size.bits() != 0 => bits, - - Scalar::Bits { .. } => { - self.check_align(ptr.into(), ptr_align)?; - self.mark_definedness(ptr, size, false)?; - return Ok(()); - } + Scalar::Bits { bits, size } => { + assert_eq!(size as u64, type_size.bytes()); + debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits, + "Unexpected value of size {} when writing to memory", size); + bits + }, }; - let ptr = ptr.to_ptr()?; - { - let align = self.int_align(size); - let dst = self.get_bytes_mut(ptr, size, ptr_align.min(align))?; - if signed { - write_target_int(endianness, dst, bytes as i128).unwrap(); - } else { - write_target_uint(endianness, dst, bytes).unwrap(); - } + // get_bytes_mut checks alignment + let endian = self.tcx.data_layout.endian; + let dst = self.get_bytes_mut(ptr, type_size, ptr_align)?; + write_target_uint(endian, dst, bytes).unwrap(); } // See if we have to also write a relocation @@ -835,9 +855,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } - pub fn write_ptr_sized_unsigned(&mut self, ptr: Pointer, ptr_align: Align, val: Scalar) -> EvalResult<'tcx> { + pub fn write_ptr_sized(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef) + -> EvalResult<'tcx> { let ptr_size = self.pointer_size(); - self.write_scalar(ptr.into(), ptr_align, val, ptr_size, false) + self.write_scalar(ptr.into(), ptr_align, val, ptr_size) } fn int_align(&self, size: Size) -> Align { @@ -857,16 +878,35 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Relocations impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { + /// Return all relocations overlapping with the given ptr-offset pair. fn relocations( &self, ptr: Pointer, size: Size, ) -> EvalResult<'tcx, &[(Size, AllocId)]> { + // We have to go back `pointer_size - 1` bytes, as that one would still overlap with + // the beginning of this range. let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1); - let end = ptr.offset + size; + let end = ptr.offset + size; // this does overflow checking Ok(self.get(ptr.alloc_id)?.relocations.range(Size::from_bytes(start)..end)) } + /// Check that there ar eno relocations overlapping with the given range. + #[inline(always)] + fn check_relocations(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { + if self.relocations(ptr, size)?.len() != 0 { + err!(ReadPointerAsBytes) + } else { + Ok(()) + } + } + + /// Remove all relocations inside the given range. + /// If there are relocations overlapping with the edges, they + /// are removed as well *and* the bytes they cover are marked as + /// uninitialized. This is a somewhat odd "spooky action at a distance", + /// but it allows strictly more code to run than if we would just error + /// immediately in that case. fn clear_relocations(&mut self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { // Find the start and end of the given range and its outermost relocations. let (first, last) = { @@ -899,12 +939,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } + /// Error if there are relocations overlapping with the egdes of the + /// given memory range. + #[inline] fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { - let overlapping_start = self.relocations(ptr, Size::ZERO)?.len(); - let overlapping_end = self.relocations(ptr.offset(size, self)?, Size::ZERO)?.len(); - if overlapping_start + overlapping_end != 0 { - return err!(ReadPointerAsBytes); - } + self.check_relocations(ptr, Size::ZERO)?; + self.check_relocations(ptr.offset(size, self)?, Size::ZERO)?; Ok(()) } } @@ -939,28 +979,26 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } + /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes` + /// error which will report the first byte which is undefined. + #[inline] fn check_defined(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { let alloc = self.get(ptr.alloc_id)?; - if !alloc.undef_mask.is_range_defined( + alloc.undef_mask.is_range_defined( ptr.offset, ptr.offset + size, - ) - { - return err!(ReadUndefBytes); - } - Ok(()) + ).or_else(|idx| err!(ReadUndefBytes(idx))) } pub fn mark_definedness( &mut self, - ptr: Scalar, + ptr: Pointer, size: Size, new_state: bool, ) -> EvalResult<'tcx> { if size.bytes() == 0 { return Ok(()); } - let ptr = ptr.to_ptr()?; let alloc = self.get_mut(ptr.alloc_id)?; alloc.undef_mask.set_range( ptr.offset, @@ -970,100 +1008,3 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } } - -//////////////////////////////////////////////////////////////////////////////// -// Unaligned accesses -//////////////////////////////////////////////////////////////////////////////// - -pub trait HasMemory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { - fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M>; - fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M>; - - /// Convert the value into a pointer (or a pointer-sized integer). If the value is a ByRef, - /// this may have to perform a load. - fn into_ptr( - &self, - value: Value, - ) -> EvalResult<'tcx, Scalar> { - Ok(match value { - Value::ByRef(ptr, align) => { - self.memory().read_ptr_sized(ptr.to_ptr()?, align)? - } - Value::Scalar(ptr) | - Value::ScalarPair(ptr, _) => ptr, - }.into()) - } - - fn into_ptr_vtable_pair( - &self, - value: Value, - ) -> EvalResult<'tcx, (Scalar, Pointer)> { - match value { - Value::ByRef(ref_ptr, align) => { - let mem = self.memory(); - let ptr = mem.read_ptr_sized(ref_ptr.to_ptr()?, align)?.into(); - let vtable = mem.read_ptr_sized( - ref_ptr.ptr_offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?, - align - )?.to_ptr()?; - Ok((ptr, vtable)) - } - - Value::ScalarPair(ptr, vtable) => Ok((ptr.into(), vtable.to_ptr()?)), - _ => bug!("expected ptr and vtable, got {:?}", value), - } - } - - fn into_slice( - &self, - value: Value, - ) -> EvalResult<'tcx, (Scalar, u64)> { - match value { - Value::ByRef(ref_ptr, align) => { - let mem = self.memory(); - let ptr = mem.read_ptr_sized(ref_ptr.to_ptr()?, align)?.into(); - let len = mem.read_ptr_sized( - ref_ptr.ptr_offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?, - align - )?.to_bits(mem.pointer_size())? as u64; - Ok((ptr, len)) - } - Value::ScalarPair(ptr, val) => { - let len = val.to_bits(self.memory().pointer_size())?; - Ok((ptr.into(), len as u64)) - } - Value::Scalar(_) => bug!("expected ptr and length, got {:?}", value), - } - } -} - -impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasMemory<'a, 'mir, 'tcx, M> for Memory<'a, 'mir, 'tcx, M> { - #[inline] - fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> { - self - } - - #[inline] - fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> { - self - } -} - -impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasMemory<'a, 'mir, 'tcx, M> for EvalContext<'a, 'mir, 'tcx, M> { - #[inline] - fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> { - &mut self.memory - } - - #[inline] - fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> { - &self.memory - } -} - -impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasDataLayout for &'a Memory<'a, 'mir, 'tcx, M> { - #[inline] - fn data_layout(&self) -> &TargetDataLayout { - &self.tcx.data_layout - } -} diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 0c921f6619..1e8de02923 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -1,59 +1,50 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! An interpreter for MIR used in CTFE and by miri mod cast; -mod const_eval; mod eval_context; mod place; +mod operand; mod machine; mod memory; mod operator; +mod snapshot; mod step; mod terminator; mod traits; +mod validity; +mod intrinsics; + +pub use self::eval_context::{ + EvalContext, Frame, StackPopCleanup, LocalValue, +}; + +pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy}; -pub use self::eval_context::{EvalContext, Frame, StackPopCleanup, - TyAndPacked, ValTy}; +pub use self::memory::{Memory, MemoryKind}; -pub use self::place::{Place, PlaceExtra}; +pub use self::machine::Machine; -pub use self::memory::{Memory, MemoryKind, HasMemory}; +pub use self::operand::{Value, ValTy, Operand, OpTy}; -pub use self::const_eval::{ +// reexports for compatibility +pub use const_eval::{ eval_promoted, mk_borrowck_eval_cx, mk_eval_cx, CompileTimeEvaluator, - const_value_to_allocation_provider, + const_to_allocation_provider, const_eval_provider, - const_val_field, + const_field, const_variant_index, - value_to_const_value, + op_to_const, }; - -pub use self::machine::Machine; - -pub use self::memory::{write_target_uint, write_target_int, read_target_uint}; - -use rustc::mir::interpret::{EvalResult, EvalErrorKind}; -use rustc::ty::{Ty, TyCtxt, ParamEnv}; - -pub fn sign_extend<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { - let param_env = ParamEnv::empty(); - let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?; - let size = layout.size.bits(); - assert!(layout.abi.is_signed()); - // sign extend - let shift = 128 - size; - // shift the unsigned value to the left - // and back to the right as signed (essentially fills with FF on the left) - Ok((((value << shift) as i128) >> shift) as u128) -} - -pub fn truncate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { - let param_env = ParamEnv::empty(); - let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?; - let size = layout.size.bits(); - let shift = 128 - size; - // truncate (shift left to drop out leftover values, shift right to fill with zeroes) - Ok((value << shift) >> shift) -} diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs new file mode 100644 index 0000000000..c7f84f7683 --- /dev/null +++ b/src/librustc_mir/interpret/operand.rs @@ -0,0 +1,614 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Functions concerning immediate values and operands, and reading from operands. +//! All high-level functions to read from memory work on operands as sources. + +use std::hash::{Hash, Hasher}; +use std::convert::TryInto; + +use rustc::{mir, ty}; +use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt}; + +use rustc::mir::interpret::{ + GlobalId, AllocId, + ConstValue, Pointer, Scalar, ScalarMaybeUndef, + EvalResult, EvalErrorKind +}; +use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind}; + +/// A `Value` represents a single immediate self-contained Rust value. +/// +/// For optimization of a few very common cases, there is also a representation for a pair of +/// primitive values (`ScalarPair`). It allows Miri to avoid making allocations for checked binary +/// operations and fat pointers. This idea was taken from rustc's codegen. +/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely +/// defined on `Value`, and do not have to work with a `Place`. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub enum Value { + Scalar(ScalarMaybeUndef), + ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef), +} + +impl<'tcx> Value { + pub fn new_slice( + val: Scalar, + len: u64, + cx: impl HasDataLayout + ) -> Self { + Value::ScalarPair(val.into(), Scalar::from_uint(len, cx.data_layout().pointer_size).into()) + } + + pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self { + Value::ScalarPair(val.into(), Scalar::Ptr(vtable).into()) + } + + #[inline] + pub fn to_scalar_or_undef(self) -> ScalarMaybeUndef { + match self { + Value::Scalar(val) => val, + Value::ScalarPair(..) => bug!("Got a fat pointer where a scalar was expected"), + } + } + + #[inline] + pub fn to_scalar(self) -> EvalResult<'tcx, Scalar> { + self.to_scalar_or_undef().not_undef() + } + + #[inline] + pub fn to_scalar_pair(self) -> EvalResult<'tcx, (Scalar, Scalar)> { + match self { + Value::Scalar(..) => bug!("Got a thin pointer where a scalar pair was expected"), + Value::ScalarPair(a, b) => Ok((a.not_undef()?, b.not_undef()?)) + } + } + + /// Convert the value into a pointer (or a pointer-sized integer). + /// Throws away the second half of a ScalarPair! + #[inline] + pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar> { + match self { + Value::Scalar(ptr) | + Value::ScalarPair(ptr, _) => ptr.not_undef(), + } + } +} + +impl_stable_hash_for!(enum ::interpret::Value { + Scalar(x), + ScalarPair(x, y), +}); + +// ScalarPair needs a type to interpret, so we often have a value and a type together +// as input for binary and cast operations. +#[derive(Copy, Clone, Debug)] +pub struct ValTy<'tcx> { + value: Value, + pub layout: TyLayout<'tcx>, +} + +impl<'tcx> ::std::ops::Deref for ValTy<'tcx> { + type Target = Value; + #[inline(always)] + fn deref(&self) -> &Value { + &self.value + } +} + +/// An `Operand` is the result of computing a `mir::Operand`. It can be immediate, +/// or still in memory. The latter is an optimization, to delay reading that chunk of +/// memory and to avoid having to store arbitrary-sized data here. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub enum Operand { + Immediate(Value), + Indirect(MemPlace), +} + +impl Operand { + #[inline] + pub fn to_mem_place(self) -> MemPlace { + match self { + Operand::Indirect(mplace) => mplace, + _ => bug!("to_mem_place: expected Operand::Indirect, got {:?}", self), + + } + } + + #[inline] + pub fn to_immediate(self) -> Value { + match self { + Operand::Immediate(val) => val, + _ => bug!("to_immediate: expected Operand::Immediate, got {:?}", self), + + } + } +} + +impl_stable_hash_for!(enum ::interpret::Operand { + Immediate(x), + Indirect(x), +}); + +#[derive(Copy, Clone, Debug)] +pub struct OpTy<'tcx> { + crate op: Operand, // ideally we'd make this private, but const_prop needs this + pub layout: TyLayout<'tcx>, +} + +impl<'tcx> ::std::ops::Deref for OpTy<'tcx> { + type Target = Operand; + #[inline(always)] + fn deref(&self) -> &Operand { + &self.op + } +} + +impl<'tcx> From> for OpTy<'tcx> { + #[inline(always)] + fn from(mplace: MPlaceTy<'tcx>) -> Self { + OpTy { + op: Operand::Indirect(*mplace), + layout: mplace.layout + } + } +} + +impl<'tcx> From> for OpTy<'tcx> { + #[inline(always)] + fn from(val: ValTy<'tcx>) -> Self { + OpTy { + op: Operand::Immediate(val.value), + layout: val.layout + } + } +} + +// Validation needs to hash OpTy, but we cannot hash Layout -- so we just hash the type +impl<'tcx> Hash for OpTy<'tcx> { + fn hash(&self, state: &mut H) { + self.op.hash(state); + self.layout.ty.hash(state); + } +} +impl<'tcx> PartialEq for OpTy<'tcx> { + fn eq(&self, other: &Self) -> bool { + self.op == other.op && self.layout.ty == other.layout.ty + } +} +impl<'tcx> Eq for OpTy<'tcx> {} + +// Use the existing layout if given (but sanity check in debug mode), +// or compute the layout. +#[inline(always)] +fn from_known_layout<'tcx>( + layout: Option>, + compute: impl FnOnce() -> EvalResult<'tcx, TyLayout<'tcx>> +) -> EvalResult<'tcx, TyLayout<'tcx>> { + match layout { + None => compute(), + Some(layout) => { + if cfg!(debug_assertions) { + let layout2 = compute()?; + assert_eq!(layout.details, layout2.details, + "Mismatch in layout of supposedly equal-layout types {:?} and {:?}", + layout.ty, layout2.ty); + } + Ok(layout) + } + } +} + +impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { + /// Try reading a value in memory; this is interesting particularily for ScalarPair. + /// Return None if the layout does not permit loading this as a value. + pub(super) fn try_read_value_from_mplace( + &self, + mplace: MPlaceTy<'tcx>, + ) -> EvalResult<'tcx, Option> { + if mplace.layout.is_unsized() { + // Dont touch unsized + return Ok(None); + } + let (ptr, ptr_align) = mplace.to_scalar_ptr_align(); + + if mplace.layout.is_zst() { + // Not all ZSTs have a layout we would handle below, so just short-circuit them + // all here. + self.memory.check_align(ptr, ptr_align)?; + return Ok(Some(Value::Scalar(Scalar::zst().into()))); + } + + let ptr = ptr.to_ptr()?; + match mplace.layout.abi { + layout::Abi::Scalar(..) => { + let scalar = self.memory.read_scalar(ptr, ptr_align, mplace.layout.size)?; + Ok(Some(Value::Scalar(scalar))) + } + layout::Abi::ScalarPair(ref a, ref b) => { + let (a, b) = (&a.value, &b.value); + let (a_size, b_size) = (a.size(self), b.size(self)); + let a_ptr = ptr; + let b_offset = a_size.abi_align(b.align(self)); + assert!(b_offset.bytes() > 0); // we later use the offset to test which field to use + let b_ptr = ptr.offset(b_offset, self)?.into(); + let a_val = self.memory.read_scalar(a_ptr, ptr_align, a_size)?; + let b_val = self.memory.read_scalar(b_ptr, ptr_align, b_size)?; + Ok(Some(Value::ScalarPair(a_val, b_val))) + } + _ => Ok(None), + } + } + + /// Try returning an immediate value for the operand. + /// If the layout does not permit loading this as a value, return where in memory + /// we can find the data. + /// Note that for a given layout, this operation will either always fail or always + /// succeed! Whether it succeeds depends on whether the layout can be represented + /// in a `Value`, not on which data is stored there currently. + pub(crate) fn try_read_value( + &self, + src: OpTy<'tcx>, + ) -> EvalResult<'tcx, Result> { + Ok(match src.try_as_mplace() { + Ok(mplace) => { + if let Some(val) = self.try_read_value_from_mplace(mplace)? { + Ok(val) + } else { + Err(*mplace) + } + }, + Err(val) => Ok(val), + }) + } + + /// Read a value from a place, asserting that that is possible with the given layout. + #[inline(always)] + pub fn read_value(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> { + if let Ok(value) = self.try_read_value(op)? { + Ok(ValTy { value, layout: op.layout }) + } else { + bug!("primitive read failed for type: {:?}", op.layout.ty); + } + } + + /// Read a scalar from a place + pub fn read_scalar(&self, op: OpTy<'tcx>) -> EvalResult<'tcx, ScalarMaybeUndef> { + match *self.read_value(op)? { + Value::ScalarPair(..) => bug!("got ScalarPair for type: {:?}", op.layout.ty), + Value::Scalar(val) => Ok(val), + } + } + + // Turn the MPlace into a string (must already be dereferenced!) + pub fn read_str( + &self, + mplace: MPlaceTy<'tcx>, + ) -> EvalResult<'tcx, &str> { + let len = mplace.len(self)?; + let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?; + let str = ::std::str::from_utf8(bytes) + .map_err(|err| EvalErrorKind::ValidationFailure(err.to_string()))?; + Ok(str) + } + + pub fn uninit_operand(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Operand> { + // This decides which types we will use the Immediate optimization for, and hence should + // match what `try_read_value` and `eval_place_to_op` support. + if layout.is_zst() { + return Ok(Operand::Immediate(Value::Scalar(Scalar::zst().into()))); + } + + Ok(match layout.abi { + layout::Abi::Scalar(..) => + Operand::Immediate(Value::Scalar(ScalarMaybeUndef::Undef)), + layout::Abi::ScalarPair(..) => + Operand::Immediate(Value::ScalarPair( + ScalarMaybeUndef::Undef, + ScalarMaybeUndef::Undef, + )), + _ => { + trace!("Forcing allocation for local of type {:?}", layout.ty); + Operand::Indirect( + *self.allocate(layout, MemoryKind::Stack)? + ) + } + }) + } + + /// Projection functions + pub fn operand_field( + &self, + op: OpTy<'tcx>, + field: u64, + ) -> EvalResult<'tcx, OpTy<'tcx>> { + let base = match op.try_as_mplace() { + Ok(mplace) => { + // The easy case + let field = self.mplace_field(mplace, field)?; + return Ok(field.into()); + }, + Err(value) => value + }; + + let field = field.try_into().unwrap(); + let field_layout = op.layout.field(self, field)?; + if field_layout.is_zst() { + let val = Value::Scalar(Scalar::zst().into()); + return Ok(OpTy { op: Operand::Immediate(val), layout: field_layout }); + } + let offset = op.layout.fields.offset(field); + let value = match base { + // the field covers the entire type + _ if offset.bytes() == 0 && field_layout.size == op.layout.size => base, + // extract fields from types with `ScalarPair` ABI + Value::ScalarPair(a, b) => { + let val = if offset.bytes() == 0 { a } else { b }; + Value::Scalar(val) + }, + Value::Scalar(val) => + bug!("field access on non aggregate {:#?}, {:#?}", val, op.layout), + }; + Ok(OpTy { op: Operand::Immediate(value), layout: field_layout }) + } + + pub fn operand_downcast( + &self, + op: OpTy<'tcx>, + variant: usize, + ) -> EvalResult<'tcx, OpTy<'tcx>> { + // Downcasts only change the layout + Ok(match op.try_as_mplace() { + Ok(mplace) => { + self.mplace_downcast(mplace, variant)?.into() + }, + Err(..) => { + let layout = op.layout.for_variant(self, variant); + OpTy { layout, ..op } + } + }) + } + + // Take an operand, representing a pointer, and dereference it to a place -- that + // will always be a MemPlace. + pub(super) fn deref_operand( + &self, + src: OpTy<'tcx>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + let val = self.read_value(src)?; + trace!("deref to {} on {:?}", val.layout.ty, *val); + Ok(self.ref_to_mplace(val)?) + } + + pub fn operand_projection( + &self, + base: OpTy<'tcx>, + proj_elem: &mir::PlaceElem<'tcx>, + ) -> EvalResult<'tcx, OpTy<'tcx>> { + use rustc::mir::ProjectionElem::*; + Ok(match *proj_elem { + Field(field, _) => self.operand_field(base, field.index() as u64)?, + Downcast(_, variant) => self.operand_downcast(base, variant)?, + Deref => self.deref_operand(base)?.into(), + Subslice { .. } | ConstantIndex { .. } | Index(_) => if base.layout.is_zst() { + OpTy { + op: Operand::Immediate(Value::Scalar(Scalar::zst().into())), + // the actual index doesn't matter, so we just pick a convenient one like 0 + layout: base.layout.field(self, 0)?, + } + } else { + // The rest should only occur as mplace, we do not use Immediates for types + // allowing such operations. This matches place_projection forcing an allocation. + let mplace = base.to_mem_place(); + self.mplace_projection(mplace, proj_elem)?.into() + } + }) + } + + // Evaluate a place with the goal of reading from it. This lets us sometimes + // avoid allocations. If you already know the layout, you can pass it in + // to avoid looking it up again. + fn eval_place_to_op( + &self, + mir_place: &mir::Place<'tcx>, + layout: Option>, + ) -> EvalResult<'tcx, OpTy<'tcx>> { + use rustc::mir::Place::*; + let op = match *mir_place { + Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer), + Local(local) => { + let op = *self.frame().locals[local].access()?; + let layout = from_known_layout(layout, + || self.layout_of_local(self.cur_frame(), local))?; + OpTy { op, layout } + }, + + Projection(ref proj) => { + let op = self.eval_place_to_op(&proj.base, None)?; + self.operand_projection(op, &proj.elem)? + } + + _ => self.eval_place_to_mplace(mir_place)?.into(), + }; + + trace!("eval_place_to_op: got {:?}", *op); + Ok(op) + } + + /// Evaluate the operand, returning a place where you can then find the data. + /// if you already know the layout, you can save two some table lookups + /// by passing it in here. + pub fn eval_operand( + &self, + mir_op: &mir::Operand<'tcx>, + layout: Option>, + ) -> EvalResult<'tcx, OpTy<'tcx>> { + use rustc::mir::Operand::*; + let op = match *mir_op { + // FIXME: do some more logic on `move` to invalidate the old location + Copy(ref place) | + Move(ref place) => + self.eval_place_to_op(place, layout)?, + + Constant(ref constant) => { + let layout = from_known_layout(layout, || { + let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs()); + self.layout_of(ty) + })?; + let op = self.const_value_to_op(constant.literal.val)?; + OpTy { op, layout } + } + }; + trace!("{:?}: {:?}", mir_op, *op); + Ok(op) + } + + /// Evaluate a bunch of operands at once + pub(super) fn eval_operands( + &self, + ops: &[mir::Operand<'tcx>], + ) -> EvalResult<'tcx, Vec>> { + ops.into_iter() + .map(|op| self.eval_operand(op, None)) + .collect() + } + + // Also used e.g. when miri runs into a constant. + pub(super) fn const_value_to_op( + &self, + val: ConstValue<'tcx>, + ) -> EvalResult<'tcx, Operand> { + trace!("const_value_to_op: {:?}", val); + match val { + ConstValue::Unevaluated(def_id, substs) => { + let instance = self.resolve(def_id, substs)?; + self.global_to_op(GlobalId { + instance, + promoted: None, + }) + } + ConstValue::ByRef(id, alloc, offset) => { + // We rely on mutability being set correctly in that allocation to prevent writes + // where none should happen -- and for `static mut`, we copy on demand anyway. + Ok(Operand::Indirect(MemPlace::from_ptr(Pointer::new(id, offset), alloc.align))) + }, + ConstValue::ScalarPair(a, b) => + Ok(Operand::Immediate(Value::ScalarPair(a.into(), b))), + ConstValue::Scalar(x) => + Ok(Operand::Immediate(Value::Scalar(x.into()))), + } + } + pub fn const_to_op( + &self, + cnst: &ty::Const<'tcx>, + ) -> EvalResult<'tcx, OpTy<'tcx>> { + let op = self.const_value_to_op(cnst.val)?; + Ok(OpTy { op, layout: self.layout_of(cnst.ty)? }) + } + + pub(super) fn global_to_op(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, Operand> { + let cv = self.const_eval(gid)?; + self.const_value_to_op(cv.val) + } + + /// Read discriminant, return the runtime value as well as the variant index. + pub fn read_discriminant( + &self, + rval: OpTy<'tcx>, + ) -> EvalResult<'tcx, (u128, usize)> { + trace!("read_discriminant_value {:#?}", rval.layout); + if rval.layout.abi == layout::Abi::Uninhabited { + return err!(Unreachable); + } + + match rval.layout.variants { + layout::Variants::Single { index } => { + let discr_val = rval.layout.ty.ty_adt_def().map_or( + index as u128, + |def| def.discriminant_for_variant(*self.tcx, index).val); + return Ok((discr_val, index)); + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => {}, + } + // read raw discriminant value + let discr_op = self.operand_field(rval, 0)?; + let discr_val = self.read_value(discr_op)?; + let raw_discr = discr_val.to_scalar()?; + trace!("discr value: {:?}", raw_discr); + // post-process + Ok(match rval.layout.variants { + layout::Variants::Single { .. } => bug!(), + layout::Variants::Tagged { .. } => { + let real_discr = if discr_val.layout.ty.is_signed() { + let i = raw_discr.to_bits(discr_val.layout.size)? as i128; + // going from layout tag type to typeck discriminant type + // requires first sign extending with the layout discriminant + let shift = 128 - discr_val.layout.size.bits(); + let sexted = (i << shift) >> shift; + // and then zeroing with the typeck discriminant type + let discr_ty = rval.layout.ty + .ty_adt_def().expect("tagged layout corresponds to adt") + .repr + .discr_type(); + let discr_ty = layout::Integer::from_attr(self.tcx.tcx, discr_ty); + let shift = 128 - discr_ty.size().bits(); + let truncatee = sexted as u128; + (truncatee << shift) >> shift + } else { + raw_discr.to_bits(discr_val.layout.size)? + }; + // Make sure we catch invalid discriminants + let index = rval.layout.ty + .ty_adt_def() + .expect("tagged layout for non adt") + .discriminants(self.tcx.tcx) + .position(|var| var.val == real_discr) + .ok_or_else(|| EvalErrorKind::InvalidDiscriminant(real_discr))?; + (real_discr, index) + }, + layout::Variants::NicheFilling { + dataful_variant, + ref niche_variants, + niche_start, + .. + } => { + let variants_start = *niche_variants.start() as u128; + let variants_end = *niche_variants.end() as u128; + let real_discr = match raw_discr { + Scalar::Ptr(_) => { + // The niche must be just 0 (which a pointer value never is) + assert!(niche_start == 0); + assert!(variants_start == variants_end); + dataful_variant as u128 + }, + Scalar::Bits { bits: raw_discr, size } => { + assert_eq!(size as u64, discr_val.layout.size.bytes()); + let discr = raw_discr.wrapping_sub(niche_start) + .wrapping_add(variants_start); + if variants_start <= discr && discr <= variants_end { + discr + } else { + dataful_variant as u128 + } + }, + }; + let index = real_discr as usize; + assert_eq!(index as u128, real_discr); + assert!(index < rval.layout.ty + .ty_adt_def() + .expect("tagged layout for non adt") + .variants.len()); + (real_discr, index) + } + }) + } + +} diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 8320add715..d07d37d43b 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -1,109 +1,158 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use rustc::mir; -use rustc::ty::{self, Ty, layout}; +use rustc::ty::{self, layout::{Size, TyLayout}}; use syntax::ast::FloatTy; -use rustc::ty::layout::LayoutOf; use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; +use rustc::mir::interpret::{EvalResult, Scalar}; -use super::{EvalContext, Place, Machine, ValTy}; +use super::{EvalContext, PlaceTy, Value, Machine, ValTy}; -use rustc::mir::interpret::{EvalResult, Scalar, Value}; impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { - fn binop_with_overflow( - &mut self, - op: mir::BinOp, - left: ValTy<'tcx>, - right: ValTy<'tcx>, - ) -> EvalResult<'tcx, (Scalar, bool)> { - let left_val = self.value_to_scalar(left)?; - let right_val = self.value_to_scalar(right)?; - self.binary_op(op, left_val, left.ty, right_val, right.ty) - } - /// Applies the binary operation `op` to the two operands and writes a tuple of the result /// and a boolean signifying the potential overflow to the destination. - pub fn intrinsic_with_overflow( + pub fn binop_with_overflow( &mut self, op: mir::BinOp, left: ValTy<'tcx>, right: ValTy<'tcx>, - dest: Place, - dest_ty: Ty<'tcx>, + dest: PlaceTy<'tcx>, ) -> EvalResult<'tcx> { - let (val, overflowed) = self.binop_with_overflow(op, left, right)?; - let val = Value::ScalarPair(val, Scalar::from_bool(overflowed)); - let valty = ValTy { - value: val, - ty: dest_ty, - }; - self.write_value(valty, dest) + let (val, overflowed) = self.binary_op_val(op, left, right)?; + let val = Value::ScalarPair(val.into(), Scalar::from_bool(overflowed).into()); + self.write_value(val, dest) } /// Applies the binary operation `op` to the arguments and writes the result to the - /// destination. Returns `true` if the operation overflowed. - pub fn intrinsic_overflowing( + /// destination. + pub fn binop_ignore_overflow( &mut self, op: mir::BinOp, left: ValTy<'tcx>, right: ValTy<'tcx>, - dest: Place, - dest_ty: Ty<'tcx>, - ) -> EvalResult<'tcx, bool> { - let (val, overflowed) = self.binop_with_overflow(op, left, right)?; - self.write_scalar(dest, val, dest_ty)?; - Ok(overflowed) + dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + let (val, _overflowed) = self.binary_op_val(op, left, right)?; + self.write_scalar(val, dest) } } impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { - /// Returns the result of the specified operation and whether it overflowed. - pub fn binary_op( + fn binary_char_op( &self, bin_op: mir::BinOp, - left: Scalar, - left_ty: Ty<'tcx>, - right: Scalar, - right_ty: Ty<'tcx>, + l: char, + r: char, ) -> EvalResult<'tcx, (Scalar, bool)> { use rustc::mir::BinOp::*; - let left_layout = self.layout_of(left_ty)?; - let right_layout = self.layout_of(right_ty)?; - - let left_kind = match left_layout.abi { - layout::Abi::Scalar(ref scalar) => scalar.value, - _ => return err!(TypeNotPrimitive(left_ty)), + let res = match bin_op { + Eq => l == r, + Ne => l != r, + Lt => l < r, + Le => l <= r, + Gt => l > r, + Ge => l >= r, + _ => bug!("Invalid operation on char: {:?}", bin_op), }; - let right_kind = match right_layout.abi { - layout::Abi::Scalar(ref scalar) => scalar.value, - _ => return err!(TypeNotPrimitive(right_ty)), + return Ok((Scalar::from_bool(res), false)); + } + + fn binary_bool_op( + &self, + bin_op: mir::BinOp, + l: bool, + r: bool, + ) -> EvalResult<'tcx, (Scalar, bool)> { + use rustc::mir::BinOp::*; + + let res = match bin_op { + Eq => l == r, + Ne => l != r, + Lt => l < r, + Le => l <= r, + Gt => l > r, + Ge => l >= r, + BitAnd => l & r, + BitOr => l | r, + BitXor => l ^ r, + _ => bug!("Invalid operation on bool: {:?}", bin_op), }; - trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, left, left_kind, right, right_kind); + return Ok((Scalar::from_bool(res), false)); + } - // I: Handle operations that support pointers - if !left_kind.is_float() && !right_kind.is_float() { - if let Some(handled) = M::try_ptr_op(self, bin_op, left, left_ty, right, right_ty)? { - return Ok(handled); - } + fn binary_float_op( + &self, + bin_op: mir::BinOp, + fty: FloatTy, + // passing in raw bits + l: u128, + r: u128, + ) -> EvalResult<'tcx, (Scalar, bool)> { + use rustc::mir::BinOp::*; + + macro_rules! float_math { + ($ty:path, $size:expr) => {{ + let l = <$ty>::from_bits(l); + let r = <$ty>::from_bits(r); + let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>| + Scalar::from_uint(res.value.to_bits(), Size::from_bytes($size)); + let val = match bin_op { + Eq => Scalar::from_bool(l == r), + Ne => Scalar::from_bool(l != r), + Lt => Scalar::from_bool(l < r), + Le => Scalar::from_bool(l <= r), + Gt => Scalar::from_bool(l > r), + Ge => Scalar::from_bool(l >= r), + Add => bitify(l + r), + Sub => bitify(l - r), + Mul => bitify(l * r), + Div => bitify(l / r), + Rem => bitify(l % r), + _ => bug!("invalid float op: `{:?}`", bin_op), + }; + return Ok((val, false)); + }}; } + match fty { + FloatTy::F32 => float_math!(Single, 4), + FloatTy::F64 => float_math!(Double, 8), + } + } - // II: From now on, everything must be bytes, no pointers - let l = left.to_bits(left_layout.size)?; - let r = right.to_bits(right_layout.size)?; + fn binary_int_op( + &self, + bin_op: mir::BinOp, + // passing in raw bits + l: u128, + left_layout: TyLayout<'tcx>, + r: u128, + right_layout: TyLayout<'tcx>, + ) -> EvalResult<'tcx, (Scalar, bool)> { + use rustc::mir::BinOp::*; - // These ops can have an RHS with a different numeric type. - if right_kind.is_int() && (bin_op == Shl || bin_op == Shr) { + // Shift ops can have an RHS with a different numeric type. + if bin_op == Shl || bin_op == Shr { let signed = left_layout.abi.is_signed(); let mut oflo = (r as u32 as u128) != r; let mut r = r as u32; - let size = left_layout.size.bits() as u32; - oflo |= r >= size; + let size = left_layout.size; + oflo |= r >= size.bits() as u32; if oflo { - r %= size; + r %= size.bits() as u32; } let result = if signed { - let l = self.sign_extend(l, left_ty)? as i128; + let l = self.sign_extend(l, left_layout) as i128; let result = match bin_op { Shl => l << r, Shr => l >> r, @@ -117,25 +166,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { _ => bug!("it has already been checked that this is a shift op"), } }; - let truncated = self.truncate(result, left_ty)?; - return Ok((Scalar::Bits { - bits: truncated, - defined: size as u8, - }, oflo)); + let truncated = self.truncate(result, left_layout); + return Ok((Scalar::from_uint(truncated, size), oflo)); } - if left_kind != right_kind { + // For the remaining ops, the types must be the same on both sides + if left_layout.ty != right_layout.ty { let msg = format!( - "unimplemented binary op {:?}: {:?} ({:?}), {:?} ({:?})", + "unimplemented asymmetric binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, - left, - left_kind, - right, - right_kind + l, + left_layout.ty, + r, + right_layout.ty ); return err!(Unimplemented(msg)); } + // Operations that need special treatment for signed integers if left_layout.abi.is_signed() { let op: Option bool> = match bin_op { Lt => Some(i128::lt), @@ -145,8 +193,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { _ => None, }; if let Some(op) = op { - let l = self.sign_extend(l, left_ty)? as i128; - let r = self.sign_extend(r, right_ty)? as i128; + let l = self.sign_extend(l, left_layout) as i128; + let r = self.sign_extend(r, right_layout) as i128; return Ok((Scalar::from_bool(op(&l, &r)), false)); } let op: Option (i128, bool)> = match bin_op { @@ -160,14 +208,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { _ => None, }; if let Some(op) = op { - let l128 = self.sign_extend(l, left_ty)? as i128; - let r = self.sign_extend(r, right_ty)? as i128; - let size = left_layout.size.bits(); + let l128 = self.sign_extend(l, left_layout) as i128; + let r = self.sign_extend(r, right_layout) as i128; + let size = left_layout.size; match bin_op { Rem | Div => { // int_min / -1 - if r == -1 && l == (1 << (size - 1)) { - return Ok((Scalar::Bits { bits: l, defined: size as u8 }, true)); + if r == -1 && l == (1 << (size.bits() - 1)) { + return Ok((Scalar::from_uint(l, size), true)); } }, _ => {}, @@ -175,52 +223,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { trace!("{}, {}, {}", l, l128, r); let (result, mut oflo) = op(l128, r); trace!("{}, {}", result, oflo); - if !oflo && size != 128 { - let max = 1 << (size - 1); + if !oflo && size.bits() != 128 { + let max = 1 << (size.bits() - 1); oflo = result >= max || result < -max; } + // this may be out-of-bounds for the result type, so we have to truncate ourselves let result = result as u128; - let truncated = self.truncate(result, left_ty)?; - return Ok((Scalar::Bits { - bits: truncated, - defined: size as u8, - }, oflo)); - } - } - - if let ty::TyFloat(fty) = left_ty.sty { - macro_rules! float_math { - ($ty:path, $bitsize:expr) => {{ - let l = <$ty>::from_bits(l); - let r = <$ty>::from_bits(r); - let bitify = |res: ::rustc_apfloat::StatusAnd<$ty>| Scalar::Bits { - bits: res.value.to_bits(), - defined: $bitsize, - }; - let val = match bin_op { - Eq => Scalar::from_bool(l == r), - Ne => Scalar::from_bool(l != r), - Lt => Scalar::from_bool(l < r), - Le => Scalar::from_bool(l <= r), - Gt => Scalar::from_bool(l > r), - Ge => Scalar::from_bool(l >= r), - Add => bitify(l + r), - Sub => bitify(l - r), - Mul => bitify(l * r), - Div => bitify(l / r), - Rem => bitify(l % r), - _ => bug!("invalid float op: `{:?}`", bin_op), - }; - return Ok((val, false)); - }}; - } - match fty { - FloatTy::F32 => float_math!(Single, 32), - FloatTy::F64 => float_math!(Double, 64), + let truncated = self.truncate(result, left_layout); + return Ok((Scalar::from_uint(truncated, size), oflo)); } } - let bit_width = self.layout_of(left_ty).unwrap().size.bits() as u8; + let size = left_layout.size; // only ints left let val = match bin_op { @@ -232,11 +246,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Gt => Scalar::from_bool(l > r), Ge => Scalar::from_bool(l >= r), - BitOr => Scalar::Bits { bits: l | r, defined: bit_width }, - BitAnd => Scalar::Bits { bits: l & r, defined: bit_width }, - BitXor => Scalar::Bits { bits: l ^ r, defined: bit_width }, + BitOr => Scalar::from_uint(l | r, size), + BitAnd => Scalar::from_uint(l & r, size), + BitXor => Scalar::from_uint(l ^ r, size), Add | Sub | Mul | Rem | Div => { + debug_assert!(!left_layout.abi.is_signed()); let op: fn(u128, u128) -> (u128, bool) = match bin_op { Add => u128::overflowing_add, Sub => u128::overflowing_sub, @@ -248,21 +263,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { _ => bug!(), }; let (result, oflo) = op(l, r); - let truncated = self.truncate(result, left_ty)?; - return Ok((Scalar::Bits { - bits: truncated, - defined: bit_width, - }, oflo || truncated != result)); + let truncated = self.truncate(result, left_layout); + return Ok((Scalar::from_uint(truncated, size), oflo || truncated != result)); } _ => { let msg = format!( - "unimplemented binary op {:?}: {:?} ({:?}), {:?} ({:?})", + "unimplemented binary op {:?}: {:?}, {:?} (both {:?})", bin_op, - left, - left_ty, - right, - right_ty, + l, + r, + right_layout.ty, ); return err!(Unimplemented(msg)); } @@ -271,36 +282,116 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Ok((val, false)) } + /// Convenience wrapper that's useful when keeping the layout together with the + /// value. + #[inline] + pub fn binary_op_val( + &self, + bin_op: mir::BinOp, + left: ValTy<'tcx>, + right: ValTy<'tcx>, + ) -> EvalResult<'tcx, (Scalar, bool)> { + self.binary_op( + bin_op, + left.to_scalar()?, left.layout, + right.to_scalar()?, right.layout, + ) + } + + /// Returns the result of the specified operation and whether it overflowed. + pub fn binary_op( + &self, + bin_op: mir::BinOp, + left: Scalar, + left_layout: TyLayout<'tcx>, + right: Scalar, + right_layout: TyLayout<'tcx>, + ) -> EvalResult<'tcx, (Scalar, bool)> { + trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})", + bin_op, left, left_layout.ty, right, right_layout.ty); + + match left_layout.ty.sty { + ty::Char => { + assert_eq!(left_layout.ty, right_layout.ty); + let left = left.to_char()?; + let right = right.to_char()?; + self.binary_char_op(bin_op, left, right) + } + ty::Bool => { + assert_eq!(left_layout.ty, right_layout.ty); + let left = left.to_bool()?; + let right = right.to_bool()?; + self.binary_bool_op(bin_op, left, right) + } + ty::Float(fty) => { + assert_eq!(left_layout.ty, right_layout.ty); + let left = left.to_bits(left_layout.size)?; + let right = right.to_bits(right_layout.size)?; + self.binary_float_op(bin_op, fty, left, right) + } + _ => { + // Must be integer(-like) types. Don't forget about == on fn pointers. + assert!(left_layout.ty.is_integral() || left_layout.ty.is_unsafe_ptr() || + left_layout.ty.is_fn()); + assert!(right_layout.ty.is_integral() || right_layout.ty.is_unsafe_ptr() || + right_layout.ty.is_fn()); + + // Handle operations that support pointer values + if left.is_ptr() || right.is_ptr() || bin_op == mir::BinOp::Offset { + return M::ptr_op(self, bin_op, left, left_layout, right, right_layout); + } + + // Everything else only works with "proper" bits + let left = left.to_bits(left_layout.size).expect("we checked is_ptr"); + let right = right.to_bits(right_layout.size).expect("we checked is_ptr"); + self.binary_int_op(bin_op, left, left_layout, right, right_layout) + } + } + } + pub fn unary_op( &self, un_op: mir::UnOp, val: Scalar, - ty: Ty<'tcx>, + layout: TyLayout<'tcx>, ) -> EvalResult<'tcx, Scalar> { use rustc::mir::UnOp::*; use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; - let size = self.layout_of(ty)?.size; - let bytes = val.to_bits(size)?; - let size = size.bits(); - - let result_bytes = match (un_op, &ty.sty) { - - (Not, ty::TyBool) => !val.to_bool()? as u128, - - (Not, _) => !bytes, - - (Neg, ty::TyFloat(FloatTy::F32)) => Single::to_bits(-Single::from_bits(bytes)), - (Neg, ty::TyFloat(FloatTy::F64)) => Double::to_bits(-Double::from_bits(bytes)), + trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty.sty); - (Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowNeg), - (Neg, _) => (-(bytes as i128)) as u128, - }; - - Ok(Scalar::Bits { - bits: self.truncate(result_bytes, ty)?, - defined: size as u8, - }) + match layout.ty.sty { + ty::Bool => { + let val = val.to_bool()?; + let res = match un_op { + Not => !val, + _ => bug!("Invalid bool op {:?}", un_op) + }; + Ok(Scalar::from_bool(res)) + } + ty::Float(fty) => { + let val = val.to_bits(layout.size)?; + let res = match (un_op, fty) { + (Neg, FloatTy::F32) => Single::to_bits(-Single::from_bits(val)), + (Neg, FloatTy::F64) => Double::to_bits(-Double::from_bits(val)), + _ => bug!("Invalid float op {:?}", un_op) + }; + Ok(Scalar::from_uint(res, layout.size)) + } + _ => { + assert!(layout.ty.is_integral()); + let val = val.to_bits(layout.size)?; + let res = match un_op { + Not => !val, + Neg => { + assert!(layout.abi.is_signed()); + (-(val as i128)) as u128 + } + }; + // res needs tuncating + Ok(Scalar::from_uint(self.truncate(res, layout), layout.size)) + } + } } } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 59bf2ae6c0..e3f7f26f53 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -1,473 +1,802 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Computations on places -- field projections, going from mir::Place, and writing +//! into a place. +//! All high-level functions to write to memory work on places as destinations. + +use std::convert::TryFrom; +use std::mem; + +use rustc::ich::StableHashingContext; use rustc::mir; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; -use rustc_data_structures::indexed_vec::Idx; +use rustc::ty::{self, Ty}; +use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; -use rustc::mir::interpret::{GlobalId, Value, Scalar, EvalResult, Pointer}; -use super::{EvalContext, Machine, ValTy}; -use interpret::memory::HasMemory; +use rustc::mir::interpret::{ + GlobalId, AllocId, Scalar, EvalResult, Pointer, ScalarMaybeUndef, PointerArithmetic +}; +use super::{EvalContext, Machine, Value, ValTy, Operand, OpTy, MemoryKind}; #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub enum Place { +pub struct MemPlace { + /// A place may have an integral pointer for ZSTs, and since it might + /// be turned back into a reference before ever being dereferenced. + /// However, it may never be undef. + pub ptr: Scalar, + pub align: Align, + /// Metadata for unsized places. Interpretation is up to the type. + /// Must not be present for sized types, but can be missing for unsized types + /// (e.g. `extern type`). + pub extra: Option>, +} + +impl_stable_hash_for!(struct ::interpret::MemPlace { + ptr, + align, + extra, +}); + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +pub enum Place { /// A place referring to a value allocated in the `Memory` system. - Ptr { - /// A place may have an invalid (integral or undef) pointer, - /// since it might be turned back into a reference - /// before ever being dereferenced. - ptr: Scalar, - align: Align, - extra: PlaceExtra, + Ptr(MemPlace), + + /// To support alloc-free locals, we are able to write directly to a local. + /// (Without that optimization, we'd just always be a `MemPlace`.) + Local { + frame: usize, + local: mir::Local, }, +} + +// Can't use the macro here because that does not support named enum fields. +impl<'a> HashStable> for Place { + fn hash_stable( + &self, hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) + { + mem::discriminant(self).hash_stable(hcx, hasher); + match self { + Place::Ptr(mem_place) => mem_place.hash_stable(hcx, hasher), - /// A place referring to a value on the stack. Represented by a stack frame index paired with - /// a Mir local index. - Local { frame: usize, local: mir::Local }, + Place::Local { frame, local } => { + frame.hash_stable(hcx, hasher); + local.hash_stable(hcx, hasher); + }, + } + } +} +#[derive(Copy, Clone, Debug)] +pub struct PlaceTy<'tcx> { + place: Place, + pub layout: TyLayout<'tcx>, } -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -pub enum PlaceExtra { - None, - Length(u64), - Vtable(Pointer), - DowncastVariant(usize), +impl<'tcx> ::std::ops::Deref for PlaceTy<'tcx> { + type Target = Place; + #[inline(always)] + fn deref(&self) -> &Place { + &self.place + } } -impl<'tcx> Place { - /// Produces a Place that will error if attempted to be read from - pub fn undef() -> Self { - Self::from_scalar_ptr(Scalar::undef().into(), Align::from_bytes(1, 1).unwrap()) +/// A MemPlace with its layout. Constructing it is only possible in this module. +#[derive(Copy, Clone, Debug)] +pub struct MPlaceTy<'tcx> { + mplace: MemPlace, + pub layout: TyLayout<'tcx>, +} + +impl<'tcx> ::std::ops::Deref for MPlaceTy<'tcx> { + type Target = MemPlace; + #[inline(always)] + fn deref(&self) -> &MemPlace { + &self.mplace + } +} + +impl<'tcx> From> for PlaceTy<'tcx> { + #[inline(always)] + fn from(mplace: MPlaceTy<'tcx>) -> Self { + PlaceTy { + place: Place::Ptr(mplace.mplace), + layout: mplace.layout + } } +} +impl MemPlace { + #[inline(always)] pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { - Place::Ptr { + MemPlace { ptr, align, - extra: PlaceExtra::None, + extra: None, } } + #[inline(always)] pub fn from_ptr(ptr: Pointer, align: Align) -> Self { Self::from_scalar_ptr(ptr.into(), align) } - pub fn to_ptr_align_extra(self) -> (Scalar, Align, PlaceExtra) { - match self { - Place::Ptr { ptr, align, extra } => (ptr, align, extra), - _ => bug!("to_ptr_and_extra: expected Place::Ptr, got {:?}", self), + #[inline(always)] + pub fn to_scalar_ptr_align(self) -> (Scalar, Align) { + assert_eq!(self.extra, None); + (self.ptr, self.align) + } + /// Extract the ptr part of the mplace + #[inline(always)] + pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> { + // At this point, we forget about the alignment information -- + // the place has been turned into a reference, and no matter where it came from, + // it now must be aligned. + self.to_scalar_ptr_align().0.to_ptr() + } + + /// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space. + /// This is the inverse of `ref_to_mplace`. + pub fn to_ref(self) -> Value { + // We ignore the alignment of the place here -- special handling for packed structs ends + // at the `&` operator. + match self.extra { + None => Value::Scalar(self.ptr.into()), + Some(extra) => Value::ScalarPair(self.ptr.into(), extra.into()), } } +} - pub fn to_ptr_align(self) -> (Scalar, Align) { - let (ptr, align, _extra) = self.to_ptr_align_extra(); - (ptr, align) +impl<'tcx> MPlaceTy<'tcx> { + #[inline] + fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self { + MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align), layout } } - pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> { - // At this point, we forget about the alignment information -- the place has been turned into a reference, - // and no matter where it came from, it now must be aligned. - self.to_ptr_align().0.to_ptr() - } - - pub(super) fn elem_ty_and_len( - self, - ty: Ty<'tcx>, - tcx: TyCtxt<'_, 'tcx, '_> - ) -> (Ty<'tcx>, u64) { - match ty.sty { - ty::TyArray(elem, n) => (elem, n.unwrap_usize(tcx)), - - ty::TySlice(elem) => { - match self { - Place::Ptr { extra: PlaceExtra::Length(len), .. } => (elem, len), - _ => { - bug!( - "elem_ty_and_len of a TySlice given non-slice place: {:?}", - self - ) - } - } + #[inline] + pub(super) fn len(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> { + if self.layout.is_unsized() { + // We need to consult `extra` metadata + match self.layout.ty.sty { + ty::Slice(..) | ty::Str => + return self.extra.unwrap().to_usize(cx), + _ => bug!("len not supported on unsized type {:?}", self.layout.ty), } + } else { + // Go through the layout. There are lots of types that support a length, + // e.g. SIMD types. + match self.layout.fields { + layout::FieldPlacement::Array { count, .. } => Ok(count), + _ => bug!("len not supported on sized type {:?}", self.layout.ty), + } + } + } - _ => bug!("elem_ty_and_len expected array or slice, got {:?}", ty), + #[inline] + pub(super) fn vtable(self) -> EvalResult<'tcx, Pointer> { + match self.layout.ty.sty { + ty::Dynamic(..) => self.extra.unwrap().to_ptr(), + _ => bug!("vtable not supported on type {:?}", self.layout.ty), } } } +impl<'tcx> OpTy<'tcx> { + #[inline(always)] + pub fn try_as_mplace(self) -> Result, Value> { + match *self { + Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }), + Operand::Immediate(value) => Err(value), + } + } + + #[inline(always)] + pub fn to_mem_place(self) -> MPlaceTy<'tcx> { + self.try_as_mplace().unwrap() + } +} + +impl<'tcx> Place { + /// Produces a Place that will error if attempted to be read from or written to + #[inline] + pub fn null(cx: impl HasDataLayout) -> Self { + Self::from_scalar_ptr(Scalar::ptr_null(cx), Align::from_bytes(1, 1).unwrap()) + } + + #[inline] + pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { + Place::Ptr(MemPlace::from_scalar_ptr(ptr, align)) + } + + #[inline] + pub fn from_ptr(ptr: Pointer, align: Align) -> Self { + Place::Ptr(MemPlace::from_ptr(ptr, align)) + } + + #[inline] + pub fn to_mem_place(self) -> MemPlace { + match self { + Place::Ptr(mplace) => mplace, + _ => bug!("to_mem_place: expected Place::Ptr, got {:?}", self), + + } + } + + #[inline] + pub fn to_scalar_ptr_align(self) -> (Scalar, Align) { + self.to_mem_place().to_scalar_ptr_align() + } + + #[inline] + pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> { + self.to_mem_place().to_ptr() + } +} + +impl<'tcx> PlaceTy<'tcx> { + /// Produces a Place that will error if attempted to be read from or written to + #[inline] + pub fn null(cx: impl HasDataLayout, layout: TyLayout<'tcx>) -> Self { + PlaceTy { place: Place::from_scalar_ptr(Scalar::ptr_null(cx), layout.align), layout } + } + + #[inline] + pub fn to_mem_place(self) -> MPlaceTy<'tcx> { + MPlaceTy { mplace: self.place.to_mem_place(), layout: self.layout } + } +} + impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { - /// Reads a value from the place without going through the intermediate step of obtaining - /// a `miri::Place` - pub fn try_read_place( + /// Take a value, which represents a (thin or fat) reference, and make it a place. + /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref`. + pub fn ref_to_mplace( + &self, val: ValTy<'tcx> + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty; + let layout = self.layout_of(pointee_type)?; + let align = layout.align; + let mplace = match *val { + Value::Scalar(ptr) => + MemPlace { ptr: ptr.not_undef()?, align, extra: None }, + Value::ScalarPair(ptr, extra) => + MemPlace { ptr: ptr.not_undef()?, align, extra: Some(extra.not_undef()?) }, + }; + Ok(MPlaceTy { mplace, layout }) + } + + /// Offset a pointer to project to a field. Unlike place_field, this is always + /// possible without allocating, so it can take &self. Also return the field's layout. + /// This supports both struct and array fields. + #[inline(always)] + pub fn mplace_field( &self, - place: &mir::Place<'tcx>, - ) -> EvalResult<'tcx, Option> { - use rustc::mir::Place::*; - match *place { - // Might allow this in the future, right now there's no way to do this from Rust code anyway - Local(mir::RETURN_PLACE) => err!(ReadFromReturnPointer), - // Directly reading a local will always succeed - Local(local) => self.frame().get_local(local).map(Some), - // No fast path for statics. Reading from statics is rare and would require another - // Machine function to handle differently in miri. - Promoted(_) | - Static(_) => Ok(None), - Projection(ref proj) => self.try_read_place_projection(proj), - } + base: MPlaceTy<'tcx>, + field: u64, + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + // Not using the layout method because we want to compute on u64 + let offset = match base.layout.fields { + layout::FieldPlacement::Arbitrary { ref offsets, .. } => + offsets[usize::try_from(field).unwrap()], + layout::FieldPlacement::Array { stride, .. } => { + let len = base.len(self)?; + assert!(field < len, "Tried to access element {} of array/slice with length {}", + field, len); + stride * field + } + layout::FieldPlacement::Union(count) => { + assert!(field < count as u64, + "Tried to access field {} of union with {} fields", field, count); + // Offset is always 0 + Size::from_bytes(0) + } + }; + // the only way conversion can fail if is this is an array (otherwise we already panicked + // above). In that case, all fields are equal. + let field_layout = base.layout.field(self, usize::try_from(field).unwrap_or(0))?; + + // Offset may need adjustment for unsized fields + let (extra, offset) = if field_layout.is_unsized() { + // re-use parent metadata to determine dynamic field layout + let (_, align) = self.size_and_align_of(base.extra, field_layout)?; + (base.extra, offset.abi_align(align)) + + } else { + // base.extra could be present; we might be accessing a sized field of an unsized + // struct. + (None, offset) + }; + + let ptr = base.ptr.ptr_offset(offset, self)?; + let align = base.align.min(field_layout.align); // only use static information + + Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout }) } - pub fn read_field( + // Iterates over all fields of an array. Much more efficient than doing the + // same by repeatedly calling `mplace_array`. + pub fn mplace_array_fields( &self, - base: Value, - variant: Option, - field: mir::Field, - mut base_layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx, (Value, TyLayout<'tcx>)> { - if let Some(variant_index) = variant { - base_layout = base_layout.for_variant(self, variant_index); - } - let field_index = field.index(); - let field = base_layout.field(self, field_index)?; - if field.size.bytes() == 0 { - return Ok(( - Value::Scalar(Scalar::undef()), - field, - )); - } - let offset = base_layout.fields.offset(field_index); - let value = match base { - // the field covers the entire type - Value::ScalarPair(..) | - Value::Scalar(_) if offset.bytes() == 0 && field.size == base_layout.size => base, - // extract fields from types with `ScalarPair` ABI - Value::ScalarPair(a, b) => { - let val = if offset.bytes() == 0 { a } else { b }; - Value::Scalar(val) - }, - Value::ByRef(base_ptr, align) => { - let offset = base_layout.fields.offset(field_index); - let ptr = base_ptr.ptr_offset(offset, self)?; - let align = align.min(base_layout.align).min(field.align); - assert!(!field.is_unsized()); - Value::ByRef(ptr, align) - }, - Value::Scalar(val) => bug!("field access on non aggregate {:#?}, {:#?}", val, base_layout), + base: MPlaceTy<'tcx>, + ) -> EvalResult<'tcx, impl Iterator>> + 'a> { + let len = base.len(self)?; // also asserts that we have a type where this makes sense + let stride = match base.layout.fields { + layout::FieldPlacement::Array { stride, .. } => stride, + _ => bug!("mplace_array_fields: expected an array layout"), }; - Ok((value, field)) + let layout = base.layout.field(self, 0)?; + let dl = &self.tcx.data_layout; + Ok((0..len).map(move |i| { + let ptr = base.ptr.ptr_offset(i * stride, dl)?; + Ok(MPlaceTy { + mplace: MemPlace { ptr, align: base.align, extra: None }, + layout + }) + })) } - fn try_read_place_projection( + pub fn mplace_subslice( &self, - proj: &mir::PlaceProjection<'tcx>, - ) -> EvalResult<'tcx, Option> { - use rustc::mir::ProjectionElem::*; - let base = match self.try_read_place(&proj.base)? { - Some(base) => base, - None => return Ok(None), + base: MPlaceTy<'tcx>, + from: u64, + to: u64, + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + let len = base.len(self)?; // also asserts that we have a type where this makes sense + assert!(from <= len - to); + + // Not using layout method because that works with usize, and does not work with slices + // (that have count 0 in their layout). + let from_offset = match base.layout.fields { + layout::FieldPlacement::Array { stride, .. } => + stride * from, + _ => bug!("Unexpected layout of index access: {:#?}", base.layout), }; - let base_ty = self.place_ty(&proj.base); - let base_layout = self.layout_of(base_ty)?; - match proj.elem { - Field(field, _) => Ok(Some(self.read_field(base, None, field, base_layout)?.0)), - // The NullablePointer cases should work fine, need to take care for normal enums - Downcast(..) | - Subslice { .. } | - // reading index 0 or index 1 from a ByVal or ByVal pair could be optimized - ConstantIndex { .. } | Index(_) | - // No way to optimize this projection any better than the normal place path - Deref => Ok(None), - } + let ptr = base.ptr.ptr_offset(from_offset, self)?; + + // Compute extra and new layout + let inner_len = len - to - from; + let (extra, ty) = match base.layout.ty.sty { + // It is not nice to match on the type, but that seems to be the only way to + // implement this. + ty::Array(inner, _) => + (None, self.tcx.mk_array(inner, inner_len)), + ty::Slice(..) => { + let len = Scalar::from_uint(inner_len, self.pointer_size()); + (Some(len), base.layout.ty) + } + _ => + bug!("cannot subslice non-array type: `{:?}`", base.layout.ty), + }; + let layout = self.layout_of(ty)?; + + Ok(MPlaceTy { + mplace: MemPlace { ptr, align: base.align, extra }, + layout + }) + } + + pub fn mplace_downcast( + &self, + base: MPlaceTy<'tcx>, + variant: usize, + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + // Downcasts only change the layout + assert_eq!(base.extra, None); + Ok(MPlaceTy { layout: base.layout.for_variant(self, variant), ..base }) + } + + /// Project into an mplace + pub fn mplace_projection( + &self, + base: MPlaceTy<'tcx>, + proj_elem: &mir::PlaceElem<'tcx>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + use rustc::mir::ProjectionElem::*; + Ok(match *proj_elem { + Field(field, _) => self.mplace_field(base, field.index() as u64)?, + Downcast(_, variant) => self.mplace_downcast(base, variant)?, + Deref => self.deref_operand(base.into())?, + + Index(local) => { + let n = *self.frame().locals[local].access()?; + let n_layout = self.layout_of(self.tcx.types.usize)?; + let n = self.read_scalar(OpTy { op: n, layout: n_layout })?; + let n = n.to_bits(self.tcx.data_layout.pointer_size)?; + self.mplace_field(base, u64::try_from(n).unwrap())? + } + + ConstantIndex { + offset, + min_length, + from_end, + } => { + let n = base.len(self)?; + assert!(n >= min_length as u64); + + let index = if from_end { + n - u64::from(offset) + } else { + u64::from(offset) + }; + + self.mplace_field(base, index)? + } + + Subslice { from, to } => + self.mplace_subslice(base, u64::from(from), u64::from(to))?, + }) } - /// Returns a value and (in case of a ByRef) if we are supposed to use aligned accesses. - pub(super) fn eval_and_read_place( + /// Get the place of a field inside the place, and also the field's type. + /// Just a convenience function, but used quite a bit. + pub fn place_field( &mut self, - place: &mir::Place<'tcx>, - ) -> EvalResult<'tcx, Value> { - // Shortcut for things like accessing a fat pointer's field, - // which would otherwise (in the `eval_place` path) require moving a `ScalarPair` to memory - // and returning an `Place::Ptr` to it - if let Some(val) = self.try_read_place(place)? { - return Ok(val); - } - let place = self.eval_place(place)?; - self.read_place(place) + base: PlaceTy<'tcx>, + field: u64, + ) -> EvalResult<'tcx, PlaceTy<'tcx>> { + // FIXME: We could try to be smarter and avoid allocation for fields that span the + // entire place. + let mplace = self.force_allocation(base)?; + Ok(self.mplace_field(mplace, field)?.into()) } - pub fn read_place(&self, place: Place) -> EvalResult<'tcx, Value> { - match place { - Place::Ptr { ptr, align, extra } => { - assert_eq!(extra, PlaceExtra::None); - Ok(Value::ByRef(ptr, align)) + pub fn place_downcast( + &mut self, + base: PlaceTy<'tcx>, + variant: usize, + ) -> EvalResult<'tcx, PlaceTy<'tcx>> { + // Downcast just changes the layout + Ok(match base.place { + Place::Ptr(mplace) => + self.mplace_downcast(MPlaceTy { mplace, layout: base.layout }, variant)?.into(), + Place::Local { .. } => { + let layout = base.layout.for_variant(&self, variant); + PlaceTy { layout, ..base } } - Place::Local { frame, local } => self.stack[frame].get_local(local), - } + }) } - pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, Place> { - use rustc::mir::Place::*; - let place = match *mir_place { - Local(mir::RETURN_PLACE) => self.frame().return_place, - Local(local) => Place::Local { - frame: self.cur_frame(), - local, - }, + /// Project into a place + pub fn place_projection( + &mut self, + base: PlaceTy<'tcx>, + proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>, + ) -> EvalResult<'tcx, PlaceTy<'tcx>> { + use rustc::mir::ProjectionElem::*; + Ok(match *proj_elem { + Field(field, _) => self.place_field(base, field.index() as u64)?, + Downcast(_, variant) => self.place_downcast(base, variant)?, + Deref => self.deref_operand(self.place_to_op(base)?)?.into(), + // For the other variants, we have to force an allocation. + // This matches `operand_projection`. + Subslice { .. } | ConstantIndex { .. } | Index(_) => { + let mplace = self.force_allocation(base)?; + self.mplace_projection(mplace, proj_elem)?.into() + } + }) + } + /// Evaluate statics and promoteds to an `MPlace`. Used to share some code between + /// `eval_place` and `eval_place_to_op`. + pub(super) fn eval_place_to_mplace( + &self, + mir_place: &mir::Place<'tcx> + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + use rustc::mir::Place::*; + Ok(match *mir_place { Promoted(ref promoted) => { let instance = self.frame().instance; - let val = self.read_global_as_value(GlobalId { + let op = self.global_to_op(GlobalId { instance, promoted: Some(promoted.0), })?; - if let Value::ByRef(ptr, align) = val { - Place::Ptr { - ptr, - align, - extra: PlaceExtra::None, - } - } else { - bug!("evaluated promoted and got {:#?}", val); + let mplace = op.to_mem_place(); // these are always in memory + let ty = self.monomorphize(promoted.1, self.substs()); + MPlaceTy { + mplace, + layout: self.layout_of(ty)?, } } Static(ref static_) => { - let layout = self.layout_of(self.place_ty(mir_place))?; + let ty = self.monomorphize(static_.ty, self.substs()); + let layout = self.layout_of(ty)?; let instance = ty::Instance::mono(*self.tcx, static_.def_id); let cid = GlobalId { instance, promoted: None }; - let alloc = Machine::init_static(self, cid)?; - Place::Ptr { - ptr: Scalar::Ptr(alloc.into()), - align: layout.align, - extra: PlaceExtra::None, - } + // Just create a lazy reference, so we can support recursive statics. + // tcx takes are of assigning every static one and only one unique AllocId. + // When the data here is ever actually used, memory will notice, + // and it knows how to deal with alloc_id that are present in the + // global table but not in its local memory: It calls back into tcx through + // a query, triggering the CTFE machinery to actually turn this lazy reference + // into a bunch of bytes. IOW, statics are evaluated with CTFE even when + // this EvalContext uses another Machine (e.g., in miri). This is what we + // want! This way, computing statics works concistently between codegen + // and miri: They use the same query to eventually obtain a `ty::Const` + // and use that for further computation. + let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id()); + MPlaceTy::from_aligned_ptr(alloc.into(), layout) } + _ => bug!("eval_place_to_mplace called on {:?}", mir_place), + }) + } + + /// Compute a place. You should only use this if you intend to write into this + /// place; for reading, a more efficient alternative is `eval_place_for_read`. + pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, PlaceTy<'tcx>> { + use rustc::mir::Place::*; + let place = match *mir_place { + Local(mir::RETURN_PLACE) => PlaceTy { + place: self.frame().return_place, + layout: self.layout_of_local(self.cur_frame(), mir::RETURN_PLACE)?, + }, + Local(local) => PlaceTy { + place: Place::Local { + frame: self.cur_frame(), + local, + }, + layout: self.layout_of_local(self.cur_frame(), local)?, + }, + Projection(ref proj) => { - let ty = self.place_ty(&proj.base); let place = self.eval_place(&proj.base)?; - return self.eval_place_projection(place, ty, &proj.elem); + self.place_projection(place, &proj.elem)? } - }; - self.dump_local(place); + _ => self.eval_place_to_mplace(mir_place)?.into(), + }; + self.dump_place(place.place); Ok(place) } - pub fn place_field( + /// Write a scalar to a place + pub fn write_scalar( &mut self, - base: Place, - field: mir::Field, - mut base_layout: TyLayout<'tcx>, - ) -> EvalResult<'tcx, (Place, TyLayout<'tcx>)> { - match base { - Place::Ptr { extra: PlaceExtra::DowncastVariant(variant_index), .. } => { - base_layout = base_layout.for_variant(&self, variant_index); - } - _ => {} - } - let field_index = field.index(); - let field = base_layout.field(&self, field_index)?; - let offset = base_layout.fields.offset(field_index); + val: impl Into, + dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + self.write_value(Value::Scalar(val.into()), dest) + } - // Do not allocate in trivial cases - let (base_ptr, base_align, base_extra) = match base { - Place::Ptr { ptr, align, extra } => (ptr, align, extra), + /// Write a value to a place + pub fn write_value( + &mut self, + src_val: Value, + dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + trace!("write_value: {:?} <- {:?}", *dest, src_val); + // See if we can avoid an allocation. This is the counterpart to `try_read_value`, + // but not factored as a separate function. + let mplace = match dest.place { Place::Local { frame, local } => { - match (&self.stack[frame].get_local(local)?, &base_layout.abi) { - // in case the field covers the entire type, just return the value - (&Value::Scalar(_), &layout::Abi::Scalar(_)) | - (&Value::ScalarPair(..), &layout::Abi::ScalarPair(..)) - if offset.bytes() == 0 && field.size == base_layout.size => - { - return Ok((base, field)); - } - _ => self.force_allocation(base)?.to_ptr_align_extra(), + match *self.stack[frame].locals[local].access_mut()? { + Operand::Immediate(ref mut dest_val) => { + // Yay, we can just change the local directly. + *dest_val = src_val; + return Ok(()); + }, + Operand::Indirect(mplace) => mplace, // already in memory } - } - }; - - let offset = match base_extra { - PlaceExtra::Vtable(tab) => { - let (_, align) = self.size_and_align_of_dst( - base_layout.ty, - base_ptr.to_value_with_vtable(tab), - )?; - offset.abi_align(align) - } - _ => offset, - }; - - let ptr = base_ptr.ptr_offset(offset, &self)?; - let align = base_align.min(base_layout.align).min(field.align); - let extra = if !field.is_unsized() { - PlaceExtra::None - } else { - match base_extra { - PlaceExtra::None => bug!("expected fat pointer"), - PlaceExtra::DowncastVariant(..) => { - bug!("Rust doesn't support unsized fields in enum variants") - } - PlaceExtra::Vtable(_) | - PlaceExtra::Length(_) => {} - } - base_extra + }, + Place::Ptr(mplace) => mplace, // already in memory }; - Ok((Place::Ptr { ptr, align, extra }, field)) + // This is already in memory, write there. + let dest = MPlaceTy { mplace, layout: dest.layout }; + self.write_value_to_mplace(src_val, dest) } - pub fn val_to_place(&self, val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Place> { - let layout = self.layout_of(ty)?; - Ok(match self.tcx.struct_tail(ty).sty { - ty::TyDynamic(..) => { - let (ptr, vtable) = self.into_ptr_vtable_pair(val)?; - Place::Ptr { - ptr, - align: layout.align, - extra: PlaceExtra::Vtable(vtable), - } + /// Write a value to memory + fn write_value_to_mplace( + &mut self, + value: Value, + dest: MPlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + let (ptr, ptr_align) = dest.to_scalar_ptr_align(); + // Note that it is really important that the type here is the right one, and matches the + // type things are read at. In case `src_val` is a `ScalarPair`, we don't do any magic here + // to handle padding properly, which is only correct if we never look at this data with the + // wrong type. + + // Nothing to do for ZSTs, other than checking alignment + if dest.layout.is_zst() { + self.memory.check_align(ptr, ptr_align)?; + return Ok(()); + } + + let ptr = ptr.to_ptr()?; + match value { + Value::Scalar(scalar) => { + self.memory.write_scalar( + ptr, ptr_align.min(dest.layout.align), scalar, dest.layout.size + ) } - ty::TyStr | ty::TySlice(_) => { - let (ptr, len) = self.into_slice(val)?; - Place::Ptr { - ptr, - align: layout.align, - extra: PlaceExtra::Length(len), - } + Value::ScalarPair(a_val, b_val) => { + let (a, b) = match dest.layout.abi { + layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value), + _ => bug!("write_value_to_mplace: invalid ScalarPair layout: {:#?}", + dest.layout) + }; + let (a_size, b_size) = (a.size(&self), b.size(&self)); + let (a_align, b_align) = (a.align(&self), b.align(&self)); + let b_offset = a_size.abi_align(b_align); + let b_ptr = ptr.offset(b_offset, &self)?.into(); + + self.memory.write_scalar(ptr, ptr_align.min(a_align), a_val, a_size)?; + self.memory.write_scalar(b_ptr, ptr_align.min(b_align), b_val, b_size) } - _ => Place::from_scalar_ptr(self.into_ptr(val)?, layout.align), - }) + } } - pub fn place_index( + /// Copy the data from an operand to a place + pub fn copy_op( &mut self, - base: Place, - outer_ty: Ty<'tcx>, - n: u64, - ) -> EvalResult<'tcx, Place> { - // Taking the outer type here may seem odd; it's needed because for array types, the outer type gives away the length. - let base = self.force_allocation(base)?; - let (base_ptr, align) = base.to_ptr_align(); - - let (elem_ty, len) = base.elem_ty_and_len(outer_ty, self.tcx.tcx); - let elem_size = self.layout_of(elem_ty)?.size; - assert!( - n < len, - "Tried to access element {} of array/slice with length {}", - n, - len - ); - let ptr = base_ptr.ptr_offset(elem_size * n, &*self)?; - Ok(Place::Ptr { - ptr, - align, - extra: PlaceExtra::None, - }) + src: OpTy<'tcx>, + dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + assert!(!src.layout.is_unsized() && !dest.layout.is_unsized(), + "Cannot copy unsized data"); + assert_eq!(src.layout.size, dest.layout.size, + "Size mismatch when copying!\nsrc: {:#?}\ndest: {:#?}", src, dest); + + // Let us see if the layout is simple so we take a shortcut, avoid force_allocation. + let (src_ptr, src_align) = match self.try_read_value(src)? { + Ok(src_val) => + // Yay, we got a value that we can write directly. We write with the + // *source layout*, because that was used to load, and if they do not match + // this is a transmute we want to support. + return self.write_value(src_val, PlaceTy { place: *dest, layout: src.layout }), + Err(mplace) => mplace.to_scalar_ptr_align(), + }; + // Slow path, this does not fit into an immediate. Just memcpy. + trace!("copy_op: {:?} <- {:?}", *dest, *src); + let (dest_ptr, dest_align) = self.force_allocation(dest)?.to_scalar_ptr_align(); + self.memory.copy( + src_ptr, src_align, + dest_ptr, dest_align, + src.layout.size, false + ) } - pub(super) fn place_downcast( + /// Make sure that a place is in memory, and return where it is. + /// This is essentially `force_to_memplace`. + pub fn force_allocation( &mut self, - base: Place, - variant: usize, - ) -> EvalResult<'tcx, Place> { - // FIXME(solson) - let base = self.force_allocation(base)?; - let (ptr, align) = base.to_ptr_align(); - let extra = PlaceExtra::DowncastVariant(variant); - Ok(Place::Ptr { ptr, align, extra }) + place: PlaceTy<'tcx>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + let mplace = match place.place { + Place::Local { frame, local } => { + match *self.stack[frame].locals[local].access()? { + Operand::Indirect(mplace) => mplace, + Operand::Immediate(value) => { + // We need to make an allocation. + // FIXME: Consider not doing anything for a ZST, and just returning + // a fake pointer? Are we even called for ZST? + + // We need the layout of the local. We can NOT use the layout we got, + // that might e.g. be an inner field of a struct with `Scalar` layout, + // that has different alignment than the outer field. + let local_layout = self.layout_of_local(frame, local)?; + let ptr = self.allocate(local_layout, MemoryKind::Stack)?; + self.write_value_to_mplace(value, ptr)?; + let mplace = ptr.mplace; + // Update the local + *self.stack[frame].locals[local].access_mut()? = + Operand::Indirect(mplace); + mplace + } + } + } + Place::Ptr(mplace) => mplace + }; + // Return with the original layout, so that the caller can go on + Ok(MPlaceTy { mplace, layout: place.layout }) } - pub fn eval_place_projection( + pub fn allocate( &mut self, - base: Place, - base_ty: Ty<'tcx>, - proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>, - ) -> EvalResult<'tcx, Place> { - use rustc::mir::ProjectionElem::*; - match *proj_elem { - Field(field, _) => { - let layout = self.layout_of(base_ty)?; - Ok(self.place_field(base, field, layout)?.0) - } - - Downcast(_, variant) => { - self.place_downcast(base, variant) - } - - Deref => { - let val = self.read_place(base)?; - - let pointee_type = match base_ty.sty { - ty::TyRawPtr(ref tam) => tam.ty, - ty::TyRef(_, ty, _) => ty, - ty::TyAdt(def, _) if def.is_box() => base_ty.boxed_ty(), - _ => bug!("can only deref pointer types"), - }; - - trace!("deref to {} on {:?}", pointee_type, val); + layout: TyLayout<'tcx>, + kind: MemoryKind, + ) -> EvalResult<'tcx, MPlaceTy<'tcx>> { + assert!(!layout.is_unsized(), "cannot alloc memory for unsized type"); + let ptr = self.memory.allocate(layout.size, layout.align, kind)?; + Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) + } - self.val_to_place(val, pointee_type) + pub fn write_discriminant_index( + &mut self, + variant_index: usize, + dest: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + match dest.layout.variants { + layout::Variants::Single { index } => { + assert_eq!(index, variant_index); } - - Index(local) => { - let value = self.frame().get_local(local)?; - let ty = self.tcx.types.usize; - let n = self - .value_to_scalar(ValTy { value, ty })? - .to_bits(self.tcx.data_layout.pointer_size)?; - self.place_index(base, base_ty, n as u64) + layout::Variants::Tagged { ref tag, .. } => { + let adt_def = dest.layout.ty.ty_adt_def().unwrap(); + assert!(variant_index < adt_def.variants.len()); + let discr_val = adt_def + .discriminant_for_variant(*self.tcx, variant_index) + .val; + + // raw discriminants for enums are isize or bigger during + // their computation, but the in-memory tag is the smallest possible + // representation + let size = tag.value.size(self.tcx.tcx); + let shift = 128 - size.bits(); + let discr_val = (discr_val << shift) >> shift; + + let discr_dest = self.place_field(dest, 0)?; + self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?; } - - ConstantIndex { - offset, - min_length, - from_end, + layout::Variants::NicheFilling { + dataful_variant, + ref niche_variants, + niche_start, + .. } => { - // FIXME(solson) - let base = self.force_allocation(base)?; - let (base_ptr, align) = base.to_ptr_align(); - - let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx); - let elem_size = self.layout_of(elem_ty)?.size; - assert!(n >= min_length as u64); + assert!(variant_index < dest.layout.ty.ty_adt_def().unwrap().variants.len()); + if variant_index != dataful_variant { + let niche_dest = + self.place_field(dest, 0)?; + let niche_value = ((variant_index - niche_variants.start()) as u128) + .wrapping_add(niche_start); + self.write_scalar( + Scalar::from_uint(niche_value, niche_dest.layout.size), + niche_dest + )?; + } + } + } - let index = if from_end { - n - u64::from(offset) - } else { - u64::from(offset) - }; + Ok(()) + } - let ptr = base_ptr.ptr_offset(elem_size * index, &self)?; - Ok(Place::Ptr { ptr, align, extra: PlaceExtra::None }) + /// Every place can be read from, so we can turm them into an operand + #[inline(always)] + pub fn place_to_op(&self, place: PlaceTy<'tcx>) -> EvalResult<'tcx, OpTy<'tcx>> { + let op = match place.place { + Place::Ptr(mplace) => { + Operand::Indirect(mplace) } + Place::Local { frame, local } => + *self.stack[frame].locals[local].access()? + }; + Ok(OpTy { op, layout: place.layout }) + } - Subslice { from, to } => { - // FIXME(solson) - let base = self.force_allocation(base)?; - let (base_ptr, align) = base.to_ptr_align(); - - let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx); - let elem_size = self.layout_of(elem_ty)?.size; - assert!(u64::from(from) <= n - u64::from(to)); - let ptr = base_ptr.ptr_offset(elem_size * u64::from(from), &self)?; - // sublicing arrays produces arrays - let extra = if self.type_is_sized(base_ty) { - PlaceExtra::None - } else { - PlaceExtra::Length(n - u64::from(to) - u64::from(from)) - }; - Ok(Place::Ptr { ptr, align, extra }) - } + /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type. + /// Also return some more information so drop doesn't have to run the same code twice. + pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx>) + -> EvalResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx>)> { + let vtable = mplace.vtable()?; // also sanity checks the type + let (instance, ty) = self.read_drop_type_from_vtable(vtable)?; + let layout = self.layout_of(ty)?; + + // More sanity checks + if cfg!(debug_assertions) { + let (size, align) = self.read_size_and_align_from_vtable(vtable)?; + assert_eq!(size, layout.size); + assert_eq!(align.abi(), layout.align.abi()); // only ABI alignment is preserved } - } - pub fn place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> { - self.monomorphize( - place.ty(self.mir(), *self.tcx).to_ty(*self.tcx), - self.substs(), - ) + let mplace = MPlaceTy { + mplace: MemPlace { extra: None, ..*mplace }, + layout + }; + Ok((instance, mplace)) } } diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs new file mode 100644 index 0000000000..0e8466905e --- /dev/null +++ b/src/librustc_mir/interpret/snapshot.rs @@ -0,0 +1,410 @@ +//! This module contains the machinery necessary to detect infinite loops +//! during const-evaluation by taking snapshots of the state of the interpreter +//! at regular intervals. + +use std::hash::{Hash, Hasher}; + +use rustc::ich::{StableHashingContext, StableHashingContextProvider}; +use rustc::mir; +use rustc::mir::interpret::{ + AllocId, Pointer, Scalar, ScalarMaybeUndef, + Relocations, Allocation, UndefMask, + EvalResult, EvalErrorKind, +}; + +use rustc::ty::{self, TyCtxt}; +use rustc::ty::layout::Align; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; +use syntax::ast::Mutability; +use syntax::source_map::Span; + +use super::eval_context::{LocalValue, StackPopCleanup}; +use super::{Frame, Memory, Machine, Operand, MemPlace, Place, Value}; + +pub(super) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { + /// The set of all `EvalSnapshot` *hashes* observed by this detector. + /// + /// When a collision occurs in this table, we store the full snapshot in + /// `snapshots`. + hashes: FxHashSet, + + /// The set of all `EvalSnapshot`s observed by this detector. + /// + /// An `EvalSnapshot` will only be fully cloned once it has caused a + /// collision in `hashes`. As a result, the detector must observe at least + /// *two* full cycles of an infinite loop before it triggers. + snapshots: FxHashSet>, +} + +impl<'a, 'mir, 'tcx, M> Default for InfiniteLoopDetector<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, + 'tcx: 'a + 'mir, +{ + fn default() -> Self { + InfiniteLoopDetector { + hashes: FxHashSet::default(), + snapshots: FxHashSet::default(), + } + } +} + +impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, + 'tcx: 'a + 'mir, +{ + /// Returns `true` if the loop detector has not yet observed a snapshot. + pub fn is_empty(&self) -> bool { + self.hashes.is_empty() + } + + pub fn observe_and_analyze( + &mut self, + tcx: &TyCtxt<'b, 'tcx, 'tcx>, + memory: &Memory<'a, 'mir, 'tcx, M>, + stack: &[Frame<'mir, 'tcx>], + ) -> EvalResult<'tcx, ()> { + + let mut hcx = tcx.get_stable_hashing_context(); + let mut hasher = StableHasher::::new(); + stack.hash_stable(&mut hcx, &mut hasher); + let hash = hasher.finish(); + + if self.hashes.insert(hash) { + // No collision + return Ok(()) + } + + info!("snapshotting the state of the interpreter"); + + if self.snapshots.insert(EvalSnapshot::new(memory, stack)) { + // Spurious collision or first cycle + return Ok(()) + } + + // Second cycle + Err(EvalErrorKind::InfiniteLoop.into()) + } +} + +trait SnapshotContext<'a> { + fn resolve(&'a self, id: &AllocId) -> Option<&'a Allocation>; +} + +/// Taking a snapshot of the evaluation context produces a view of +/// the state of the interpreter that is invariant to `AllocId`s. +trait Snapshot<'a, Ctx: SnapshotContext<'a>> { + type Item; + fn snapshot(&self, ctx: &'a Ctx) -> Self::Item; +} + +macro_rules! __impl_snapshot_field { + ($field:ident, $ctx:expr) => ($field.snapshot($ctx)); + ($field:ident, $ctx:expr, $delegate:expr) => ($delegate); +} + +macro_rules! impl_snapshot_for { + // FIXME(mark-i-m): Some of these should be `?` rather than `*`. + (enum $enum_name:ident { + $( $variant:ident $( ( $($field:ident $(-> $delegate:expr)*),* ) )* ),* $(,)* + }) => { + + impl<'a, Ctx> self::Snapshot<'a, Ctx> for $enum_name + where Ctx: self::SnapshotContext<'a>, + { + type Item = $enum_name>; + + #[inline] + fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item { + match *self { + $( + $enum_name::$variant $( ( $(ref $field),* ) )* => + $enum_name::$variant $( + ( $( __impl_snapshot_field!($field, __ctx $(, $delegate)*) ),* ), + )* + )* + } + } + } + }; + + // FIXME(mark-i-m): same here. + (struct $struct_name:ident { $($field:ident $(-> $delegate:expr)*),* $(,)* }) => { + impl<'a, Ctx> self::Snapshot<'a, Ctx> for $struct_name + where Ctx: self::SnapshotContext<'a>, + { + type Item = $struct_name>; + + #[inline] + fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item { + let $struct_name { + $(ref $field),* + } = *self; + + $struct_name { + $( $field: __impl_snapshot_field!($field, __ctx $(, $delegate)*) ),* + } + } + } + }; +} + +impl<'a, Ctx, T> Snapshot<'a, Ctx> for Option + where Ctx: SnapshotContext<'a>, + T: Snapshot<'a, Ctx> +{ + type Item = Option<>::Item>; + + fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { + match self { + Some(x) => Some(x.snapshot(ctx)), + None => None, + } + } +} + +#[derive(Eq, PartialEq)] +struct AllocIdSnapshot<'a>(Option>); + +impl<'a, Ctx> Snapshot<'a, Ctx> for AllocId + where Ctx: SnapshotContext<'a>, +{ + type Item = AllocIdSnapshot<'a>; + + fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { + AllocIdSnapshot(ctx.resolve(self).map(|alloc| alloc.snapshot(ctx))) + } +} + +impl_snapshot_for!(struct Pointer { + alloc_id, + offset -> *offset, +}); + +impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar + where Ctx: SnapshotContext<'a>, +{ + type Item = Scalar>; + + fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { + match self { + Scalar::Ptr(p) => Scalar::Ptr(p.snapshot(ctx)), + Scalar::Bits{ size, bits } => Scalar::Bits { + size: *size, + bits: *bits, + }, + } + } +} + +impl_snapshot_for!(enum ScalarMaybeUndef { + Scalar(s), + Undef, +}); + +impl_snapshot_for!(struct MemPlace { + ptr, + extra, + align -> *align, +}); + +impl<'a, Ctx> Snapshot<'a, Ctx> for Place + where Ctx: SnapshotContext<'a>, +{ + type Item = Place>; + + fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { + match self { + Place::Ptr(p) => Place::Ptr(p.snapshot(ctx)), + + Place::Local{ frame, local } => Place::Local{ + frame: *frame, + local: *local, + }, + } + } +} + +impl_snapshot_for!(enum Value { + Scalar(s), + ScalarPair(s, t), +}); + +impl_snapshot_for!(enum Operand { + Immediate(v), + Indirect(m), +}); + +impl_snapshot_for!(enum LocalValue { + Live(v), + Dead, +}); + +impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations + where Ctx: SnapshotContext<'a>, +{ + type Item = Relocations>; + + fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { + Relocations::from_presorted(self.iter() + .map(|(size, id)| (*size, id.snapshot(ctx))) + .collect()) + } +} + +#[derive(Eq, PartialEq)] +struct AllocationSnapshot<'a> { + bytes: &'a [u8], + relocations: Relocations>, + undef_mask: &'a UndefMask, + align: &'a Align, + mutability: &'a Mutability, +} + +impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation + where Ctx: SnapshotContext<'a>, +{ + type Item = AllocationSnapshot<'a>; + + fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { + let Allocation { bytes, relocations, undef_mask, align, mutability } = self; + + AllocationSnapshot { + bytes, + undef_mask, + align, + mutability, + relocations: relocations.snapshot(ctx), + } + } +} + +#[derive(Eq, PartialEq)] +struct FrameSnapshot<'a, 'tcx: 'a> { + instance: &'a ty::Instance<'tcx>, + span: &'a Span, + return_to_block: &'a StackPopCleanup, + return_place: Place>, + locals: IndexVec>>, + block: &'a mir::BasicBlock, + stmt: usize, +} + +impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx> + where Ctx: SnapshotContext<'a>, +{ + type Item = FrameSnapshot<'a, 'tcx>; + + fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { + let Frame { + mir: _, + instance, + span, + return_to_block, + return_place, + locals, + block, + stmt, + } = self; + + FrameSnapshot { + instance, + span, + return_to_block, + block, + stmt: *stmt, + return_place: return_place.snapshot(ctx), + locals: locals.iter().map(|local| local.snapshot(ctx)).collect(), + } + } +} + +#[derive(Eq, PartialEq)] +struct MemorySnapshot<'a, 'mir: 'a, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx> + 'a> { + data: &'a M::MemoryData, +} + +impl<'a, 'mir, 'tcx, M> Memory<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, +{ + fn snapshot<'b: 'a>(&'b self) -> MemorySnapshot<'b, 'mir, 'tcx, M> { + let Memory { data, .. } = self; + MemorySnapshot { data } + } +} + +impl<'a, 'b, 'mir, 'tcx, M> SnapshotContext<'b> for Memory<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, +{ + fn resolve(&'b self, id: &AllocId) -> Option<&'b Allocation> { + self.get(*id).ok() + } +} + +/// The virtual machine state during const-evaluation at a given point in time. +struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { + memory: Memory<'a, 'mir, 'tcx, M>, + stack: Vec>, +} + +impl<'a, 'mir, 'tcx, M> EvalSnapshot<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, +{ + fn new( + memory: &Memory<'a, 'mir, 'tcx, M>, + stack: &[Frame<'mir, 'tcx>] + ) -> Self { + EvalSnapshot { + memory: memory.clone(), + stack: stack.into(), + } + } + + fn snapshot<'b: 'a>(&'b self) + -> (MemorySnapshot<'b, 'mir, 'tcx, M>, Vec>) + { + let EvalSnapshot{ memory, stack } = self; + (memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect()) + } +} + +impl<'a, 'mir, 'tcx, M> Hash for EvalSnapshot<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, +{ + fn hash(&self, state: &mut H) { + // Implement in terms of hash stable, so that k1 == k2 -> hash(k1) == hash(k2) + let mut hcx = self.memory.tcx.get_stable_hashing_context(); + let mut hasher = StableHasher::::new(); + self.hash_stable(&mut hcx, &mut hasher); + hasher.finish().hash(state) + } +} + +// Not using the macro because we need special handling for `memory`, which the macro +// does not support at the same time as the extra bounds on the type. +impl<'a, 'b, 'mir, 'tcx, M> HashStable> + for EvalSnapshot<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, +{ + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'b>, + hasher: &mut StableHasher) + { + let EvalSnapshot{ memory: _, stack } = self; + stack.hash_stable(hcx, hasher); + } +} + +impl<'a, 'mir, 'tcx, M> Eq for EvalSnapshot<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, +{} + +impl<'a, 'mir, 'tcx, M> PartialEq for EvalSnapshot<'a, 'mir, 'tcx, M> + where M: Machine<'mir, 'tcx>, +{ + fn eq(&self, other: &Self) -> bool { + self.snapshot() == other.snapshot() + } +} diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index db90714d0e..5bdaf6ba72 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -1,12 +1,50 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! This module contains the `EvalContext` methods for executing a single step of the interpreter. //! //! The main entry point is the `step` method. use rustc::mir; +use rustc::ty::layout::LayoutOf; +use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic}; -use rustc::mir::interpret::EvalResult; use super::{EvalContext, Machine}; +/// Classify whether an operator is "left-homogeneous", i.e. the LHS has the +/// same type as the result. +#[inline] +fn binop_left_homogeneous(op: mir::BinOp) -> bool { + use rustc::mir::BinOp::*; + match op { + Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | + Offset | Shl | Shr => + true, + Eq | Ne | Lt | Le | Gt | Ge => + false, + } +} +/// Classify whether an operator is "right-homogeneous", i.e. the RHS has the +/// same type as the LHS. +#[inline] +fn binop_right_homogeneous(op: mir::BinOp) -> bool { + use rustc::mir::BinOp::*; + match op { + Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | + Eq | Ne | Lt | Le | Gt | Ge => + true, + Offset | Shl | Shr => + false, + } +} + impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { pub fn inc_step_counter_and_detect_loops(&mut self) -> EvalResult<'tcx, ()> { /// The number of steps between loop detector snapshots. @@ -27,6 +65,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } } + if !M::DETECT_LOOPS { + return Ok(()); + } + if self.loop_detector.is_empty() { // First run of the loop detector @@ -35,11 +77,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { "Constant evaluating a complex constant, this might take some time"); } - self.loop_detector.observe_and_analyze(&self.machine, &self.stack, &self.memory) + self.loop_detector.observe_and_analyze( + &self.tcx, + &self.memory, + &self.stack[..], + ) + } + + pub fn run(&mut self) -> EvalResult<'tcx> { + while self.step()? {} + Ok(()) } /// Returns true as long as there are more things to do. - pub fn step(&mut self) -> EvalResult<'tcx, bool> { + fn step(&mut self) -> EvalResult<'tcx, bool> { if self.stack.is_empty() { return Ok(false); } @@ -66,12 +117,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> { - trace!("{:?}", stmt); + debug!("{:?}", stmt); use rustc::mir::StatementKind::*; - // Some statements (e.g. box) push new stack frames. We have to record the stack frame number - // *before* executing the statement. + // Some statements (e.g. box) push new stack frames. + // We have to record the stack frame number *before* executing the statement. let frame_idx = self.cur_frame(); self.tcx.span = stmt.source_info.span; self.memory.tcx.span = stmt.source_info.span; @@ -84,19 +135,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { variant_index, } => { let dest = self.eval_place(place)?; - let dest_ty = self.place_ty(place); - self.write_discriminant_value(dest_ty, dest, variant_index)?; + self.write_discriminant_index(variant_index, dest)?; } // Mark locals as alive StorageLive(local) => { - let old_val = self.frame_mut().storage_live(local); + let old_val = self.storage_live(local)?; self.deallocate_local(old_val)?; } // Mark locals as dead StorageDead(local) => { - let old_val = self.frame_mut().storage_dead(local); + let old_val = self.storage_dead(local); self.deallocate_local(old_val)?; } @@ -110,11 +160,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { M::validation_op(self, op, operand)?; } } - EndRegion(ce) => { - M::end_region(self, Some(ce))?; - } - UserAssertTy(..) => {} + EndRegion(..) => {} + AscribeUserType(..) => {} // Defined to do nothing. These are added by optimization passes, to avoid changing the // size of MIR constantly. @@ -127,13 +175,168 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Ok(()) } + /// Evaluate an assignment statement. + /// + /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue + /// type writes its results directly into the memory specified by the place. + fn eval_rvalue_into_place( + &mut self, + rvalue: &mir::Rvalue<'tcx>, + place: &mir::Place<'tcx>, + ) -> EvalResult<'tcx> { + let dest = self.eval_place(place)?; + + use rustc::mir::Rvalue::*; + match *rvalue { + Use(ref operand) => { + // Avoid recomputing the layout + let op = self.eval_operand(operand, Some(dest.layout))?; + self.copy_op(op, dest)?; + } + + BinaryOp(bin_op, ref left, ref right) => { + let layout = if binop_left_homogeneous(bin_op) { Some(dest.layout) } else { None }; + let left = self.read_value(self.eval_operand(left, layout)?)?; + let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None }; + let right = self.read_value(self.eval_operand(right, layout)?)?; + self.binop_ignore_overflow( + bin_op, + left, + right, + dest, + )?; + } + + CheckedBinaryOp(bin_op, ref left, ref right) => { + // Due to the extra boolean in the result, we can never reuse the `dest.layout`. + let left = self.read_value(self.eval_operand(left, None)?)?; + let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None }; + let right = self.read_value(self.eval_operand(right, layout)?)?; + self.binop_with_overflow( + bin_op, + left, + right, + dest, + )?; + } + + UnaryOp(un_op, ref operand) => { + // The operand always has the same type as the result. + let val = self.read_value(self.eval_operand(operand, Some(dest.layout))?)?; + let val = self.unary_op(un_op, val.to_scalar()?, dest.layout)?; + self.write_scalar(val, dest)?; + } + + Aggregate(ref kind, ref operands) => { + let (dest, active_field_index) = match **kind { + mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { + self.write_discriminant_index(variant_index, dest)?; + if adt_def.is_enum() { + (self.place_downcast(dest, variant_index)?, active_field_index) + } else { + (dest, active_field_index) + } + } + _ => (dest, None) + }; + + for (i, operand) in operands.iter().enumerate() { + let op = self.eval_operand(operand, None)?; + // Ignore zero-sized fields. + if !op.layout.is_zst() { + let field_index = active_field_index.unwrap_or(i); + let field_dest = self.place_field(dest, field_index as u64)?; + self.copy_op(op, field_dest)?; + } + } + } + + Repeat(ref operand, _) => { + let op = self.eval_operand(operand, None)?; + let dest = self.force_allocation(dest)?; + let length = dest.len(&self)?; + + if length > 0 { + // write the first + let first = self.mplace_field(dest, 0)?; + self.copy_op(op, first.into())?; + + if length > 1 { + // copy the rest + let (dest, dest_align) = first.to_scalar_ptr_align(); + let rest = dest.ptr_offset(first.layout.size, &self)?; + self.memory.copy_repeatedly( + dest, dest_align, rest, dest_align, first.layout.size, length - 1, true + )?; + } + } + } + + Len(ref place) => { + // FIXME(CTFE): don't allow computing the length of arrays in const eval + let src = self.eval_place(place)?; + let mplace = self.force_allocation(src)?; + let len = mplace.len(&self)?; + let size = self.pointer_size(); + self.write_scalar( + Scalar::from_uint(len, size), + dest, + )?; + } + + Ref(_, _, ref place) => { + let src = self.eval_place(place)?; + let val = self.force_allocation(src)?.to_ref(); + self.write_value(val, dest)?; + } + + NullaryOp(mir::NullOp::Box, _) => { + M::box_alloc(self, dest)?; + } + + NullaryOp(mir::NullOp::SizeOf, ty) => { + let ty = self.monomorphize(ty, self.substs()); + let layout = self.layout_of(ty)?; + assert!(!layout.is_unsized(), + "SizeOf nullary MIR operator called for unsized type"); + let size = self.pointer_size(); + self.write_scalar( + Scalar::from_uint(layout.size.bytes(), size), + dest, + )?; + } + + Cast(kind, ref operand, cast_ty) => { + debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty); + let src = self.eval_operand(operand, None)?; + self.cast(src, kind, dest)?; + } + + Discriminant(ref place) => { + let place = self.eval_place(place)?; + let discr_val = self.read_discriminant(self.place_to_op(place)?)?.0; + let size = dest.layout.size; + self.write_scalar(Scalar::from_uint(discr_val, size), dest)?; + } + } + + self.dump_place(*dest); + + Ok(()) + } + fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> { - trace!("{:?}", terminator.kind); + debug!("{:?}", terminator.kind); self.tcx.span = terminator.source_info.span; self.memory.tcx.span = terminator.source_info.span; + + let old_stack = self.cur_frame(); + let old_bb = self.frame().block; self.eval_terminator(terminator)?; if !self.stack.is_empty() { - trace!("// {:?}", self.frame().block); + // This should change *something* + debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); + debug!("// {:?}", self.frame().block); } Ok(()) } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs new file mode 100644 index 0000000000..7ce96b1f62 --- /dev/null +++ b/src/librustc_mir/interpret/terminator.rs @@ -0,0 +1,451 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; + +use rustc::{mir, ty}; +use rustc::ty::layout::{self, TyLayout, LayoutOf}; +use syntax::source_map::Span; +use rustc_target::spec::abi::Abi; + +use rustc::mir::interpret::{EvalResult, PointerArithmetic, EvalErrorKind, Scalar}; +use super::{ + EvalContext, Machine, Value, OpTy, Place, PlaceTy, Operand, StackPopCleanup +}; + +impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { + #[inline] + pub fn goto_block(&mut self, target: Option) -> EvalResult<'tcx> { + if let Some(target) = target { + self.frame_mut().block = target; + self.frame_mut().stmt = 0; + Ok(()) + } else { + err!(Unreachable) + } + } + + pub(super) fn eval_terminator( + &mut self, + terminator: &mir::Terminator<'tcx>, + ) -> EvalResult<'tcx> { + use rustc::mir::TerminatorKind::*; + match terminator.kind { + Return => { + self.dump_place(self.frame().return_place); + self.pop_stack_frame()? + } + + Goto { target } => self.goto_block(Some(target))?, + + SwitchInt { + ref discr, + ref values, + ref targets, + .. + } => { + let discr = self.read_value(self.eval_operand(discr, None)?)?; + trace!("SwitchInt({:?})", *discr); + + // Branch to the `otherwise` case by default, if no match is found. + let mut target_block = targets[targets.len() - 1]; + + for (index, &const_int) in values.iter().enumerate() { + // Compare using binary_op, to also support pointer values + let const_int = Scalar::from_uint(const_int, discr.layout.size); + let (res, _) = self.binary_op(mir::BinOp::Eq, + discr.to_scalar()?, discr.layout, + const_int, discr.layout, + )?; + if res.to_bool()? { + target_block = targets[index]; + break; + } + } + + self.goto_block(Some(target_block))?; + } + + Call { + ref func, + ref args, + ref destination, + .. + } => { + let (dest, ret) = match *destination { + Some((ref lv, target)) => (Some(self.eval_place(lv)?), Some(target)), + None => (None, None), + }; + + let func = self.eval_operand(func, None)?; + let (fn_def, abi) = match func.layout.ty.sty { + ty::FnPtr(sig) => { + let caller_abi = sig.abi(); + let fn_ptr = self.read_scalar(func)?.to_ptr()?; + let instance = self.memory.get_fn(fn_ptr)?; + (instance, caller_abi) + } + ty::FnDef(def_id, substs) => { + let sig = func.layout.ty.fn_sig(*self.tcx); + (self.resolve(def_id, substs)?, sig.abi()) + }, + _ => { + let msg = format!("can't handle callee of type {:?}", func.layout.ty); + return err!(Unimplemented(msg)); + } + }; + let args = self.eval_operands(args)?; + self.eval_fn_call( + fn_def, + terminator.source_info.span, + abi, + &args[..], + dest, + ret, + )?; + } + + Drop { + ref location, + target, + .. + } => { + // FIXME(CTFE): forbid drop in const eval + let place = self.eval_place(location)?; + let ty = place.layout.ty; + trace!("TerminatorKind::drop: {:?}, type {}", location, ty); + + let instance = ::monomorphize::resolve_drop_in_place(*self.tcx, ty); + self.drop_in_place( + place, + instance, + terminator.source_info.span, + target, + )?; + } + + Assert { + ref cond, + expected, + ref msg, + target, + .. + } => { + let cond_val = self.read_value(self.eval_operand(cond, None)?)? + .to_scalar()?.to_bool()?; + if expected == cond_val { + self.goto_block(Some(target))?; + } else { + // Compute error message + use rustc::mir::interpret::EvalErrorKind::*; + return match *msg { + BoundsCheck { ref len, ref index } => { + let len = self.read_value(self.eval_operand(len, None)?) + .expect("can't eval len").to_scalar()? + .to_bits(self.memory().pointer_size())? as u64; + let index = self.read_value(self.eval_operand(index, None)?) + .expect("can't eval index").to_scalar()? + .to_bits(self.memory().pointer_size())? as u64; + err!(BoundsCheck { len, index }) + } + Overflow(op) => Err(Overflow(op).into()), + OverflowNeg => Err(OverflowNeg.into()), + DivisionByZero => Err(DivisionByZero.into()), + RemainderByZero => Err(RemainderByZero.into()), + GeneratorResumedAfterReturn | + GeneratorResumedAfterPanic => unimplemented!(), + _ => bug!(), + }; + } + } + + Yield { .. } | + GeneratorDrop | + DropAndReplace { .. } | + Resume | + Abort => unimplemented!("{:#?}", terminator.kind), + FalseEdges { .. } => bug!("should have been eliminated by\ + `simplify_branches` mir pass"), + FalseUnwind { .. } => bug!("should have been eliminated by\ + `simplify_branches` mir pass"), + Unreachable => return err!(Unreachable), + } + + Ok(()) + } + + fn check_argument_compat( + caller: TyLayout<'tcx>, + callee: TyLayout<'tcx>, + ) -> bool { + if caller.ty == callee.ty { + // No question + return true; + } + // Compare layout + match (&caller.abi, &callee.abi) { + (layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) => + // Different valid ranges are okay (once we enforce validity, + // that will take care to make it UB to leave the range, just + // like for transmute). + caller.value == callee.value, + // Be conservative + _ => false + } + } + + /// Pass a single argument, checking the types for compatibility. + fn pass_argument( + &mut self, + skip_zst: bool, + caller_arg: &mut impl Iterator>, + callee_arg: PlaceTy<'tcx>, + ) -> EvalResult<'tcx> { + if skip_zst && callee_arg.layout.is_zst() { + // Nothing to do. + trace!("Skipping callee ZST"); + return Ok(()); + } + let caller_arg = caller_arg.next() + .ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?; + if skip_zst { + debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); + } + // Now, check + if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) { + return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty)); + } + self.copy_op(caller_arg, callee_arg) + } + + /// Call this function -- pushing the stack frame and initializing the arguments. + fn eval_fn_call( + &mut self, + instance: ty::Instance<'tcx>, + span: Span, + caller_abi: Abi, + args: &[OpTy<'tcx>], + dest: Option>, + ret: Option, + ) -> EvalResult<'tcx> { + trace!("eval_fn_call: {:#?}", instance); + + match instance.def { + ty::InstanceDef::Intrinsic(..) => { + if caller_abi != Abi::RustIntrinsic { + return err!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic)); + } + // The intrinsic itself cannot diverge, so if we got here without a return + // place... (can happen e.g. for transmute returning `!`) + let dest = match dest { + Some(dest) => dest, + None => return err!(Unreachable) + }; + M::call_intrinsic(self, instance, args, dest)?; + // No stack frame gets pushed, the main loop will just act as if the + // call completed. + self.goto_block(ret)?; + self.dump_place(*dest); + Ok(()) + } + ty::InstanceDef::ClosureOnceShim { .. } | + ty::InstanceDef::FnPtrShim(..) | + ty::InstanceDef::DropGlue(..) | + ty::InstanceDef::CloneShim(..) | + ty::InstanceDef::Item(_) => { + // ABI check + { + let callee_abi = { + let instance_ty = instance.ty(*self.tcx); + match instance_ty.sty { + ty::FnDef(..) => + instance_ty.fn_sig(*self.tcx).abi(), + ty::Closure(..) => Abi::RustCall, + ty::Generator(..) => Abi::Rust, + _ => bug!("unexpected callee ty: {:?}", instance_ty), + } + }; + // Rust and RustCall are compatible + let normalize_abi = |abi| if abi == Abi::RustCall { Abi::Rust } else { abi }; + if normalize_abi(caller_abi) != normalize_abi(callee_abi) { + return err!(FunctionAbiMismatch(caller_abi, callee_abi)); + } + } + + // We need MIR for this fn + let mir = match M::find_fn(self, instance, args, dest, ret)? { + Some(mir) => mir, + None => return Ok(()), + }; + + let return_place = match dest { + Some(place) => *place, + None => Place::null(&self), + }; + self.push_stack_frame( + instance, + span, + mir, + return_place, + StackPopCleanup::Goto(ret), + )?; + + // We want to pop this frame again in case there was an error, to put + // the blame in the right location. Until the 2018 edition is used in + // the compiler, we have to do this with an immediately invoked function. + let res = (||{ + trace!( + "caller ABI: {:?}, args: {:#?}", + caller_abi, + args.iter() + .map(|arg| (arg.layout.ty, format!("{:?}", **arg))) + .collect::>() + ); + trace!( + "spread_arg: {:?}, locals: {:#?}", + mir.spread_arg, + mir.args_iter() + .map(|local| + (local, self.layout_of_local(self.cur_frame(), local).unwrap().ty) + ) + .collect::>() + ); + + // Figure out how to pass which arguments. + // We have two iterators: Where the arguments come from, + // and where they go to. + let skip_zst = match caller_abi { + Abi::Rust | Abi::RustCall => true, + _ => false + }; + + // For where they come from: If the ABI is RustCall, we untuple the + // last incoming argument. These two iterators do not have the same type, + // so to keep the code paths uniform we accept an allocation + // (for RustCall ABI only). + let caller_args : Cow<[OpTy<'tcx>]> = + if caller_abi == Abi::RustCall && !args.is_empty() { + // Untuple + let (&untuple_arg, args) = args.split_last().unwrap(); + trace!("eval_fn_call: Will pass last argument by untupling"); + Cow::from(args.iter().map(|&a| Ok(a)) + .chain((0..untuple_arg.layout.fields.count()).into_iter() + .map(|i| self.operand_field(untuple_arg, i as u64)) + ) + .collect::>>>()?) + } else { + // Plain arg passing + Cow::from(args) + }; + // Skip ZSTs + let mut caller_iter = caller_args.iter() + .filter(|op| !skip_zst || !op.layout.is_zst()) + .map(|op| *op); + + // Now we have to spread them out across the callee's locals, + // taking into account the `spread_arg`. If we could write + // this is a single iterator (that handles `spread_arg`), then + // `pass_argument` would be the loop body. It takes care to + // not advance `caller_iter` for ZSTs. + let mut locals_iter = mir.args_iter(); + while let Some(local) = locals_iter.next() { + let dest = self.eval_place(&mir::Place::Local(local))?; + if Some(local) == mir.spread_arg { + // Must be a tuple + for i in 0..dest.layout.fields.count() { + let dest = self.place_field(dest, i as u64)?; + self.pass_argument(skip_zst, &mut caller_iter, dest)?; + } + } else { + // Normal argument + self.pass_argument(skip_zst, &mut caller_iter, dest)?; + } + } + // Now we should have no more caller args + if caller_iter.next().is_some() { + trace!("Caller has too many args over"); + return err!(FunctionArgCountMismatch); + } + Ok(()) + })(); + match res { + Err(err) => { + self.stack.pop(); + Err(err) + } + Ok(v) => Ok(v) + } + } + // cannot use the shim here, because that will only result in infinite recursion + ty::InstanceDef::Virtual(_, idx) => { + let ptr_size = self.pointer_size(); + let ptr_align = self.tcx.data_layout.pointer_align; + let ptr = self.ref_to_mplace(self.read_value(args[0])?)?; + let vtable = ptr.vtable()?; + let fn_ptr = self.memory.read_ptr_sized( + vtable.offset(ptr_size * (idx as u64 + 3), &self)?, + ptr_align + )?.to_ptr()?; + let instance = self.memory.get_fn(fn_ptr)?; + + // We have to patch the self argument, in particular get the layout + // expected by the actual function. Cannot just use "field 0" due to + // Box. + let mut args = args.to_vec(); + let pointee = args[0].layout.ty.builtin_deref(true).unwrap().ty; + let fake_fat_ptr_ty = self.tcx.mk_mut_ptr(pointee); + args[0].layout = self.layout_of(fake_fat_ptr_ty)?.field(&self, 0)?; + args[0].op = Operand::Immediate(Value::Scalar(ptr.ptr.into())); // strip vtable + trace!("Patched self operand to {:#?}", args[0]); + // recurse with concrete function + self.eval_fn_call(instance, span, caller_abi, &args, dest, ret) + } + } + } + + fn drop_in_place( + &mut self, + place: PlaceTy<'tcx>, + instance: ty::Instance<'tcx>, + span: Span, + target: mir::BasicBlock, + ) -> EvalResult<'tcx> { + trace!("drop_in_place: {:?},\n {:?}, {:?}", *place, place.layout.ty, instance); + // We take the address of the object. This may well be unaligned, which is fine + // for us here. However, unaligned accesses will probably make the actual drop + // implementation fail -- a problem shared by rustc. + let place = self.force_allocation(place)?; + + let (instance, place) = match place.layout.ty.sty { + ty::Dynamic(..) => { + // Dropping a trait object. + self.unpack_dyn_trait(place)? + } + _ => (instance, place), + }; + + let arg = OpTy { + op: Operand::Immediate(place.to_ref()), + layout: self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?, + }; + + let ty = self.tcx.mk_unit(); // return type is () + let dest = PlaceTy::null(&self, self.layout_of(ty)?); + + self.eval_fn_call( + instance, + span, + Abi::Rust, + &[arg], + Some(dest), + Some(target), + ) + } +} diff --git a/src/librustc_mir/interpret/terminator/drop.rs b/src/librustc_mir/interpret/terminator/drop.rs deleted file mode 100644 index d750c1f47a..0000000000 --- a/src/librustc_mir/interpret/terminator/drop.rs +++ /dev/null @@ -1,86 +0,0 @@ -use rustc::mir::BasicBlock; -use rustc::ty::{self, Ty}; -use syntax::codemap::Span; - -use rustc::mir::interpret::{EvalResult, Scalar, Value}; -use interpret::{Machine, ValTy, EvalContext, Place, PlaceExtra}; - -impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { - pub(crate) fn drop_place( - &mut self, - place: Place, - instance: ty::Instance<'tcx>, - ty: Ty<'tcx>, - span: Span, - target: BasicBlock, - ) -> EvalResult<'tcx> { - trace!("drop_place: {:#?}", place); - // We take the address of the object. This may well be unaligned, which is fine for us here. - // However, unaligned accesses will probably make the actual drop implementation fail -- a problem shared - // by rustc. - let val = match self.force_allocation(place)? { - Place::Ptr { - ptr, - align: _, - extra: PlaceExtra::Vtable(vtable), - } => ptr.to_value_with_vtable(vtable), - Place::Ptr { - ptr, - align: _, - extra: PlaceExtra::Length(len), - } => ptr.to_value_with_len(len, self.tcx.tcx), - Place::Ptr { - ptr, - align: _, - extra: PlaceExtra::None, - } => ptr.to_value(), - _ => bug!("force_allocation broken"), - }; - self.drop(val, instance, ty, span, target) - } - - fn drop( - &mut self, - arg: Value, - instance: ty::Instance<'tcx>, - ty: Ty<'tcx>, - span: Span, - target: BasicBlock, - ) -> EvalResult<'tcx> { - trace!("drop: {:#?}, {:?}, {:?}", arg, ty.sty, instance.def); - - let instance = match ty.sty { - ty::TyDynamic(..) => { - let vtable = match arg { - Value::ScalarPair(_, Scalar::Ptr(vtable)) => vtable, - _ => bug!("expected fat ptr, got {:?}", arg), - }; - match self.read_drop_type_from_vtable(vtable)? { - Some(func) => func, - // no drop fn -> bail out - None => { - self.goto_block(target); - return Ok(()) - }, - } - } - _ => instance, - }; - - // the drop function expects a reference to the value - let valty = ValTy { - value: arg, - ty: self.tcx.mk_mut_ptr(ty), - }; - - let fn_sig = self.tcx.fn_sig(instance.def_id()).skip_binder().clone(); - - self.eval_fn_call( - instance, - Some((Place::undef(), target)), - &[valty], - span, - fn_sig, - ) - } -} diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs deleted file mode 100644 index 56dd3f603b..0000000000 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ /dev/null @@ -1,406 +0,0 @@ -use rustc::mir; -use rustc::ty::{self, Ty}; -use rustc::ty::layout::{LayoutOf, Size}; -use syntax::codemap::Span; -use rustc_target::spec::abi::Abi; - -use rustc::mir::interpret::{EvalResult, Scalar}; -use super::{EvalContext, Place, Machine, ValTy}; - -use rustc_data_structures::indexed_vec::Idx; -use interpret::memory::HasMemory; - -mod drop; - -impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { - pub fn goto_block(&mut self, target: mir::BasicBlock) { - self.frame_mut().block = target; - self.frame_mut().stmt = 0; - } - - pub(super) fn eval_terminator( - &mut self, - terminator: &mir::Terminator<'tcx>, - ) -> EvalResult<'tcx> { - use rustc::mir::TerminatorKind::*; - match terminator.kind { - Return => { - self.dump_local(self.frame().return_place); - self.pop_stack_frame()? - } - - Goto { target } => self.goto_block(target), - - SwitchInt { - ref discr, - ref values, - ref targets, - .. - } => { - let discr_val = self.eval_operand(discr)?; - let discr_prim = self.value_to_scalar(discr_val)?; - let discr_layout = self.layout_of(discr_val.ty).unwrap(); - trace!("SwitchInt({:?}, {:#?})", discr_prim, discr_layout); - - // Branch to the `otherwise` case by default, if no match is found. - let mut target_block = targets[targets.len() - 1]; - - for (index, &const_int) in values.iter().enumerate() { - // Compare using binary_op - let const_int = Scalar::Bits { bits: const_int, defined: 128 }; - let res = self.binary_op(mir::BinOp::Eq, - discr_prim, discr_val.ty, - const_int, discr_val.ty - )?; - if res.0.to_bits(Size::from_bytes(1))? != 0 { - target_block = targets[index]; - break; - } - } - - self.goto_block(target_block); - } - - Call { - ref func, - ref args, - ref destination, - .. - } => { - let destination = match *destination { - Some((ref lv, target)) => Some((self.eval_place(lv)?, target)), - None => None, - }; - - let func = self.eval_operand(func)?; - let (fn_def, sig) = match func.ty.sty { - ty::TyFnPtr(sig) => { - let fn_ptr = self.value_to_scalar(func)?.to_ptr()?; - let instance = self.memory.get_fn(fn_ptr)?; - let instance_ty = instance.ty(*self.tcx); - match instance_ty.sty { - ty::TyFnDef(..) => { - let real_sig = instance_ty.fn_sig(*self.tcx); - let sig = self.tcx.normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - let real_sig = self.tcx.normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &real_sig, - ); - if !self.check_sig_compat(sig, real_sig)? { - return err!(FunctionPointerTyMismatch(real_sig, sig)); - } - } - ref other => bug!("instance def ty: {:?}", other), - } - (instance, sig) - } - ty::TyFnDef(def_id, substs) => ( - self.resolve(def_id, substs)?, - func.ty.fn_sig(*self.tcx), - ), - _ => { - let msg = format!("can't handle callee of type {:?}", func.ty); - return err!(Unimplemented(msg)); - } - }; - let args = self.operands_to_args(args)?; - let sig = self.tcx.normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - self.eval_fn_call( - fn_def, - destination, - &args, - terminator.source_info.span, - sig, - )?; - } - - Drop { - ref location, - target, - .. - } => { - // FIXME(CTFE): forbid drop in const eval - let place = self.eval_place(location)?; - let ty = self.place_ty(location); - let ty = self.tcx.subst_and_normalize_erasing_regions( - self.substs(), - ty::ParamEnv::reveal_all(), - &ty, - ); - trace!("TerminatorKind::drop: {:?}, type {}", location, ty); - - let instance = ::monomorphize::resolve_drop_in_place(*self.tcx, ty); - self.drop_place( - place, - instance, - ty, - terminator.source_info.span, - target, - )?; - } - - Assert { - ref cond, - expected, - ref msg, - target, - .. - } => { - let cond_val = self.eval_operand_to_scalar(cond)?.to_bool()?; - if expected == cond_val { - self.goto_block(target); - } else { - use rustc::mir::interpret::EvalErrorKind::*; - return match *msg { - BoundsCheck { ref len, ref index } => { - let len = self.eval_operand_to_scalar(len) - .expect("can't eval len") - .to_bits(self.memory().pointer_size())? as u64; - let index = self.eval_operand_to_scalar(index) - .expect("can't eval index") - .to_bits(self.memory().pointer_size())? as u64; - err!(BoundsCheck { len, index }) - } - Overflow(op) => Err(Overflow(op).into()), - OverflowNeg => Err(OverflowNeg.into()), - DivisionByZero => Err(DivisionByZero.into()), - RemainderByZero => Err(RemainderByZero.into()), - GeneratorResumedAfterReturn | - GeneratorResumedAfterPanic => unimplemented!(), - _ => bug!(), - }; - } - } - - Yield { .. } => unimplemented!("{:#?}", terminator.kind), - GeneratorDrop => unimplemented!(), - DropAndReplace { .. } => unimplemented!(), - Resume => unimplemented!(), - Abort => unimplemented!(), - FalseEdges { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"), - FalseUnwind { .. } => bug!("should have been eliminated by `simplify_branches` mir pass"), - Unreachable => return err!(Unreachable), - } - - Ok(()) - } - - /// Decides whether it is okay to call the method with signature `real_sig` using signature `sig`. - /// FIXME: This should take into account the platform-dependent ABI description. - fn check_sig_compat( - &mut self, - sig: ty::FnSig<'tcx>, - real_sig: ty::FnSig<'tcx>, - ) -> EvalResult<'tcx, bool> { - fn check_ty_compat<'tcx>(ty: Ty<'tcx>, real_ty: Ty<'tcx>) -> bool { - if ty == real_ty { - return true; - } // This is actually a fast pointer comparison - return match (&ty.sty, &real_ty.sty) { - // Permit changing the pointer type of raw pointers and references as well as - // mutability of raw pointers. - // TODO: Should not be allowed when fat pointers are involved. - (&ty::TyRawPtr(_), &ty::TyRawPtr(_)) => true, - (&ty::TyRef(_, _, _), &ty::TyRef(_, _, _)) => { - ty.is_mutable_pointer() == real_ty.is_mutable_pointer() - } - // rule out everything else - _ => false, - }; - } - - if sig.abi == real_sig.abi && sig.variadic == real_sig.variadic && - sig.inputs_and_output.len() == real_sig.inputs_and_output.len() && - sig.inputs_and_output - .iter() - .zip(real_sig.inputs_and_output) - .all(|(ty, real_ty)| check_ty_compat(ty, real_ty)) - { - // Definitely good. - return Ok(true); - } - - if sig.variadic || real_sig.variadic { - // We're not touching this - return Ok(false); - } - - // We need to allow what comes up when a non-capturing closure is cast to a fn(). - match (sig.abi, real_sig.abi) { - (Abi::Rust, Abi::RustCall) // check the ABIs. This makes the test here non-symmetric. - if check_ty_compat(sig.output(), real_sig.output()) && real_sig.inputs_and_output.len() == 3 => { - // First argument of real_sig must be a ZST - let fst_ty = real_sig.inputs_and_output[0]; - if self.layout_of(fst_ty)?.is_zst() { - // Second argument must be a tuple matching the argument list of sig - let snd_ty = real_sig.inputs_and_output[1]; - match snd_ty.sty { - ty::TyTuple(tys) if sig.inputs().len() == tys.len() => - if sig.inputs().iter().zip(tys).all(|(ty, real_ty)| check_ty_compat(ty, real_ty)) { - return Ok(true) - }, - _ => {} - } - } - } - _ => {} - }; - - // Nope, this doesn't work. - return Ok(false); - } - - fn eval_fn_call( - &mut self, - instance: ty::Instance<'tcx>, - destination: Option<(Place, mir::BasicBlock)>, - args: &[ValTy<'tcx>], - span: Span, - sig: ty::FnSig<'tcx>, - ) -> EvalResult<'tcx> { - trace!("eval_fn_call: {:#?}", instance); - match instance.def { - ty::InstanceDef::Intrinsic(..) => { - let (ret, target) = match destination { - Some(dest) => dest, - _ => return err!(Unreachable), - }; - let ty = sig.output(); - let layout = self.layout_of(ty)?; - M::call_intrinsic(self, instance, args, ret, layout, target)?; - self.dump_local(ret); - Ok(()) - } - // FIXME: figure out why we can't just go through the shim - ty::InstanceDef::ClosureOnceShim { .. } => { - if M::eval_fn_call(self, instance, destination, args, span, sig)? { - return Ok(()); - } - let mut arg_locals = self.frame().mir.args_iter(); - match sig.abi { - // closure as closure once - Abi::RustCall => { - for (arg_local, &valty) in arg_locals.zip(args) { - let dest = self.eval_place(&mir::Place::Local(arg_local))?; - self.write_value(valty, dest)?; - } - } - // non capture closure as fn ptr - // need to inject zst ptr for closure object (aka do nothing) - // and need to pack arguments - Abi::Rust => { - trace!( - "arg_locals: {:#?}", - self.frame().mir.args_iter().collect::>() - ); - trace!("args: {:#?}", args); - let local = arg_locals.nth(1).unwrap(); - for (i, &valty) in args.into_iter().enumerate() { - let dest = self.eval_place(&mir::Place::Local(local).field( - mir::Field::new(i), - valty.ty, - ))?; - self.write_value(valty, dest)?; - } - } - _ => bug!("bad ABI for ClosureOnceShim: {:?}", sig.abi), - } - Ok(()) - } - ty::InstanceDef::FnPtrShim(..) | - ty::InstanceDef::DropGlue(..) | - ty::InstanceDef::CloneShim(..) | - ty::InstanceDef::Item(_) => { - // Push the stack frame, and potentially be entirely done if the call got hooked - if M::eval_fn_call(self, instance, destination, args, span, sig)? { - return Ok(()); - } - - // Pass the arguments - let mut arg_locals = self.frame().mir.args_iter(); - trace!("ABI: {:?}", sig.abi); - trace!( - "arg_locals: {:#?}", - self.frame().mir.args_iter().collect::>() - ); - trace!("args: {:#?}", args); - match sig.abi { - Abi::RustCall => { - assert_eq!(args.len(), 2); - - { - // write first argument - let first_local = arg_locals.next().unwrap(); - let dest = self.eval_place(&mir::Place::Local(first_local))?; - self.write_value(args[0], dest)?; - } - - // unpack and write all other args - let layout = self.layout_of(args[1].ty)?; - if let ty::TyTuple(_) = args[1].ty.sty { - if layout.is_zst() { - // Nothing to do, no need to unpack zsts - return Ok(()); - } - if self.frame().mir.args_iter().count() == layout.fields.count() + 1 { - for (i, arg_local) in arg_locals.enumerate() { - let field = mir::Field::new(i); - let (value, layout) = self.read_field(args[1].value, None, field, layout)?; - let dest = self.eval_place(&mir::Place::Local(arg_local))?; - let valty = ValTy { - value, - ty: layout.ty, - }; - self.write_value(valty, dest)?; - } - } else { - trace!("manual impl of rust-call ABI"); - // called a manual impl of a rust-call function - let dest = self.eval_place( - &mir::Place::Local(arg_locals.next().unwrap()), - )?; - self.write_value(args[1], dest)?; - } - } else { - bug!( - "rust-call ABI tuple argument was {:#?}, {:#?}", - args[1].ty, - layout - ); - } - } - _ => { - for (arg_local, &valty) in arg_locals.zip(args) { - let dest = self.eval_place(&mir::Place::Local(arg_local))?; - self.write_value(valty, dest)?; - } - } - } - Ok(()) - } - // cannot use the shim here, because that will only result in infinite recursion - ty::InstanceDef::Virtual(_, idx) => { - let ptr_size = self.memory.pointer_size(); - let ptr_align = self.tcx.data_layout.pointer_align; - let (ptr, vtable) = self.into_ptr_vtable_pair(args[0].value)?; - let fn_ptr = self.memory.read_ptr_sized( - vtable.offset(ptr_size * (idx as u64 + 3), &self)?, - ptr_align - )?.to_ptr()?; - let instance = self.memory.get_fn(fn_ptr)?; - let mut args = args.to_vec(); - let ty = self.layout_of(args[0].ty)?.field(&self, 0)?.ty; - args[0].ty = ty; - args[0].value = ptr.to_value(); - // recurse with concrete function - self.eval_fn_call(instance, destination, &args, span, sig) - } - } - } -} diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index b6c7feda19..0e09f65f0a 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,6 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use rustc::ty::{self, Ty}; use rustc::ty::layout::{Size, Align, LayoutOf}; -use rustc::mir::interpret::{Scalar, Value, Pointer, EvalResult}; +use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic}; use syntax::ast::Mutability; @@ -25,7 +35,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { let size = layout.size.bytes(); let align = layout.align.abi(); - let ptr_size = self.memory.pointer_size(); + let ptr_size = self.pointer_size(); let ptr_align = self.tcx.data_layout.pointer_align; let methods = self.tcx.vtable_methods(trait_ref); let vtable = self.memory.allocate( @@ -36,29 +46,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty); let drop = self.memory.create_fn_alloc(drop); - self.memory.write_ptr_sized_unsigned(vtable, ptr_align, drop.into())?; + self.memory.write_ptr_sized(vtable, ptr_align, Scalar::Ptr(drop).into())?; let size_ptr = vtable.offset(ptr_size, &self)?; - self.memory.write_ptr_sized_unsigned(size_ptr, ptr_align, Scalar::Bits { - bits: size as u128, - defined: ptr_size.bits() as u8, - })?; + self.memory.write_ptr_sized(size_ptr, ptr_align, Scalar::from_uint(size, ptr_size).into())?; let align_ptr = vtable.offset(ptr_size * 2, &self)?; - self.memory.write_ptr_sized_unsigned(align_ptr, ptr_align, Scalar::Bits { - bits: align as u128, - defined: ptr_size.bits() as u8, - })?; + self.memory.write_ptr_sized(align_ptr, ptr_align, + Scalar::from_uint(align, ptr_size).into())?; for (i, method) in methods.iter().enumerate() { if let Some((def_id, substs)) = *method { let instance = self.resolve(def_id, substs)?; let fn_ptr = self.memory.create_fn_alloc(instance); let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?; - self.memory.write_ptr_sized_unsigned(method_ptr, ptr_align, fn_ptr.into())?; + self.memory.write_ptr_sized(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?; } } - self.memory.mark_static_initialized( + self.memory.intern_static( vtable.alloc_id, Mutability::Immutable, )?; @@ -66,28 +71,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Ok(vtable) } + /// Return the drop fn instance as well as the actual dynamic type pub fn read_drop_type_from_vtable( &self, vtable: Pointer, - ) -> EvalResult<'tcx, Option>> { + ) -> EvalResult<'tcx, (ty::Instance<'tcx>, ty::Ty<'tcx>)> { // we don't care about the pointee type, we just want a pointer let pointer_align = self.tcx.data_layout.pointer_align; - let pointer_size = self.tcx.data_layout.pointer_size.bits() as u8; - match self.read_ptr(vtable, pointer_align, self.tcx.mk_nil_ptr())? { - // some values don't need to call a drop impl, so the value is null - Value::Scalar(Scalar::Bits { bits: 0, defined} ) if defined == pointer_size => Ok(None), - Value::Scalar(Scalar::Ptr(drop_fn)) => self.memory.get_fn(drop_fn).map(Some), - _ => err!(ReadBytesAsPointer), - } + let drop_fn = self.memory.read_ptr_sized(vtable, pointer_align)?.to_ptr()?; + let drop_instance = self.memory.get_fn(drop_fn)?; + trace!("Found drop fn: {:?}", drop_instance); + let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx); + let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig); + // the drop function takes *mut T where T is the type being dropped, so get that + let ty = fn_sig.inputs()[0].builtin_deref(true).unwrap().ty; + Ok((drop_instance, ty)) } pub fn read_size_and_align_from_vtable( &self, vtable: Pointer, ) -> EvalResult<'tcx, (Size, Align)> { - let pointer_size = self.memory.pointer_size(); + let pointer_size = self.pointer_size(); let pointer_align = self.tcx.data_layout.pointer_align; - let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?, pointer_align)?.to_bits(pointer_size)? as u64; + let size = self.memory.read_ptr_sized(vtable.offset(pointer_size, self)?,pointer_align)? + .to_bits(pointer_size)? as u64; let align = self.memory.read_ptr_sized( vtable.offset(pointer_size * 2, self)?, pointer_align diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs new file mode 100644 index 0000000000..8292869ca5 --- /dev/null +++ b/src/librustc_mir/interpret/validity.rs @@ -0,0 +1,509 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fmt::Write; + +use syntax_pos::symbol::Symbol; +use rustc::ty::layout::{self, Size, Primitive}; +use rustc::ty::{self, Ty}; +use rustc_data_structures::fx::FxHashSet; +use rustc::mir::interpret::{ + Scalar, AllocType, EvalResult, ScalarMaybeUndef, EvalErrorKind, PointerArithmetic +}; + +use super::{ + OpTy, Machine, EvalContext +}; + +macro_rules! validation_failure{ + ($what:expr, $where:expr, $details:expr) => {{ + let where_ = path_format($where); + let where_ = if where_.is_empty() { + String::new() + } else { + format!(" at {}", where_) + }; + err!(ValidationFailure(format!( + "encountered {}{}, but expected {}", + $what, where_, $details, + ))) + }}; + ($what:expr, $where:expr) => {{ + let where_ = path_format($where); + let where_ = if where_.is_empty() { + String::new() + } else { + format!(" at {}", where_) + }; + err!(ValidationFailure(format!( + "encountered {}{}", + $what, where_, + ))) + }}; +} + +/// We want to show a nice path to the invalid field for diagnotsics, +/// but avoid string operations in the happy case where no error happens. +/// So we track a `Vec` where `PathElem` contains all the data we +/// need to later print something for the user. +#[derive(Copy, Clone, Debug)] +pub enum PathElem { + Field(Symbol), + ClosureVar(Symbol), + ArrayElem(usize), + TupleElem(usize), + Deref, + Tag, +} + +// Adding a Deref and making a copy of the path to be put into the queue +// always go together. This one does it with only new allocation. +fn path_clone_and_deref(path: &Vec) -> Vec { + let mut new_path = Vec::with_capacity(path.len()+1); + new_path.clone_from(path); + new_path.push(PathElem::Deref); + new_path +} + +/// Format a path +fn path_format(path: &Vec) -> String { + use self::PathElem::*; + + let mut out = String::new(); + for elem in path.iter() { + match elem { + Field(name) => write!(out, ".{}", name).unwrap(), + ClosureVar(name) => write!(out, ".", name).unwrap(), + TupleElem(idx) => write!(out, ".{}", idx).unwrap(), + ArrayElem(idx) => write!(out, "[{}]", idx).unwrap(), + Deref => + // This does not match Rust syntax, but it is more readable for long paths -- and + // some of the other items here also are not Rust syntax. Actually we can't + // even use the usual syntax because we are just showing the projections, + // not the root. + write!(out, ".").unwrap(), + Tag => write!(out, ".").unwrap(), + } + } + out +} + +impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { + fn validate_scalar( + &self, + value: ScalarMaybeUndef, + size: Size, + scalar: &layout::Scalar, + path: &Vec, + ty: Ty, + ) -> EvalResult<'tcx> { + trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty); + let (lo, hi) = scalar.valid_range.clone().into_inner(); + + let value = match value { + ScalarMaybeUndef::Scalar(scalar) => scalar, + ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path), + }; + + let bits = match value { + Scalar::Bits { bits, size: value_size } => { + assert_eq!(value_size as u64, size.bytes()); + bits + }, + Scalar::Ptr(_) => { + match ty.sty { + ty::Bool | + ty::Char | + ty::Float(_) | + ty::Int(_) | + ty::Uint(_) => { + return validation_failure!( + "a pointer", + path, + format!("the type {}", ty.sty) + ); + } + ty::RawPtr(_) | + ty::Ref(_, _, _) | + ty::FnPtr(_) => {} + _ => { unreachable!(); } + } + + let ptr_size = self.pointer_size(); + let ptr_max = u128::max_value() >> (128 - ptr_size.bits()); + return if lo > hi { + if lo - hi == 1 { + // no gap, all values are ok + Ok(()) + } else if hi < ptr_max || lo > 1 { + let max = u128::max_value() >> (128 - size.bits()); + validation_failure!( + "pointer", + path, + format!("something in the range {:?} or {:?}", 0..=lo, hi..=max) + ) + } else { + Ok(()) + } + } else if hi < ptr_max || lo > 1 { + validation_failure!( + "pointer", + path, + format!("something in the range {:?}", scalar.valid_range) + ) + } else { + Ok(()) + }; + }, + }; + + // char gets a special treatment, because its number space is not contiguous so `TyLayout` + // has no special checks for chars + match ty.sty { + ty::Char => { + debug_assert_eq!(size.bytes(), 4); + if ::std::char::from_u32(bits as u32).is_none() { + return validation_failure!( + "character", + path, + "a valid unicode codepoint" + ); + } + } + _ => {}, + } + + use std::ops::RangeInclusive; + let in_range = |bound: RangeInclusive| bound.contains(&bits); + if lo > hi { + if in_range(0..=hi) || in_range(lo..=u128::max_value()) { + Ok(()) + } else { + validation_failure!( + bits, + path, + format!("something in the range {:?} or {:?}", ..=hi, lo..) + ) + } + } else { + if in_range(scalar.valid_range.clone()) { + Ok(()) + } else { + validation_failure!( + bits, + path, + format!("something in the range {:?}", scalar.valid_range) + ) + } + } + } + + /// This function checks the data at `op`. + /// It will error if the bits at the destination do not match the ones described by the layout. + /// The `path` may be pushed to, but the part that is present when the function + /// starts must not be changed! + pub fn validate_operand( + &self, + dest: OpTy<'tcx>, + path: &mut Vec, + seen: &mut FxHashSet<(OpTy<'tcx>)>, + todo: &mut Vec<(OpTy<'tcx>, Vec)>, + ) -> EvalResult<'tcx> { + trace!("validate_operand: {:?}, {:#?}", *dest, dest.layout); + + // Find the right variant. We have to handle this as a prelude, not via + // proper recursion with the new inner layout, to be able to later nicely + // print the field names of the enum field that is being accessed. + let (variant, dest) = match dest.layout.variants { + layout::Variants::NicheFilling { .. } | + layout::Variants::Tagged { .. } => { + let variant = match self.read_discriminant(dest) { + Ok(res) => res.1, + Err(err) => match err.kind { + EvalErrorKind::InvalidDiscriminant(val) => + return validation_failure!( + format!("invalid enum discriminant {}", val), path + ), + _ => + return validation_failure!( + format!("non-integer enum discriminant"), path + ), + } + }; + let inner_dest = self.operand_downcast(dest, variant)?; + // Put the variant projection onto the path, as a field + path.push(PathElem::Field(dest.layout.ty + .ty_adt_def() + .unwrap() + .variants[variant].name)); + trace!("variant layout: {:#?}", dest.layout); + (variant, inner_dest) + }, + layout::Variants::Single { index } => { + // Pre-processing for trait objects: Treat them at their real type. + // (We do not do this for slices and strings: For slices it is not needed, + // `mplace_array_fields` does the right thing, and for strings there is no + // real type that would show the actual length.) + let dest = match dest.layout.ty.sty { + ty::Dynamic(..) => { + let dest = dest.to_mem_place(); // immediate trait objects are not a thing + match self.unpack_dyn_trait(dest) { + Ok(res) => res.1.into(), + Err(_) => + return validation_failure!( + "invalid vtable in fat pointer", path + ), + } + } + _ => dest + }; + (index, dest) + } + }; + + // Remember the length, in case we need to truncate + let path_len = path.len(); + + // Validate all fields + match dest.layout.fields { + // primitives are unions with zero fields + // We still check `layout.fields`, not `layout.abi`, because `layout.abi` + // is `Scalar` for newtypes around scalars, but we want to descend through the + // fields to get a proper `path`. + layout::FieldPlacement::Union(0) => { + match dest.layout.abi { + // nothing to do, whatever the pointer points to, it is never going to be read + layout::Abi::Uninhabited => + return validation_failure!("a value of an uninhabited type", path), + // check that the scalar is a valid pointer or that its bit range matches the + // expectation. + layout::Abi::Scalar(ref scalar_layout) => { + let size = scalar_layout.value.size(self); + let value = match self.read_value(dest) { + Ok(val) => val, + Err(err) => match err.kind { + EvalErrorKind::PointerOutOfBounds { .. } | + EvalErrorKind::ReadUndefBytes(_) => + return validation_failure!( + "uninitialized or out-of-bounds memory", path + ), + _ => + return validation_failure!( + "unrepresentable data", path + ), + } + }; + let scalar = value.to_scalar_or_undef(); + self.validate_scalar(scalar, size, scalar_layout, &path, dest.layout.ty)?; + if scalar_layout.value == Primitive::Pointer { + // ignore integer pointers, we can't reason about the final hardware + if let Scalar::Ptr(ptr) = scalar.not_undef()? { + let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id); + if let Some(AllocType::Static(did)) = alloc_kind { + // statics from other crates are already checked. + // extern statics cannot be validated as they have no body. + if !did.is_local() || self.tcx.is_foreign_item(did) { + return Ok(()); + } + } + if value.layout.ty.builtin_deref(false).is_some() { + let ptr_op = self.ref_to_mplace(value)?.into(); + // we have not encountered this pointer+layout combination + // before. + if seen.insert(ptr_op) { + trace!("Recursing below ptr {:#?}", *value); + todo.push((ptr_op, path_clone_and_deref(path))); + } + } + } + } + }, + _ => bug!("bad abi for FieldPlacement::Union(0): {:#?}", dest.layout.abi), + } + } + layout::FieldPlacement::Union(_) => { + // We can't check unions, their bits are allowed to be anything. + // The fields don't need to correspond to any bit pattern of the union's fields. + // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389 + }, + layout::FieldPlacement::Array { stride, .. } if !dest.layout.is_zst() => { + let dest = dest.to_mem_place(); // non-ZST array/slice/str cannot be immediate + match dest.layout.ty.sty { + // Special handling for strings to verify UTF-8 + ty::Str => { + match self.read_str(dest) { + Ok(_) => {}, + Err(err) => match err.kind { + EvalErrorKind::PointerOutOfBounds { .. } | + EvalErrorKind::ReadUndefBytes(_) => + // The error here looks slightly different than it does + // for slices, because we do not report the index into the + // str at which we are OOB. + return validation_failure!( + "uninitialized or out-of-bounds memory", path + ), + _ => + return validation_failure!( + "non-UTF-8 data in str", path + ), + } + } + } + // Special handling for arrays/slices of builtin integer types + ty::Array(tys, ..) | ty::Slice(tys) if { + // This optimization applies only for integer types + match tys.sty { + ty::Int(..) | ty::Uint(..) => true, + _ => false, + } + } => { + // This is the length of the array/slice. + let len = dest.len(self)?; + // Since primitive types are naturally aligned and tightly packed in arrays, + // we can use the stride to get the size of the integral type. + let ty_size = stride.bytes(); + // This is the size in bytes of the whole array. + let size = Size::from_bytes(ty_size * len); + + match self.memory.read_bytes(dest.ptr, size) { + // In the happy case, we needn't check anything else. + Ok(_) => {}, + // Some error happened, try to provide a more detailed description. + Err(err) => { + // For some errors we might be able to provide extra information + match err.kind { + EvalErrorKind::ReadUndefBytes(offset) => { + // Some byte was undefined, determine which + // element that byte belongs to so we can + // provide an index. + let i = (offset.bytes() / ty_size) as usize; + path.push(PathElem::ArrayElem(i)); + + return validation_failure!( + "undefined bytes", path + ) + }, + EvalErrorKind::PointerOutOfBounds { allocation_size, .. } => { + // If the array access is out-of-bounds, the first + // undefined access is the after the end of the array. + let i = (allocation_size.bytes() * ty_size) as usize; + path.push(PathElem::ArrayElem(i)); + }, + _ => (), + } + + return validation_failure!( + "uninitialized or out-of-bounds memory", path + ) + } + } + }, + _ => { + // This handles the unsized case correctly as well, as well as + // SIMD an all sorts of other array-like types. + for (i, field) in self.mplace_array_fields(dest)?.enumerate() { + let field = field?; + path.push(PathElem::ArrayElem(i)); + self.validate_operand(field.into(), path, seen, todo)?; + path.truncate(path_len); + } + } + } + }, + layout::FieldPlacement::Array { .. } => { + // An empty array. Nothing to do. + } + layout::FieldPlacement::Arbitrary { ref offsets, .. } => { + // Fat pointers are treated like pointers, not aggregates. + if dest.layout.ty.builtin_deref(true).is_some() { + // This is a fat pointer. + let ptr = match self.read_value(dest.into()) + .and_then(|val| self.ref_to_mplace(val)) + { + Ok(ptr) => ptr, + Err(_) => + return validation_failure!( + "undefined location or metadata in fat pointer", path + ), + }; + // check metadata early, for better diagnostics + match self.tcx.struct_tail(ptr.layout.ty).sty { + ty::Dynamic(..) => { + match ptr.extra.unwrap().to_ptr() { + Ok(_) => {}, + Err(_) => + return validation_failure!( + "non-pointer vtable in fat pointer", path + ), + } + // FIXME: More checks for the vtable. + } + ty::Slice(..) | ty::Str => { + match ptr.extra.unwrap().to_usize(self) { + Ok(_) => {}, + Err(_) => + return validation_failure!( + "non-integer slice length in fat pointer", path + ), + } + } + _ => + bug!("Unexpected unsized type tail: {:?}", + self.tcx.struct_tail(ptr.layout.ty) + ), + } + // for safe ptrs, recursively check it + if !dest.layout.ty.is_unsafe_ptr() { + let ptr = ptr.into(); + if seen.insert(ptr) { + trace!("Recursing below fat ptr {:?}", ptr); + todo.push((ptr, path_clone_and_deref(path))); + } + } + } else { + // Not a pointer, perform regular aggregate handling below + for i in 0..offsets.len() { + let field = self.operand_field(dest, i as u64)?; + path.push(self.aggregate_field_path_elem(dest.layout.ty, variant, i)); + self.validate_operand(field, path, seen, todo)?; + path.truncate(path_len); + } + } + } + } + Ok(()) + } + + fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize) -> PathElem { + match ty.sty { + // generators and closures. + ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => { + let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); + let freevar = self.tcx.with_freevars(node_id, |fv| fv[field]); + PathElem::ClosureVar(self.tcx.hir.name(freevar.var_id())) + } + + // tuples + ty::Tuple(_) => PathElem::TupleElem(field), + + // enums + ty::Adt(def, ..) if def.is_enum() => { + let variant = &def.variants[variant]; + PathElem::Field(variant.fields[field].ident.name) + } + + // other ADTs + ty::Adt(def, _) => PathElem::Field(def.non_enum_variant().fields[field].ident.name), + + // nothing else has an aggregate layout + _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", ty), + } + } +} diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 3f32d30740..1594755b4a 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -14,30 +14,33 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! */ -#![feature(infer_outlives_requirements)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(in_band_lifetimes)] +#![feature(impl_header_lifetime_elision)] #![feature(slice_patterns)] #![feature(slice_sort_by_cached_key)] -#![feature(from_ref)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(catch_expr)] #![feature(crate_visibility_modifier)] -#![feature(const_fn)] #![feature(core_intrinsics)] +#![feature(const_fn)] #![feature(decl_macro)] -#![feature(fs_read_write)] -#![feature(in_band_lifetimes)] -#![feature(macro_vis_matcher)] +#![cfg_attr(stage0, feature(macro_vis_matcher))] #![feature(exhaustive_patterns)] #![feature(range_contains)] #![feature(rustc_diagnostic_macros)] -#![feature(crate_visibility_modifier)] +#![feature(rustc_attrs)] +#![cfg_attr(stage0, feature(attr_literals))] #![feature(never_type)] #![feature(specialization)] #![feature(try_trait)] #![feature(unicode_internals)] #![feature(step_trait)] +#![feature(slice_concat_ext)] +#![feature(if_while_or_patterns)] +#![feature(try_from)] +#![feature(reverse_bits)] +#![feature(underscore_imports)] #![recursion_limit="256"] @@ -62,6 +65,15 @@ extern crate log_settings; extern crate rustc_apfloat; extern crate byteorder; extern crate core; +extern crate smallvec; + +// Once we can use edition 2018 in the compiler, +// replace this with real try blocks. +macro_rules! try_block { + ($($inside:tt)*) => ( + (||{ ::std::ops::Try::from_ok({ $($inside)* }) })() + ) +} mod diagnostics; @@ -74,6 +86,7 @@ pub mod transform; pub mod util; pub mod interpret; pub mod monomorphize; +pub mod const_eval; pub use hair::pattern::check_crate as matchck_crate; use rustc::ty::query::Providers; @@ -83,7 +96,6 @@ pub fn provide(providers: &mut Providers) { shim::provide(providers); transform::provide(providers); providers.const_eval = interpret::const_eval_provider; - providers.const_value_to_allocation = interpret::const_value_to_allocation_provider; providers.check_match = hair::pattern::check_match; } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 5f05783b15..52bbffa751 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -191,9 +191,9 @@ use rustc::hir::{self, CodegenFnAttrFlags}; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::hir::map as hir_map; +use rustc::hir::Node; use rustc::hir::def_id::DefId; -use rustc::mir::interpret::{AllocId, ConstValue}; +use rustc::mir::interpret::{AllocId, ConstValue, ScalarMaybeUndef}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; use rustc::ty::subst::Substs; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind}; @@ -240,7 +240,7 @@ impl<'tcx> InliningMap<'tcx> { InliningMap { index: FxHashMap(), targets: Vec::new(), - inlines: BitVector::new(1024), + inlines: BitVector::with_capacity(1024), } } @@ -571,7 +571,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { &source_ty, ); match source_ty.sty { - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { let instance = monomorphize::resolve_closure( self.tcx, def_id, substs, ty::ClosureKind::FnOnce); if should_monomorphize_locally(self.tcx, &instance) { @@ -680,7 +680,7 @@ fn visit_fn_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, is_direct_call: bool, output: &mut Vec>) { - if let ty::TyFnDef(def_id, substs) = ty.sty { + if let ty::FnDef(def_id, substs) = ty.sty { let instance = ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, @@ -740,7 +740,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: }; return match tcx.hir.get_if_local(def_id) { - Some(hir_map::NodeForeignItem(..)) => { + Some(Node::ForeignItem(..)) => { false // foreign items are linked against, not codegened. } Some(_) => true, @@ -770,7 +770,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: // If we are not in share generics mode, we don't link to upstream // monomorphizations but always instantiate our own internal versions // instead. - if !tcx.share_generics() { + if !tcx.sess.opts.share_generics() { return false } @@ -838,8 +838,8 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let tail = tcx.struct_tail(ty); match tail.sty { - ty::TyForeign(..) => false, - ty::TyStr | ty::TySlice(..) | ty::TyDynamic(..) => true, + ty::Foreign(..) => false, + ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, _ => bug!("unexpected unsized tail: {:?}", tail.sty), } }; @@ -851,20 +851,20 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; match (&source_ty.sty, &target_ty.sty) { - (&ty::TyRef(_, a, _), - &ty::TyRef(_, b, _)) | - (&ty::TyRef(_, a, _), - &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) | - (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }), - &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => { + (&ty::Ref(_, a, _), + &ty::Ref(_, b, _)) | + (&ty::Ref(_, a, _), + &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) | + (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), + &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { ptr_vtable(a, b) } - (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => { + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) } - (&ty::TyAdt(source_adt_def, source_substs), - &ty::TyAdt(target_adt_def, target_substs)) => { + (&ty::Adt(source_adt_def, source_substs), + &ty::Adt(target_adt_def, target_substs)) => { assert_eq!(source_adt_def, target_adt_def); let kind = @@ -906,7 +906,7 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() && !impl_ty.needs_subst() && !impl_ty.has_escaping_regions()); - if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty { + if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty { if let Some(principal) = trait_ty.principal() { let poly_trait_ref = principal.with_self_ty(tcx, impl_ty); assert!(!poly_trait_ref.has_escaping_regions()); @@ -1023,7 +1023,6 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { MonoItemCollectionMode::Lazy => { self.entry_fn == Some(def_id) || self.tcx.is_reachable_non_generic(def_id) || - self.tcx.is_weak_lang_item(def_id) || self.tcx.codegen_fn_attrs(def_id).flags.contains( CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) } @@ -1047,7 +1046,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { /// the return type of `main`. This is not needed when /// the user writes their own `start` manually. fn push_extra_entry_roots(&mut self) { - if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryMain) { + if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryFnType::Main) { return } @@ -1264,15 +1263,15 @@ fn collect_const<'a, 'tcx>( }; match val { ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"), - ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => { + ConstValue::ScalarPair(Scalar::Ptr(a), ScalarMaybeUndef::Scalar(Scalar::Ptr(b))) => { collect_miri(tcx, a.alloc_id, output); collect_miri(tcx, b.alloc_id, output); } - ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) | + ConstValue::ScalarPair(_, ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr))) | ConstValue::ScalarPair(Scalar::Ptr(ptr), _) | ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), - ConstValue::ByRef(alloc, _offset) => { + ConstValue::ByRef(_id, alloc, _offset) => { for &id in alloc.relocations.values() { collect_miri(tcx, id, output); } diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 95968c0ea4..3f5a05f9d0 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -26,7 +26,7 @@ use std::fmt::{self, Write}; use std::iter; use rustc::mir::mono::Linkage; use syntax_pos::symbol::Symbol; -use syntax::codemap::Span; +use syntax::source_map::Span; pub use rustc::mir::mono::MonoItem; /// Describes how a monomorphization will be instantiated in object files. @@ -257,29 +257,29 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) { match t.sty { - ty::TyBool => output.push_str("bool"), - ty::TyChar => output.push_str("char"), - ty::TyStr => output.push_str("str"), - ty::TyNever => output.push_str("!"), - ty::TyInt(ast::IntTy::Isize) => output.push_str("isize"), - ty::TyInt(ast::IntTy::I8) => output.push_str("i8"), - ty::TyInt(ast::IntTy::I16) => output.push_str("i16"), - ty::TyInt(ast::IntTy::I32) => output.push_str("i32"), - ty::TyInt(ast::IntTy::I64) => output.push_str("i64"), - ty::TyInt(ast::IntTy::I128) => output.push_str("i128"), - ty::TyUint(ast::UintTy::Usize) => output.push_str("usize"), - ty::TyUint(ast::UintTy::U8) => output.push_str("u8"), - ty::TyUint(ast::UintTy::U16) => output.push_str("u16"), - ty::TyUint(ast::UintTy::U32) => output.push_str("u32"), - ty::TyUint(ast::UintTy::U64) => output.push_str("u64"), - ty::TyUint(ast::UintTy::U128) => output.push_str("u128"), - ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"), - ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"), - ty::TyAdt(adt_def, substs) => { + ty::Bool => output.push_str("bool"), + 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::Adt(adt_def, substs) => { self.push_def_path(adt_def.did, output); self.push_type_params(substs, iter::empty(), output); }, - ty::TyTuple(component_types) => { + ty::Tuple(component_types) => { output.push('('); for &component_type in component_types { self.push_type_name(component_type, output); @@ -291,7 +291,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { } output.push(')'); }, - ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { + ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { output.push('*'); match mutbl { hir::MutImmutable => output.push_str("const "), @@ -300,7 +300,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_type_name(inner_type, output); }, - ty::TyRef(_, inner_type, mutbl) => { + ty::Ref(_, inner_type, mutbl) => { output.push('&'); if mutbl == hir::MutMutable { output.push_str("mut "); @@ -308,18 +308,18 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_type_name(inner_type, output); }, - ty::TyArray(inner_type, len) => { + ty::Array(inner_type, len) => { output.push('['); self.push_type_name(inner_type, output); write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap(); output.push(']'); }, - ty::TySlice(inner_type) => { + ty::Slice(inner_type) => { output.push('['); self.push_type_name(inner_type, output); output.push(']'); }, - ty::TyDynamic(ref trait_data, ..) => { + ty::Dynamic(ref trait_data, ..) => { if let Some(principal) = trait_data.principal() { self.push_def_path(principal.def_id(), output); self.push_type_params(principal.skip_binder().substs, @@ -327,9 +327,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output); } }, - ty::TyForeign(did) => self.push_def_path(did, output), - ty::TyFnDef(..) | - ty::TyFnPtr(_) => { + 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 "); @@ -368,24 +368,24 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.push(')'); - if !sig.output().is_nil() { + if !sig.output().is_unit() { output.push_str(" -> "); self.push_type_name(sig.output(), output); } }, - ty::TyGenerator(def_id, GeneratorSubsts { ref substs }, _) | - ty::TyClosure(def_id, ClosureSubsts { ref substs }) => { + ty::Generator(def_id, GeneratorSubsts { ref substs }, _) | + ty::Closure(def_id, ClosureSubsts { ref substs }) => { self.push_def_path(def_id, output); let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id)); let substs = substs.truncate_to(self.tcx, generics); self.push_type_params(substs, iter::empty(), output); } - ty::TyError | - ty::TyInfer(_) | - ty::TyProjection(..) | - ty::TyParam(_) | - ty::TyGeneratorWitness(_) | - ty::TyAnon(..) => { + ty::Error | + ty::Infer(_) | + ty::Projection(..) | + ty::Param(_) | + ty::GeneratorWitness(_) | + ty::Opaque(..) => { bug!("DefPathBasedNames: Trying to create type name for \ unexpected type: {:?}", t); } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index bd0b2c6c27..fd094ffc1c 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -103,10 +103,11 @@ //! inlining, even when they are not marked #[inline]. use monomorphize::collector::InliningMap; -use rustc::dep_graph::WorkProductId; -use rustc::hir::def_id::DefId; +use rustc::dep_graph::{WorkProductId, WorkProduct, DepNode, DepConstructor}; +use rustc::hir::CodegenFnAttrFlags; +use rustc::hir::def_id::{DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; use rustc::hir::map::DefPathData; -use rustc::mir::mono::{Linkage, Visibility}; +use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder}; use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; @@ -114,7 +115,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry; use std::cmp; use syntax::ast::NodeId; -use syntax::symbol::{Symbol, InternedString}; +use syntax::symbol::InternedString; use rustc::mir::mono::MonoItem; use monomorphize::item::{MonoItemExt, InstantiationMode}; @@ -149,6 +150,15 @@ pub trait CodegenUnitExt<'tcx> { WorkProductId::from_cgu_name(&self.name().as_str()) } + fn work_product(&self, tcx: TyCtxt) -> WorkProduct { + let work_product_id = self.work_product_id(); + tcx.dep_graph + .previous_work_product(&work_product_id) + .unwrap_or_else(|| { + panic!("Could not find work-product for CGU `{}`", self.name()) + }) + } + fn items_in_deterministic_order<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec<(MonoItem<'tcx>, @@ -193,6 +203,10 @@ pub trait CodegenUnitExt<'tcx> { items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i)); items } + + fn codegen_dep_node(&self, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> DepNode { + DepNode::new(tcx, DepConstructor::CompileCodegenUnit(self.name().clone())) + } } impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> { @@ -202,17 +216,10 @@ impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> { } // Anything we can't find a proper codegen unit for goes into this. -fn fallback_cgu_name(tcx: TyCtxt) -> InternedString { - const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit"; - - if tcx.sess.opts.debugging_opts.human_readable_cgu_names { - Symbol::intern(FALLBACK_CODEGEN_UNIT).as_interned_str() - } else { - Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_interned_str() - } +fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder) -> InternedString { + name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu")) } - pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mono_items: I, strategy: PartitioningStrategy, @@ -223,8 +230,7 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // In the first step, we place all regular monomorphizations into their // respective 'home' codegen unit. Regular monomorphizations are all // functions and statics defined in the local crate. - let mut initial_partitioning = place_root_mono_items(tcx, - mono_items); + let mut initial_partitioning = place_root_mono_items(tcx, mono_items); initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(&tcx)); @@ -233,7 +239,7 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // If the partitioning should produce a fixed count of codegen units, merge // until that count is reached. if let PartitioningStrategy::FixedUnitCount(count) = strategy { - merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name.as_str()); + merge_codegen_units(tcx, &mut initial_partitioning, count); debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter()); } @@ -304,9 +310,12 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // available to downstream crates. This depends on whether we are in // share-generics mode and whether the current crate can even have // downstream crates. - let export_generics = tcx.share_generics() && + let export_generics = tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics(); + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); + let cgu_name_cache = &mut FxHashMap(); + for mono_item in mono_items { match mono_item.instantiation_mode(tcx) { InstantiationMode::GloballyShared { .. } => {} @@ -318,150 +327,24 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mono_item.is_generic_fn(); let codegen_unit_name = match characteristic_def_id { - Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile), - None => fallback_cgu_name(tcx), - }; - - let make_codegen_unit = || { - CodegenUnit::new(codegen_unit_name.clone()) + Some(def_id) => compute_codegen_unit_name(tcx, + cgu_name_builder, + def_id, + is_volatile, + cgu_name_cache), + None => fallback_cgu_name(cgu_name_builder), }; let codegen_unit = codegen_units.entry(codegen_unit_name.clone()) - .or_insert_with(make_codegen_unit); + .or_insert_with(|| CodegenUnit::new(codegen_unit_name.clone())); let mut can_be_internalized = true; - let default_visibility = |id: DefId, is_generic: bool| { - if !tcx.sess.target.target.options.default_hidden_visibility { - return Visibility::Default - } - - // Generic functions never have export level C - if is_generic { - return Visibility::Hidden - } - - // Things with export level C don't get instantiated in downstream - // crates - if !id.is_local() { - return Visibility::Hidden - } - - if let Some(&SymbolExportLevel::C) = tcx.reachable_non_generics(id.krate) - .get(&id) { - Visibility::Default - } else { - Visibility::Hidden - } - }; - let (linkage, visibility) = match mono_item.explicit_linkage(tcx) { - Some(explicit_linkage) => (explicit_linkage, Visibility::Default), - None => { - match mono_item { - MonoItem::Fn(ref instance) => { - let visibility = match instance.def { - InstanceDef::Item(def_id) => { - let is_generic = instance.substs - .types() - .next() - .is_some(); - - // The `start_fn` lang item is actually a - // monomorphized instance of a function in the - // standard library, used for the `main` - // function. We don't want to export it so we - // tag it with `Hidden` visibility but this - // symbol is only referenced from the actual - // `main` symbol which we unfortunately don't - // know anything about during - // partitioning/collection. As a result we - // forcibly keep this symbol out of the - // `internalization_candidates` set. - // - // FIXME: eventually we don't want to always - // force this symbol to have hidden - // visibility, it should indeed be a candidate - // for internalization, but we have to - // understand that it's referenced from the - // `main` symbol we'll generate later. - if tcx.lang_items().start_fn() == Some(def_id) { - can_be_internalized = false; - Visibility::Hidden - } else if def_id.is_local() { - if is_generic { - if export_generics { - if tcx.is_unreachable_local_definition(def_id) { - // This instance cannot be used - // from another crate. - Visibility::Hidden - } else { - // This instance might be useful in - // a downstream crate. - can_be_internalized = false; - default_visibility(def_id, true) - } - } else { - // We are not exporting generics or - // the definition is not reachable - // for downstream crates, we can - // internalize its instantiations. - Visibility::Hidden - } - } else { - // This isn't a generic function. - if tcx.is_reachable_non_generic(def_id) { - can_be_internalized = false; - debug_assert!(!is_generic); - default_visibility(def_id, false) - } else { - Visibility::Hidden - } - } - } else { - // This is an upstream DefId. - if export_generics && is_generic { - // If it is a upstream monomorphization - // and we export generics, we must make - // it available to downstream crates. - can_be_internalized = false; - default_visibility(def_id, true) - } else { - Visibility::Hidden - } - } - } - InstanceDef::FnPtrShim(..) | - InstanceDef::Virtual(..) | - InstanceDef::Intrinsic(..) | - InstanceDef::ClosureOnceShim { .. } | - InstanceDef::DropGlue(..) | - InstanceDef::CloneShim(..) => { - Visibility::Hidden - } - }; - (Linkage::External, visibility) - } - MonoItem::Static(def_id) => { - let visibility = if tcx.is_reachable_non_generic(def_id) { - can_be_internalized = false; - default_visibility(def_id, false) - } else { - Visibility::Hidden - }; - (Linkage::External, visibility) - } - MonoItem::GlobalAsm(node_id) => { - let def_id = tcx.hir.local_def_id(node_id); - let visibility = if tcx.is_reachable_non_generic(def_id) { - can_be_internalized = false; - default_visibility(def_id, false) - } else { - Visibility::Hidden - }; - (Linkage::External, visibility) - } - } - } - }; + let (linkage, visibility) = mono_item_linkage_and_visibility( + tcx, + &mono_item, + &mut can_be_internalized, + export_generics, + ); if visibility == Visibility::Hidden && can_be_internalized { internalization_candidates.insert(mono_item); } @@ -473,7 +356,7 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // always ensure we have at least one CGU; otherwise, if we have a // crate with just types (for example), we could wind up with no CGU if codegen_units.is_empty() { - let codegen_unit_name = fallback_cgu_name(tcx); + let codegen_unit_name = fallback_cgu_name(cgu_name_builder); codegen_units.insert(codegen_unit_name.clone(), CodegenUnit::new(codegen_unit_name.clone())); } @@ -487,9 +370,201 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<'tcx>, - target_cgu_count: usize, - crate_name: &str) { +fn mono_item_linkage_and_visibility( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mono_item: &MonoItem<'tcx>, + can_be_internalized: &mut bool, + export_generics: bool, +) -> (Linkage, Visibility) { + if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) { + return (explicit_linkage, Visibility::Default) + } + let vis = mono_item_visibility( + tcx, + mono_item, + can_be_internalized, + export_generics, + ); + (Linkage::External, vis) +} + +fn mono_item_visibility( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mono_item: &MonoItem<'tcx>, + can_be_internalized: &mut bool, + export_generics: bool, +) -> Visibility { + let instance = match mono_item { + // This is pretty complicated, go below + MonoItem::Fn(instance) => instance, + + // Misc handling for generics and such, but otherwise + MonoItem::Static(def_id) => { + return if tcx.is_reachable_non_generic(*def_id) { + *can_be_internalized = false; + default_visibility(tcx, *def_id, false) + } else { + Visibility::Hidden + }; + } + MonoItem::GlobalAsm(node_id) => { + let def_id = tcx.hir.local_def_id(*node_id); + return if tcx.is_reachable_non_generic(def_id) { + *can_be_internalized = false; + default_visibility(tcx, def_id, false) + } else { + Visibility::Hidden + }; + } + }; + + let def_id = match instance.def { + InstanceDef::Item(def_id) => def_id, + + // These are all compiler glue and such, never exported, always hidden. + InstanceDef::FnPtrShim(..) | + InstanceDef::Virtual(..) | + InstanceDef::Intrinsic(..) | + InstanceDef::ClosureOnceShim { .. } | + InstanceDef::DropGlue(..) | + InstanceDef::CloneShim(..) => { + return Visibility::Hidden + } + }; + + // The `start_fn` lang item is actually a monomorphized instance of a + // function in the standard library, used for the `main` function. We don't + // want to export it so we tag it with `Hidden` visibility but this symbol + // is only referenced from the actual `main` symbol which we unfortunately + // don't know anything about during partitioning/collection. As a result we + // forcibly keep this symbol out of the `internalization_candidates` set. + // + // FIXME: eventually we don't want to always force this symbol to have + // hidden visibility, it should indeed be a candidate for + // internalization, but we have to understand that it's referenced + // from the `main` symbol we'll generate later. + // + // This may be fixable with a new `InstanceDef` perhaps? Unsure! + if tcx.lang_items().start_fn() == Some(def_id) { + *can_be_internalized = false; + return Visibility::Hidden + } + + let is_generic = instance.substs.types().next().is_some(); + + // Upstream `DefId` instances get different handling than local ones + if !def_id.is_local() { + return if export_generics && is_generic { + // If it is a upstream monomorphization + // and we export generics, we must make + // it available to downstream crates. + *can_be_internalized = false; + default_visibility(tcx, def_id, true) + } else { + Visibility::Hidden + } + } + + if is_generic { + if export_generics { + if tcx.is_unreachable_local_definition(def_id) { + // This instance cannot be used + // from another crate. + Visibility::Hidden + } else { + // This instance might be useful in + // a downstream crate. + *can_be_internalized = false; + default_visibility(tcx, def_id, true) + } + } else { + // We are not exporting generics or + // the definition is not reachable + // for downstream crates, we can + // internalize its instantiations. + Visibility::Hidden + } + } else { + + // If this isn't a generic function then we mark this a `Default` if + // this is a reachable item, meaning that it's a symbol other crates may + // access when they link to us. + if tcx.is_reachable_non_generic(def_id) { + *can_be_internalized = false; + debug_assert!(!is_generic); + return default_visibility(tcx, def_id, false) + } + + // If this isn't reachable then we're gonna tag this with `Hidden` + // visibility. In some situations though we'll want to prevent this + // symbol from being internalized. + // + // There's two categories of items here: + // + // * First is weak lang items. These are basically mechanisms for + // libcore to forward-reference symbols defined later in crates like + // the standard library or `#[panic_implementation]` definitions. The + // definition of these weak lang items needs to be referenceable by + // libcore, so we're no longer a candidate for internalization. + // Removal of these functions can't be done by LLVM but rather must be + // done by the linker as it's a non-local decision. + // + // * Second is "std internal symbols". Currently this is primarily used + // for allocator symbols. Allocators are a little weird in their + // implementation, but the idea is that the compiler, at the last + // minute, defines an allocator with an injected object file. The + // `alloc` crate references these symbols (`__rust_alloc`) and the + // definition doesn't get hooked up until a linked crate artifact is + // generated. + // + // The symbols synthesized by the compiler (`__rust_alloc`) are thin + // veneers around the actual implementation, some other symbol which + // implements the same ABI. These symbols (things like `__rg_alloc`, + // `__rdl_alloc`, `__rde_alloc`, etc), are all tagged with "std + // internal symbols". + // + // The std-internal symbols here **should not show up in a dll as an + // exported interface**, so they return `false` from + // `is_reachable_non_generic` above and we'll give them `Hidden` + // visibility below. Like the weak lang items, though, we can't let + // LLVM internalize them as this decision is left up to the linker to + // omit them, so prevent them from being internalized. + let attrs = tcx.codegen_fn_attrs(def_id); + if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { + *can_be_internalized = false; + } + + Visibility::Hidden + } +} + +fn default_visibility(tcx: TyCtxt, id: DefId, is_generic: bool) -> Visibility { + if !tcx.sess.target.target.options.default_hidden_visibility { + return Visibility::Default + } + + // Generic functions never have export level C + if is_generic { + return Visibility::Hidden + } + + // Things with export level C don't get instantiated in + // downstream crates + if !id.is_local() { + return Visibility::Hidden + } + + // C-export level items remain at `Default`, all other internal + // items become `Hidden` + match tcx.reachable_non_generics(id.krate).get(&id) { + Some(SymbolExportLevel::C) => Visibility::Default, + _ => Visibility::Hidden, + } +} + +fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, + initial_partitioning: &mut PreInliningPartitioning<'tcx>, + target_cgu_count: usize) { assert!(target_cgu_count >= 1); let codegen_units = &mut initial_partitioning.codegen_units; @@ -517,14 +592,15 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning< } } + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); for (index, cgu) in codegen_units.iter_mut().enumerate() { - cgu.set_name(numbered_codegen_unit_name(crate_name, index)); + cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index)); } } fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning<'tcx>, - inlining_map: &InliningMap<'tcx>) - -> PostInliningPartitioning<'tcx> { + inlining_map: &InliningMap<'tcx>) + -> PostInliningPartitioning<'tcx> { let mut new_partitioning = Vec::new(); let mut mono_item_placements = FxHashMap(); @@ -631,7 +707,7 @@ fn internalize_symbols<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, inlining_map.iter_accesses(|accessor, accessees| { for accessee in accessees { accessor_map.entry(*accessee) - .or_insert(Vec::new()) + .or_default() .push(accessor); } }); @@ -718,46 +794,72 @@ fn characteristic_def_id_of_mono_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId, - volatile: bool) - -> InternedString { - // Unfortunately we cannot just use the `ty::item_path` infrastructure here - // because we need paths to modules and the DefIds of those are not - // available anymore for external items. - let mut cgu_name = String::with_capacity(64); - - let def_path = tcx.def_path(def_id); - cgu_name.push_str(&tcx.crate_name(def_path.krate).as_str()); - - for part in tcx.def_path(def_id) - .data - .iter() - .take_while(|part| { - match part.data { - DefPathData::Module(..) => true, - _ => false, - } - }) { - cgu_name.push_str("-"); - cgu_name.push_str(&part.data.as_interned_str().as_str()); - } +type CguNameCache = FxHashMap<(DefId, bool), InternedString>; + +fn compute_codegen_unit_name(tcx: TyCtxt, + name_builder: &mut CodegenUnitNameBuilder, + def_id: DefId, + volatile: bool, + cache: &mut CguNameCache) + -> InternedString { + // Find the innermost module that is not nested within a function + let mut current_def_id = def_id; + let mut cgu_def_id = None; + // Walk backwards from the item we want to find the module for: + loop { + let def_key = tcx.def_key(current_def_id); + + match def_key.disambiguated_data.data { + DefPathData::Module(..) => { + if cgu_def_id.is_none() { + cgu_def_id = Some(current_def_id); + } + } + DefPathData::CrateRoot { .. } => { + if cgu_def_id.is_none() { + // If we have not found a module yet, take the crate root. + cgu_def_id = Some(DefId { + krate: def_id.krate, + index: CRATE_DEF_INDEX, + }); + } + break + } + _ => { + // If we encounter something that is not a module, throw away + // any module that we've found so far because we now know that + // it is nested within something else. + cgu_def_id = None; + } + } - if volatile { - cgu_name.push_str(".volatile"); + current_def_id.index = def_key.parent.unwrap(); } - let cgu_name = if tcx.sess.opts.debugging_opts.human_readable_cgu_names { - cgu_name - } else { - CodegenUnit::mangle_name(&cgu_name) - }; + let cgu_def_id = cgu_def_id.unwrap(); + + cache.entry((cgu_def_id, volatile)).or_insert_with(|| { + let def_path = tcx.def_path(cgu_def_id); + + let components = def_path + .data + .iter() + .map(|part| part.data.as_interned_str()); + + let volatile_suffix = if volatile { + Some("volatile") + } else { + None + }; - Symbol::intern(&cgu_name[..]).as_interned_str() + name_builder.build_cgu_name(def_path.krate, components, volatile_suffix) + }).clone() } -fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString { - Symbol::intern(&format!("{}{}", crate_name, index)).as_interned_str() +fn numbered_codegen_unit_name(name_builder: &mut CodegenUnitNameBuilder, + index: usize) + -> InternedString { + name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index)) } fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 7bfbda8b78..a6c0397568 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -140,7 +140,9 @@ enum CallKind { fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl { let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span }; LocalDecl { - mutability, ty, name: None, + mutability, ty, + user_ty: None, + name: None, source_info, visibility_scope: source_info.scope, internal: false, @@ -165,7 +167,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); // Check if this is a generator, if so, return the drop glue for it - if let Some(&ty::TyS { sty: ty::TyGenerator(gen_def_id, substs, _), .. }) = ty { + if let Some(&ty::TyS { sty: ty::Generator(gen_def_id, substs, _), .. }) = ty { let mir = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap(); return mir.subst(tcx, substs.substs); } @@ -301,17 +303,17 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match self_ty.sty { _ if is_copy => builder.copy_shim(), - ty::TyArray(ty, len) => { + ty::Array(ty, len) => { let len = len.unwrap_usize(tcx); builder.array_shim(dest, src, ty, len) } - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { builder.tuple_like_shim( dest, src, substs.upvar_tys(def_id, tcx) ) } - ty::TyTuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().cloned()), + ty::Tuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().cloned()), _ => { bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty) } @@ -440,6 +442,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { let func = Operand::Constant(box Constant { span: self.span, ty: func_ty, + user_ty: None, literal: ty::Const::zero_sized(self.tcx, func_ty), }); @@ -498,6 +501,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { box Constant { span: self.span, ty: self.tcx.types.usize, + user_ty: None, literal: ty::Const::from_usize(self.tcx, value), } } @@ -725,6 +729,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (Operand::Constant(box Constant { span, ty, + user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }), vec![rcvr]) @@ -821,7 +826,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, let sig = gcx.normalize_erasing_regions(param_env, sig); let (adt_def, substs) = match sig.output().sty { - ty::TyAdt(adt_def, substs) => (adt_def, substs), + ty::Adt(adt_def, substs) => (adt_def, substs), _ => bug!("unexpected type for ADT ctor {:?}", sig.output()) }; @@ -847,7 +852,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, kind: StatementKind::Assign( Place::Local(RETURN_PLACE), Rvalue::Aggregate( - box AggregateKind::Adt(adt_def, variant_no, substs, None), + box AggregateKind::Adt(adt_def, variant_no, substs, None, None), (1..sig.inputs().len()+1).map(|i| { Operand::Move(Place::Local(Local::new(i))) }).collect() diff --git a/src/librustc_mir/transform/add_validation.rs b/src/librustc_mir/transform/add_validation.rs index 4f7f45f173..6efefdaa00 100644 --- a/src/librustc_mir/transform/add_validation.rs +++ b/src/librustc_mir/transform/add_validation.rs @@ -45,7 +45,7 @@ fn place_context<'a, 'tcx, D>( // A Deref projection may restrict the context, this depends on the type // being deref'd. let context = match ty.sty { - ty::TyRef(re, _, mutbl) => { + ty::Ref(re, _, mutbl) => { let re = match re { &RegionKind::ReScope(ce) => Some(ce), &RegionKind::ReErased => @@ -54,12 +54,12 @@ fn place_context<'a, 'tcx, D>( }; (re, mutbl) } - ty::TyRawPtr(_) => + ty::RawPtr(_) => // There is no guarantee behind even a mutable raw pointer, // no write locks are acquired there, so we also don't want to // release any. (None, hir::MutImmutable), - ty::TyAdt(adt, _) if adt.is_box() => (None, hir::MutMutable), + ty::Adt(adt, _) if adt.is_box() => (None, hir::MutMutable), _ => bug!("Deref on a non-pointer type {:?}", ty), }; // "Intersect" this restriction with proj.base. @@ -85,7 +85,7 @@ fn place_context<'a, 'tcx, D>( fn fn_contains_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource) -> bool { use rustc::hir::intravisit::{self, Visitor, FnKind}; use rustc::hir::map::blocks::FnLikeNode; - use rustc::hir::map::Node; + use rustc::hir::Node; /// Decide if this is an unsafe block fn block_is_unsafe(block: &hir::Block) -> bool { @@ -142,13 +142,13 @@ fn fn_contains_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource) -> } // Check if this is an unsafe block, or an item match node { - Node::NodeExpr(&hir::Expr { node: hir::ExprKind::Block(ref block, _), ..}) => { + Node::Expr(&hir::Expr { node: hir::ExprKind::Block(ref block, _), ..}) => { if block_is_unsafe(&*block) { // Found an unsafe block, we can bail out here. return true; } } - Node::NodeItem(..) => { + Node::Item(..) => { // No walking up beyond items. This makes sure the loop always terminates. break; } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index aba3996611..6fbc2f85c0 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -15,6 +15,7 @@ use rustc_data_structures::sync::Lrc; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; use rustc::hir; +use rustc::hir::Node; use rustc::hir::def_id::DefId; use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSAFE}; use rustc::mir::*; @@ -27,6 +28,7 @@ use util; pub struct UnsafetyChecker<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, + min_const_fn: bool, source_scope_local_data: &'a IndexVec, violations: Vec, source_info: SourceInfo, @@ -37,12 +39,16 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> { - fn new(mir: &'a Mir<'tcx>, - source_scope_local_data: &'a IndexVec, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>) -> Self { + fn new( + min_const_fn: bool, + mir: &'a Mir<'tcx>, + source_scope_local_data: &'a IndexVec, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Self { Self { mir, + min_const_fn, source_scope_local_data, violations: vec![], source_info: SourceInfo { @@ -108,7 +114,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { StatementKind::StorageDead(..) | StatementKind::EndRegion(..) | StatementKind::Validate(..) | - StatementKind::UserAssertTy(..) | + StatementKind::AscribeUserType(..) | StatementKind::Nop => { // safe (at least as emitted during MIR construction) } @@ -179,13 +185,13 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx); match base_ty.sty { - ty::TyRawPtr(..) => { + ty::RawPtr(..) => { self.require_unsafe("dereference of raw pointer", "raw pointers may be NULL, dangling or unaligned; they can violate \ aliasing rules and cause data races: all of these are undefined \ behavior") } - ty::TyAdt(adt, _) => { + ty::Adt(adt, _) => { if adt.is_union() { if context == PlaceContext::Store || context == PlaceContext::AsmOutput || @@ -268,6 +274,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { fn register_violations(&mut self, violations: &[UnsafetyViolation], unsafe_blocks: &[(ast::NodeId, bool)]) { + if self.min_const_fn { + for violation in violations { + let mut violation = violation.clone(); + violation.kind = UnsafetyViolationKind::MinConstFn; + if !self.violations.contains(&violation) { + self.violations.push(violation) + } + } + } let within_unsafe = match self.source_scope_local_data[self.source_info.scope].safety { Safety::Safe => { for violation in violations { @@ -275,7 +290,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { self.violations.push(violation.clone()) } } - false } Safety::BuiltinUnsafe | Safety::FnUnsafe => true, @@ -368,6 +382,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) let param_env = tcx.param_env(def_id); let mut checker = UnsafetyChecker::new( + tcx.is_const_fn(def_id) && tcx.is_min_const_fn(def_id), mir, source_scope_local_data, tcx, param_env); checker.visit_mir(mir); @@ -407,7 +422,7 @@ fn is_enclosed(tcx: TyCtxt, if parent_id != id { if used_unsafe.contains(&parent_id) { Some(("block".to_string(), parent_id)) - } else if let Some(hir::map::NodeItem(&hir::Item { + } else if let Some(Node::Item(&hir::Item { node: hir::ItemKind::Fn(_, header, _, _), .. })) = tcx.hir.find(parent_id) { @@ -424,12 +439,12 @@ fn is_enclosed(tcx: TyCtxt, } fn report_unused_unsafe(tcx: TyCtxt, used_unsafe: &FxHashSet, id: ast::NodeId) { - let span = tcx.sess.codemap().def_span(tcx.hir.span(id)); + let span = tcx.sess.source_map().def_span(tcx.hir.span(id)); let msg = "unnecessary `unsafe` block"; let mut db = tcx.struct_span_lint_node(UNUSED_UNSAFE, id, span, msg); db.span_label(span, msg); if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) { - db.span_label(tcx.sess.codemap().def_span(tcx.hir.span(id)), + db.span_label(tcx.sess.source_map().def_span(tcx.hir.span(id)), format!("because it's nested under this `unsafe` {}", kind)); } db.emit(); @@ -477,6 +492,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { .note(&details.as_str()[..]) .emit(); } + UnsafetyViolationKind::MinConstFn => { + tcx.sess.struct_span_err( + source_info.span, + &format!("{} is unsafe and unsafe operations \ + are not allowed in const fn", description)) + .span_label(source_info.span, &description.as_str()[..]) + .note(&details.as_str()[..]) + .emit(); + } UnsafetyViolationKind::ExternStatic(lint_node_id) => { tcx.lint_node_note(SAFE_EXTERN_STATICS, lint_node_id, diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 256b1fd66e..9edb1a1f76 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -12,7 +12,7 @@ //! //! - `CleanEndRegions`, that reduces the set of `EndRegion` statements //! in the MIR. -//! - `CleanUserAssertTy`, that replaces all `UserAssertTy` statements +//! - `CleanAscribeUserType`, that replaces all `AscribeUserType` statements //! with `Nop`. //! //! The `CleanEndRegions` "pass" is actually implemented as two @@ -24,10 +24,10 @@ //! MIR and removes any `EndRegion` that is applied to a region that //! was not seen in the previous pass. //! -//! The `CleanUserAssertTy` pass runs at a distinct time from the -//! `CleanEndRegions` pass. It is important that the `CleanUserAssertTy` +//! The `CleanAscribeUserType` pass runs at a distinct time from the +//! `CleanEndRegions` pass. It is important that the `CleanAscribeUserType` //! pass runs after the MIR borrowck so that the NLL type checker can -//! perform the type assertion when it encounters the `UserAssertTy` +//! perform the type assertion when it encounters the `AscribeUserType` //! statements. use rustc_data_structures::fx::FxHashSet; @@ -110,26 +110,26 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> { } } -pub struct CleanUserAssertTy; +pub struct CleanAscribeUserType; -pub struct DeleteUserAssertTy; +pub struct DeleteAscribeUserType; -impl MirPass for CleanUserAssertTy { +impl MirPass for CleanAscribeUserType { fn run_pass<'a, 'tcx>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _source: MirSource, mir: &mut Mir<'tcx>) { - let mut delete = DeleteUserAssertTy; + let mut delete = DeleteAscribeUserType; delete.visit_mir(mir); } } -impl<'tcx> MutVisitor<'tcx> for DeleteUserAssertTy { +impl<'tcx> MutVisitor<'tcx> for DeleteAscribeUserType { fn visit_statement(&mut self, block: BasicBlock, statement: &mut Statement<'tcx>, location: Location) { - if let StatementKind::UserAssertTy(..) = statement.kind { + if let StatementKind::AscribeUserType(..) = statement.kind { statement.make_nop(); } self.super_statement(block, statement, location); diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index ab221eb7a9..aaf4cf69b3 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -14,17 +14,17 @@ use rustc::hir::def::Def; use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local}; -use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind}; +use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind}; use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem}; use rustc::mir::visit::{Visitor, PlaceContext}; -use rustc::mir::interpret::{ConstEvalErr, EvalErrorKind}; +use rustc::mir::interpret::{ + ConstEvalErr, EvalErrorKind, ScalarMaybeUndef, Scalar, GlobalId, EvalResult +}; use rustc::ty::{TyCtxt, self, Instance}; -use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult}; -use interpret::EvalContext; -use interpret::CompileTimeEvaluator; -use interpret::{eval_promoted, mk_borrowck_eval_cx, ValTy}; +use interpret::{EvalContext, CompileTimeEvaluator, eval_promoted, mk_borrowck_eval_cx}; +use interpret::{self, Value, OpTy, MemoryKind}; use transform::{MirPass, MirSource}; -use syntax::codemap::{Span, DUMMY_SP}; +use syntax::source_map::{Span, DUMMY_SP}; use rustc::ty::subst::Substs; use rustc_data_structures::indexed_vec::IndexVec; use rustc::ty::ParamEnv; @@ -65,7 +65,7 @@ impl MirPass for ConstProp { } } -type Const<'tcx> = (Value, TyLayout<'tcx>, Span); +type Const<'tcx> = (OpTy<'tcx>, Span); /// Finds optimization opportunities on the MIR. struct ConstPropagator<'b, 'a, 'tcx:'a+'b> { @@ -133,7 +133,6 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { self.ecx.tcx.span = source_info.span; let lint_root = match self.mir.source_scope_local_data { ClearCrossCrate::Set(ref ivs) => { - use rustc_data_structures::indexed_vec::Idx; //FIXME(#51314): remove this check if source_info.scope.index() >= ivs.len() { return None; @@ -153,7 +152,9 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { | MachineError(_) // at runtime these transformations might make sense // FIXME: figure out the rules and start linting - | FunctionPointerTyMismatch(..) + | FunctionAbiMismatch(..) + | FunctionArgMismatch(..) + | FunctionArgCountMismatch // fine at runtime, might be a register address or sth | ReadBytesAsPointer // fine at runtime @@ -170,7 +171,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { | DoubleFree | InvalidFunctionPointer | InvalidBool - | InvalidDiscriminant + | InvalidDiscriminant(..) | PointerOutOfBounds { .. } | InvalidNullPointerUsage | MemoryLockViolation { .. } @@ -179,7 +180,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { | InvalidMemoryLockRelease { .. } | DeallocatedLockedMemory { .. } | InvalidPointerMath - | ReadUndefBytes + | ReadUndefBytes(_) | DeadLocal | InvalidBoolOp(_) | DerefFunctionPointer @@ -230,7 +231,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { // FIXME: implement => {}, - | Panic + | Panic { .. } | BoundsCheck{..} | Overflow(_) | OverflowNeg @@ -257,10 +258,9 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { source_info: SourceInfo, ) -> Option> { self.ecx.tcx.span = source_info.span; - match self.ecx.const_to_value(c.literal.val) { - Ok(val) => { - let layout = self.tcx.layout_of(self.param_env.and(c.literal.ty)).ok()?; - Some((val, layout, c.span)) + match self.ecx.const_to_op(c.literal) { + Ok(op) => { + Some((op, c.span)) }, Err(error) => { let (stacktrace, span) = self.ecx.generate_stacktrace(None); @@ -284,12 +284,15 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { Place::Projection(ref proj) => match proj.elem { ProjectionElem::Field(field, _) => { trace!("field proj on {:?}", proj.base); - let (base, layout, span) = self.eval_place(&proj.base, source_info)?; - let valty = self.use_ecx(source_info, |this| { - this.ecx.read_field(base, None, field, layout) + let (base, span) = self.eval_place(&proj.base, source_info)?; + let res = self.use_ecx(source_info, |this| { + this.ecx.operand_field(base, field.index() as u64) })?; - Some((valty.0, valty.1, span)) + Some((res, span)) }, + // We could get more projections by using e.g. `operand_projection`, + // but we do not even have the stack frame set up properly so + // an `Index` projection would throw us off-track. _ => None, }, Place::Promoted(ref promoted) => { @@ -306,12 +309,11 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { }; // cannot use `const_eval` here, because that would require having the MIR // for the current function available, but we're producing said MIR right now - let (value, _, ty) = self.use_ecx(source_info, |this| { + let res = self.use_ecx(source_info, |this| { eval_promoted(&mut this.ecx, cid, this.mir, this.param_env) })?; - let val = (value, ty, source_info.span); - trace!("evaluated promoted {:?} to {:?}", promoted, val); - Some(val) + trace!("evaluated promoted {:?} to {:?}", promoted, res); + Some((res, source_info.span)) }, _ => None, } @@ -343,17 +345,11 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { Rvalue::Discriminant(..) => None, Rvalue::Cast(kind, ref operand, _) => { - let (value, layout, span) = self.eval_operand(operand, source_info)?; + let (op, span) = self.eval_operand(operand, source_info)?; self.use_ecx(source_info, |this| { - let dest_ptr = this.ecx.alloc_ptr(place_layout)?; - let place_align = place_layout.align; - let dest = ::interpret::Place::from_ptr(dest_ptr, place_align); - this.ecx.cast(ValTy { value, ty: layout.ty }, kind, place_layout.ty, dest)?; - Ok(( - Value::ByRef(dest_ptr.into(), place_align), - place_layout, - span, - )) + let dest = this.ecx.allocate(place_layout, MemoryKind::Stack)?; + this.ecx.cast(op, kind, dest.into())?; + Ok((dest.into(), span)) }) } @@ -361,11 +357,15 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { Rvalue::Len(_) => None, Rvalue::NullaryOp(NullOp::SizeOf, ty) => { type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(( - Value::Scalar(Scalar::Bits { - bits: n as u128, - defined: self.tcx.data_layout.pointer_size.bits() as u8, - }), - self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, + OpTy { + op: interpret::Operand::Immediate(Value::Scalar( + Scalar::Bits { + bits: n as u128, + size: self.tcx.data_layout.pointer_size.bytes() as u8, + }.into() + )), + layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, + }, span, ))) } @@ -381,12 +381,30 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { return None; } - let val = self.eval_operand(arg, source_info)?; - let prim = self.use_ecx(source_info, |this| { - this.ecx.value_to_scalar(ValTy { value: val.0, ty: val.1.ty }) + let (arg, _) = self.eval_operand(arg, source_info)?; + let val = self.use_ecx(source_info, |this| { + let prim = this.ecx.read_scalar(arg)?.not_undef()?; + match op { + UnOp::Neg => { + // Need to do overflow check here: For actual CTFE, MIR + // generation emits code that does this before calling the op. + let size = arg.layout.size; + if prim.to_bits(size)? == (1 << (size.bits() - 1)) { + return err!(OverflowNeg); + } + } + UnOp::Not => { + // Cannot overflow + } + } + // Now run the actual operation. + this.ecx.unary_op(op, prim, arg.layout) })?; - let val = self.use_ecx(source_info, |this| this.ecx.unary_op(op, prim, val.1.ty))?; - Some((Value::Scalar(val), place_layout, span)) + let res = OpTy { + op: interpret::Operand::Immediate(Value::Scalar(val.into())), + layout: place_layout, + }; + Some((res, span)) } Rvalue::CheckedBinaryOp(op, ref left, ref right) | Rvalue::BinaryOp(op, ref left, ref right) => { @@ -404,7 +422,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { } let r = self.use_ecx(source_info, |this| { - this.ecx.value_to_scalar(ValTy { value: right.0, ty: right.1.ty }) + this.ecx.read_value(right.0) })?; if op == BinOp::Shr || op == BinOp::Shl { let left_ty = left.ty(self.mir, self.tcx); @@ -414,8 +432,9 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { .unwrap() .size .bits(); - let right_size = right.1.size; - if r.to_bits(right_size).ok().map_or(false, |b| b >= left_bits as u128) { + let right_size = right.0.layout.size; + let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); + if r_bits.ok().map_or(false, |b| b >= left_bits as u128) { let source_scope_local_data = match self.mir.source_scope_local_data { ClearCrossCrate::Set(ref data) => data, ClearCrossCrate::Clear => return None, @@ -436,16 +455,16 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { } let left = self.eval_operand(left, source_info)?; let l = self.use_ecx(source_info, |this| { - this.ecx.value_to_scalar(ValTy { value: left.0, ty: left.1.ty }) + this.ecx.read_value(left.0) })?; trace!("const evaluating {:?} for {:?} and {:?}", op, left, right); let (val, overflow) = self.use_ecx(source_info, |this| { - this.ecx.binary_op(op, l, left.1.ty, r, right.1.ty) + this.ecx.binary_op_val(op, l, r) })?; let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue { Value::ScalarPair( - val, - Scalar::from_bool(overflow), + val.into(), + Scalar::from_bool(overflow).into(), ) } else { if overflow { @@ -453,9 +472,13 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { let _: Option<()> = self.use_ecx(source_info, |_| Err(err)); return None; } - Value::Scalar(val) + Value::Scalar(val.into()) + }; + let res = OpTy { + op: interpret::Operand::Immediate(val), + layout: place_layout, }; - Some((val, place_layout, span)) + Some((res, span)) }, } } @@ -571,7 +594,8 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { if let TerminatorKind::Assert { expected, msg, cond, .. } = kind { if let Some(value) = self.eval_operand(cond, source_info) { trace!("assertion on {:?} should be {:?}", value, expected); - if Value::Scalar(Scalar::from_bool(*expected)) != value.0 { + let expected = Value::Scalar(Scalar::from_bool(*expected).into()); + if expected != value.0.to_immediate() { // poison all places this operand references so that further code // doesn't use the invalid value match cond { @@ -607,15 +631,19 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { let len = self .eval_operand(len, source_info) .expect("len must be const"); - let len = match len.0 { - Value::Scalar(Scalar::Bits { bits, ..}) => bits, + let len = match len.0.to_immediate() { + Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { + bits, .. + })) => bits, _ => bug!("const len not primitive: {:?}", len), }; let index = self .eval_operand(index, source_info) .expect("index must be const"); - let index = match index.0 { - Value::Scalar(Scalar::Bits { bits, .. }) => bits, + let index = match index.0.to_immediate() { + Value::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { + bits, .. + })) => bits, _ => bug!("const index not primitive: {:?}", index), }; format!( diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 8b2b9ef7e8..cff098c7b7 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -48,7 +48,7 @@ impl MirPass for Deaggregator { let mut set_discriminant = None; let active_field_index = match *kind { - AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => { + AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { if adt_def.is_enum() { set_discriminant = Some(Statement { kind: StatementKind::SetDiscriminant { diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 937d01a0c5..bf538112e4 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -18,8 +18,7 @@ use dataflow::{self, do_dataflow, DebugFormatted}; use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_set::IdxSetBuf; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::indexed_set::IdxSet; use transform::{MirPass, MirSource}; use util::patch::MirPatch; use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop}; @@ -93,12 +92,12 @@ fn find_dead_unwinds<'a, 'tcx>( mir: &Mir<'tcx>, id: ast::NodeId, env: &MoveDataParamEnv<'tcx, 'tcx>) - -> IdxSetBuf + -> IdxSet { debug!("find_dead_unwinds({:?})", mir.span); // We only need to do this pass once, because unwind edges can only // reach cleanup blocks, which can't have unwind edges themselves. - let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); + let mut dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len()); let flow_inits = do_dataflow(tcx, mir, id, &[], &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &env), @@ -112,7 +111,7 @@ fn find_dead_unwinds<'a, 'tcx>( let mut init_data = InitializationData { live: flow_inits.sets().on_entry_set_for(bb.index()).to_owned(), - dead: IdxSetBuf::new_empty(env.move_data.move_paths.len()), + dead: IdxSet::new_empty(env.move_data.move_paths.len()), }; debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}", bb, bb_data, init_data.live); @@ -147,8 +146,8 @@ fn find_dead_unwinds<'a, 'tcx>( } struct InitializationData { - live: IdxSetBuf, - dead: IdxSetBuf + live: IdxSet, + dead: IdxSet } impl InitializationData { @@ -543,6 +542,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, ty: self.tcx.types.bool, + user_ty: None, literal: ty::Const::from_bool(self.tcx, val), }))) } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 6a9258fe2c..01edfd2bfc 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -66,10 +66,10 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor}; use rustc::ty::{self, TyCtxt, AdtDef, Ty}; use rustc::ty::subst::Substs; use util::dump_mir; -use util::liveness::{self, IdentityMap, LivenessMode}; +use util::liveness::{self, IdentityMap}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::indexed_set::IdxSetBuf; -use std::collections::HashMap; +use rustc_data_structures::indexed_set::IdxSet; use std::borrow::Cow; use std::iter::once; use std::mem; @@ -142,10 +142,12 @@ struct TransformVisitor<'a, 'tcx: 'a> { state_field: usize, // Mapping from Local to (type of local, generator struct index) - remap: HashMap, usize)>, + // FIXME(eddyb) This should use `IndexVec>`. + remap: FxHashMap, usize)>, // A map from a suspension point in a block to the locals which have live storage at that point - storage_liveness: HashMap>, + // FIXME(eddyb) This should use `IndexVec>`. + storage_liveness: FxHashMap>, // A list of suspension points, generated during the transform suspension_points: Vec, @@ -157,7 +159,7 @@ struct TransformVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { // Make a GeneratorState rvalue fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> { - let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None); + let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None); Rvalue::Aggregate(box adt, vec![val]) } @@ -177,6 +179,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { let val = Operand::Constant(box Constant { span: source_info.span, ty: self.tcx.types.u32, + user_ty: None, literal: ty::Const::from_bits( self.tcx, state_disc.into(), @@ -300,6 +303,7 @@ fn replace_result_variable<'tcx>( let new_ret = LocalDecl { mutability: Mutability::Mut, ty: ret_ty, + user_ty: None, name: None, source_info, visibility_scope: source_info.scope, @@ -363,13 +367,16 @@ impl<'tcx> Visitor<'tcx> for BorrowedLocals { } } -fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir: &Mir<'tcx>, - source: MirSource, - movable: bool) -> - (liveness::LiveVarSet, - HashMap>) { - let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); +fn locals_live_across_suspend_points( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + source: MirSource, + movable: bool, +) -> ( + liveness::LiveVarSet, + FxHashMap>, +) { + let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len()); let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); // Calculate when MIR locals have live storage. This gives us an upper bound of their @@ -381,7 +388,7 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Find the MIR locals which do not use StorageLive/StorageDead statements. // The storage of these locals are always live. - let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len())); + let mut ignored = StorageIgnored(IdxSet::new_filled(mir.local_decls.len())); ignored.visit_mir(mir); // Calculate the MIR locals which have been previously @@ -401,10 +408,6 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut set = liveness::LiveVarSet::new_empty(mir.local_decls.len()); let mut liveness = liveness::liveness_of_locals( mir, - LivenessMode { - include_regular_use: true, - include_drops: true, - }, &IdentityMap::new(mir), ); liveness::dump_mir( @@ -416,7 +419,7 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &liveness, ); - let mut storage_liveness_map = HashMap::new(); + let mut storage_liveness_map = FxHashMap::default(); for (block, data) in mir.basic_blocks().iter_enumerated() { if let TerminatorKind::Yield { .. } = data.terminator().kind { @@ -433,7 +436,8 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // The `liveness` variable contains the liveness of MIR locals ignoring borrows. // This is correct for movable generators since borrows cannot live across // suspension points. However for immovable generators we need to account for - // borrows, so we conseratively assume that all borrowed locals live forever. + // borrows, so we conseratively assume that all borrowed locals are live until + // we find a StorageDead statement referencing the locals. // To do this we just union our `liveness` result with `borrowed_locals`, which // contains all the locals which has been borrowed before this suspension point. // If a borrow is converted to a raw reference, we must also assume that it lives @@ -479,9 +483,9 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, interior: Ty<'tcx>, movable: bool, mir: &mut Mir<'tcx>) - -> (HashMap, usize)>, + -> (FxHashMap, usize)>, GeneratorLayout<'tcx>, - HashMap>) + FxHashMap>) { // Use a liveness analysis to compute locals which are live across a suspension point let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx, @@ -492,7 +496,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // MIR types let allowed_upvars = tcx.erase_regions(&upvars); let allowed = match interior.sty { - ty::TyGeneratorWitness(s) => tcx.erase_late_bound_regions(&s), + ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s), _ => bug!(), }; @@ -514,7 +518,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let upvar_len = mir.upvar_decls.len(); - let dummy_local = LocalDecl::new_internal(tcx.mk_nil(), mir.span); + let dummy_local = LocalDecl::new_internal(tcx.mk_unit(), mir.span); // Gather live locals and their indices replacing values in mir.local_decls with a dummy // to avoid changing local indices @@ -652,7 +656,8 @@ fn create_generator_drop_shim<'a, 'tcx>( // Replace the return variable mir.local_decls[RETURN_PLACE] = LocalDecl { mutability: Mutability::Mut, - ty: tcx.mk_nil(), + ty: tcx.mk_unit(), + user_ty: None, name: None, source_info, visibility_scope: source_info.scope, @@ -669,6 +674,7 @@ fn create_generator_drop_shim<'a, 'tcx>( ty: gen_ty, mutbl: hir::Mutability::MutMutable, }), + user_ty: None, name: None, source_info, visibility_scope: source_info.scope, @@ -709,6 +715,7 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cond: Operand::Constant(box Constant { span: mir.span, ty: tcx.types.bool, + user_ty: None, literal: ty::Const::from_bool(tcx, false), }), expected: true, @@ -862,7 +869,7 @@ impl MirPass for StateTransform { // Get the interior types and substs which typeck computed let (upvars, interior, movable) = match gen_ty.sty { - ty::TyGenerator(_, substs, movability) => { + ty::Generator(_, substs, movability) => { (substs.upvar_tys(def_id, tcx).collect(), substs.witness(def_id, tcx), movability == hir::GeneratorMovability::Movable) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 46fab544aa..31e437ce22 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -14,7 +14,7 @@ use rustc::hir; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::DefId; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::*; @@ -95,7 +95,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { + if let ty::FnDef(callee_def_id, substs) = f.ty.sty { if let Some(instance) = Instance::resolve(self.tcx, param_env, callee_def_id, @@ -158,7 +158,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: Operand::Constant(ref f), .. } = terminator.kind { - if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { + if let ty::FnDef(callee_def_id, substs) = f.ty.sty { // Don't inline the same function multiple times. if callsite.callee != callee_def_id { callsites.push_back(CallSite { @@ -271,7 +271,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { // Traverse the MIR manually so we can account for the effects of // inlining on the CFG. let mut work_list = vec![START_BLOCK]; - let mut visited = BitVector::new(callee_mir.basic_blocks().len()); + let mut visited = BitArray::new(callee_mir.basic_blocks().len()); while let Some(bb) = work_list.pop() { if !visited.insert(bb.index()) { continue; } let blk = &callee_mir.basic_blocks()[bb]; @@ -314,7 +314,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::TyFnDef(def_id, _) = f.ty.sty { + if let ty::FnDef(def_id, _) = f.ty.sty { // Don't give intrinsics the extra penalty for calls let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { @@ -538,7 +538,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { assert!(args.next().is_none()); let tuple = Place::Local(tuple); - let tuple_tys = if let ty::TyTuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty { + let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty { s } else { bug!("Closure arguments are not passed as a tuple"); @@ -704,7 +704,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { *unwind = Some(self.update_target(tgt)); } else if !self.in_cleanup_block { // Unless this drop is in a cleanup block, add an unwind edge to - // the orignal call's cleanup block + // the original call's cleanup block *unwind = self.cleanup_block; } } @@ -716,7 +716,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { *cleanup = Some(self.update_target(tgt)); } else if !self.in_cleanup_block { // Unless this call is in a cleanup block, add an unwind edge to - // the orignal call's cleanup block + // the original call's cleanup block *cleanup = self.cleanup_block; } } @@ -726,7 +726,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { *cleanup = Some(self.update_target(tgt)); } else if !self.in_cleanup_block { // Unless this assert is in a cleanup block, add an unwind edge to - // the orignal call's cleanup block + // the original call's cleanup block *cleanup = self.cleanup_block; } } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 6e06beb304..12780ef8be 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -12,7 +12,7 @@ use rustc::mir::{Constant, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local}; use rustc::mir::visit::{MutVisitor, Visitor}; -use rustc::ty::{TyCtxt, TypeVariants}; +use rustc::ty::{TyCtxt, TyKind}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::Idx; use std::mem; @@ -100,10 +100,10 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> { if let Rvalue::Len(ref place) = *rvalue { let place_ty = place.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx); - if let TypeVariants::TyArray(_, len) = place_ty.sty { + if let TyKind::Array(_, len) = place_ty.sty { let span = self.mir.source_info(location).span; let ty = self.tcx.types.usize; - let constant = Constant { span, ty, literal: len }; + let constant = Constant { span, ty, literal: len, user_ty: None }; self.optimizations.arrays_lengths.insert(location, constant); } } diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs index 83cd7bf549..8ed5600400 100644 --- a/src/librustc_mir/transform/lower_128bit.rs +++ b/src/librustc_mir/transform/lower_128bit.rs @@ -13,7 +13,7 @@ use rustc::hir::def_id::DefId; use rustc::middle::lang_items::LangItem; use rustc::mir::*; -use rustc::ty::{Slice, Ty, TyCtxt, TypeVariants}; +use rustc::ty::{List, Ty, TyCtxt, TyKind}; use rustc_data_structures::indexed_vec::{Idx}; use transform::{MirPass, MirSource}; use syntax; @@ -114,7 +114,7 @@ impl Lower128Bit { source_info, kind: TerminatorKind::Call { func: Operand::function_handle(tcx, call_did, - Slice::empty(), source_info.span), + List::empty(), source_info.span), args: vec![lhs, rhs], destination: Some((place, bb)), cleanup: None, @@ -190,8 +190,8 @@ impl RhsKind { fn sign_of_128bit(ty: Ty) -> Option { match ty.sty { - TypeVariants::TyInt(syntax::ast::IntTy::I128) => Some(true), - TypeVariants::TyUint(syntax::ast::UintTy::U128) => Some(false), + TyKind::Int(syntax::ast::IntTy::I128) => Some(true), + TyKind::Uint(syntax::ast::UintTy::U128) => Some(false), _ => None, } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 90dfebeef1..19fb35be9d 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -36,6 +36,7 @@ pub mod elaborate_drops; pub mod add_call_guards; pub mod promote_consts; pub mod qualify_consts; +mod qualify_min_const_fn; pub mod remove_noop_landing_pads; pub mod dump_mir; pub mod deaggregator; @@ -237,8 +238,8 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx simplify_branches::SimplifyBranches::new("initial"), remove_noop_landing_pads::RemoveNoopLandingPads, simplify::SimplifyCfg::new("early-opt"), - // Remove all `UserAssertTy` statements. - cleanup_post_borrowck::CleanUserAssertTy, + // Remove all `AscribeUserType` statements. + cleanup_post_borrowck::CleanAscribeUserType, // These next passes must be executed together add_call_guards::CriticalCallEdges, diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index b3ae65f532..bb66b9ed6e 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -302,7 +302,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; match statement.kind { StatementKind::Assign(_, Rvalue::Ref(_, _, ref mut place)) => { - // Find the underlying local for this (necessarilly interior) borrow. + // Find the underlying local for this (necessarily interior) borrow. // HACK(eddyb) using a recursive function because of mutable borrows. fn interior_base<'a, 'tcx>(place: &'a mut Place<'tcx>) -> &'a mut Place<'tcx> { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 673cf6aa11..a2175dce33 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -14,9 +14,9 @@ //! The Qualif flags below can be used to also provide better //! diagnostics as to why a constant rvalue wasn't promoted. -use rustc_data_structures::bitvec::BitVector; -use rustc_data_structures::indexed_set::IdxSetBuf; -use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc_data_structures::bitvec::BitArray; +use rustc_data_structures::indexed_set::IdxSet; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashSet; use rustc::hir; use rustc::hir::def_id::DefId; @@ -116,7 +116,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { param_env: ty::ParamEnv<'tcx>, local_qualif: IndexVec>, qualif: Qualif, - const_fn_arg_vars: BitVector, + const_fn_arg_vars: BitArray, temp_promotion_state: IndexVec, promotion_candidates: Vec } @@ -151,7 +151,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { param_env, local_qualif, qualif: Qualif::empty(), - const_fn_arg_vars: BitVector::new(mir.local_decls.len()), + const_fn_arg_vars: BitArray::new(mir.local_decls.len()), temp_promotion_state: temps, promotion_candidates: vec![] } @@ -280,12 +280,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } /// Qualify a whole const, static initializer or const fn. - fn qualify_const(&mut self) -> (Qualif, Lrc>) { + fn qualify_const(&mut self) -> (Qualif, Lrc>) { debug!("qualifying {} {:?}", self.mode, self.def_id); let mir = self.mir; - let mut seen_blocks = BitVector::new(mir.basic_blocks().len()); + let mut seen_blocks = BitArray::new(mir.basic_blocks().len()); let mut bb = START_BLOCK; loop { seen_blocks.insert(bb.index()); @@ -383,7 +383,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { // Collect all the temps we need to promote. - let mut promoted_temps = IdxSetBuf::new_empty(self.temp_promotion_state.len()); + let mut promoted_temps = IdxSet::new_empty(self.temp_promotion_state.len()); for candidate in &self.promotion_candidates { match *candidate { @@ -401,6 +401,11 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { (self.qualif, Lrc::new(promoted_temps)) } + + fn is_const_panic_fn(&self, def_id: DefId) -> bool { + Some(def_id) == self.tcx.lang_items().panic_fn() || + Some(def_id) == self.tcx.lang_items().begin_panic_fn() + } } /// Accumulates an Rvalue or Call's effects in self.qualif. @@ -492,41 +497,46 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { this.super_place(place, context, location); match proj.elem { ProjectionElem::Deref => { - this.add(Qualif::NOT_CONST); - - let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx); - if let ty::TyRawPtr(_) = base_ty.sty { - if this.mode != Mode::Fn { - let mut err = struct_span_err!( - this.tcx.sess, - this.span, - E0396, - "raw pointers cannot be dereferenced in {}s", - this.mode - ); - err.span_label(this.span, - "dereference of raw pointer in constant"); - if this.tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "The value behind a raw pointer can't be determined \ - at compile-time (or even link-time), which means it \ - can't be used in a constant expression." + if let Mode::Fn = this.mode { + this.add(Qualif::NOT_CONST); + } else { + let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx); + if let ty::RawPtr(_) = base_ty.sty { + if !this.tcx.sess.features_untracked().const_raw_ptr_deref { + emit_feature_err( + &this.tcx.sess.parse_sess, "const_raw_ptr_deref", + this.span, GateIssue::Language, + &format!( + "dereferencing raw pointers in {}s is unstable", + this.mode, + ), ); - err.help("A possible fix is to dereference your pointer \ - at some point in run-time."); } - err.emit(); } } } ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - if this.mode == Mode::Fn { - let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx); - if let Some(def) = base_ty.ty_adt_def() { - if def.is_union() { - this.not_const(); + let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx); + if let Some(def) = base_ty.ty_adt_def() { + if def.is_union() { + match this.mode { + Mode::Fn => this.not_const(), + Mode::ConstFn => { + if !this.tcx.sess.features_untracked().const_fn_union { + emit_feature_err( + &this.tcx.sess.parse_sess, "const_fn_union", + this.span, GateIssue::Language, + "unions in const fn are unstable", + ); + } + }, + + | Mode::Static + | Mode::StaticMut + | Mode::Const + => {}, } } } @@ -587,7 +597,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if let Place::Projection(ref proj) = *place { if let ProjectionElem::Deref = proj.elem { let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); - if let ty::TyRef(..) = base_ty.sty { + if let ty::Ref(..) = base_ty.sty { is_reborrow = true; } } @@ -634,10 +644,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if self.mode == Mode::StaticMut { // Inside a `static mut`, &mut [...] is also allowed. match ty.sty { - ty::TyArray(..) | ty::TySlice(_) => forbidden_mut = false, + ty::Array(..) | ty::Slice(_) => forbidden_mut = false, _ => {} } - } else if let ty::TyArray(_, len) = ty.sty { + } else if let ty::Array(_, len) = ty.sty { // FIXME(eddyb) the `self.mode == Mode::Fn` condition // seems unnecessary, given that this is merely a ZST. if len.unwrap_usize(self.tcx) == 0 && self.mode == Mode::Fn { @@ -723,44 +733,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { match (cast_in, cast_out) { (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => { - self.add(Qualif::NOT_CONST); - if self.mode != Mode::Fn { - let mut err = struct_span_err!( - self.tcx.sess, - self.span, - E0018, - "raw pointers cannot be cast to integers in {}s", - self.mode + if let Mode::Fn = self.mode { + self.add(Qualif::NOT_CONST); + } else if !self.tcx.sess.features_untracked().const_raw_ptr_to_usize_cast { + emit_feature_err( + &self.tcx.sess.parse_sess, "const_raw_ptr_to_usize_cast", + self.span, GateIssue::Language, + &format!( + "casting pointers to integers in {}s is unstable", + self.mode, + ), ); - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note("\ -The value of static and constant integers must be known at compile time. You can't cast a pointer \ -to an integer because the address of a pointer can vary. - -For example, if you write: - -``` -static MY_STATIC: u32 = 42; -static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize; -static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR; -``` - -Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However, the address can change \ -when the program is linked, as well as change between different executions due to ASLR, and many \ -linkers would not be able to calculate the value of `WHAT`. - -On the other hand, static and constant pointers can point either to a known numeric address or to \ -the address of a symbol. - -``` -static MY_STATIC: u32 = 42; -static MY_STATIC_ADDR: &'static u32 = &MY_STATIC; -const CONST_ADDR: *const u8 = 0x5f3759df as *const u8; -``` - -This does not pose a problem by itself because they can't be accessed directly."); - } - err.emit(); } } _ => {} @@ -768,22 +751,22 @@ This does not pose a problem by itself because they can't be accessed directly." } Rvalue::BinaryOp(op, ref lhs, _) => { - if let ty::TyRawPtr(_) = lhs.ty(self.mir, self.tcx).sty { + if let ty::RawPtr(_) = lhs.ty(self.mir, self.tcx).sty { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || op == BinOp::Offset); - self.add(Qualif::NOT_CONST); - if self.mode != Mode::Fn { - struct_span_err!( - self.tcx.sess, self.span, E0395, - "raw pointers cannot be compared in {}s", - self.mode) - .span_label( + if let Mode::Fn = self.mode { + self.add(Qualif::NOT_CONST); + } else if !self.tcx.sess.features_untracked().const_compare_raw_pointers { + emit_feature_err( + &self.tcx.sess.parse_sess, + "const_compare_raw_pointers", self.span, - "comparing raw pointers in static") - .emit(); + GateIssue::Language, + &format!("comparing raw pointers inside {}", self.mode), + ); } } } @@ -832,7 +815,7 @@ This does not pose a problem by itself because they can't be accessed directly." let fn_ty = func.ty(self.mir, self.tcx); let mut callee_def_id = None; let (mut is_shuffle, mut is_const_fn) = (false, None); - if let ty::TyFnDef(def_id, _) = fn_ty.sty { + if let ty::FnDef(def_id, _) = fn_ty.sty { callee_def_id = Some(def_id); match self.tcx.fn_sig(def_id).abi() { Abi::RustIntrinsic | @@ -843,11 +826,32 @@ This does not pose a problem by itself because they can't be accessed directly." | "min_align_of" | "type_id" | "bswap" + | "bitreverse" | "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" - | "ctlz_nonzero" => is_const_fn = Some(def_id), + | "ctlz_nonzero" + | "overflowing_add" + | "overflowing_sub" + | "overflowing_mul" + | "unchecked_shl" + | "unchecked_shr" + | "add_with_overflow" + | "sub_with_overflow" + | "mul_with_overflow" => is_const_fn = Some(def_id), + "transmute" => { + if self.mode != Mode::Fn { + is_const_fn = Some(def_id); + if !self.tcx.sess.features_untracked().const_transmute { + emit_feature_err( + &self.tcx.sess.parse_sess, "const_transmute", + self.span, GateIssue::Language, + &format!("The use of std::mem::transmute() \ + is gated in {}s", self.mode)); + } + } + } name if name.starts_with("simd_shuffle") => { is_shuffle = true; @@ -857,7 +861,7 @@ This does not pose a problem by itself because they can't be accessed directly." } } _ => { - if self.tcx.is_const_fn(def_id) { + if self.tcx.is_const_fn(def_id) || self.is_const_panic_fn(def_id) { is_const_fn = Some(def_id); } } @@ -903,11 +907,26 @@ This does not pose a problem by itself because they can't be accessed directly." // Const fn calls. if let Some(def_id) = is_const_fn { + // check the const_panic feature gate or // find corresponding rustc_const_unstable feature - if let Some(&attr::Stability { - rustc_const_unstable: Some(attr::RustcConstUnstable { - feature: ref feature_name - }), + // FIXME: cannot allow this inside `allow_internal_unstable` because that would make + // `panic!` insta stable in constants, since the macro is marked with the attr + if self.is_const_panic_fn(def_id) { + if self.mode == Mode::Fn { + // never promote panics + self.qualif = Qualif::NOT_CONST; + } else if !self.tcx.sess.features_untracked().const_panic { + // don't allow panics in constants without the feature gate + emit_feature_err( + &self.tcx.sess.parse_sess, + "const_panic", + self.span, + GateIssue::Language, + &format!("panicking in {}s is unstable", self.mode), + ); + } + } else if let Some(&attr::Stability { + const_stability: Some(ref feature_name), .. }) = self.tcx.lookup_stability(def_id) { if // feature-gate is not enabled, @@ -1079,7 +1098,7 @@ This does not pose a problem by itself because they can't be accessed directly." StatementKind::InlineAsm {..} | StatementKind::EndRegion(_) | StatementKind::Validate(..) | - StatementKind::UserAssertTy(..) | + StatementKind::AscribeUserType(..) | StatementKind::Nop => {} } }); @@ -1102,7 +1121,7 @@ pub fn provide(providers: &mut Providers) { fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> (u8, Lrc>) { + -> (u8, Lrc>) { // NB: This `borrow()` is guaranteed to be valid (i.e., the value // cannot yet be stolen), because `mir_validated()`, which steals // from `mir_const(), forces this query to execute before @@ -1111,7 +1130,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if mir.return_ty().references_error() { tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors"); - return (Qualif::NOT_CONST.bits(), Lrc::new(IdxSetBuf::new_empty(0))); + return (Qualif::NOT_CONST.bits(), Lrc::new(IdxSet::new_empty(0))); } let mut qualifier = Qualifier::new(tcx, def_id, mir, Mode::Const); @@ -1161,8 +1180,20 @@ impl MirPass for QualifyAndPromoteConstants { let (temps, candidates) = { let mut qualifier = Qualifier::new(tcx, def_id, mir, mode); if mode == Mode::ConstFn { - // Enforce a constant-like CFG for `const fn`. - qualifier.qualify_const(); + if tcx.is_min_const_fn(def_id) { + // enforce `min_const_fn` for stable const fns + use super::qualify_min_const_fn::is_min_const_fn; + if let Err((span, err)) = is_min_const_fn(tcx, def_id, mir) { + tcx.sess.span_err(span, &err); + } else { + // this should not produce any errors, but better safe than sorry + // FIXME(#53819) + qualifier.qualify_const(); + } + } else { + // Enforce a constant-like CFG for `const fn`. + qualifier.qualify_const(); + } } else { while let Some((bb, data)) = qualifier.rpo.next() { qualifier.visit_basic_block_data(bb, data); diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs new file mode 100644 index 0000000000..f7e44dde18 --- /dev/null +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -0,0 +1,358 @@ +use rustc::hir::def_id::DefId; +use rustc::hir; +use rustc::mir::*; +use rustc::ty::{self, Predicate, TyCtxt}; +use std::borrow::Cow; +use syntax_pos::Span; + +type McfResult = Result<(), (Span, Cow<'static, str>)>; + +pub fn is_min_const_fn( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + mir: &'a Mir<'tcx>, +) -> McfResult { + let mut current = def_id; + loop { + let predicates = tcx.predicates_of(current); + for predicate in &predicates.predicates { + match predicate { + | Predicate::RegionOutlives(_) + | Predicate::TypeOutlives(_) + | Predicate::WellFormed(_) + | Predicate::ConstEvaluatable(..) => continue, + | Predicate::ObjectSafe(_) => { + bug!("object safe predicate on function: {:#?}", predicate) + } + Predicate::ClosureKind(..) => { + bug!("closure kind predicate on function: {:#?}", predicate) + } + Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate), + Predicate::Projection(_) => { + let span = tcx.def_span(current); + // we'll hit a `Predicate::Trait` later which will report an error + tcx.sess + .delay_span_bug(span, "projection without trait bound"); + continue; + } + Predicate::Trait(pred) => { + if Some(pred.def_id()) == tcx.lang_items().sized_trait() { + continue; + } + match pred.skip_binder().self_ty().sty { + ty::Param(ref p) => { + let generics = tcx.generics_of(current); + let def = generics.type_param(p, tcx); + let span = tcx.def_span(def.def_id); + return Err(( + span, + "trait bounds other than `Sized` \ + on const fn parameters are unstable" + .into(), + )); + } + // other kinds of bounds are either tautologies + // or cause errors in other passes + _ => continue, + } + } + } + } + match predicates.parent { + Some(parent) => current = parent, + None => break, + } + } + + for local in mir.vars_iter() { + return Err(( + mir.local_decls[local].source_info.span, + "local variables in const fn are unstable".into(), + )); + } + for local in &mir.local_decls { + check_ty(tcx, local.ty, local.source_info.span)?; + } + // impl trait is gone in MIR, so check the return type manually + check_ty( + tcx, + tcx.fn_sig(def_id).output().skip_binder(), + mir.local_decls.iter().next().unwrap().source_info.span, + )?; + + for bb in mir.basic_blocks() { + check_terminator(tcx, mir, bb.terminator())?; + for stmt in &bb.statements { + check_statement(tcx, mir, stmt)?; + } + } + Ok(()) +} + +fn check_ty( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + ty: ty::Ty<'tcx>, + span: Span, +) -> McfResult { + for ty in ty.walk() { + match ty.sty { + ty::Ref(_, _, hir::Mutability::MutMutable) => return Err(( + span, + "mutable references in const fn are unstable".into(), + )), + ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())), + ty::FnPtr(..) => { + return Err((span, "function pointers in const fn are unstable".into())) + } + ty::Dynamic(preds, _) => { + for pred in preds.iter() { + match pred.skip_binder() { + | ty::ExistentialPredicate::AutoTrait(_) + | ty::ExistentialPredicate::Projection(_) => { + return Err(( + span, + "trait bounds other than `Sized` \ + on const fn parameters are unstable" + .into(), + )) + } + ty::ExistentialPredicate::Trait(trait_ref) => { + if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() { + return Err(( + span, + "trait bounds other than `Sized` \ + on const fn parameters are unstable" + .into(), + )); + } + } + } + } + } + _ => {} + } + } + Ok(()) +} + +fn check_rvalue( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + rvalue: &Rvalue<'tcx>, + span: Span, +) -> McfResult { + match rvalue { + Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { + check_operand(tcx, mir, operand, span) + } + Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { + check_place(tcx, mir, place, span, PlaceMode::Read) + } + Rvalue::Cast(_, operand, cast_ty) => { + use rustc::ty::cast::CastTy; + let cast_in = CastTy::from_ty(operand.ty(mir, tcx)).expect("bad input type for cast"); + let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); + match (cast_in, cast_out) { + (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => Err(( + span, + "casting pointers to ints is unstable in const fn".into(), + )), + (CastTy::RPtr(_), CastTy::Float) => bug!(), + (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), + (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), + _ => check_operand(tcx, mir, operand, span), + } + } + // binops are fine on integers + Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { + check_operand(tcx, mir, lhs, span)?; + check_operand(tcx, mir, rhs, span)?; + let ty = lhs.ty(mir, tcx); + if ty.is_integral() || ty.is_bool() || ty.is_char() { + Ok(()) + } else { + Err(( + span, + "only int, `bool` and `char` operations are stable in const fn".into(), + )) + } + } + // checked by regular const fn checks + Rvalue::NullaryOp(..) => Ok(()), + Rvalue::UnaryOp(_, operand) => { + let ty = operand.ty(mir, tcx); + if ty.is_integral() || ty.is_bool() { + check_operand(tcx, mir, operand, span) + } else { + Err(( + span, + "only int and `bool` operations are stable in const fn".into(), + )) + } + } + Rvalue::Aggregate(_, operands) => { + for operand in operands { + check_operand(tcx, mir, operand, span)?; + } + Ok(()) + } + } +} + +enum PlaceMode { + Assign, + Read, +} + +fn check_statement( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + statement: &Statement<'tcx>, +) -> McfResult { + let span = statement.source_info.span; + match &statement.kind { + StatementKind::Assign(place, rval) => { + check_place(tcx, mir, place, span, PlaceMode::Assign)?; + check_rvalue(tcx, mir, rval, span) + } + + StatementKind::ReadForMatch(_) => Err((span, "match in const fn is unstable".into())), + + // just an assignment + StatementKind::SetDiscriminant { .. } => Ok(()), + + | StatementKind::InlineAsm { .. } => { + Err((span, "cannot use inline assembly in const fn".into())) + } + + // These are all NOPs + | StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) + | StatementKind::Validate(..) + | StatementKind::EndRegion(_) + | StatementKind::AscribeUserType(..) + | StatementKind::Nop => Ok(()), + } +} + +fn check_operand( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + operand: &Operand<'tcx>, + span: Span, +) -> McfResult { + match operand { + Operand::Move(place) | Operand::Copy(place) => { + check_place(tcx, mir, place, span, PlaceMode::Read) + } + Operand::Constant(_) => Ok(()), + } +} + +fn check_place( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + place: &Place<'tcx>, + span: Span, + mode: PlaceMode, +) -> McfResult { + match place { + Place::Local(l) => match mode { + PlaceMode::Assign => match mir.local_kind(*l) { + LocalKind::Temp | LocalKind::ReturnPointer => Ok(()), + LocalKind::Arg | LocalKind::Var => { + Err((span, "assignments in const fn are unstable".into())) + } + }, + PlaceMode::Read => Ok(()), + }, + // promoteds are always fine, they are essentially constants + Place::Promoted(_) => Ok(()), + Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())), + Place::Projection(proj) => { + match proj.elem { + | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { + check_place(tcx, mir, &proj.base, span, mode) + } + // slice patterns are unstable + | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { + return Err((span, "slice patterns in const fn are unstable".into())) + } + | ProjectionElem::Downcast(..) => { + Err((span, "`match` or `if let` in `const fn` is unstable".into())) + } + } + } + } +} + +fn check_terminator( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + terminator: &Terminator<'tcx>, +) -> McfResult { + let span = terminator.source_info.span; + match &terminator.kind { + | TerminatorKind::Goto { .. } + | TerminatorKind::Return + | TerminatorKind::Resume => Ok(()), + + TerminatorKind::Drop { location, .. } => { + check_place(tcx, mir, location, span, PlaceMode::Read) + } + TerminatorKind::DropAndReplace { location, value, .. } => { + check_place(tcx, mir, location, span, PlaceMode::Read)?; + check_operand(tcx, mir, value, span) + }, + TerminatorKind::SwitchInt { .. } => Err(( + span, + "`if`, `match`, `&&` and `||` are not stable in const fn".into(), + )), + | TerminatorKind::Abort | TerminatorKind::Unreachable => { + Err((span, "const fn with unreachable code is not stable".into())) + } + | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { + Err((span, "const fn generators are unstable".into())) + } + + TerminatorKind::Call { + func, + args, + destination: _, + cleanup: _, + } => { + let fn_ty = func.ty(mir, tcx); + if let ty::FnDef(def_id, _) = fn_ty.sty { + if tcx.is_min_const_fn(def_id) { + check_operand(tcx, mir, func, span)?; + + for arg in args { + check_operand(tcx, mir, arg, span)?; + } + Ok(()) + } else { + Err(( + span, + "can only call other `min_const_fn` within a `min_const_fn`".into(), + )) + } + } else { + Err((span, "can only call other const fns within const fn".into())) + } + } + + TerminatorKind::Assert { + cond, + expected: _, + msg: _, + target: _, + cleanup: _, + } => check_operand(tcx, mir, cond, span), + + | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!( + terminator.source_info.span, + "min_const_fn encountered `{:#?}`", + terminator + ), + } +} diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index a7ef93eaec..a2561d3d79 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -10,7 +10,7 @@ use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use transform::{MirPass, MirSource}; use util::patch::MirPatch; @@ -45,7 +45,7 @@ impl RemoveNoopLandingPads { &self, bb: BasicBlock, mir: &Mir, - nop_landing_pads: &BitVector, + nop_landing_pads: &BitArray, ) -> bool { for stmt in &mir[bb].statements { match stmt.kind { @@ -53,7 +53,7 @@ impl RemoveNoopLandingPads { StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::EndRegion(_) | - StatementKind::UserAssertTy(..) | + StatementKind::AscribeUserType(..) | StatementKind::Nop => { // These are all nops in a landing pad (there's some // borrowck interaction between EndRegion and storage @@ -111,7 +111,7 @@ impl RemoveNoopLandingPads { let mut jumps_folded = 0; let mut landing_pads_removed = 0; - let mut nop_landing_pads = BitVector::new(mir.basic_blocks().len()); + let mut nop_landing_pads = BitArray::new(mir.basic_blocks().len()); // This is a post-order traversal, so that if A post-dominates B // then A will be visited before B. diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index da149f4206..f3e0f55736 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -14,8 +14,7 @@ use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::indexed_set::IdxSetBuf; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::indexed_set::IdxSet; use transform::{MirPass, MirSource}; use dataflow::{do_dataflow, DebugFormatted}; @@ -47,7 +46,7 @@ impl MirPass for SanityCheck { let param_env = tcx.param_env(def_id); let move_data = MoveData::gather_moves(mir, tcx).unwrap(); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; - let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); + let dead_unwinds = IdxSet::new_empty(mir.basic_blocks().len()); let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &mdpe), @@ -138,9 +137,9 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; - let mut entry = results.0.sets.on_entry_set_for(bb.index()).to_owned(); - let mut gen = results.0.sets.gen_set_for(bb.index()).to_owned(); - let mut kill = results.0.sets.kill_set_for(bb.index()).to_owned(); + let mut on_entry = results.0.sets.on_entry_set_for(bb.index()).to_owned(); + let mut gen_set = results.0.sets.gen_set_for(bb.index()).clone(); + let mut kill_set = results.0.sets.kill_set_for(bb.index()).clone(); // Emulate effect of all statements in the block up to (but not // including) the borrow within `peek_arg_place`. Do *not* include @@ -148,9 +147,9 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // of the argument at time immediate preceding Call to // `rustc_peek`). - let mut sets = dataflow::BlockSets { on_entry: &mut entry, - gen_set: &mut gen, - kill_set: &mut kill }; + let mut sets = dataflow::BlockSets { on_entry: &mut on_entry, + gen_set: &mut gen_set, + kill_set: &mut kill_set }; for (j, stmt) in statements.iter().enumerate() { debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt); @@ -164,7 +163,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir::StatementKind::InlineAsm { .. } | mir::StatementKind::EndRegion(_) | mir::StatementKind::Validate(..) | - mir::StatementKind::UserAssertTy(..) | + mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => span_bug!(stmt.source_info.span, @@ -203,8 +202,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}", place, lhs_mpi, stmt); // reset GEN and KILL sets before emulating their effect. - for e in sets.gen_set.words_mut() { *e = 0; } - for e in sets.kill_set.words_mut() { *e = 0; } + sets.gen_set.clear(); + sets.kill_set.clear(); results.0.operator.before_statement_effect( &mut sets, Location { block: bb, statement_index: j }); results.0.operator.statement_effect( @@ -229,7 +228,7 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { if let mir::Operand::Constant(ref func) = *oper { - if let ty::TyFnDef(def_id, _) = func.ty.sty { + if let ty::FnDef(def_id, _) = func.ty.sty { let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); if abi == Abi::RustIntrinsic && name == "rustc_peek" { diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 6b8d5a1489..164790db4b 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -37,12 +37,12 @@ //! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! return. -use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::bitvec::BitArray; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::ty::TyCtxt; use rustc::mir::*; use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext}; -use rustc::session::config::FullDebugInfo; +use rustc::session::config::DebugInfo; use std::borrow::Cow; use transform::{MirPass, MirSource}; @@ -249,7 +249,7 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { } pub fn remove_dead_blocks(mir: &mut Mir) { - let mut seen = BitVector::new(mir.basic_blocks().len()); + let mut seen = BitArray::new(mir.basic_blocks().len()); for (bb, _) in traversal::preorder(mir) { seen.insert(bb.index()); } @@ -285,7 +285,7 @@ impl MirPass for SimplifyLocals { tcx: TyCtxt<'a, 'tcx, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) { - let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) }; + let mut marker = DeclMarker { locals: BitArray::new(mir.local_decls.len()) }; marker.visit_mir(mir); // Return pointer and arguments are always live marker.locals.insert(RETURN_PLACE); @@ -294,7 +294,7 @@ impl MirPass for SimplifyLocals { } // We may need to keep dead user variables live for debuginfo. - if tcx.sess.opts.debuginfo == FullDebugInfo { + if tcx.sess.opts.debuginfo == DebugInfo::Full { for local in mir.vars_iter() { marker.locals.insert(local); } @@ -310,7 +310,7 @@ impl MirPass for SimplifyLocals { /// Construct the mapping while swapping out unused stuff out from the `vec`. fn make_local_map<'tcx, V>( vec: &mut IndexVec, - mask: BitVector, + mask: BitArray, ) -> IndexVec> { let mut map: IndexVec> = IndexVec::from_elem(None, &*vec); let mut used = Local::new(0); @@ -326,7 +326,7 @@ fn make_local_map<'tcx, V>( } struct DeclMarker { - pub locals: BitVector, + pub locals: BitArray, } impl<'tcx> Visitor<'tcx> for DeclMarker { diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 7a8c35e7b9..78464b2a10 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -80,7 +80,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> { // no need to transformation } else { let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); - if let ty::TyArray(item_ty, const_size) = place_ty.sty { + if let ty::Array(item_ty, const_size) = place_ty.sty { if let Some(size) = const_size.assert_usize(self.tcx) { assert!(size <= u32::max_value() as u64, "uniform array move out doesn't supported @@ -190,7 +190,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut { let local_use = &visitor.locals_use[*local]; let opt_index_and_place = Self::try_get_item_source(local_use, mir); // each local should be used twice: - // in assign and in aggregate statments + // in assign and in aggregate statements if local_use.use_count == 2 && opt_index_and_place.is_some() { let (index, src_place) = opt_index_and_place.unwrap(); return Some((local_use, index, src_place)); @@ -202,7 +202,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut { let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2); let opt_size = opt_src_place.and_then(|src_place| { let src_ty = src_place.ty(mir, tcx).to_ty(tcx); - if let ty::TyArray(_, ref size_o) = src_ty.sty { + if let ty::Array(_, ref size_o) = src_ty.sty { size_o.assert_usize(tcx) } else { None @@ -231,15 +231,15 @@ impl RestoreSubsliceArrayMoveOut { if opt_size.is_some() && items.iter().all( |l| l.is_some() && l.unwrap().2 == opt_src_place.unwrap()) { - let indicies: Vec<_> = items.iter().map(|x| x.unwrap().1).collect(); - for i in 1..indicies.len() { - if indicies[i - 1] + 1 != indicies[i] { + let indices: Vec<_> = items.iter().map(|x| x.unwrap().1).collect(); + for i in 1..indices.len() { + if indices[i - 1] + 1 != indices[i] { return; } } - let min = *indicies.first().unwrap(); - let max = *indicies.last().unwrap(); + let min = *indices.first().unwrap(); + let max = *indices.last().unwrap(); for item in items { let locals_use = item.unwrap().0; diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs index d1410210bd..8717bd08ae 100644 --- a/src/librustc_mir/util/alignment.rs +++ b/src/librustc_mir/util/alignment.rs @@ -59,7 +59,7 @@ fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ProjectionElem::Field(..) => { let ty = base.ty(local_decls, tcx).to_ty(tcx); match ty.sty { - ty::TyAdt(def, _) if def.repr.packed() => { + ty::Adt(def, _) if def.repr.packed() => { return true } _ => {} diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 2d6b6cea03..b67780ccdb 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -203,8 +203,15 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { desc, OGN = o ); - err.span_label(old_loan_span, "first closure is constructed here"); - err.span_label(new_loan_span, "second closure is constructed here"); + if old_loan_span == new_loan_span { + err.span_label( + old_loan_span, + "closures are constructed here in different iterations of loop" + ); + } else { + err.span_label(old_loan_span, "first closure is constructed here"); + err.span_label(new_loan_span, "second closure is constructed here"); + } if let Some(old_load_end_span) = old_load_end_span { err.span_label(old_load_end_span, "borrow from first closure ends here"); } @@ -418,8 +425,8 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { o: Origin, ) -> DiagnosticBuilder<'cx> { let type_name = match (&ty.sty, is_index) { - (&ty::TyArray(_, _), Some(true)) | (&ty::TyArray(_, _), None) => "array", - (&ty::TySlice(_), _) => "slice", + (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", + (&ty::Slice(_), _) => "slice", _ => span_bug!(move_from_span, "this path should not cause illegal move"), }; let mut err = struct_span_err!( @@ -467,7 +474,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { ) -> DiagnosticBuilder<'cx> { let moved_path = moved_path .map(|mp| format!(": `{}`", mp)) - .unwrap_or("".to_owned()); + .unwrap_or(String::new()); let err = struct_span_err!( self, @@ -668,6 +675,22 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { self.cancel_if_wrong_origin(err, o) } + + fn thread_local_value_does_not_live_long_enough( + self, + span: Span, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0712, + "thread-local variable borrowed past end of function{OGN}", + OGN = o + ); + + self.cancel_if_wrong_origin(err, o) + } } impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> { diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index bbffeec631..50bdc14d50 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -529,7 +529,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> mutbl: hir::Mutability::MutMutable }); let ref_place = self.new_temp(ref_ty); - let unit_temp = Place::Local(self.new_temp(tcx.mk_nil())); + let unit_temp = Place::Local(self.new_temp(tcx.mk_unit())); let result = BasicBlockData { statements: vec![self.assign( @@ -562,7 +562,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> /// if can_go then succ else drop-block /// drop-block: /// if ptr_based { - /// ptr = cur + /// ptr = &mut *cur /// cur = cur.offset(1) /// } else { /// ptr = &mut P[cur] @@ -591,7 +591,14 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let one = self.constant_usize(1); let (ptr_next, cur_next) = if ptr_based { - (Rvalue::Use(copy(&Place::Local(cur))), + (Rvalue::Ref( + tcx.types.re_erased, + BorrowKind::Mut { allow_two_phase_borrow: false }, + Place::Projection(Box::new(Projection { + base: Place::Local(cur), + elem: ProjectionElem::Deref, + })) + ), Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Local(cur)), one)) } else { (Rvalue::Ref( @@ -736,7 +743,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::Local(self.new_temp(tmp_ty)); - // tmp = &P; + // tmp = &mut P; // cur = tmp as *mut T; // end = Offset(cur, len); drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref( @@ -780,7 +787,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> fn open_drop<'a>(&mut self) -> BasicBlock { let ty = self.place_ty(self.place); match ty.sty { - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); self.open_drop_for_tuple(&tys) } @@ -790,30 +797,30 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> // This should only happen for the self argument on the resume function. // It effetively only contains upvars until the generator transformation runs. // See librustc_mir/transform/generator.rs for more details. - ty::TyGenerator(def_id, substs, _) => { + ty::Generator(def_id, substs, _) => { let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); self.open_drop_for_tuple(&tys) } - ty::TyTuple(tys) => { + ty::Tuple(tys) => { self.open_drop_for_tuple(tys) } - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { if def.is_box() { self.open_drop_for_box(def, substs) } else { self.open_drop_for_adt(def, substs) } } - ty::TyDynamic(..) => { + ty::Dynamic(..) => { let unwind = self.unwind; // FIXME(#43234) let succ = self.succ; self.complete_drop(Some(DropFlagMode::Deep), succ, unwind) } - ty::TyArray(ety, size) => { + ty::Array(ety, size) => { let size = size.assert_usize(self.tcx()); self.open_drop_for_array(ety, size) }, - ty::TySlice(ety) => self.open_drop_for_array(ety, None), + ty::Slice(ety) => self.open_drop_for_array(ety, None), _ => bug!("open drop from non-ADT `{:?}`", ty) } @@ -884,7 +891,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> unwind: Unwind ) -> BasicBlock { let tcx = self.tcx(); - let unit_temp = Place::Local(self.new_temp(tcx.mk_nil())); + let unit_temp = Place::Local(self.new_temp(tcx.mk_unit())); let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); @@ -962,6 +969,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> Operand::Constant(box Constant { span: self.source_info.span, ty: self.tcx().types.usize, + user_ty: None, literal: ty::Const::from_usize(self.tcx(), val.into()), }) } diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 22e2b1b0b0..0b883f68bf 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -15,8 +15,6 @@ use rustc::ty::TyCtxt; use std::fmt::Debug; use std::io::{self, Write}; -use rustc_data_structures::indexed_vec::Idx; - use super::pretty::dump_mir_def_ids; /// Write a graphviz DOT graph of a list of MIRs. diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 6c5b38a806..3ae470e1d4 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -33,12 +33,11 @@ //! generator yield points, all pre-existing references are invalidated, so this //! doesn't matter). -use rustc::mir::visit::MirVisitable; use rustc::mir::visit::{PlaceContext, Visitor}; use rustc::mir::Local; use rustc::mir::*; use rustc::ty::{item_path, TyCtxt}; -use rustc_data_structures::indexed_set::IdxSetBuf; +use rustc_data_structures::indexed_set::IdxSet; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::work_queue::WorkQueue; use std::fs; @@ -47,20 +46,16 @@ use std::path::{Path, PathBuf}; use transform::MirSource; use util::pretty::{dump_enabled, write_basic_block, write_mir_intro}; -pub type LiveVarSet = IdxSetBuf; +pub type LiveVarSet = IdxSet; /// This gives the result of the liveness analysis at the boundary of -/// basic blocks. You can use `simulate_block` to obtain the -/// intra-block results. +/// basic blocks. /// /// The `V` type defines the set of variables that we computed /// liveness for. This is often `Local`, in which case we computed /// liveness for all variables -- but it can also be some other type, /// which indicates a subset of the variables within the graph. pub struct LivenessResult { - /// Liveness mode in use when these results were computed. - pub mode: LivenessMode, - /// Live variables on exit to each basic block. This is equal to /// the union of the `ins` for each successor. pub outs: IndexVec>, @@ -104,68 +99,11 @@ impl<'a, 'tcx> LiveVariableMap for IdentityMap<'a, 'tcx> { } } -#[derive(Copy, Clone, Debug)] -pub struct LivenessMode { - /// If true, then we will consider "regular uses" of a variable to be live. - /// For example, if the user writes `foo(x)`, then this is a regular use of - /// the variable `x`. - pub include_regular_use: bool, - - /// If true, then we will consider (implicit) drops of a variable - /// to be live. For example, if the user writes `{ let x = - /// vec![...]; .. }`, then the drop at the end of the block is an - /// implicit drop. - /// - /// NB. Despite its name, a call like `::std::mem::drop(x)` is - /// **not** considered a drop for this purposes, but rather a - /// regular use. - pub include_drops: bool, -} - -/// A combination of liveness results, used in NLL. -pub struct LivenessResults { - /// Liveness results where a regular use makes a variable X live, - /// but not a drop. - pub regular: LivenessResult, - - /// Liveness results where a drop makes a variable X live, - /// but not a regular use. - pub drop: LivenessResult, -} - -impl LivenessResults { - pub fn compute<'tcx>( - mir: &Mir<'tcx>, - map: &impl LiveVariableMap, - ) -> LivenessResults { - LivenessResults { - regular: liveness_of_locals( - &mir, - LivenessMode { - include_regular_use: true, - include_drops: false, - }, - map, - ), - - drop: liveness_of_locals( - &mir, - LivenessMode { - include_regular_use: false, - include_drops: true, - }, - map, - ), - } - } -} - /// Compute which local variables are live within the given function /// `mir`. The liveness mode `mode` determines what sorts of uses are /// considered to make a variable live (e.g., do drops count?). pub fn liveness_of_locals<'tcx, V: Idx>( mir: &Mir<'tcx>, - mode: LivenessMode, map: &impl LiveVariableMap, ) -> LivenessResult { let num_live_vars = map.num_variables(); @@ -173,7 +111,7 @@ pub fn liveness_of_locals<'tcx, V: Idx>( let def_use: IndexVec<_, DefsUses> = mir .basic_blocks() .iter() - .map(|b| block(mode, map, b, num_live_vars)) + .map(|b| block(map, b, num_live_vars)) .collect(); let mut outs: IndexVec<_, LiveVarSet> = mir @@ -208,80 +146,17 @@ pub fn liveness_of_locals<'tcx, V: Idx>( } } - LivenessResult { mode, outs } -} - -impl LivenessResult { - /// Walks backwards through the statements/terminator in the given - /// basic block `block`. At each point within `block`, invokes - /// the callback `op` with the current location and the set of - /// variables that are live on entry to that location. - pub fn simulate_block<'tcx, OP>( - &self, - mir: &Mir<'tcx>, - block: BasicBlock, - map: &impl LiveVariableMap, - mut callback: OP, - ) where - OP: FnMut(Location, &LiveVarSet), - { - let data = &mir[block]; - - // Get a copy of the bits on exit from the block. - let mut bits = self.outs[block].clone(); - - // Start with the maximal statement index -- i.e., right before - // the terminator executes. - let mut statement_index = data.statements.len(); - - // Compute liveness right before terminator and invoke callback. - let terminator_location = Location { - block, - statement_index, - }; - let num_live_vars = map.num_variables(); - let mut visitor = DefsUsesVisitor { - mode: self.mode, - map, - defs_uses: DefsUses { - defs: LiveVarSet::new_empty(num_live_vars), - uses: LiveVarSet::new_empty(num_live_vars), - }, - }; - // Visit the various parts of the basic block in reverse. If we go - // forward, the logic in `add_def` and `add_use` would be wrong. - visitor.update_bits_and_do_callback( - terminator_location, - &data.terminator, - &mut bits, - &mut callback, - ); - - // Compute liveness before each statement (in rev order) and invoke callback. - for statement in data.statements.iter().rev() { - statement_index -= 1; - let statement_location = Location { - block, - statement_index, - }; - visitor.defs_uses.clear(); - visitor.update_bits_and_do_callback( - statement_location, - statement, - &mut bits, - &mut callback, - ); - } - } + LivenessResult { outs } } #[derive(Eq, PartialEq, Clone)] pub enum DefUse { Def, Use, + Drop, } -pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Option { +pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { match context { /////////////////////////////////////////////////////////////////////////// // DEFS @@ -322,13 +197,8 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti PlaceContext::Inspect | PlaceContext::Copy | PlaceContext::Move | - PlaceContext::Validate => { - if mode.include_regular_use { - Some(DefUse::Use) - } else { - None - } - } + PlaceContext::Validate => + Some(DefUse::Use), /////////////////////////////////////////////////////////////////////////// // DROP USES @@ -338,13 +208,8 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti // uses in drop are special because `#[may_dangle]` // attributes can affect whether lifetimes must be live. - PlaceContext::Drop => { - if mode.include_drops { - Some(DefUse::Use) - } else { - None - } - } + PlaceContext::Drop => + Some(DefUse::Drop), } } @@ -353,7 +218,6 @@ where V: Idx, M: LiveVariableMap + 'lv, { - mode: LivenessMode, map: &'lv M, defs_uses: DefsUses, } @@ -365,11 +229,6 @@ struct DefsUses { } impl DefsUses { - fn clear(&mut self) { - self.uses.clear(); - self.defs.clear(); - } - fn apply(&self, bits: &mut LiveVarSet) -> bool { bits.subtract(&self.defs) | bits.union(&self.uses) } @@ -404,29 +263,6 @@ impl DefsUses { } } -impl<'lv, V, M> DefsUsesVisitor<'lv, V, M> -where - V: Idx, - M: LiveVariableMap, -{ - /// Update `bits` with the effects of `value` and call `callback`. We - /// should always visit in reverse order. This method assumes that we have - /// not visited anything before; if you have, clear `bits` first. - fn update_bits_and_do_callback<'tcx, OP>( - &mut self, - location: Location, - value: &impl MirVisitable<'tcx>, - bits: &mut LiveVarSet, - callback: &mut OP, - ) where - OP: FnMut(Location, &LiveVarSet), - { - value.apply(location, self); - self.defs_uses.apply(bits); - callback(location, bits); - } -} - impl<'tcx, 'lv, V, M> Visitor<'tcx> for DefsUsesVisitor<'lv, V, M> where V: Idx, @@ -434,23 +270,21 @@ where { fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) { if let Some(v_index) = self.map.from_local(local) { - match categorize(context, self.mode) { + match categorize(context) { Some(DefUse::Def) => self.defs_uses.add_def(v_index), - Some(DefUse::Use) => self.defs_uses.add_use(v_index), - None => (), + Some(DefUse::Use) | Some(DefUse::Drop) => self.defs_uses.add_use(v_index), + _ => (), } } } } fn block<'tcx, V: Idx>( - mode: LivenessMode, map: &impl LiveVariableMap, b: &BasicBlockData<'tcx>, locals: usize, ) -> DefsUses { let mut visitor = DefsUsesVisitor { - mode, map, defs_uses: DefsUses { defs: LiveVarSet::new_empty(locals), @@ -526,7 +360,8 @@ pub fn write_mir_fn<'a, 'tcx, V: Idx>( write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { let print = |w: &mut dyn Write, prefix, result: &IndexVec>| { - let live: Vec = result[block].iter() + let live: Vec = result[block] + .iter() .map(|v| map.from_live_var(v)) .map(|local| format!("{:?}", local)) .collect(); diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs index 78e9dd23e8..1e624081bc 100644 --- a/src/librustc_mir/util/mod.rs +++ b/src/librustc_mir/util/mod.rs @@ -31,14 +31,14 @@ pub use self::graphviz::write_node_label as write_graphviz_node_label; /// If possible, suggest replacing `ref` with `ref mut`. pub fn suggest_ref_mut<'cx, 'gcx, 'tcx>( tcx: ty::TyCtxt<'cx, 'gcx, 'tcx>, - pattern_span: Span, -) -> Option<(Span, String)> { - let hi_src = tcx.sess.codemap().span_to_snippet(pattern_span).unwrap(); + binding_span: Span, +) -> Option<(String)> { + let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).unwrap(); if hi_src.starts_with("ref") && hi_src["ref".len()..].starts_with(Pattern_White_Space) { let replacement = format!("ref mut{}", &hi_src["ref".len()..]); - Some((pattern_span, replacement)) + Some(replacement) } else { None } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 4bb74c6097..710ccb2053 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -17,6 +17,7 @@ use rustc::ty::item_path; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; use std::fmt::Display; +use std::fmt::Write as _; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -140,7 +141,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( ) where F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { - let _: io::Result<()> = do catch { + let _: io::Result<()> = try_block! { let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?; writeln!(file, "// MIR for `{}`", node_path)?; writeln!(file, "// source = {:?}", source)?; @@ -156,7 +157,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( }; if tcx.sess.opts.debugging_opts.dump_mir_graphviz { - let _: io::Result<()> = do catch { + let _: io::Result<()> = try_block! { let mut file = create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?; write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?; @@ -397,10 +398,13 @@ impl<'cx, 'gcx, 'tcx> ExtraComments<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); - let Constant { span, ty, literal } = constant; + let Constant { span, ty, user_ty, literal } = constant; self.push("mir::Constant"); self.push(&format!("+ span: {:?}", span)); self.push(&format!("+ ty: {:?}", ty)); + if let Some(user_ty) = user_ty { + self.push(&format!("+ user_ty: {:?}", user_ty)); + } self.push(&format!("+ literal: {:?}", literal)); } @@ -429,6 +433,11 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> { self.push(&format!("+ movability: {:?}", movability)); } + AggregateKind::Adt(_, _, _, Some(user_ty), _) => { + self.push("adt"); + self.push(&format!("+ user_ty: {:?}", user_ty)); + } + _ => {} }, @@ -441,7 +450,7 @@ fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String { format!( "scope {} at {}", scope.index(), - tcx.sess.codemap().span_to_string(span) + tcx.sess.source_map().span_to_string(span) ) } @@ -459,7 +468,7 @@ fn write_scope_tree( let indent = depth * INDENT.len(); let children = match scope_tree.get(&parent) { - Some(childs) => childs, + Some(children) => children, None => return Ok(()), }; @@ -485,14 +494,18 @@ fn write_scope_tree( }; let indent = indent + INDENT.len(); - let indented_var = format!( - "{0:1$}let {2}{3:?}: {4:?};", + let mut indented_var = format!( + "{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, var.ty ); + if let Some(user_ty) = var.user_ty { + write!(indented_var, " as {:?}", user_ty).unwrap(); + } + indented_var.push_str(";"); writeln!( w, "{0:1$} // \"{2}\" in {3}", @@ -528,7 +541,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>( if let Some(parent) = scope_data.parent_scope { scope_tree .entry(parent) - .or_insert(vec![]) + .or_default() .push(SourceScope::new(index)); } else { // Only the argument scope has no parent, because it's the root. @@ -604,8 +617,9 @@ fn write_temp_decls(mir: &Mir, w: &mut dyn Write) -> io::Result<()> { for temp in mir.temps_iter() { writeln!( w, - "{}let mut {:?}: {};", + "{}let {}{:?}: {};", INDENT, + if mir.local_decls[temp].mutability == Mutability::Mut {"mut "} else {""}, temp, mir.local_decls[temp].ty )?; diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs index 0c78fd74a2..b3ba86ad8a 100644 --- a/src/librustc_msan/lib.rs +++ b/src/librustc_msan/lib.rs @@ -10,6 +10,7 @@ #![sanitizer_runtime] #![feature(alloc_system)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index c6bad9e198..2ee5415018 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -20,11 +20,13 @@ use rustc::lint; use rustc::session::Session; use syntax::ast::*; use syntax::attr; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use syntax::symbol::keywords; +use syntax::ptr::P; use syntax::visit::{self, Visitor}; use syntax_pos::Span; use errors; +use errors::Applicability; struct AstValidator<'a> { session: &'a Session, @@ -32,7 +34,7 @@ struct AstValidator<'a> { impl<'a> AstValidator<'a> { fn err_handler(&self) -> &errors::Handler { - &self.session.parse_sess.span_diagnostic + &self.session.diagnostic() } fn check_lifetime(&self, ident: Ident) { @@ -97,14 +99,11 @@ impl<'a> AstValidator<'a> { } fn check_trait_fn_not_const(&self, constness: Spanned) { - match constness.node { - Constness::Const => { - struct_span_err!(self.session, constness.span, E0379, - "trait fns cannot be declared const") - .span_label(constness.span, "trait fns cannot be const") - .emit(); - } - _ => {} + if constness.node == Constness::Const { + struct_span_err!(self.session, constness.span, E0379, + "trait fns cannot be declared const") + .span_label(constness.span, "trait fns cannot be const") + .emit(); } } @@ -112,7 +111,7 @@ impl<'a> AstValidator<'a> { for bound in bounds { if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound { let mut err = self.err_handler().struct_span_err(poly.span, - &format!("`?Trait` is not permitted in {}", where_)); + &format!("`?Trait` is not permitted in {}", where_)); if is_trait { err.note(&format!("traits are `?{}` by default", poly.trait_ref.path)); } @@ -151,26 +150,76 @@ impl<'a> AstValidator<'a> { // Check only lifetime parameters are present and that the lifetime // parameters that are present have no bounds. let non_lt_param_spans: Vec<_> = params.iter().filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - if !param.bounds.is_empty() { - let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); - self.err_handler() - .span_err(spans, "lifetime bounds cannot be used in this context"); - } - None + GenericParamKind::Lifetime { .. } => { + if !param.bounds.is_empty() { + let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); + self.err_handler() + .span_err(spans, "lifetime bounds cannot be used in this context"); } - _ => Some(param.ident.span), - }).collect(); + None + } + _ => Some(param.ident.span), + }).collect(); if !non_lt_param_spans.is_empty() { self.err_handler().span_err(non_lt_param_spans, "only lifetime parameters can be used in this context"); } } + + /// With eRFC 2497, we need to check whether an expression is ambigious and warn or error + /// depending on the edition, this function handles that. + fn while_if_let_ambiguity(&self, expr: &P) { + if let Some((span, op_kind)) = self.while_if_let_expr_ambiguity(&expr) { + let mut err = self.err_handler().struct_span_err( + span, &format!("ambigious use of `{}`", op_kind.to_string()) + ); + + err.note( + "this will be a error until the `let_chains` feature is stabilized" + ); + err.note( + "see rust-lang/rust#53668 for more information" + ); + + if let Ok(snippet) = self.session.source_map().span_to_snippet(span) { + err.span_suggestion( + span, "consider adding parentheses", format!("({})", snippet), + ); + } + + err.emit(); + } + } + + /// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of + /// `&&` and `||` in a if-let statement be unambigious. This function returns a span and + /// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined + /// that the current expression parsed is ambigious and will break in future. + fn while_if_let_expr_ambiguity(&self, expr: &P) -> Option<(Span, BinOpKind)> { + debug!("while_if_let_expr_ambiguity: expr.node: {:?}", expr.node); + match &expr.node { + ExprKind::Binary(op, _, _) if op.node == BinOpKind::And || op.node == BinOpKind::Or => { + Some((expr.span, op.node)) + }, + ExprKind::Range(ref lhs, ref rhs, _) => { + let lhs_ambigious = lhs.as_ref() + .and_then(|lhs| self.while_if_let_expr_ambiguity(lhs)); + let rhs_ambigious = rhs.as_ref() + .and_then(|rhs| self.while_if_let_expr_ambiguity(rhs)); + + lhs_ambigious.or(rhs_ambigious) + } + _ => None, + } + } + } impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_expr(&mut self, expr: &'a Expr) { match expr.node { + ExprKind::IfLet(_, ref expr, _, _) | ExprKind::WhileLet(_, ref expr, _, _) => + self.while_if_let_ambiguity(&expr), ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => { span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target"); } @@ -185,11 +234,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ); match val.node { ExprKind::Lit(ref v) if v.node.is_numeric() => { - err.span_suggestion( + err.span_suggestion_with_applicability( place.span.between(val.span), "if you meant to write a comparison against a negative value, add a \ space in between `<` and `-`", "< -".to_string(), + Applicability::MaybeIncorrect ); } _ => {} @@ -385,7 +435,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.err_handler().span_err(item.span, "tuple and unit unions are not permitted"); } - if vdata.fields().len() == 0 { + if vdata.fields().is_empty() { self.err_handler().span_err(item.span, "unions cannot have zero fields"); } @@ -412,14 +462,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_vis(&mut self, vis: &'a Visibility) { - match vis.node { - VisibilityKind::Restricted { ref path, .. } => { - path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { - self.err_handler().span_err(segment.args.as_ref().unwrap().span(), - "generic arguments in visibility path"); - }); - } - _ => {} + if let VisibilityKind::Restricted { ref path, .. } = vis.node { + path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { + self.err_handler().span_err(segment.args.as_ref().unwrap().span(), + "generic arguments in visibility path"); + }); } visit::walk_vis(self, vis) @@ -539,10 +586,9 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> { fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) { match *generic_args { GenericArgs::AngleBracketed(ref data) => { - data.args.iter().for_each(|arg| match arg { - GenericArg::Type(ty) => self.visit_ty(ty), - _ => {} - }); + for arg in &data.args { + self.visit_generic_arg(arg) + } for type_binding in &data.bindings { // Type bindings such as `Item=impl Debug` in `Iterator` // are allowed to contain nested `impl Trait`. @@ -590,8 +636,7 @@ impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> { TyKind::ImplTrait(..) => { if self.is_banned { struct_span_err!(self.session, t.span, E0667, - "`impl Trait` is not allowed in path parameters") - .emit(); + "`impl Trait` is not allowed in path parameters").emit(); } } TyKind::Path(ref qself, ref path) => { @@ -615,7 +660,7 @@ impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> { for (i, segment) in path.segments.iter().enumerate() { // Allow `impl Trait` iff we're on the final path segment - if i == (path.segments.len() - 1) { + if i == path.segments.len() - 1 { visit::walk_path_segment(self, path.span, segment); } else { self.with_ban(|this| diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index f1ec3371c3..f1d0a4fee3 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -261,6 +261,27 @@ let result = loop { // ok! ``` "##, +E0642: r##" +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! +} +``` +"##, + E0695: r##" A `break` statement without a label appeared inside a labeled block. @@ -306,7 +327,6 @@ register_diagnostics! { E0561, // patterns aren't allowed in function pointer types E0567, // auto traits can not have generic parameters E0568, // auto traits can not have super traits - E0642, // patterns aren't allowed in methods without bodies E0666, // nested `impl Trait` is illegal E0667, // `impl Trait` in projections E0696, // `continue` pointing to a labeled block diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index e7b2869dfe..b65a2e3f0e 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -61,10 +61,8 @@ pub fn print_ast_stats<'v>(krate: &'v ast::Crate, title: &str) { impl<'k> StatCollector<'k> { fn record(&mut self, label: &'static str, id: Id, node: &T) { - if id != Id::None { - if !self.seen.insert(id) { - return - } + if id != Id::None && !self.seen.insert(id) { + return } let entry = self.data.entry(label).or_insert(NodeData { @@ -135,40 +133,46 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_item(self, i) } - /////////////////////////////////////////////////////////////////////////// - fn visit_mod(&mut self, m: &'v hir::Mod, _s: Span, n: NodeId) { self.record("Mod", Id::None, m); hir_visit::walk_mod(self, m, n) } + fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem) { self.record("ForeignItem", Id::Node(i.id), i); hir_visit::walk_foreign_item(self, i) } + fn visit_local(&mut self, l: &'v hir::Local) { self.record("Local", Id::Node(l.id), l); hir_visit::walk_local(self, l) } + fn visit_block(&mut self, b: &'v hir::Block) { self.record("Block", Id::Node(b.id), b); hir_visit::walk_block(self, b) } + fn visit_stmt(&mut self, s: &'v hir::Stmt) { self.record("Stmt", Id::Node(s.node.id()), s); hir_visit::walk_stmt(self, s) } + fn visit_arm(&mut self, a: &'v hir::Arm) { self.record("Arm", Id::None, a); hir_visit::walk_arm(self, a) } + fn visit_pat(&mut self, p: &'v hir::Pat) { self.record("Pat", Id::Node(p.id), p); hir_visit::walk_pat(self, p) } + fn visit_decl(&mut self, d: &'v hir::Decl) { self.record("Decl", Id::None, d); hir_visit::walk_decl(self, d) } + fn visit_expr(&mut self, ex: &'v hir::Expr) { self.record("Expr", Id::Node(ex.id), ex); hir_visit::walk_expr(self, ex) @@ -198,6 +202,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { self.record("TraitItem", Id::Node(ti.id), ti); hir_visit::walk_trait_item(self, ti) } + fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) { self.record("ImplItem", Id::Node(ii.id), ii); hir_visit::walk_impl_item(self, ii) @@ -220,31 +225,38 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { self.record("Variant", Id::None, v); hir_visit::walk_variant(self, v, g, item_id) } + fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { self.record("Lifetime", Id::Node(lifetime.id), lifetime); hir_visit::walk_lifetime(self, lifetime) } - fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: NodeId, span: Span) { + + fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: hir::HirId, span: Span) { self.record("QPath", Id::None, qpath); hir_visit::walk_qpath(self, qpath, id, span) } - fn visit_path(&mut self, path: &'v hir::Path, _id: NodeId) { + + fn visit_path(&mut self, path: &'v hir::Path, _id: hir::HirId) { self.record("Path", Id::None, path); hir_visit::walk_path(self, path) } + fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v hir::PathSegment) { self.record("PathSegment", Id::None, path_segment); hir_visit::walk_path_segment(self, path_span, path_segment) } + fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding) { self.record("TypeBinding", Id::Node(type_binding.id), type_binding); hir_visit::walk_assoc_type_binding(self, type_binding) } + fn visit_attribute(&mut self, attr: &'v ast::Attribute) { self.record("Attribute", Id::Attr(attr.id), attr); } + fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef) { self.record("MacroDef", Id::Node(macro_def.id), macro_def); hir_visit::walk_macro_def(self, macro_def) diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 41f1e78296..d62cb00923 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -18,6 +18,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] +#![cfg_attr(not(stage0), feature(nll))] #![feature(rustc_diagnostic_macros)] #[macro_use] diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 8ef20126e0..61c2ac161b 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -13,7 +13,7 @@ use rustc::session::Session; use rustc::hir::map::Map; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::{self, Destination}; +use rustc::hir::{self, Node, Destination}; use syntax::ast; use syntax_pos::Span; @@ -114,9 +114,8 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { }; if loop_id != ast::DUMMY_NODE_ID { - match self.hir_map.find(loop_id).unwrap() { - hir::map::NodeBlock(_) => return, - _=> (), + if let Node::Block(_) = self.hir_map.find(loop_id).unwrap() { + return } } @@ -153,12 +152,12 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { self.require_break_cx("break", e.span); } - hir::ExprKind::Continue(label) => { - self.require_label_in_labeled_block(e.span, &label, "continue"); + hir::ExprKind::Continue(destination) => { + self.require_label_in_labeled_block(e.span, &destination, "continue"); - match label.target_id { + match destination.target_id { Ok(loop_id) => { - if let hir::map::NodeBlock(block) = self.hir_map.find(loop_id).unwrap() { + if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() { struct_span_err!(self.sess, e.span, E0696, "`continue` pointing to a labeled block") .span_label(e.span, @@ -171,7 +170,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { self.emit_unlabled_cf_in_while_condition(e.span, "continue"); } - _ => {} + Err(_) => {} } self.require_break_cx("continue", e.span) }, @@ -192,8 +191,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { fn require_break_cx(&self, name: &str, span: Span) { match self.cx { - LabeledBlock | - Loop(_) => {} + LabeledBlock | Loop(_) => {} Closure => { struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name) .span_label(span, "cannot break inside of a closure") diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 3206fa6e17..0120b5bc53 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -65,15 +65,12 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.super_mir(mir); } - fn visit_basic_block_data(&mut self, - block: BasicBlock, - data: &BasicBlockData<'tcx>) { + fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) { self.record("BasicBlockData", data); self.super_basic_block_data(block, data); } - fn visit_source_scope_data(&mut self, - scope_data: &SourceScopeData) { + fn visit_source_scope_data(&mut self, scope_data: &SourceScopeData) { self.record("SourceScopeData", scope_data); self.super_source_scope_data(scope_data); } @@ -92,7 +89,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { StatementKind::StorageLive(..) => "StatementKind::StorageLive", StatementKind::StorageDead(..) => "StatementKind::StorageDead", StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm", - StatementKind::UserAssertTy(..) => "StatementKind::UserAssertTy", + StatementKind::AscribeUserType(..) => "StatementKind::AscribeUserType", StatementKind::Nop => "StatementKind::Nop", }, &statement.kind); self.super_statement(block, statement, location); @@ -130,9 +127,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.super_terminator_kind(block, kind, location); } - fn visit_assert_message(&mut self, - msg: &AssertMessage<'tcx>, - location: Location) { + fn visit_assert_message(&mut self, msg: &AssertMessage<'tcx>, location: Location) { self.record("AssertMessage", msg); self.record(match *msg { EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck", @@ -151,9 +146,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.super_assert_message(msg, location); } - fn visit_rvalue(&mut self, - rvalue: &Rvalue<'tcx>, - location: Location) { + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { self.record("Rvalue", rvalue); let rvalue_kind = match *rvalue { Rvalue::Use(..) => "Rvalue::Use", @@ -184,9 +177,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.super_rvalue(rvalue, location); } - fn visit_operand(&mut self, - operand: &Operand<'tcx>, - location: Location) { + fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { self.record("Operand", operand); self.record(match *operand { Operand::Copy(..) => "Operand::Copy", @@ -234,42 +225,32 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.super_projection_elem(place, context, location); } - fn visit_constant(&mut self, - constant: &Constant<'tcx>, - location: Location) { + fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.record("Constant", constant); self.super_constant(constant, location); } - fn visit_source_info(&mut self, - source_info: &SourceInfo) { + fn visit_source_info(&mut self, source_info: &SourceInfo) { self.record("SourceInfo", source_info); self.super_source_info(source_info); } - fn visit_closure_substs(&mut self, - substs: &ClosureSubsts<'tcx>, - _: Location) { + fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, _: Location) { self.record("ClosureSubsts", substs); self.super_closure_substs(substs); } - fn visit_const(&mut self, - constant: &&'tcx ty::Const<'tcx>, - _: Location) { + fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) { self.record("Const", constant); self.super_const(constant); } - fn visit_local_decl(&mut self, - local: Local, - local_decl: &LocalDecl<'tcx>) { + fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { self.record("LocalDecl", local_decl); self.super_local_decl(local, local_decl); } - fn visit_source_scope(&mut self, - scope: &SourceScope) { + fn visit_source_scope(&mut self, scope: &SourceScope) { self.record("VisiblityScope", scope); self.super_source_scope(scope); } diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 7a64f8e292..8288004652 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -41,8 +41,7 @@ use syntax::ast; use syntax::attr; use syntax_pos::{Span, DUMMY_SP}; use self::Promotability::*; -use std::ops::{BitAnd, BitOr}; - +use std::ops::{BitAnd, BitAndAssign, BitOr}; pub fn provide(providers: &mut Providers) { *providers = Providers { @@ -114,7 +113,7 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> { } #[must_use] -#[derive(Debug, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] enum Promotability { Promotable, NotPromotable @@ -125,23 +124,25 @@ impl BitAnd for Promotability { fn bitand(self, rhs: Self) -> Self { match (self, rhs) { - (Promotable, NotPromotable) => NotPromotable, - (NotPromotable, Promotable) => NotPromotable, - (NotPromotable, NotPromotable) => NotPromotable, (Promotable, Promotable) => Promotable, + _ => NotPromotable, } } } +impl BitAndAssign for Promotability { + fn bitand_assign(&mut self, rhs: Self) { + *self = *self & rhs + } +} + impl BitOr for Promotability { type Output = Self; fn bitor(self, rhs: Self) -> Self { match (self, rhs) { - (Promotable, NotPromotable) => Promotable, - (NotPromotable, Promotable) => Promotable, (NotPromotable, NotPromotable) => NotPromotable, - (Promotable, Promotable) => Promotable, + _ => Promotable, } } } @@ -161,7 +162,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>, span: Span) -> Promotability { - if let NotPromotable = self.type_promotability(ret_ty) { + if self.type_promotability(ret_ty) == NotPromotable { return NotPromotable; } @@ -178,9 +179,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { } if let Some(&attr::Stability { - rustc_const_unstable: Some(attr::RustcConstUnstable { - feature: ref feature_name - }), + const_stability: Some(ref feature_name), .. }) = self.tcx.lookup_stability(def_id) { let stable_check = // feature-gate is enabled, @@ -268,9 +267,8 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { } } - match local.init { - Some(ref expr) => { let _ = self.check_expr(&expr); }, - None => {}, + if let Some(ref expr) = local.init { + let _ = self.check_expr(&expr); } NotPromotable } @@ -289,7 +287,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { fn check_expr(&mut self, ex: &'tcx hir::Expr) -> Promotability { let node_ty = self.tables.node_id_to_type(ex.hir_id); let mut outer = check_expr_kind(self, ex, node_ty); - outer = outer & check_adjustments(self, ex); + outer &= check_adjustments(self, ex); // Handle borrows on (or inside the autorefs of) this expression. if self.mut_rvalue_borrows.remove(&ex.id) { @@ -305,7 +303,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { fn check_block(&mut self, block: &'tcx hir::Block) -> Promotability { let mut iter_result = Promotable; for index in block.stmts.iter() { - iter_result = iter_result & self.check_stmt(index); + iter_result &= self.check_stmt(index); } match block.expr { Some(ref box_expr) => iter_result & self.check_expr(&*box_expr), @@ -325,7 +323,7 @@ fn check_expr_kind<'a, 'tcx>( e: &'tcx hir::Expr, node_ty: Ty<'tcx>) -> Promotability { let ty_result = match node_ty.sty { - ty::TyAdt(def, _) if def.has_dtor(v.tcx) => { + ty::Adt(def, _) if def.has_dtor(v.tcx) => { NotPromotable } _ => Promotable @@ -338,10 +336,7 @@ fn check_expr_kind<'a, 'tcx>( } hir::ExprKind::Unary(op, ref expr) => { let expr_promotability = v.check_expr(expr); - if v.tables.is_method_call(e) { - return NotPromotable; - } - if op == hir::UnDeref { + if v.tables.is_method_call(e) || op == hir::UnDeref { return NotPromotable; } expr_promotability @@ -353,10 +348,10 @@ fn check_expr_kind<'a, 'tcx>( return NotPromotable; } match v.tables.node_id_to_type(lhs.hir_id).sty { - ty::TyRawPtr(_) => { + ty::RawPtr(_) => { assert!(op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne || - op.node == hir::BinOpKind::Le || op.node == hir::BinOpKind::Lt || - op.node == hir::BinOpKind::Ge || op.node == hir::BinOpKind::Gt); + op.node == hir::BinOpKind::Le || op.node == hir::BinOpKind::Lt || + op.node == hir::BinOpKind::Ge || op.node == hir::BinOpKind::Gt); NotPromotable } @@ -381,7 +376,7 @@ fn check_expr_kind<'a, 'tcx>( let def = v.tables.qpath_def(qpath, e.hir_id); match def { Def::VariantCtor(..) | Def::StructCtor(..) | - Def::Fn(..) | Def::Method(..) => Promotable, + Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => Promotable, // References to a static that are themselves within a static // are inherently promotable with the exception @@ -402,7 +397,6 @@ fn check_expr_kind<'a, 'tcx>( debug!("Reference to Static(id={:?}) is unpromotable as it is not \ referenced from a static", did); NotPromotable - } } @@ -427,7 +421,7 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::Call(ref callee, ref hirvec) => { let mut call_result = v.check_expr(callee); for index in hirvec.iter() { - call_result = call_result & v.check_expr(index); + call_result &= v.check_expr(index); } let mut callee = &**callee; loop { @@ -447,7 +441,8 @@ fn check_expr_kind<'a, 'tcx>( }; let def_result = match def { Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Fn) => Promotable, + Def::VariantCtor(_, CtorKind::Fn) | + Def::SelfCtor(..) => Promotable, Def::Fn(did) => { v.handle_const_fn_call(did, node_ty, e.span) } @@ -466,7 +461,7 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::MethodCall(ref _pathsegment, ref _span, ref hirvec) => { let mut method_call_result = Promotable; for index in hirvec.iter() { - method_call_result = method_call_result & v.check_expr(index); + method_call_result &= v.check_expr(index); } if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) { let def_id = def.def_id(); @@ -485,13 +480,12 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::Struct(ref _qpath, ref hirvec, ref option_expr) => { let mut struct_result = Promotable; for index in hirvec.iter() { - struct_result = struct_result & v.check_expr(&index.expr); + struct_result &= v.check_expr(&index.expr); } - match *option_expr { - Some(ref expr) => { struct_result = struct_result & v.check_expr(&expr); }, - None => {}, + if let Some(ref expr) = *option_expr { + struct_result &= v.check_expr(&expr); } - if let ty::TyAdt(adt, ..) = v.tables.expr_ty(e).sty { + if let ty::Adt(adt, ..) = v.tables.expr_ty(e).sty { // unsafe_cell_type doesn't necessarily exist with no_core if Some(adt.did) == v.tcx.lang_items().unsafe_cell_type() { return NotPromotable; @@ -508,7 +502,7 @@ fn check_expr_kind<'a, 'tcx>( } hir::ExprKind::Closure(_capture_clause, ref _box_fn_decl, - body_id, _span, _option_generator_movability) => { + body_id, _span, _option_generator_movability) => { let nested_body_promotable = v.check_nested_body(body_id); // Paths in constant contexts cannot refer to local variables, // as there are none, and thus closures can't have upvars there. @@ -545,7 +539,7 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::Array(ref hirvec) => { let mut array_result = Promotable; for index in hirvec.iter() { - array_result = array_result & v.check_expr(index); + array_result &= v.check_expr(index); } array_result } @@ -557,7 +551,7 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::Tup(ref hirvec) => { let mut tup_result = Promotable; for index in hirvec.iter() { - tup_result = tup_result & v.check_expr(index); + tup_result &= v.check_expr(index); } tup_result } @@ -578,12 +572,9 @@ fn check_expr_kind<'a, 'tcx>( let _ = v.check_expr(expr); for index in hirvec_arm.iter() { let _ = v.check_expr(&*index.body); - match index.guard { - Some(ref expr) => { - let _ = v.check_expr(&expr); - }, - None => {}, - }; + if let Some(hir::Guard::If(ref expr)) = index.guard { + let _ = v.check_expr(&expr); + } } NotPromotable } @@ -591,10 +582,9 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::If(ref lhs, ref rhs, ref option_expr) => { let _ = v.check_expr(lhs); let _ = v.check_expr(rhs); - match option_expr { - Some(ref expr) => { let _ = v.check_expr(&expr); }, - None => {}, - }; + if let Some(ref expr) = option_expr { + let _ = v.check_expr(&expr); + } NotPromotable } @@ -612,9 +602,8 @@ fn check_expr_kind<'a, 'tcx>( // More control flow (also not very meaningful). hir::ExprKind::Break(_, ref option_expr) | hir::ExprKind::Ret(ref option_expr) => { - match *option_expr { - Some(ref expr) => { let _ = v.check_expr(&expr); }, - None => {}, + if let Some(ref expr) = *option_expr { + let _ = v.check_expr(&expr); } NotPromotable } @@ -637,10 +626,7 @@ fn check_expr_kind<'a, 'tcx>( } hir::ExprKind::InlineAsm(ref _inline_asm, ref hirvec_lhs, ref hirvec_rhs) => { - for index in hirvec_lhs.iter() { - let _ = v.check_expr(index); - } - for index in hirvec_rhs.iter() { + for index in hirvec_lhs.iter().chain(hirvec_rhs.iter()) { let _ = v.check_expr(index); } NotPromotable @@ -705,11 +691,8 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { // These occur when we convert a &T or *T to a *U, as well as // when making a thin pointer (e.g., `*T`) into a fat pointer // (e.g., `*Trait`). - match loan_cause { - euv::LoanCause::AutoUnsafe => { - return; - } - _ => {} + if let euv::LoanCause::AutoUnsafe = loan_cause { + return; } let mut cur = cmt; diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs index b57debdd99..fa7008be73 100644 --- a/src/librustc_platform_intrinsics/lib.rs +++ b/src/librustc_platform_intrinsics/lib.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(bad_style)] +#![allow(nonstandard_style)] + +#![cfg_attr(not(stage0), feature(nll))] pub struct Intrinsic { pub inputs: &'static [&'static Type], diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 348aa6a7ce..67f53a6731 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -64,6 +64,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] +#![cfg_attr(not(stage0), feature(nll))] #![feature(rustc_diagnostic_macros)] #[macro_use] extern crate syntax; diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index b1ab86674c..6c10ac7ea5 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -12,6 +12,7 @@ use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint}; use rustc::session::Session; +use rustc::util::nodemap::FxHashMap; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT}; use syntax::ext::base::MacroExpanderFn; @@ -21,7 +22,6 @@ use syntax::ast; use syntax::feature_gate::AttributeType; use syntax_pos::Span; -use std::collections::HashMap; use std::borrow::ToOwned; /// Structure used to register plugins. @@ -53,7 +53,7 @@ pub struct Registry<'a> { pub late_lint_passes: Vec, #[doc(hidden)] - pub lint_groups: HashMap<&'static str, Vec>, + pub lint_groups: FxHashMap<&'static str, (Vec, Option<&'static str>)>, #[doc(hidden)] pub llvm_passes: Vec, @@ -74,7 +74,7 @@ impl<'a> Registry<'a> { syntax_exts: vec![], early_lint_passes: vec![], late_lint_passes: vec![], - lint_groups: HashMap::new(), + lint_groups: FxHashMap::default(), llvm_passes: vec![], attributes: vec![], whitelisted_custom_derives: Vec::new(), @@ -170,8 +170,15 @@ impl<'a> Registry<'a> { self.late_lint_passes.push(lint_pass); } /// Register a lint group. - pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) { - self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect()); + pub fn register_lint_group( + &mut self, + name: &'static str, + deprecated_name: Option<&'static str>, + to: Vec<&'static Lint> + ) { + self.lint_groups.insert(name, + (to.into_iter().map(|x| LintId::of(x)).collect(), + deprecated_name)); } /// Register an LLVM pass. diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 405952065d..47e8588857 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -12,6 +12,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] +#![cfg_attr(not(stage0), feature(nll))] #![feature(rustc_diagnostic_macros)] #![recursion_limit="256"] @@ -22,7 +23,8 @@ extern crate rustc_typeck; extern crate syntax_pos; extern crate rustc_data_structures; -use rustc::hir::{self, GenericParamKind, PatKind}; +use rustc::hir::{self, PatKind}; +use hir::Node; use rustc::hir::def::Def; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; @@ -81,6 +83,7 @@ struct EmbargoVisitor<'a, 'tcx: 'a> { } struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> { + access_level: Option, item_def_id: DefId, ev: &'b mut EmbargoVisitor<'a, 'tcx>, } @@ -88,11 +91,11 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> { impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { fn item_ty_level(&self, item_def_id: DefId) -> Option { let ty_def_id = match self.tcx.type_of(item_def_id).sty { - ty::TyAdt(adt, _) => adt.did, - ty::TyForeign(did) => did, - ty::TyDynamic(ref obj, ..) if obj.principal().is_some() => + ty::Adt(adt, _) => adt.did, + ty::Foreign(did) => did, + ty::Dynamic(ref obj, ..) if obj.principal().is_some() => obj.principal().unwrap().def_id(), - ty::TyProjection(ref proj) => proj.trait_ref(self.tcx).def_id, + ty::Projection(ref proj) => proj.trait_ref(self.tcx).def_id, _ => return Some(AccessLevel::Public) }; if let Some(node_id) = self.tcx.hir.as_local_node_id(ty_def_id) { @@ -131,6 +134,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { fn reach<'b>(&'b mut self, item_id: ast::NodeId) -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { ReachEverythingInTheInterfaceVisitor { + access_level: self.prev_level.map(|l| l.min(AccessLevel::Reachable)), item_def_id: self.tcx.hir.local_def_id(item_id), ev: self, } @@ -213,7 +217,15 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - hir::ItemKind::Existential(..) | + // Impl trait return types mark their parent function. + // It (and its children) are revisited if the change applies. + hir::ItemKind::Existential(ref ty_data) => { + if let Some(impl_trait_fn) = ty_data.impl_trait_fn { + if let Some(node_id) = self.tcx.hir.as_local_node_id(impl_trait_fn) { + self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); + } + } + } hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) | @@ -225,6 +237,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ExternCrate(..) => {} } + // Store this node's access level here to propagate the correct + // reachability level through interfaces and children. + let orig_level = replace(&mut self.prev_level, item_level); + // Mark all items in interfaces of reachable items as reachable match item.node { // The interface is empty @@ -323,9 +339,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } - let orig_level = self.prev_level; - self.prev_level = item_level; - intravisit::walk_item(self, item); self.prev_level = orig_level; @@ -442,7 +455,7 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { fn ty(&mut self) -> &mut Self { let ty = self.ev.tcx.type_of(self.item_def_id); ty.visit_with(self); - if let ty::TyFnDef(def_id, _) = ty.sty { + if let ty::FnDef(def_id, _) = ty.sty { if def_id == self.item_def_id { self.ev.tcx.fn_sig(def_id).visit_with(self); } @@ -461,7 +474,7 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) { let item = self.ev.tcx.hir.expect_item(node_id); - self.ev.update(item.id, Some(AccessLevel::Reachable)); + self.ev.update(item.id, self.access_level); } } } @@ -469,20 +482,20 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let ty_def_id = match ty.sty { - ty::TyAdt(adt, _) => Some(adt.did), - ty::TyForeign(did) => Some(did), - ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), - ty::TyProjection(ref proj) => Some(proj.item_def_id), - ty::TyFnDef(def_id, ..) | - ty::TyClosure(def_id, ..) | - ty::TyGenerator(def_id, ..) | - ty::TyAnon(def_id, _) => Some(def_id), + ty::Adt(adt, _) => Some(adt.did), + ty::Foreign(did) => Some(did), + ty::Dynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), + ty::Projection(ref proj) => Some(proj.item_def_id), + ty::FnDef(def_id, ..) | + ty::Closure(def_id, ..) | + ty::Generator(def_id, ..) | + ty::Opaque(def_id, _) => Some(def_id), _ => None }; if let Some(def_id) = ty_def_id { if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(def_id) { - self.ev.update(node_id, Some(AccessLevel::Reachable)); + self.ev.update(node_id, self.access_level); } } @@ -638,7 +651,7 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> { in_body: bool, span: Span, empty_tables: &'a ty::TypeckTables<'tcx>, - visited_anon_tys: FxHashSet + visited_opaque_tys: FxHashSet } impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { @@ -646,17 +659,17 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { match self.tcx.hir.as_local_node_id(did) { Some(node_id) => { let vis = match self.tcx.hir.get(node_id) { - hir::map::NodeItem(item) => &item.vis, - hir::map::NodeForeignItem(foreign_item) => &foreign_item.vis, - hir::map::NodeImplItem(impl_item) => &impl_item.vis, - hir::map::NodeTraitItem(..) | - hir::map::NodeVariant(..) => { + Node::Item(item) => &item.vis, + Node::ForeignItem(foreign_item) => &foreign_item.vis, + Node::ImplItem(impl_item) => &impl_item.vis, + Node::TraitItem(..) | + Node::Variant(..) => { return self.def_id_visibility(self.tcx.hir.get_parent_did(node_id)); } - hir::map::NodeStructCtor(vdata) => { + Node::StructCtor(vdata) => { let struct_node_id = self.tcx.hir.get_parent(node_id); let struct_vis = match self.tcx.hir.get(struct_node_id) { - hir::map::NodeItem(item) => &item.vis, + Node::Item(item) => &item.vis, node => bug!("unexpected node kind: {:?}", node), }; let mut ctor_vis @@ -672,7 +685,9 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { // visibility to within the crate. let struct_def_id = self.tcx.hir.get_parent_did(node_id); let adt_def = self.tcx.adt_def(struct_def_id); - if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public { + if adt_def.non_enum_variant().is_field_list_non_exhaustive() + && ctor_vis == ty::Visibility::Public + { ctor_vis = ty::Visibility::Restricted( DefId::local(CRATE_DEF_INDEX)); } @@ -815,7 +830,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // we prohibit access to private statics from other crates, this allows to give // more code internal visibility at link time. (Access to private functions // is already prohibited by type privacy for function types.) - fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: ast::NodeId, span: Span) { + fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: hir::HirId, span: Span) { let def = match *qpath { hir::QPath::Resolved(_, ref path) => match path.def { Def::Method(..) | Def::AssociatedConst(..) | @@ -823,8 +838,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { _ => None, } hir::QPath::TypeRelative(..) => { - let hir_id = self.tcx.hir.node_to_hir_id(id); - self.tables.type_dependent_defs().get(hir_id).cloned() + self.tables.type_dependent_defs().get(id).cloned() } }; if let Some(def) = def { @@ -896,15 +910,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { match ty.sty { - ty::TyAdt(&ty::AdtDef { did: def_id, .. }, ..) | - ty::TyFnDef(def_id, ..) | - ty::TyForeign(def_id) => { + ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | + ty::FnDef(def_id, ..) | + ty::Foreign(def_id) => { if !self.item_is_accessible(def_id) { let msg = format!("type `{}` is private", ty); self.tcx.sess.span_err(self.span, &msg); return true; } - if let ty::TyFnDef(..) = ty.sty { + if let ty::FnDef(..) = ty.sty { if self.tcx.fn_sig(def_id).visit_with(self) { return true; } @@ -919,7 +933,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } } } - ty::TyDynamic(ref predicates, ..) => { + ty::Dynamic(ref predicates, ..) => { let is_private = predicates.skip_binder().iter().any(|predicate| { let def_id = match *predicate { ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, @@ -935,13 +949,13 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { return true; } } - ty::TyProjection(ref proj) => { + ty::Projection(ref proj) => { let tcx = self.tcx; if self.check_trait_ref(proj.trait_ref(tcx)) { return true; } } - ty::TyAnon(def_id, ..) => { + ty::Opaque(def_id, ..) => { for predicate in &self.tcx.predicates_of(def_id).predicates { let trait_ref = match *predicate { ty::Predicate::Trait(ref poly_trait_predicate) => { @@ -964,10 +978,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { return true; } for subst in trait_ref.substs.iter() { - // Skip repeated `TyAnon`s to avoid infinite recursion. + // Skip repeated `Opaque`s to avoid infinite recursion. if let UnpackedKind::Type(ty) = subst.unpack() { - if let ty::TyAnon(def_id, ..) = ty.sty { - if !self.visited_anon_tys.insert(def_id) { + if let ty::Opaque(def_id, ..) = ty.sty { + if !self.visited_opaque_tys.insert(def_id) { continue; } } @@ -1015,7 +1029,7 @@ struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> { impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { fn path_is_private_type(&self, path: &hir::Path) -> bool { let did = match path.def { - Def::PrimTy(..) | Def::SelfTy(..) => return false, + Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => return false, def => def.def_id(), }; @@ -1025,7 +1039,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // .. and it corresponds to a private type in the AST (this returns // None for type parameters) match self.tcx.hir.find(node_id) { - Some(hir::map::NodeItem(ref item)) => !item.vis.node.is_pub(), + Some(Node::Item(ref item)) => !item.vis.node.is_pub(), Some(_) | None => false, } } else { @@ -1270,14 +1284,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { - generics.params.iter().for_each(|param| match param.kind { - GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { .. } => { - for bound in ¶m.bounds { - self.check_generic_bound(bound); - } + for param in &generics.params { + for bound in ¶m.bounds { + self.check_generic_bound(bound); } - }); + } for predicate in &generics.where_clause.predicates { match predicate { &hir::WherePredicate::BoundPredicate(ref bound_pred) => { @@ -1369,7 +1380,13 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - let predicates = self.tcx.predicates_of(self.item_def_id); + // NB: We use `explicit_predicates_of` and not `predicates_of` + // because we don't want to report privacy errors due to where + // clauses that the compiler inferred. We only want to + // consider the ones that the user wrote. This is important + // for the inferred outlives rules; see + // `src/test/ui/rfc-2093-infer-outlives/privacy.rs`. + let predicates = self.tcx.explicit_predicates_of(self.item_def_id); for predicate in &predicates.predicates { predicate.visit_with(self); match predicate { @@ -1391,7 +1408,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { fn ty(&mut self) -> &mut Self { let ty = self.tcx.type_of(self.item_def_id); ty.visit_with(self); - if let ty::TyFnDef(def_id, _) = ty.sty { + if let ty::FnDef(def_id, _) = ty.sty { if def_id == self.item_def_id { self.tcx.fn_sig(def_id).visit_with(self); } @@ -1437,10 +1454,10 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let ty_def_id = match ty.sty { - ty::TyAdt(adt, _) => Some(adt.did), - ty::TyForeign(did) => Some(did), - ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), - ty::TyProjection(ref proj) => { + ty::Adt(adt, _) => Some(adt.did), + ty::Foreign(did) => Some(did), + ty::Dynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), + ty::Projection(ref proj) => { if self.required_visibility == ty::Visibility::Invisible { // Conservatively approximate the whole type alias as public without // recursing into its components when determining impl publicity. @@ -1460,8 +1477,8 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' // Non-local means public (private items can't leave their crate, modulo bugs) if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { let hir_vis = match self.tcx.hir.find(node_id) { - Some(hir::map::NodeItem(item)) => &item.vis, - Some(hir::map::NodeForeignItem(item)) => &item.vis, + Some(Node::Item(item)) => &item.vis, + Some(Node::ForeignItem(item)) => &item.vis, _ => bug!("expected item of foreign item"), }; @@ -1716,7 +1733,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, in_body: false, span: krate.span, empty_tables: &empty_tables, - visited_anon_tys: FxHashSet() + visited_opaque_tys: FxHashSet() }; intravisit::walk_crate(&mut visitor, krate); diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 4c8d42cf02..837340f70f 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -17,3 +17,4 @@ arena = { path = "../libarena" } rustc_errors = { path = "../librustc_errors" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_metadata = { path = "../librustc_metadata" } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index da2847dc55..25a7ff9cd3 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -13,18 +13,19 @@ //! Here we build the "reduced graph": the graph of the module tree without //! any imports resolved. -use macros::{InvocationData, LegacyScope}; +use macros::{InvocationData, ParentScope, LegacyScope}; use resolve_imports::ImportDirective; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; -use {PerNS, Resolver, ResolverArenas}; +use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use {resolve_error, resolve_struct_error, ResolutionError}; -use rustc::middle::cstore::LoadedMacro; use rustc::hir::def::*; -use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; +use rustc::middle::cstore::CrateStore; +use rustc_metadata::cstore::LoadedMacro; use std::cell::Cell; use rustc_data_structures::sync::Lrc; @@ -38,6 +39,7 @@ use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; +use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; use syntax::std_inject::injected_crate_name; use syntax::symbol::keywords; @@ -59,7 +61,20 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) { impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Def(self.0), + kind: NameBindingKind::Def(self.0, false), + vis: self.1, + span: self.2, + expansion: self.3, + }) + } +} + +pub(crate) struct IsMacroExport; + +impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport) { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { + arenas.alloc_name_binding(NameBinding { + kind: NameBindingKind::Def(self.0, true), vis: self.1, span: self.2, expansion: self.3, @@ -73,7 +88,7 @@ struct LegacyMacroImports { imports: Vec<(Name, Span)>, } -impl<'a> Resolver<'a> { +impl<'a, 'cl> Resolver<'a, 'cl> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. pub fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) @@ -99,27 +114,151 @@ impl<'a> Resolver<'a> { } } - fn build_reduced_graph_for_use_tree(&mut self, - root_use_tree: &ast::UseTree, - root_id: NodeId, - use_tree: &ast::UseTree, - id: NodeId, - vis: ty::Visibility, - prefix: &ast::Path, - nested: bool, - item: &Item, - expansion: Mark) { + fn build_reduced_graph_for_use_tree( + &mut self, + root_use_tree: &ast::UseTree, + root_id: NodeId, + use_tree: &ast::UseTree, + id: NodeId, + vis: ty::Visibility, + parent_prefix: &[Ident], + mut uniform_paths_canary_emitted: bool, + nested: bool, + item: &Item, + expansion: Mark, + ) { + debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, \ + uniform_paths_canary_emitted={}, \ + use_tree={:?}, nested={})", + parent_prefix, uniform_paths_canary_emitted, use_tree, nested); + let is_prelude = attr::contains_name(&item.attrs, "prelude_import"); - let path = &use_tree.prefix; + let uniform_paths = + self.session.rust_2018() && + self.session.features_untracked().uniform_paths; + + let prefix_iter = || parent_prefix.iter().cloned() + .chain(use_tree.prefix.segments.iter().map(|seg| seg.ident)); + let prefix_start = prefix_iter().nth(0); + let starts_with_non_keyword = prefix_start.map_or(false, |ident| { + !ident.is_path_segment_keyword() + }); - let mut module_path: Vec<_> = prefix.segments.iter() - .chain(path.segments.iter()) - .map(|seg| seg.ident) - .collect(); + // Imports are resolved as global by default, prepend `CrateRoot`, + // unless `#![feature(uniform_paths)]` is enabled. + let inject_crate_root = + !uniform_paths && + match use_tree.kind { + // HACK(eddyb) special-case `use *` to mean `use ::*`. + ast::UseTreeKind::Glob if prefix_start.is_none() => true, + _ => starts_with_non_keyword, + }; + let root = if inject_crate_root { + let span = use_tree.prefix.span.shrink_to_lo(); + Some(Ident::new(keywords::CrateRoot.name(), span)) + } else { + None + }; + + let prefix: Vec<_> = root.into_iter().chain(prefix_iter()).collect(); + + debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix); + + // `#[feature(uniform_paths)]` allows an unqualified import path, + // e.g. `use x::...;` to resolve not just globally (`use ::x::...;`) + // but also relatively (`use self::x::...;`). To catch ambiguities + // that might arise from both of these being available and resolution + // silently picking one of them, an artificial `use self::x as _;` + // import is injected as a "canary", and an error is emitted if it + // successfully resolves while an `x` external crate exists. + // + // For each block scope around the `use` item, one special canary + // import of the form `use x as _;` is also injected, having its + // parent set to that scope; `resolve_imports` will only resolve + // it within its appropriate scope; if any of them successfully + // resolve, an ambiguity error is emitted, since the original + // import can't see the item in the block scope (`self::x` only + // looks in the enclosing module), but a non-`use` path could. + // + // Additionally, the canary might be able to catch limitations of the + // current implementation, where `::x` may be chosen due to `self::x` + // not existing, but `self::x` could appear later, from macro expansion. + // + // NB. The canary currently only errors if the `x::...` path *could* + // resolve as a relative path through the extern crate, i.e. `x` is + // in `extern_prelude`, *even though* `::x` might still forcefully + // load a non-`extern_prelude` crate. + // While always producing an ambiguity errors if `self::x` exists and + // a crate *could* be loaded, would be more conservative, imports for + // local modules named `test` (or less commonly, `syntax` or `log`), + // would need to be qualified (e.g. `self::test`), which is considered + // ergonomically unacceptable. + let emit_uniform_paths_canary = + !uniform_paths_canary_emitted && + self.session.rust_2018() && + starts_with_non_keyword; + if emit_uniform_paths_canary { + let source = prefix_start.unwrap(); + + // Helper closure to emit a canary with the given base path. + let emit = |this: &mut Self, base: Option| { + let subclass = SingleImport { + target: Ident { + name: keywords::Underscore.name().gensymed(), + span: source.span, + }, + source, + result: PerNS { + type_ns: Cell::new(Err(Undetermined)), + value_ns: Cell::new(Err(Undetermined)), + macro_ns: Cell::new(Err(Undetermined)), + }, + type_ns_only: false, + }; + this.add_import_directive( + base.into_iter().collect(), + subclass.clone(), + source.span, + id, + root_use_tree.span, + root_id, + ty::Visibility::Invisible, + expansion, + true, // is_uniform_paths_canary + ); + }; + + // A single simple `self::x` canary. + emit(self, Some(Ident { + name: keywords::SelfValue.name(), + span: source.span, + })); + + // One special unprefixed canary per block scope around + // the import, to detect items unreachable by `self::x`. + let orig_current_module = self.current_module; + let mut span = source.span.modern(); + loop { + match self.current_module.kind { + ModuleKind::Block(..) => emit(self, None), + ModuleKind::Def(..) => break, + } + match self.hygienic_lexical_parent(self.current_module, &mut span) { + Some(module) => { + self.current_module = module; + } + None => break, + } + } + self.current_module = orig_current_module; + + uniform_paths_canary_emitted = true; + } match use_tree.kind { ast::UseTreeKind::Simple(rename, ..) => { let mut ident = use_tree.ident(); + let mut module_path = prefix; let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; @@ -128,8 +267,10 @@ impl<'a> Resolver<'a> { if source.name == keywords::SelfValue.name() { type_ns_only = true; - let last_segment = *module_path.last().unwrap(); - if last_segment.name == keywords::CrateRoot.name() { + let empty_prefix = module_path.last().map_or(true, |ident| { + ident.name == keywords::CrateRoot.name() + }); + if empty_prefix { resolve_error( self, use_tree.span, @@ -140,10 +281,9 @@ impl<'a> Resolver<'a> { } // Replace `use foo::self;` with `use foo;` - let _ = module_path.pop(); - source = last_segment; + source = module_path.pop().unwrap(); if rename.is_none() { - ident = last_segment; + ident = source; } } } else { @@ -155,13 +295,23 @@ impl<'a> Resolver<'a> { } // Disallow `use $crate;` - if source.name == keywords::DollarCrate.name() && path.segments.len() == 1 { + if source.name == keywords::DollarCrate.name() && module_path.is_empty() { let crate_root = self.resolve_crate_root(source); let crate_name = match crate_root.kind { ModuleKind::Def(_, name) => name, ModuleKind::Block(..) => unreachable!(), }; - source.name = crate_name; + // HACK(eddyb) unclear how good this is, but keeping `$crate` + // in `source` breaks `src/test/compile-fail/import-crate-var.rs`, + // while the current crate doesn't have a valid `crate_name`. + if crate_name != keywords::Invalid.name() { + // `crate_name` should not be interpreted as relative. + module_path.push(Ident { + name: keywords::CrateRoot.name(), + span: source.span, + }); + source.name = crate_name; + } if rename.is_none() { ident.name = crate_name; } @@ -173,6 +323,12 @@ impl<'a> Resolver<'a> { } } + if ident.name == keywords::Crate.name() { + self.session.span_err(ident.span, + "crate root imports need to be explicitly named: \ + `use crate as name;`"); + } + let subclass = SingleImport { target: ident, source, @@ -192,6 +348,7 @@ impl<'a> Resolver<'a> { root_id, vis, expansion, + false, // is_uniform_paths_canary ); } ast::UseTreeKind::Glob => { @@ -200,7 +357,7 @@ impl<'a> Resolver<'a> { max_vis: Cell::new(ty::Visibility::Invisible), }; self.add_import_directive( - module_path, + prefix, subclass, use_tree.span, id, @@ -208,16 +365,10 @@ impl<'a> Resolver<'a> { root_id, vis, expansion, + false, // is_uniform_paths_canary ); } ast::UseTreeKind::Nested(ref items) => { - let prefix = ast::Path { - segments: module_path.into_iter() - .map(|ident| ast::PathSegment::from_ident(ident)) - .collect(), - span: path.span, - }; - // Ensure there is at most one `self` in the list let self_spans = items.iter().filter_map(|&(ref use_tree, _)| { if let ast::UseTreeKind::Simple(..) = use_tree.kind { @@ -242,7 +393,16 @@ impl<'a> Resolver<'a> { for &(ref tree, id) in items { self.build_reduced_graph_for_use_tree( - root_use_tree, root_id, tree, id, vis, &prefix, true, item, expansion + root_use_tree, + root_id, + tree, + id, + vis, + &prefix, + uniform_paths_canary_emitted, + true, + item, + expansion, ); } } @@ -258,14 +418,17 @@ impl<'a> Resolver<'a> { match item.node { ItemKind::Use(ref use_tree) => { - // Imports are resolved as global by default, add starting root segment. - let prefix = ast::Path { - segments: use_tree.prefix.make_root().into_iter().collect(), - span: use_tree.span, - }; - self.build_reduced_graph_for_use_tree( - use_tree, item.id, use_tree, item.id, vis, &prefix, false, item, expansion, + use_tree, + item.id, + use_tree, + item.id, + vis, + &[], + false, // uniform_paths_canary_emitted + false, + item, + expansion, ); } @@ -285,7 +448,7 @@ impl<'a> Resolver<'a> { root_id: item.id, id: item.id, parent, - imported_module: Cell::new(Some(module)), + imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), subclass: ImportDirectiveSubclass::ExternCrate(orig_name), root_span: item.span, span: item.span, @@ -293,6 +456,7 @@ impl<'a> Resolver<'a> { vis: Cell::new(vis), expansion, used: Cell::new(used), + is_uniform_paths_canary: false, }); self.potentially_unused_imports.push(directive); let imported_binding = self.import(binding, directive); @@ -490,7 +654,7 @@ impl<'a> Resolver<'a> { (Def::Static(self.definitions.local_def_id(item.id), m), ValueNS) } ForeignItemKind::Ty => { - (Def::TyForeign(self.definitions.local_def_id(item.id)), TypeNS) + (Def::ForeignTy(self.definitions.local_def_id(item.id)), TypeNS) } ForeignItemKind::Macro(_) => unreachable!(), }; @@ -526,7 +690,7 @@ impl<'a> Resolver<'a> { span); self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); } - Def::Variant(..) | Def::TyAlias(..) | Def::TyForeign(..) => { + Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) => { self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); } Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { @@ -605,7 +769,7 @@ impl<'a> Resolver<'a> { let def_id = self.macro_defs[&expansion]; if let Some(id) = self.definitions.as_local_node_id(def_id) { self.local_macro_def_scopes[&id] - } else if def_id.krate == BUILTIN_MACROS_CRATE { + } else if def_id.krate == CrateNum::BuiltinMacros { self.injected_crate.unwrap_or(self.graph_root) } else { let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); @@ -616,7 +780,10 @@ impl<'a> Resolver<'a> { pub fn get_macro(&mut self, def: Def) -> Lrc { let def_id = match def { Def::Macro(def_id, ..) => def_id, - _ => panic!("Expected Def::Macro(..)"), + Def::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::NonMacroAttr { + mark_used: attr_kind == NonMacroAttrKind::Tool, + }), + _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"), }; if let Some(ext) = self.macro_map.get(&def_id) { return ext.clone(); @@ -651,7 +818,7 @@ impl<'a> Resolver<'a> { binding: &'a NameBinding<'a>, span: Span, allow_shadowing: bool) { - if self.macro_prelude.insert(name, binding).is_some() && !allow_shadowing { + if self.macro_use_prelude.insert(name, binding).is_some() && !allow_shadowing { let msg = format!("`{}` is already in scope", name); let note = "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)"; @@ -664,19 +831,12 @@ impl<'a> Resolver<'a> { -> bool { let allow_shadowing = expansion == Mark::root(); let legacy_imports = self.legacy_macro_imports(&item.attrs); - let mut used = legacy_imports != LegacyMacroImports::default(); + let used = legacy_imports != LegacyMacroImports::default(); // `#[macro_use]` is only allowed at the crate root. if self.current_module.parent.is_some() && used { span_err!(self.session, item.span, E0468, "an `extern crate` loading macros must be at the crate root"); - } else if !self.use_extern_macros && !used && - self.cstore.dep_kind_untracked(module.def_id().unwrap().krate) - .macros_only() { - let msg = "proc macro crates and `#[no_link]` crates have no effect without \ - `#[macro_use]`"; - self.session.span_warn(item.span, msg); - used = true; // Avoid the normal unused extern crate warning } let (graph_root, arenas) = (self.graph_root, self.arenas); @@ -684,7 +844,7 @@ impl<'a> Resolver<'a> { root_id: item.id, id: item.id, parent: graph_root, - imported_module: Cell::new(Some(module)), + imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), subclass: ImportDirectiveSubclass::MacroUse, root_span: span, span, @@ -692,6 +852,7 @@ impl<'a> Resolver<'a> { vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))), expansion, used: Cell::new(false), + is_uniform_paths_canary: false, }); if let Some(span) = legacy_imports.import_all { @@ -704,7 +865,13 @@ impl<'a> Resolver<'a> { } else { for (name, span) in legacy_imports.imports { let ident = Ident::with_empty_ctxt(name); - let result = self.resolve_ident_in_module(module, ident, MacroNS, false, span); + let result = self.resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + ident, + MacroNS, + false, + span, + ); if let Ok(binding) = result { let directive = macro_use_directive(span); self.potentially_unused_imports.push(directive); @@ -762,19 +929,20 @@ impl<'a> Resolver<'a> { } } -pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { - pub resolver: &'a mut Resolver<'b>, - pub legacy_scope: LegacyScope<'b>, +pub struct BuildReducedGraphVisitor<'a, 'b: 'a, 'c: 'b> { + pub resolver: &'a mut Resolver<'b, 'c>, + pub current_legacy_scope: LegacyScope<'b>, pub expansion: Mark, } -impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { +impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> { fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { let mark = id.placeholder_to_mark(); self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark); let invocation = self.resolver.invocations[&mark]; invocation.module.set(self.resolver.current_module); - invocation.legacy_scope.set(self.legacy_scope); + invocation.parent_legacy_scope.set(self.current_legacy_scope); + invocation.output_legacy_scope.set(self.current_legacy_scope); invocation } } @@ -791,7 +959,7 @@ macro_rules! method { } } -impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { +impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> { method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item); method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr); method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat); @@ -800,29 +968,30 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { fn visit_item(&mut self, item: &'a Item) { let macro_use = match item.node { ItemKind::MacroDef(..) => { - self.resolver.define_macro(item, self.expansion, &mut self.legacy_scope); + self.resolver.define_macro(item, self.expansion, &mut self.current_legacy_scope); return } ItemKind::Mac(..) => { - self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id)); + self.current_legacy_scope = LegacyScope::Invocation(self.visit_invoc(item.id)); return } ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs), _ => false, }; - let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); + let orig_current_module = self.resolver.current_module; + let orig_current_legacy_scope = self.current_legacy_scope; self.resolver.build_reduced_graph_for_item(item, self.expansion); visit::walk_item(self, item); - self.resolver.current_module = parent; + self.resolver.current_module = orig_current_module; if !macro_use { - self.legacy_scope = legacy_scope; + self.current_legacy_scope = orig_current_legacy_scope; } } fn visit_stmt(&mut self, stmt: &'a ast::Stmt) { if let ast::StmtKind::Mac(..) = stmt.node { - self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(stmt.id)); + self.current_legacy_scope = LegacyScope::Invocation(self.visit_invoc(stmt.id)); } else { visit::walk_stmt(self, stmt); } @@ -839,11 +1008,12 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { } fn visit_block(&mut self, block: &'a Block) { - let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); + let orig_current_module = self.resolver.current_module; + let orig_current_legacy_scope = self.current_legacy_scope; self.resolver.build_reduced_graph_for_block(block, self.expansion); visit::walk_block(self, block); - self.resolver.current_module = parent; - self.legacy_scope = legacy_scope; + self.resolver.current_module = orig_current_module; + self.current_legacy_scope = orig_current_legacy_scope; } fn visit_trait_item(&mut self, item: &'a TraitItem) { @@ -888,4 +1058,20 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { } } } + + fn visit_attribute(&mut self, attr: &'a ast::Attribute) { + if !attr.is_sugared_doc && is_builtin_attr(attr) { + let parent_scope = ParentScope { + module: self.resolver.current_module.nearest_item_scope(), + expansion: self.expansion, + legacy: self.current_legacy_scope, + // Let's hope discerning built-in attributes from derive helpers is not necessary + derives: Vec::new(), + }; + parent_scope.module.builtin_attrs.borrow_mut().push(( + attr.path.segments[0].ident, parent_scope + )); + } + visit::walk_attribute(self, attr); + } } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index ec067a6477..de9481579e 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -31,8 +31,8 @@ use syntax::visit::{self, Visitor}; use syntax_pos::{Span, MultiSpan, DUMMY_SP}; -struct UnusedImportCheckVisitor<'a, 'b: 'a> { - resolver: &'a mut Resolver<'b>, +struct UnusedImportCheckVisitor<'a, 'b: 'a, 'd: 'b> { + resolver: &'a mut Resolver<'b, 'd>, /// All the (so far) unused imports, grouped path list unused_imports: NodeMap>, base_id: ast::NodeId, @@ -40,21 +40,21 @@ struct UnusedImportCheckVisitor<'a, 'b: 'a> { } // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver. -impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> { - type Target = Resolver<'b>; +impl<'a, 'b, 'd> Deref for UnusedImportCheckVisitor<'a, 'b, 'd> { + type Target = Resolver<'b, 'd>; - fn deref<'c>(&'c self) -> &'c Resolver<'b> { + fn deref<'c>(&'c self) -> &'c Resolver<'b, 'd> { &*self.resolver } } -impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> { - fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> { +impl<'a, 'b, 'd> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'd> { + fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'd> { &mut *self.resolver } } -impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { +impl<'a, 'b, 'd> UnusedImportCheckVisitor<'a, 'b, 'd> { // We have information about whether `use` (import) directives are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) { @@ -65,7 +65,7 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { // Check later. return; } - self.unused_imports.entry(item_id).or_insert_with(NodeMap).insert(id, span); + self.unused_imports.entry(item_id).or_default().insert(id, span); } else { // This trait import is definitely used, in a way other than // method resolution. @@ -77,7 +77,7 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { } } -impl<'a, 'b> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b> { +impl<'a, 'b, 'cl> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'cl> { fn visit_item(&mut self, item: &'a ast::Item) { self.item_span = item.span; @@ -112,7 +112,7 @@ impl<'a, 'b> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b> { if items.len() == 0 { self.unused_imports .entry(self.base_id) - .or_insert_with(NodeMap) + .or_default() .insert(id, span); } } else { @@ -131,8 +131,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { directive.vis.get() == ty::Visibility::Public || directive.span.is_dummy() => { if let ImportDirectiveSubclass::MacroUse = directive.subclass { - if resolver.session.features_untracked().use_extern_macros && - !directive.span.is_dummy() { + if !directive.span.is_dummy() { resolver.session.buffer_lint( lint::builtin::MACRO_USE_EXTERN_CRATE, directive.id, @@ -176,7 +175,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { let ms = MultiSpan::from_spans(spans.clone()); let mut span_snippets = spans.iter() .filter_map(|s| { - match visitor.session.codemap().span_to_snippet(*s) { + match visitor.session.source_map().span_to_snippet(*s) { Ok(s) => Some(format!("`{}`", s)), _ => None, } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 6593e239bc..c1dc3041d7 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -770,17 +770,18 @@ match x { "##, E0411: r##" -The `Self` keyword was used outside an impl or a trait. +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 or trait +::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 or a trait. It gives access to the associated items of a -type: +be used inside an impl, trait, or type definition. It gives access to the +associated items of a type: ``` trait Foo { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d41f3ec1d9..168603d417 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -9,10 +9,11 @@ // except according to those terms. #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] + html_favicon_url = "https://doc.rust-lang.org/favicon.ico", + html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] @@ -26,6 +27,7 @@ extern crate arena; #[macro_use] extern crate rustc; extern crate rustc_data_structures; +extern crate rustc_metadata; pub use rustc::hir::def::{Namespace, PerNS}; @@ -33,8 +35,8 @@ use self::TypeParameters::*; use self::RibKind::*; use rustc::hir::map::{Definitions, DefCollector}; -use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; -use rustc::middle::cstore::{CrateStore, CrateLoader}; +use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str}; +use rustc::middle::cstore::CrateStore; use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; @@ -44,7 +46,10 @@ use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; -use syntax::codemap::CodeMap; +use rustc_metadata::creader::CrateLoader; +use rustc_metadata::cstore::CStore; + +use syntax::source_map::SourceMap; use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; @@ -60,11 +65,10 @@ use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generi use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; -use syntax::feature_gate::{feature_err, GateIssue}; use syntax::ptr::P; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; -use errors::{DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use std::cell::{Cell, RefCell}; use std::cmp; @@ -75,7 +79,7 @@ use std::mem::replace; use rustc_data_structures::sync::Lrc; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; -use macros::{InvocationData, LegacyBinding, LegacyScope, MacroBinding}; +use macros::{InvocationData, LegacyBinding, ParentScope}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. @@ -86,6 +90,10 @@ mod check_unused; mod build_reduced_graph; mod resolve_imports; +fn is_known_tool(name: Name) -> bool { + ["clippy", "rustfmt"].contains(&&*name.as_str()) +} + /// A free importable items suggested in case of resolution failure. struct ImportSuggestion { path: Path, @@ -150,8 +158,6 @@ enum ResolutionError<'a> { SelfImportCanOnlyAppearOnceInTheList, /// error E0431: `self` import can only appear in an import list with a non-empty prefix SelfImportOnlyInImportListWithNonEmptyPrefix, - /// error E0432: unresolved import - UnresolvedImport(Option<(Span, &'a str, &'a str)>), /// error E0433: failed to resolve FailedToResolve(&'a str), /// error E0434: can't capture dynamic environment in a fn item @@ -186,29 +192,37 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, "can't use type parameters from outer function"); err.span_label(span, "use of type variable from outer function"); - let cm = resolver.session.codemap(); + let cm = resolver.session.source_map(); match outer_def { - Def::SelfTy(_, maybe_impl_defid) => { - if let Some(impl_span) = maybe_impl_defid.map_or(None, - |def_id| resolver.definitions.opt_span(def_id)) { - err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span), - "`Self` type implicitely declared here, on the `impl`"); + Def::SelfTy(maybe_trait_defid, maybe_impl_defid) => { + if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| { + resolver.definitions.opt_span(def_id) + }) { + err.span_label( + reduce_impl_span_to_impl_keyword(cm, impl_span), + "`Self` type implicitly declared here, by this `impl`", + ); } + match (maybe_trait_defid, maybe_impl_defid) { + (Some(_), None) => { + err.span_label(span, "can't use `Self` here"); + } + (_, Some(_)) => { + err.span_label(span, "use a type here instead"); + } + (None, None) => bug!("`impl` without trait nor type?"), + } + return err; }, Def::TyParam(typaram_defid) => { if let Some(typaram_span) = resolver.definitions.opt_span(typaram_defid) { err.span_label(typaram_span, "type variable from outer function"); } }, - Def::Mod(..) | Def::Struct(..) | Def::Union(..) | Def::Enum(..) | Def::Variant(..) | - Def::Trait(..) | Def::TyAlias(..) | Def::TyForeign(..) | Def::TraitAlias(..) | - Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) | - Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) | - Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) | - Def::Existential(..) | Def::AssociatedExistential(..) | - Def::Macro(..) | Def::GlobalAsm(..) | Def::Err => + _ => { bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \ Def::TyParam") + } } // Try to retrieve the span of the function signature and generate a new message with @@ -216,9 +230,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, let sugg_msg = "try using a local type parameter instead"; if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) { // Suggest the modification to the user - err.span_suggestion(sugg_span, - sugg_msg, - new_snippet); + err.span_suggestion_with_applicability( + sugg_span, + sugg_msg, + new_snippet, + Applicability::MachineApplicable, + ); } else if let Some(sp) = cm.generate_fn_name_span(span) { err.span_label(sp, "try adding a local type parameter in this method instead"); } else { @@ -349,17 +366,6 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, err.span_label(span, "can only appear in an import list with a non-empty prefix"); err } - ResolutionError::UnresolvedImport(name) => { - let (span, msg) = match name { - Some((sp, n, _)) => (sp, format!("unresolved import `{}`", n)), - None => (span, "unresolved import".to_owned()), - }; - let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg); - if let Some((_, _, p)) = name { - err.span_label(span, p); - } - err - } ResolutionError::FailedToResolve(msg) => { let mut err = struct_span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg); @@ -410,8 +416,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, /// /// Attention: The method used is very fragile since it essentially duplicates the work of the /// parser. If you need to use this function or something similar, please consider updating the -/// codemap functions and this function to something more robust. -fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span { +/// source_map functions and this function to something more robust. +fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span { let impl_span = cm.span_until_char(impl_span, '<'); let impl_span = cm.span_until_whitespace(impl_span); impl_span @@ -535,7 +541,7 @@ impl<'a> PathSource<'a> { Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) | Def::Existential(..) | - Def::TyForeign(..) => true, + Def::ForeignTy(..) => true, _ => false, }, PathSource::Trait(AliasPossibility::No) => match def { @@ -551,17 +557,21 @@ impl<'a> PathSource<'a> { Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) | Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) | - Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) => true, + Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) | + Def::SelfCtor(..) => true, _ => false, }, PathSource::Pat => match def { Def::StructCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Const) | - Def::Const(..) | Def::AssociatedConst(..) => true, + Def::Const(..) | Def::AssociatedConst(..) | + Def::SelfCtor(..) => true, _ => false, }, PathSource::TupleStruct => match def { - Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => true, + Def::StructCtor(_, CtorKind::Fn) | + Def::VariantCtor(_, CtorKind::Fn) | + Def::SelfCtor(..) => true, _ => false, }, PathSource::Struct => match def { @@ -688,7 +698,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { } /// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes. -impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { +impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> { fn visit_item(&mut self, item: &'tcx Item) { self.resolve_item(item); } @@ -818,11 +828,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => None, GenericParamKind::Type { ref default, .. } => { - if found_default || default.is_some() { - found_default = true; - return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err)); + found_default |= default.is_some(); + if found_default { + Some((Ident::with_empty_ctxt(param.ident.name), Def::Err)) + } else { + None } - None } })); @@ -949,9 +960,20 @@ impl<'a> LexicalScopeBinding<'a> { } } +#[derive(Copy, Clone, Debug)] +pub enum ModuleOrUniformRoot<'a> { + /// Regular module. + Module(Module<'a>), + + /// The `{{root}}` (`CrateRoot` aka "global") / `extern` initial segment + /// in which external crates resolve, and also `crate` (only in `{{root}}`, + /// but *not* `extern`), in the Rust 2018 edition. + UniformRoot(Name), +} + #[derive(Clone, Debug)] enum PathResult<'a> { - Module(Module<'a>), + Module(ModuleOrUniformRoot<'a>), NonModule(PathResolution), Indeterminate, Failed(Span, String, bool /* is the error from the last segment? */), @@ -990,8 +1012,9 @@ pub struct ModuleData<'a> { normal_ancestor_id: DefId, resolutions: RefCell>>>, - legacy_macro_resolutions: RefCell)>>, + legacy_macro_resolutions: RefCell, Option)>>, macro_resolutions: RefCell, Span)>>, + builtin_attrs: RefCell)>>, // Macro invocations that can expand into items in this module. unresolved_invocations: RefCell>, @@ -1030,6 +1053,7 @@ impl<'a> ModuleData<'a> { resolutions: RefCell::new(FxHashMap()), legacy_macro_resolutions: RefCell::new(Vec::new()), macro_resolutions: RefCell::new(Vec::new()), + builtin_attrs: RefCell::new(Vec::new()), unresolved_invocations: RefCell::new(FxHashSet()), no_implicit_prelude: false, glob_importers: RefCell::new(Vec::new()), @@ -1118,7 +1142,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { #[derive(Clone, Debug)] enum NameBindingKind<'a> { - Def(Def), + Def(Def, /* is_macro_export */ bool), Module(Module<'a>), Import { binding: &'a NameBinding<'a>, @@ -1144,9 +1168,7 @@ struct UseError<'a> { } struct AmbiguityError<'a> { - span: Span, - name: Name, - lexical: bool, + ident: Ident, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>, } @@ -1162,7 +1184,7 @@ impl<'a> NameBinding<'a> { fn def(&self) -> Def { match self.kind { - NameBindingKind::Def(def) => def, + NameBindingKind::Def(def, _) => def, NameBindingKind::Module(module) => module.def().unwrap(), NameBindingKind::Import { binding, .. } => binding.def(), NameBindingKind::Ambiguity { .. } => Def::Err, @@ -1177,7 +1199,7 @@ impl<'a> NameBinding<'a> { } } - fn get_macro(&self, resolver: &mut Resolver<'a>) -> Lrc { + fn get_macro<'b: 'a>(&self, resolver: &mut Resolver<'a, 'b>) -> Lrc { resolver.get_macro(self.def_ignoring_ambiguity()) } @@ -1192,8 +1214,8 @@ impl<'a> NameBinding<'a> { fn is_variant(&self) -> bool { match self.kind { - NameBindingKind::Def(Def::Variant(..)) | - NameBindingKind::Def(Def::VariantCtor(..)) => true, + NameBindingKind::Def(Def::Variant(..), _) | + NameBindingKind::Def(Def::VariantCtor(..), _) => true, _ => false, } } @@ -1242,14 +1264,41 @@ impl<'a> NameBinding<'a> { fn is_macro_def(&self) -> bool { match self.kind { - NameBindingKind::Def(Def::Macro(..)) => true, + NameBindingKind::Def(Def::Macro(..), _) => true, _ => false, } } + fn macro_kind(&self) -> Option { + match self.def_ignoring_ambiguity() { + Def::Macro(_, kind) => Some(kind), + Def::NonMacroAttr(..) => Some(MacroKind::Attr), + _ => None, + } + } + fn descr(&self) -> &'static str { if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() } } + + // Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding` + // at some expansion round `max(invoc, binding)` when they both emerged from macros. + // Then this function returns `true` if `self` may emerge from a macro *after* that + // in some later round and screw up our previously found resolution. + // See more detailed explanation in + // https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049 + fn may_appear_after(&self, invoc_parent_expansion: Mark, binding: &NameBinding) -> bool { + // self > max(invoc, binding) => !(self <= invoc || self <= binding) + // Expansions are partially ordered, so "may appear after" is an inversion of + // "certainly appears before or simultaneously" and includes unordered cases. + let self_parent_expansion = self.expansion; + let other_parent_expansion = binding.expansion; + let certainly_before_other_or_simultaneously = + other_parent_expansion.is_descendant_of(self_parent_expansion); + let certainly_before_invoc_or_simultaneously = + invoc_parent_expansion.is_descendant_of(self_parent_expansion); + !(certainly_before_other_or_simultaneously || certainly_before_invoc_or_simultaneously) + } } /// Interns the names of the primitive types. @@ -1264,23 +1313,23 @@ impl PrimitiveTypeTable { fn new() -> PrimitiveTypeTable { let mut table = PrimitiveTypeTable { primitive_types: FxHashMap() }; - table.intern("bool", TyBool); - table.intern("char", TyChar); - table.intern("f32", TyFloat(FloatTy::F32)); - table.intern("f64", TyFloat(FloatTy::F64)); - table.intern("isize", TyInt(IntTy::Isize)); - table.intern("i8", TyInt(IntTy::I8)); - table.intern("i16", TyInt(IntTy::I16)); - table.intern("i32", TyInt(IntTy::I32)); - table.intern("i64", TyInt(IntTy::I64)); - table.intern("i128", TyInt(IntTy::I128)); - table.intern("str", TyStr); - table.intern("usize", TyUint(UintTy::Usize)); - table.intern("u8", TyUint(UintTy::U8)); - table.intern("u16", TyUint(UintTy::U16)); - table.intern("u32", TyUint(UintTy::U32)); - table.intern("u64", TyUint(UintTy::U64)); - table.intern("u128", TyUint(UintTy::U128)); + table.intern("bool", Bool); + table.intern("char", Char); + table.intern("f32", Float(FloatTy::F32)); + table.intern("f64", Float(FloatTy::F64)); + table.intern("isize", Int(IntTy::Isize)); + table.intern("i8", Int(IntTy::I8)); + table.intern("i16", Int(IntTy::I16)); + table.intern("i32", Int(IntTy::I32)); + table.intern("i64", Int(IntTy::I64)); + table.intern("i128", Int(IntTy::I128)); + table.intern("str", Str); + table.intern("usize", Uint(UintTy::Usize)); + table.intern("u8", Uint(UintTy::U8)); + table.intern("u16", Uint(UintTy::U16)); + table.intern("u32", Uint(UintTy::U32)); + table.intern("u64", Uint(UintTy::U64)); + table.intern("u128", Uint(UintTy::U128)); table } @@ -1292,9 +1341,9 @@ impl PrimitiveTypeTable { /// The main resolver class. /// /// This is the visitor that walks the whole crate. -pub struct Resolver<'a> { +pub struct Resolver<'a, 'b: 'a> { session: &'a Session, - cstore: &'a dyn CrateStore, + cstore: &'a CStore, pub definitions: Definitions, @@ -1379,26 +1428,20 @@ pub struct Resolver<'a> { ambiguity_errors: Vec>, /// `use` injections are delayed for better placement and deduplication use_injections: Vec>, - /// `use` injections for proc macros wrongly imported with #[macro_use] - proc_mac_errors: Vec, - - gated_errors: FxHashSet, - disallowed_shadowing: Vec<&'a LegacyBinding<'a>>, + /// crate-local macro expanded `macro_export` referred to by a module-relative path + macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, - /// true if `#![feature(use_extern_macros)]` - use_extern_macros: bool, - crate_loader: &'a mut dyn CrateLoader, + crate_loader: &'a mut CrateLoader<'b>, macro_names: FxHashSet, - macro_prelude: FxHashMap>, + builtin_macros: FxHashMap>, + macro_use_prelude: FxHashMap>, pub all_macros: FxHashMap, - lexical_macro_resolutions: Vec<(Ident, &'a Cell>)>, macro_map: FxHashMap>, macro_defs: FxHashMap, local_macro_def_scopes: FxHashMap>, - macro_exports: Vec, pub whitelisted_legacy_custom_derives: Vec, pub found_unresolved_macro: bool, @@ -1412,9 +1455,6 @@ pub struct Resolver<'a> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, - /// A set of procedural macros imported by `#[macro_use]` that have already been warned about - warned_proc_macros: FxHashSet, - potentially_unused_imports: Vec<&'a ImportDirective<'a>>, /// This table maps struct IDs into struct constructor IDs, @@ -1425,9 +1465,6 @@ pub struct Resolver<'a> { current_type_ascription: Vec, injected_crate: Option>, - - /// Only supposed to be used by rustdoc, otherwise should be false. - pub ignore_extern_prelude_feature: bool, } /// Nothing really interesting here, it just provides memory for the rest of the crate. @@ -1471,7 +1508,7 @@ impl<'a> ResolverArenas<'a> { } } -impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> { +impl<'a, 'b: 'a, 'cl: 'b> ty::DefIdTree for &'a Resolver<'b, 'cl> { fn parent(self, id: DefId) -> Option { match id.krate { LOCAL_CRATE => self.definitions.def_key(id.index).parent, @@ -1482,7 +1519,7 @@ impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. -impl<'a> hir::lowering::Resolver for Resolver<'a> { +impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) { self.resolve_hir_path_cb(path, is_value, |resolver, span, error| resolve_error(resolver, span, error)) @@ -1535,7 +1572,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { } } -impl<'a> Resolver<'a> { +impl<'a, 'crateloader> Resolver<'a, 'crateloader> { /// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a> /// isn't something that can be returned because it can't be made to live that long, /// and also it's a private type. Fortunately rustdoc doesn't need to know the error, @@ -1577,11 +1614,13 @@ impl<'a> Resolver<'a> { let hir::Path { ref segments, span, ref mut def } = *path; let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); // FIXME (Manishearth): Intra doc links won't get warned of epoch changes - match self.resolve_path(&path, Some(namespace), true, span, CrateLint::No) { - PathResult::Module(module) => *def = module.def().unwrap(), + match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) { + PathResult::Module(ModuleOrUniformRoot::Module(module)) => + *def = module.def().unwrap(), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => *def = path_res.base_def(), PathResult::NonModule(..) => match self.resolve_path( + None, &path, None, true, @@ -1593,6 +1632,7 @@ impl<'a> Resolver<'a> { } _ => {} }, + PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | PathResult::Indeterminate => unreachable!(), PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); @@ -1601,15 +1641,15 @@ impl<'a> Resolver<'a> { } } -impl<'a> Resolver<'a> { +impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { pub fn new(session: &'a Session, - cstore: &'a dyn CrateStore, + cstore: &'a CStore, krate: &Crate, crate_name: &str, make_glob_map: MakeGlobMap, - crate_loader: &'a mut dyn CrateLoader, + crate_loader: &'a mut CrateLoader<'crateloader>, arenas: &'a ResolverArenas<'a>) - -> Resolver<'a> { + -> Resolver<'a, 'crateloader> { let root_def_id = DefId::local(CRATE_DEF_INDEX); let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name()); let graph_root = arenas.alloc_module(ModuleData { @@ -1625,20 +1665,19 @@ impl<'a> Resolver<'a> { let mut extern_prelude: FxHashSet = session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(); - if !attr::contains_name(&krate.attrs, "no_core") { - if !attr::contains_name(&krate.attrs, "no_std") { - extern_prelude.insert(Symbol::intern("std")); - } else { - extern_prelude.insert(Symbol::intern("core")); - } - } + + // HACK(eddyb) this ignore the `no_{core,std}` attributes. + // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`. + // if !attr::contains_name(&krate.attrs, "no_core") { + // if !attr::contains_name(&krate.attrs, "no_std") { + extern_prelude.insert(Symbol::intern("core")); + extern_prelude.insert(Symbol::intern("std")); + extern_prelude.insert(Symbol::intern("meta")); let mut invocations = FxHashMap(); invocations.insert(Mark::root(), arenas.alloc_invocation_data(InvocationData::root(graph_root))); - let features = session.features_untracked(); - let mut macro_defs = FxHashMap(); macro_defs.insert(Mark::root(), root_def_id); @@ -1696,42 +1735,33 @@ impl<'a> Resolver<'a> { privacy_errors: Vec::new(), ambiguity_errors: Vec::new(), use_injections: Vec::new(), - proc_mac_errors: Vec::new(), - gated_errors: FxHashSet(), - disallowed_shadowing: Vec::new(), + macro_expanded_macro_export_errors: BTreeSet::new(), arenas, dummy_binding: arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Def(Def::Err), + kind: NameBindingKind::Def(Def::Err, false), expansion: Mark::root(), span: DUMMY_SP, vis: ty::Visibility::Public, }), - // The `proc_macro` and `decl_macro` features imply `use_extern_macros` - use_extern_macros: - features.use_extern_macros || features.decl_macro, - crate_loader, macro_names: FxHashSet(), - macro_prelude: FxHashMap(), + builtin_macros: FxHashMap(), + macro_use_prelude: FxHashMap(), all_macros: FxHashMap(), - lexical_macro_resolutions: Vec::new(), macro_map: FxHashMap(), - macro_exports: Vec::new(), invocations, macro_defs, local_macro_def_scopes: FxHashMap(), name_already_seen: FxHashMap(), whitelisted_legacy_custom_derives: Vec::new(), - warned_proc_macros: FxHashSet(), potentially_unused_imports: Vec::new(), struct_constructors: DefIdMap(), found_unresolved_macro: false, unused_macros: FxHashSet(), current_type_ascription: Vec::new(), injected_crate: None, - ignore_extern_prelude_feature: false, } } @@ -1751,9 +1781,7 @@ impl<'a> Resolver<'a> { fn per_ns(&mut self, mut f: F) { f(self, TypeNS); f(self, ValueNS); - if self.use_extern_macros { - f(self, MacroNS); - } + f(self, MacroNS); } fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId { @@ -1790,7 +1818,7 @@ impl<'a> Resolver<'a> { self.arenas.alloc_module(module) } - fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) + fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>) -> bool /* true if an error was reported */ { match binding.kind { NameBindingKind::Import { directive, binding, ref used } @@ -1799,13 +1827,11 @@ impl<'a> Resolver<'a> { directive.used.set(true); self.used_imports.insert((directive.id, ns)); self.add_to_glob_map(directive.id, ident); - self.record_use(ident, ns, binding, span) + self.record_use(ident, ns, binding) } NameBindingKind::Import { .. } => false, NameBindingKind::Ambiguity { b1, b2 } => { - self.ambiguity_errors.push(AmbiguityError { - span, name: ident.name, lexical: false, b1, b2, - }); + self.ambiguity_errors.push(AmbiguityError { ident, b1, b2 }); true } _ => false @@ -1814,7 +1840,7 @@ impl<'a> Resolver<'a> { fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) { if self.make_glob_map { - self.glob_map.entry(id).or_insert_with(FxHashSet).insert(ident.name); + self.glob_map.entry(id).or_default().insert(ident.name); } } @@ -1842,6 +1868,7 @@ impl<'a> Resolver<'a> { path_span: Span) -> Option> { let record_used = record_used_id.is_some(); + assert!(ns == TypeNS || ns == ValueNS); if ns == TypeNS { ident.span = if ident.name == keywords::SelfType.name() { // FIXME(jseyfried) improve `Self` hygiene @@ -1875,7 +1902,12 @@ impl<'a> Resolver<'a> { }; let item = self.resolve_ident_in_module_unadjusted( - module, ident, ns, false, record_used, path_span, + ModuleOrUniformRoot::Module(module), + ident, + ns, + false, + record_used, + path_span, ); if let Ok(binding) = item { // The ident resolves to an item. @@ -1901,7 +1933,12 @@ impl<'a> Resolver<'a> { let orig_current_module = self.current_module; self.current_module = module; // Lexical resolutions can never be a privacy error. let result = self.resolve_ident_in_module_unadjusted( - module, ident, ns, false, record_used, path_span, + ModuleOrUniformRoot::Module(module), + ident, + ns, + false, + record_used, + path_span, ); self.current_module = orig_current_module; @@ -1927,24 +1964,28 @@ impl<'a> Resolver<'a> { if !module.no_implicit_prelude { // `record_used` means that we don't try to load crates during speculative resolution if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) { - if !self.session.features_untracked().extern_prelude && - !self.ignore_extern_prelude_feature { - feature_err(&self.session.parse_sess, "extern_prelude", - ident.span, GateIssue::Language, - "access to extern crates through prelude is experimental").emit(); - } - let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(crate_root); + self.populate_module_if_necessary(&crate_root); let binding = (crate_root, ty::Visibility::Public, ident.span, Mark::root()).to_name_binding(self.arenas); return Some(LexicalScopeBinding::Item(binding)); } + if ns == TypeNS && is_known_tool(ident.name) { + let binding = (Def::ToolMod, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + return Some(LexicalScopeBinding::Item(binding)); + } if let Some(prelude) = self.prelude { - if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns, - false, false, path_span) { + if let Ok(binding) = self.resolve_ident_in_module_unadjusted( + ModuleOrUniformRoot::Module(prelude), + ident, + ns, + false, + false, + path_span, + ) { return Some(LexicalScopeBinding::Item(binding)); } } @@ -2003,7 +2044,7 @@ impl<'a> Resolver<'a> { } fn resolve_ident_in_module(&mut self, - module: Module<'a>, + module: ModuleOrUniformRoot<'a>, mut ident: Ident, ns: Namespace, record_used: bool, @@ -2011,8 +2052,10 @@ impl<'a> Resolver<'a> { -> Result<&'a NameBinding<'a>, Determinacy> { ident.span = ident.span.modern(); let orig_current_module = self.current_module; - if let Some(def) = ident.span.adjust(module.expansion) { - self.current_module = self.macro_def_scope(def); + if let ModuleOrUniformRoot::Module(module) = module { + if let Some(def) = ident.span.adjust(module.expansion) { + self.current_module = self.macro_def_scope(def); + } } let result = self.resolve_ident_in_module_unadjusted( module, ident, ns, false, record_used, span, @@ -2142,22 +2185,35 @@ impl<'a> Resolver<'a> { None } + fn resolve_adt(&mut self, item: &Item, generics: &Generics) { + self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { + let item_def_id = this.definitions.local_def_id(item.id); + if this.session.features_untracked().self_in_typedefs { + this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| { + visit::walk_item(this, item); + }); + } else { + visit::walk_item(this, item); + } + }); + } + fn resolve_item(&mut self, item: &Item) { let name = item.ident.name; - debug!("(resolving item) resolving {}", name); - self.check_proc_macro_attrs(&item.attrs); - match item.node { - ItemKind::Enum(_, ref generics) | ItemKind::Ty(_, ref generics) | - ItemKind::Existential(_, ref generics) | - ItemKind::Struct(_, ref generics) | - ItemKind::Union(_, ref generics) | - ItemKind::Fn(_, _, ref generics, _) => { + ItemKind::Fn(_, _, ref generics, _) | + ItemKind::Existential(_, ref generics) => { self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), - |this| visit::walk_item(this, item)); + |this| visit::walk_item(this, item)); + } + + ItemKind::Enum(_, ref generics) | + ItemKind::Struct(_, ref generics) | + ItemKind::Union(_, ref generics) => { + self.resolve_adt(item, generics); } ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => @@ -2176,8 +2232,6 @@ impl<'a> Resolver<'a> { walk_list!(this, visit_param_bound, bounds); for trait_item in trait_items { - this.check_proc_macro_attrs(&trait_item.attrs); - let type_parameters = HasTypeParameters(&trait_item.generics, TraitOrImplItemRibKind); this.with_type_parameter_rib(type_parameters, |this| { @@ -2304,28 +2358,30 @@ impl<'a> Resolver<'a> { HasTypeParameters(generics, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap(); - generics.params.iter().for_each(|param| match param.kind { - GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { .. } => { - let ident = param.ident.modern(); - debug!("with_type_parameter_rib: {}", param.id); - - if seen_bindings.contains_key(&ident) { - let span = seen_bindings.get(&ident).unwrap(); - let err = ResolutionError::NameAlreadyUsedInTypeParameterList( - ident.name, - span, - ); - resolve_error(self, param.ident.span, err); - } - seen_bindings.entry(ident).or_insert(param.ident.span); + for param in &generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { .. } => { + let ident = param.ident.modern(); + debug!("with_type_parameter_rib: {}", param.id); + + if seen_bindings.contains_key(&ident) { + let span = seen_bindings.get(&ident).unwrap(); + let err = ResolutionError::NameAlreadyUsedInTypeParameterList( + ident.name, + span, + ); + resolve_error(self, param.ident.span, err); + } + seen_bindings.entry(ident).or_insert(param.ident.span); - // Plain insert (no renaming). - let def = Def::TyParam(self.definitions.local_def_id(param.id)); - function_type_rib.bindings.insert(ident, def); - self.record_def(param.id, PathResolution::new(def)); + // Plain insert (no renaming). + let def = Def::TyParam(self.definitions.local_def_id(param.id)); + function_type_rib.bindings.insert(ident, def); + self.record_def(param.id, PathResolution::new(def)); + } } - }); + } self.ribs[TypeNS].push(function_type_rib); } @@ -2400,13 +2456,16 @@ impl<'a> Resolver<'a> { if def != Def::Err { new_id = Some(def.def_id()); let span = trait_ref.path.span; - if let PathResult::Module(module) = self.resolve_path( - &path, - None, - false, - span, - CrateLint::SimplePath(trait_ref.ref_id), - ) { + if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = + self.resolve_path( + None, + &path, + None, + false, + span, + CrateLint::SimplePath(trait_ref.ref_id), + ) + { new_val = Some((module, trait_ref.clone())); } } @@ -2429,6 +2488,17 @@ impl<'a> Resolver<'a> { self.ribs[TypeNS].pop(); } + fn with_self_struct_ctor_rib(&mut self, impl_id: DefId, f: F) + where F: FnOnce(&mut Resolver) + { + let self_def = Def::SelfCtor(impl_id); + let mut self_type_rib = Rib::new(NormalRibKind); + self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def); + self.ribs[ValueNS].push(self_type_rib); + f(self); + self.ribs[ValueNS].pop(); + } + fn resolve_implementation(&mut self, generics: &Generics, opt_trait_reference: &Option, @@ -2444,72 +2514,74 @@ impl<'a> Resolver<'a> { let item_def_id = this.definitions.local_def_id(item_id); this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| { if let Some(trait_ref) = opt_trait_reference.as_ref() { - // Resolve type arguments in trait path + // Resolve type arguments in the trait path. visit::walk_trait_ref(this, trait_ref); } // Resolve the self type. this.visit_ty(self_type); // Resolve the type parameters. this.visit_generics(generics); + // Resolve the items within the impl. this.with_current_self_type(self_type, |this| { - for impl_item in impl_items { - this.check_proc_macro_attrs(&impl_item.attrs); - this.resolve_visibility(&impl_item.vis); - - // We also need a new scope for the impl item type parameters. - let type_parameters = HasTypeParameters(&impl_item.generics, - TraitOrImplItemRibKind); - this.with_type_parameter_rib(type_parameters, |this| { - use self::ResolutionError::*; - match impl_item.node { - ImplItemKind::Const(..) => { - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item(impl_item.ident, - ValueNS, - impl_item.span, - |n, s| ConstNotMemberOfTrait(n, s)); - this.with_constant_rib(|this| - visit::walk_impl_item(this, impl_item) - ); - } - ImplItemKind::Method(..) => { - // If this is a trait impl, ensure the method - // exists in trait - this.check_trait_item(impl_item.ident, - ValueNS, - impl_item.span, - |n, s| MethodNotMemberOfTrait(n, s)); - - visit::walk_impl_item(this, impl_item); - } - ImplItemKind::Type(ref ty) => { - // If this is a trait impl, ensure the type - // exists in trait - this.check_trait_item(impl_item.ident, - TypeNS, - impl_item.span, - |n, s| TypeNotMemberOfTrait(n, s)); - - this.visit_ty(ty); - } - ImplItemKind::Existential(ref bounds) => { - // If this is a trait impl, ensure the type - // exists in trait - this.check_trait_item(impl_item.ident, - TypeNS, - impl_item.span, - |n, s| TypeNotMemberOfTrait(n, s)); - - for bound in bounds { - this.visit_param_bound(bound); + this.with_self_struct_ctor_rib(item_def_id, |this| { + for impl_item in impl_items { + this.resolve_visibility(&impl_item.vis); + + // We also need a new scope for the impl item type parameters. + let type_parameters = HasTypeParameters(&impl_item.generics, + TraitOrImplItemRibKind); + this.with_type_parameter_rib(type_parameters, |this| { + use self::ResolutionError::*; + match impl_item.node { + ImplItemKind::Const(..) => { + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item(impl_item.ident, + ValueNS, + impl_item.span, + |n, s| ConstNotMemberOfTrait(n, s)); + this.with_constant_rib(|this| + visit::walk_impl_item(this, impl_item) + ); + } + ImplItemKind::Method(..) => { + // If this is a trait impl, ensure the method + // exists in trait + this.check_trait_item(impl_item.ident, + ValueNS, + impl_item.span, + |n, s| MethodNotMemberOfTrait(n, s)); + + visit::walk_impl_item(this, impl_item); } + ImplItemKind::Type(ref ty) => { + // If this is a trait impl, ensure the type + // exists in trait + this.check_trait_item(impl_item.ident, + TypeNS, + impl_item.span, + |n, s| TypeNotMemberOfTrait(n, s)); + + this.visit_ty(ty); + } + ImplItemKind::Existential(ref bounds) => { + // If this is a trait impl, ensure the type + // exists in trait + this.check_trait_item(impl_item.ident, + TypeNS, + impl_item.span, + |n, s| TypeNotMemberOfTrait(n, s)); + + for bound in bounds { + this.visit_param_bound(bound); + } + } + ImplItemKind::Macro(_) => + panic!("unexpanded macro in resolve!"), } - ImplItemKind::Macro(_) => - panic!("unexpanded macro in resolve!"), - } - }); - } + }); + } + }); }); }); }); @@ -2523,7 +2595,13 @@ impl<'a> Resolver<'a> { // If there is a TraitRef in scope for an impl, then the method must be in the // trait. if let Some((module, _)) = self.current_trait_ref { - if self.resolve_ident_in_module(module, ident, ns, false, span).is_err() { + if self.resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + ident, + ns, + false, + span, + ).is_err() { let path = &self.current_trait_ref.as_ref().unwrap().1.path; resolve_error(self, span, err(ident.name, &path_names_to_string(path))); } @@ -2644,7 +2722,10 @@ impl<'a> Resolver<'a> { // This has to happen *after* we determine which pat_idents are variants self.check_consistent_bindings(&arm.pats); - walk_list!(self, visit_expr, &arm.guard); + match arm.guard { + Some(ast::Guard::If(ref expr)) => self.visit_expr(expr), + _ => {} + } self.visit_expr(&arm.body); self.ribs[ValueNS].pop(); @@ -2688,7 +2769,7 @@ impl<'a> Resolver<'a> { self.label_ribs.pop(); } self.ribs[ValueNS].pop(); - if let Some(_) = anonymous_module { + if anonymous_module.is_some() { self.ribs[TypeNS].pop(); } debug!("(resolving block) leaving block"); @@ -2775,7 +2856,7 @@ impl<'a> Resolver<'a> { Def::Const(..) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant // or constant pattern. - self.record_use(ident, ValueNS, binding.unwrap(), ident.span); + self.record_use(ident, ValueNS, binding.unwrap()); Some(PathResolution::new(def)) } Def::StructCtor(..) | Def::VariantCtor(..) | @@ -2898,9 +2979,10 @@ impl<'a> Resolver<'a> { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; - let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), + let mod_prefix = match this.resolve_path(None, mod_path, Some(TypeNS), false, span, CrateLint::No) { - PathResult::Module(module) => module.def(), + PathResult::Module(ModuleOrUniformRoot::Module(module)) => + module.def(), _ => None, }.map_or(String::new(), |def| format!("{} ", def.kind_name())); (mod_prefix, format!("`{}`", names_to_string(mod_path))) @@ -2916,7 +2998,12 @@ impl<'a> Resolver<'a> { if is_self_type(path, ns) { __diagnostic_used!(E0411); err.code(DiagnosticId::Error("E0411".into())); - err.span_label(span, "`Self` is only available in traits and impls"); + let available_in = if this.session.features_untracked().self_in_typedefs { + "impls, traits, and type definitions" + } else { + "traits and impls" + }; + err.span_label(span, format!("`Self` is only available in {}", available_in)); return (err, Vec::new()); } if is_self_value(path, ns) { @@ -2944,8 +3031,12 @@ impl<'a> Resolver<'a> { enum_path); err.help(&msg); } else { - err.span_suggestion(span, "you can try using the variant's enum", - enum_path); + err.span_suggestion_with_applicability( + span, + "you can try using the variant's enum", + enum_path, + Applicability::MachineApplicable, + ); } } } @@ -2954,20 +3045,32 @@ impl<'a> Resolver<'a> { let self_is_available = this.self_value_is_available(path[0].span, span); match candidate { AssocSuggestion::Field => { - err.span_suggestion(span, "try", - format!("self.{}", path_str)); + err.span_suggestion_with_applicability( + span, + "try", + format!("self.{}", path_str), + Applicability::MachineApplicable, + ); if !self_is_available { err.span_label(span, format!("`self` value is only available in \ methods with `self` parameter")); } } AssocSuggestion::MethodWithSelf if self_is_available => { - err.span_suggestion(span, "try", - format!("self.{}", path_str)); + err.span_suggestion_with_applicability( + span, + "try", + format!("self.{}", path_str), + Applicability::MachineApplicable, + ); } AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => { - err.span_suggestion(span, "try", - format!("Self::{}", path_str)); + err.span_suggestion_with_applicability( + span, + "try", + format!("Self::{}", path_str), + Applicability::MachineApplicable, + ); } } return (err, candidates); @@ -3035,7 +3138,7 @@ impl<'a> Resolver<'a> { // parser issue where a struct literal is being used on an expression // where a brace being opened means a block is being started. Look // ahead for the next text to see if `span` is followed by a `{`. - let cm = this.session.codemap(); + let cm = this.session.source_map(); let mut sp = span; loop { sp = cm.next_point(sp); @@ -3162,7 +3265,7 @@ impl<'a> Resolver<'a> { err: &mut DiagnosticBuilder, base_span: Span) { debug!("type_ascription_suggetion {:?}", base_span); - let cm = self.session.codemap(); + let cm = self.session.source_map(); debug!("self.current_type_ascription {:?}", self.current_type_ascription); if let Some(sp) = self.current_type_ascription.last() { let mut sp = *sp; @@ -3230,10 +3333,12 @@ impl<'a> Resolver<'a> { }; } } - let is_global = self.macro_prelude.get(&path[0].name).cloned() - .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false); - if primary_ns != MacroNS && (is_global || - self.macro_names.contains(&path[0].modern())) { + if primary_ns != MacroNS && + (self.macro_names.contains(&path[0].modern()) || + self.builtin_macros.get(&path[0].name).cloned() + .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) || + self.macro_use_prelude.get(&path[0].name).cloned() + .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) { // Return some dummy definition, it's enough for error reporting. return Some( PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang)) @@ -3309,6 +3414,7 @@ impl<'a> Resolver<'a> { } let result = match self.resolve_path( + None, &path, Some(ns), true, @@ -3316,7 +3422,7 @@ impl<'a> Resolver<'a> { crate_lint, ) { PathResult::NonModule(path_res) => path_res, - PathResult::Module(module) if !module.is_normal() => { + PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { PathResolution::new(module.def().unwrap()) } // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we @@ -3331,18 +3437,21 @@ impl<'a> Resolver<'a> { // // Such behavior is required for backward compatibility. // The same fallback is used when `a` resolves to nothing. - PathResult::Module(..) | PathResult::Failed(..) + PathResult::Module(ModuleOrUniformRoot::Module(_)) | + PathResult::Failed(..) if (ns == TypeNS || path.len() > 1) && self.primitive_type_table.primitive_types .contains_key(&path[0].name) => { let prim = self.primitive_type_table.primitive_types[&path[0].name]; PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } - PathResult::Module(module) => PathResolution::new(module.def().unwrap()), + PathResult::Module(ModuleOrUniformRoot::Module(module)) => + PathResolution::new(module.def().unwrap()), PathResult::Failed(span, msg, false) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); err_path_resolution() } + PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | PathResult::Failed(..) => return None, PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; @@ -3352,6 +3461,7 @@ impl<'a> Resolver<'a> { path[0].name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path( + None, &[*path.last().unwrap()], Some(ns), false, @@ -3359,7 +3469,8 @@ impl<'a> Resolver<'a> { CrateLint::No, ) { PathResult::NonModule(path_res) => path_res.base_def(), - PathResult::Module(module) => module.def().unwrap(), + PathResult::Module(ModuleOrUniformRoot::Module(module)) => + module.def().unwrap(), _ => return Some(result), } }; @@ -3374,15 +3485,32 @@ impl<'a> Resolver<'a> { fn resolve_path( &mut self, + base_module: Option>, path: &[Ident], opt_ns: Option, // `None` indicates a module path record_used: bool, path_span: Span, crate_lint: CrateLint, ) -> PathResult<'a> { - let mut module = None; + let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() }; + self.resolve_path_with_parent_scope(base_module, path, opt_ns, &parent_scope, + record_used, path_span, crate_lint) + } + + fn resolve_path_with_parent_scope( + &mut self, + base_module: Option>, + path: &[Ident], + opt_ns: Option, // `None` indicates a module path + parent_scope: &ParentScope<'a>, + record_used: bool, + path_span: Span, + crate_lint: CrateLint, + ) -> PathResult<'a> { + let mut module = base_module; let mut allow_super = true; let mut second_binding = None; + self.current_module = parent_scope.module; debug!( "resolve_path(path={:?}, opt_ns={:?}, record_used={:?}, \ @@ -3400,65 +3528,56 @@ impl<'a> Resolver<'a> { let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; let name = ident.name; - if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() { - let mut ctxt = ident.span.ctxt().modern(); - module = Some(self.resolve_self(&mut ctxt, self.current_module)); - continue - } else if allow_super && ns == TypeNS && name == keywords::Super.name() { - let mut ctxt = ident.span.ctxt().modern(); - let self_module = match i { - 0 => self.resolve_self(&mut ctxt, self.current_module), - _ => module.unwrap(), - }; - if let Some(parent) = self_module.parent { - module = Some(self.resolve_self(&mut ctxt, parent)); - continue - } else { + allow_super &= ns == TypeNS && + (name == keywords::SelfValue.name() || + name == keywords::Super.name()); + + if ns == TypeNS { + if allow_super && name == keywords::Super.name() { + let mut ctxt = ident.span.ctxt().modern(); + let self_module = match i { + 0 => Some(self.resolve_self(&mut ctxt, self.current_module)), + _ => match module { + Some(ModuleOrUniformRoot::Module(module)) => Some(module), + _ => None, + }, + }; + if let Some(self_module) = self_module { + if let Some(parent) = self_module.parent { + module = Some(ModuleOrUniformRoot::Module( + self.resolve_self(&mut ctxt, parent))); + continue; + } + } let msg = "There are too many initial `super`s.".to_string(); return PathResult::Failed(ident.span, msg, false); } - } else if i == 0 && ns == TypeNS && name == keywords::Extern.name() { - continue; - } - allow_super = false; - - if ns == TypeNS { - if (i == 0 && name == keywords::CrateRoot.name()) || - (i == 0 && name == keywords::Crate.name()) || - (i == 0 && name == keywords::DollarCrate.name()) || - (i == 1 && name == keywords::Crate.name() && - path[0].name == keywords::CrateRoot.name()) { - // `::a::b`, `crate::a::b`, `::crate::a::b` or `$crate::a::b` - module = Some(self.resolve_crate_root(ident)); - continue - } else if i == 1 && !ident.is_path_segment_keyword() { - let prev_name = path[0].name; - if prev_name == keywords::Extern.name() || - prev_name == keywords::CrateRoot.name() && - self.session.features_untracked().extern_absolute_paths && + if i == 0 { + if name == keywords::SelfValue.name() { + let mut ctxt = ident.span.ctxt().modern(); + module = Some(ModuleOrUniformRoot::Module( + self.resolve_self(&mut ctxt, self.current_module))); + continue; + } + if name == keywords::Extern.name() || + name == keywords::CrateRoot.name() && self.session.rust_2018() { - // `::extern_crate::a::b` - let crate_id = self.crate_loader.process_path_extern(name, ident.span); - let crate_root = - self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(crate_root); - module = Some(crate_root); - continue + module = Some(ModuleOrUniformRoot::UniformRoot(name)); + continue; + } + if name == keywords::CrateRoot.name() || + name == keywords::Crate.name() || + name == keywords::DollarCrate.name() { + // `::a::b`, `crate::a::b` or `$crate::a::b` + module = Some(ModuleOrUniformRoot::Module( + self.resolve_crate_root(ident))); + continue; } } } // Report special messages for path segment keywords in wrong positions. - if name == keywords::CrateRoot.name() && i != 0 || - name == keywords::DollarCrate.name() && i != 0 || - name == keywords::SelfValue.name() && i != 0 || - name == keywords::SelfType.name() && i != 0 || - name == keywords::Super.name() && i != 0 || - name == keywords::Extern.name() && i != 0 || - // we allow crate::foo and ::crate::foo but nothing else - name == keywords::Crate.name() && i > 1 && - path[0].name != keywords::CrateRoot.name() || - name == keywords::Crate.name() && path.len() == 1 { + if ident.is_path_segment_keyword() && i != 0 { let name_str = if name == keywords::CrateRoot.name() { "crate root".to_string() } else { @@ -3475,8 +3594,9 @@ impl<'a> Resolver<'a> { let binding = if let Some(module) = module { self.resolve_ident_in_module(module, ident, ns, record_used, path_span) } else if opt_ns == Some(MacroNS) { - self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span) - .map(MacroBinding::binding) + assert!(ns == TypeNS); + self.resolve_lexical_macro_path_segment(ident, ns, None, parent_scope, record_used, + record_used, path_span).map(|(b, _)| b) } else { let record_used_id = if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None }; @@ -3502,7 +3622,10 @@ impl<'a> Resolver<'a> { let def = binding.def(); let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def); if let Some(next_module) = binding.module() { - module = Some(next_module); + module = Some(ModuleOrUniformRoot::Module(next_module)); + } else if def == Def::ToolMod && i + 1 != path.len() { + let def = Def::NonMacroAttr(NonMacroAttrKind::Tool); + return PathResult::NonModule(PathResolution::new(def)); } else if def == Def::Err { return PathResult::NonModule(err_path_resolution()); } else if opt_ns.is_some() && (is_last || maybe_assoc) { @@ -3523,14 +3646,18 @@ impl<'a> Resolver<'a> { } Err(Undetermined) => return PathResult::Indeterminate, Err(Determined) => { - if let Some(module) = module { + if let Some(ModuleOrUniformRoot::Module(module)) = module { if opt_ns.is_some() && !module.is_normal() { return PathResult::NonModule(PathResolution::with_unresolved_segments( module.def().unwrap(), path.len() - i )); } } - let msg = if module.and_then(ModuleData::def) == self.graph_root.def() { + let module_def = match module { + Some(ModuleOrUniformRoot::Module(module)) => module.def(), + _ => None, + }; + let msg = if module_def == self.graph_root.def() { let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; let mut candidates = self.lookup_import_candidates(name, TypeNS, is_mod); @@ -3554,7 +3681,10 @@ impl<'a> Resolver<'a> { self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding); - PathResult::Module(module.unwrap_or(self.graph_root)) + PathResult::Module(module.unwrap_or_else(|| { + span_bug!(path_span, "resolve_path: empty(?) path {:?} has no module", path); + })) + } fn lint_if_path_starts_with_module( @@ -3564,6 +3694,11 @@ impl<'a> Resolver<'a> { path_span: Span, second_binding: Option<&NameBinding>, ) { + // In the 2018 edition this lint is a hard error, so nothing to do + if self.session.rust_2018() { + return + } + let (diag_id, diag_span) = match crate_lint { CrateLint::No => return, CrateLint::SimplePath(id) => (id, path_span), @@ -3606,24 +3741,11 @@ impl<'a> Resolver<'a> { } } - self.lint_path_starts_with_module(diag_id, diag_span); - } - - fn lint_path_starts_with_module(&self, id: NodeId, span: Span) { - // In the 2018 edition this lint is a hard error, so nothing to do - if self.session.rust_2018() { - return - } - // In the 2015 edition there's no use in emitting lints unless the - // crate's already enabled the feature that we're going to suggest - if !self.session.features_untracked().crate_in_paths { - return - } let diag = lint::builtin::BuiltinLintDiagnostics - ::AbsPathWithModule(span); + ::AbsPathWithModule(diag_span); self.session.buffer_lint_with_diagnostic( lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, - id, span, + diag_id, diag_span, "absolute paths must start with `self`, `super`, \ `crate`, or an external crate name in the 2018 edition", diag); @@ -3663,14 +3785,14 @@ impl<'a> Resolver<'a> { let seen = self.freevars_seen .entry(function_id) - .or_insert_with(|| NodeMap()); + .or_default(); if let Some(&index) = seen.get(&node_id) { def = Def::Upvar(node_id, index, function_id); continue; } let vec = self.freevars .entry(function_id) - .or_insert_with(|| vec![]); + .or_default(); let depth = vec.len(); def = Def::Upvar(node_id, depth, function_id); @@ -3768,8 +3890,13 @@ impl<'a> Resolver<'a> { // Look for associated items in the current trait. if let Some((module, _)) = self.current_trait_ref { - if let Ok(binding) = - self.resolve_ident_in_module(module, ident, ns, false, module.span) { + if let Ok(binding) = self.resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + ident, + ns, + false, + module.span, + ) { let def = binding.def(); if filter_fn(def) { return Some(if self.has_self.contains(&def.def_id()) { @@ -3833,7 +3960,7 @@ impl<'a> Resolver<'a> { } } // Add primitive types to the mix - if filter_fn(Def::PrimTy(TyBool)) { + if filter_fn(Def::PrimTy(Bool)) { names.extend( self.primitive_type_table.primitive_types.iter().map(|(name, _)| name) ) @@ -3841,9 +3968,11 @@ impl<'a> Resolver<'a> { } else { // Search in module. let mod_path = &path[..path.len() - 1]; - if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), + if let PathResult::Module(module) = self.resolve_path(None, mod_path, Some(TypeNS), false, span, CrateLint::No) { - add_module_candidates(module, &mut names); + if let ModuleOrUniformRoot::Module(module) = module { + add_module_candidates(module, &mut names); + } } } @@ -4082,7 +4211,13 @@ impl<'a> Resolver<'a> { let mut found_traits = Vec::new(); // Look for the current trait. if let Some((module, _)) = self.current_trait_ref { - if self.resolve_ident_in_module(module, ident, ns, false, module.span).is_ok() { + if self.resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + ident, + ns, + false, + module.span, + ).is_ok() { let def_id = module.def_id().unwrap(); found_traits.push(TraitCandidate { def_id: def_id, import_id: None }); } @@ -4111,6 +4246,7 @@ impl<'a> Resolver<'a> { ns: Namespace, module: Module<'a>, found_traits: &mut Vec) { + assert!(ns == TypeNS || ns == ValueNS); let mut traits = module.traits.borrow_mut(); if traits.is_none() { let mut collected_traits = Vec::new(); @@ -4129,8 +4265,14 @@ impl<'a> Resolver<'a> { if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() { continue } - if self.resolve_ident_in_module_unadjusted(module, ident, ns, false, false, module.span) - .is_ok() { + if self.resolve_ident_in_module_unadjusted( + ModuleOrUniformRoot::Module(module), + ident, + ns, + false, + false, + module.span, + ).is_ok() { let import_id = match binding.kind { NameBindingKind::Import { directive, .. } => { self.maybe_unused_trait_imports.insert(directive.id); @@ -4145,16 +4287,11 @@ impl<'a> Resolver<'a> { } } - /// When name resolution fails, this method can be used to look up candidate - /// entities with the expected name. It allows filtering them using the - /// supplied predicate (which should be used to only accept the types of - /// definitions expected e.g. traits). The lookup spans across all crates. - /// - /// NOTE: The method does not look into imports, but this is not a problem, - /// since we report the definitions (thus, the de-aliased imports). - fn lookup_import_candidates(&mut self, + fn lookup_import_candidates_from_module(&mut self, lookup_name: Name, namespace: Namespace, + start_module: &'a ModuleData<'a>, + crate_name: Ident, filter_fn: FilterFn) -> Vec where FilterFn: Fn(Def) -> bool @@ -4162,7 +4299,8 @@ impl<'a> Resolver<'a> { let mut candidates = Vec::new(); let mut worklist = Vec::new(); let mut seen_modules = FxHashSet(); - worklist.push((self.graph_root, Vec::new(), false)); + let not_local_module = crate_name != keywords::Crate.ident(); + worklist.push((start_module, Vec::::new(), not_local_module)); while let Some((in_module, path_segments, @@ -4181,17 +4319,14 @@ impl<'a> Resolver<'a> { if ident.name == lookup_name && ns == namespace { if filter_fn(name_binding.def()) { // create the path - let mut segms = if self.session.rust_2018() && !in_module_is_extern { + let mut segms = path_segments.clone(); + if self.session.rust_2018() { // crate-local absolute paths start with `crate::` in edition 2018 // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660) - let mut full_segms = vec![ - ast::PathSegment::from_ident(keywords::Crate.ident()) - ]; - full_segms.extend(path_segments.clone()); - full_segms - } else { - path_segments.clone() - }; + segms.insert( + 0, ast::PathSegment::from_ident(crate_name) + ); + } segms.push(ast::PathSegment::from_ident(ident)); let path = Path { @@ -4217,7 +4352,14 @@ impl<'a> Resolver<'a> { let mut path_segments = path_segments.clone(); path_segments.push(ast::PathSegment::from_ident(ident)); - if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { + let is_extern_crate_that_also_appears_in_prelude = + name_binding.is_extern_crate() && + self.session.rust_2018(); + + let is_visible_to_user = + !in_module_is_extern || name_binding.vis == ty::Visibility::Public; + + if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user { // add the module to the lookup let is_extern = in_module_is_extern || name_binding.is_extern_crate(); if seen_modules.insert(module.def_id().unwrap()) { @@ -4231,6 +4373,54 @@ impl<'a> Resolver<'a> { candidates } + /// When name resolution fails, this method can be used to look up candidate + /// entities with the expected name. It allows filtering them using the + /// supplied predicate (which should be used to only accept the types of + /// definitions expected e.g. traits). The lookup spans across all crates. + /// + /// NOTE: The method does not look into imports, but this is not a problem, + /// since we report the definitions (thus, the de-aliased imports). + fn lookup_import_candidates(&mut self, + lookup_name: Name, + namespace: Namespace, + filter_fn: FilterFn) + -> Vec + where FilterFn: Fn(Def) -> bool + { + let mut suggestions = vec![]; + + suggestions.extend( + self.lookup_import_candidates_from_module( + lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn + ) + ); + + if self.session.rust_2018() { + let extern_prelude_names = self.extern_prelude.clone(); + for &name in extern_prelude_names.iter() { + let ident = Ident::with_empty_ctxt(name); + match self.crate_loader.maybe_process_path_extern(name, ident.span) { + Some(crate_id) => { + let crate_root = self.get_module(DefId { + krate: crate_id, + index: CRATE_DEF_INDEX, + }); + self.populate_module_if_necessary(&crate_root); + + suggestions.extend( + self.lookup_import_candidates_from_module( + lookup_name, namespace, crate_root, ident, &filter_fn + ) + ); + } + None => {} + } + } + } + + suggestions + } + fn find_module(&mut self, module_def: Def) -> Option<(Module<'a>, ImportSuggestion)> @@ -4242,7 +4432,7 @@ impl<'a> Resolver<'a> { while let Some((in_module, path_segments)) = worklist.pop() { // abort if the module is already found - if let Some(_) = result { break; } + if result.is_some() { break; } self.populate_module_if_necessary(in_module); @@ -4350,37 +4540,59 @@ impl<'a> Resolver<'a> { vis.is_accessible_from(module.normal_ancestor_id, self) } - fn report_errors(&mut self, krate: &Crate) { - self.report_shadowing_errors(); - self.report_with_use_injections(krate); - self.report_proc_macro_import(krate); - let mut reported_spans = FxHashSet(); - - for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors { - if !reported_spans.insert(span) { continue } - let participle = |binding: &NameBinding| { - if binding.is_import() { "imported" } else { "defined" } - }; - let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1)); - let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2)); - let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() { - format!("consider adding an explicit import of `{}` to disambiguate", name) - } else if let Def::Macro(..) = b1.def() { + fn report_ambiguity_error(&self, ident: Ident, b1: &NameBinding, b2: &NameBinding) { + let participle = |is_import: bool| if is_import { "imported" } else { "defined" }; + let msg1 = + format!("`{}` could refer to the name {} here", ident, participle(b1.is_import())); + let msg2 = + format!("`{}` could also refer to the name {} here", ident, participle(b2.is_import())); + let note = if b1.expansion != Mark::root() { + Some(if let Def::Macro(..) = b1.def() { format!("macro-expanded {} do not shadow", if b1.is_import() { "macro imports" } else { "macros" }) } else { format!("macro-expanded {} do not shadow when used in a macro invocation path", if b1.is_import() { "imports" } else { "items" }) - }; + }) + } else if b1.is_glob_import() { + Some(format!("consider adding an explicit import of `{}` to disambiguate", ident)) + } else { + None + }; - let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name); - err.span_note(b1.span, &msg1); - match b2.def() { - Def::Macro(..) if b2.span.is_dummy() => - err.note(&format!("`{}` is also a builtin macro", name)), - _ => err.span_note(b2.span, &msg2), - }; - err.note(¬e).emit(); + let mut err = struct_span_err!(self.session, ident.span, E0659, "`{}` is ambiguous", ident); + err.span_label(ident.span, "ambiguous name"); + err.span_note(b1.span, &msg1); + match b2.def() { + Def::Macro(..) if b2.span.is_dummy() => + err.note(&format!("`{}` is also a builtin macro", ident)), + _ => err.span_note(b2.span, &msg2), + }; + if let Some(note) = note { + err.note(¬e); + } + err.emit(); + } + + fn report_errors(&mut self, krate: &Crate) { + self.report_with_use_injections(krate); + let mut reported_spans = FxHashSet(); + + for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { + let msg = "macro-expanded `macro_export` macros from the current crate \ + cannot be referred to by absolute paths"; + self.session.buffer_lint_with_diagnostic( + lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, + CRATE_NODE_ID, span_use, msg, + lint::builtin::BuiltinLintDiagnostics:: + MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def), + ); + } + + for &AmbiguityError { ident, b1, b2 } in &self.ambiguity_errors { + if reported_spans.insert(ident.span) { + self.report_ambiguity_error(ident, b1, b2); + } } for &PrivacyError(span, name, binding) in &self.privacy_errors { @@ -4399,24 +4611,6 @@ impl<'a> Resolver<'a> { } } - fn report_shadowing_errors(&mut self) { - for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { - self.resolve_legacy_scope(scope, ident, true); - } - - let mut reported_errors = FxHashSet(); - for binding in replace(&mut self.disallowed_shadowing, Vec::new()) { - if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() && - reported_errors.insert((binding.ident, binding.span)) { - let msg = format!("`{}` is already in scope", binding.ident); - self.session.struct_span_err(binding.span, &msg) - .note("macro-expanded `macro_rules!`s may not shadow \ - existing macros (see RFC 1560)") - .emit(); - } - } - } - fn report_conflict<'b>(&mut self, parent: Module, ident: Ident, @@ -4445,7 +4639,7 @@ impl<'a> Resolver<'a> { false => "defined", }; - let (name, span) = (ident.name, self.session.codemap().def_span(new_binding.span)); + let (name, span) = (ident.name, self.session.source_map().def_span(new_binding.span)); if let Some(s) = self.name_already_seen.get(&name) { if s == &span { @@ -4484,7 +4678,7 @@ impl<'a> Resolver<'a> { err.span_label(span, format!("`{}` re{} here", name, new_participle)); if !old_binding.span.is_dummy() { - err.span_label(self.session.codemap().def_span(old_binding.span), + err.span_label(self.session.source_map().def_span(old_binding.span), format!("previous {} of the {} `{}` here", old_noun, old_kind, name)); } @@ -4496,7 +4690,7 @@ impl<'a> Resolver<'a> { old_binding }; - let cm = self.session.codemap(); + let cm = self.session.source_map(); let rename_msg = "You can use `as` to change the binding name of the import"; if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span), @@ -4507,15 +4701,16 @@ impl<'a> Resolver<'a> { format!("other_{}", name) }; - err.span_suggestion(binding.span, - rename_msg, - if snippet.ends_with(';') { - format!("{} as {};", - &snippet[..snippet.len()-1], - suggested_name) - } else { - format!("{} as {}", snippet, suggested_name) - }); + err.span_suggestion_with_applicability( + binding.span, + rename_msg, + if snippet.ends_with(';') { + format!("{} as {};", &snippet[..snippet.len() - 1], suggested_name) + } else { + format!("{} as {}", snippet, suggested_name) + }, + Applicability::MachineApplicable, + ); } else { err.span_label(binding.span, rename_msg); } @@ -4524,34 +4719,6 @@ impl<'a> Resolver<'a> { err.emit(); self.name_already_seen.insert(name, span); } - - fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) { - if self.use_extern_macros { return; } - - for attr in attrs { - if attr.path.segments.len() > 1 { - continue - } - let ident = attr.path.segments[0].ident; - let result = self.resolve_lexical_macro_path_segment(ident, - MacroNS, - false, - attr.path.span); - if let Ok(binding) = result { - if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) { - attr::mark_known(attr); - - let msg = "attribute procedural macros are experimental"; - let feature = "use_extern_macros"; - - feature_err(&self.session.parse_sess, feature, - attr.span, GateIssue::Language, msg) - .span_label(binding.span(), "procedural macro imported here") - .emit(); - } - } - } - } } fn is_self_type(path: &[Ident], namespace: Namespace) -> bool { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 29b6f958cc..35d96b9302 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,48 +8,57 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {AmbiguityError, CrateLint, Resolver, ResolutionError, resolve_error}; -use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult}; -use Namespace::{self, MacroNS}; -use build_reduced_graph::BuildReducedGraphVisitor; +use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error}; +use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding}; +use ModuleOrUniformRoot; +use Namespace::{self, TypeNS, MacroNS}; +use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use resolve_imports::ImportResolver; -use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex, - DefIndexAddressSpace}; -use rustc::hir::def::{Def, Export}; +use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex, + CrateNum, DefIndexAddressSpace}; +use rustc::hir::def::{Def, NonMacroAttrKind}; use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; use syntax::ast::{self, Name, Ident}; -use syntax::attr::{self, HasAttrs}; +use syntax::attr; use syntax::errors::DiagnosticBuilder; -use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator}; +use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver}; -use syntax::ext::expand::{self, AstFragment, AstFragmentKind, Invocation, InvocationKind}; +use syntax::ext::expand::{AstFragment, Invocation, InvocationKind, TogetherWith}; use syntax::ext::hygiene::{self, Mark}; -use syntax::ext::placeholders::placeholder; use syntax::ext::tt::macro_rules; -use syntax::feature_gate::{self, emit_feature_err, GateIssue}; +use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue}; +use syntax::feature_gate::EXPLAIN_DERIVE_UNDERSCORE; use syntax::fold::{self, Folder}; use syntax::parse::parser::PathStyle; use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; -use syntax::tokenstream::{TokenStream, TokenTree, Delimited}; +use syntax::tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan}; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{Span, DUMMY_SP}; +use errors::Applicability; use std::cell::Cell; use std::mem; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::small_vec::ExpectOne; + +#[derive(Clone, Copy)] +crate struct FromPrelude(bool); #[derive(Clone)] pub struct InvocationData<'a> { - pub module: Cell>, - pub def_index: DefIndex, - // The scope in which the invocation path is resolved. - pub legacy_scope: Cell>, - // The smallest scope that includes this invocation's expansion, - // or `Empty` if this invocation has not been expanded yet. - pub expansion: Cell>, + def_index: DefIndex, + /// Module in which the macro was invoked. + crate module: Cell>, + /// Legacy scope in which the macro was invoked. + /// The invocation path is resolved in this scope. + crate parent_legacy_scope: Cell>, + /// Legacy scope *produced* by expanding this macro invocation, + /// includes all the macro_rules items, other invocations, etc generated by it. + /// Set to the parent scope if the macro is not expanded yet (as if the macro produced nothing). + crate output_legacy_scope: Cell>, } impl<'a> InvocationData<'a> { @@ -57,67 +66,67 @@ impl<'a> InvocationData<'a> { InvocationData { module: Cell::new(graph_root), def_index: CRATE_DEF_INDEX, - legacy_scope: Cell::new(LegacyScope::Empty), - expansion: Cell::new(LegacyScope::Empty), + parent_legacy_scope: Cell::new(LegacyScope::Empty), + output_legacy_scope: Cell::new(LegacyScope::Empty), } } } +/// Binding produced by a `macro_rules` item. +/// Not modularized, can shadow previous legacy bindings, etc. +pub struct LegacyBinding<'a> { + binding: &'a NameBinding<'a>, + /// Legacy scope into which the `macro_rules` item was planted. + parent_legacy_scope: LegacyScope<'a>, + ident: Ident, +} + +/// Scope introduced by a `macro_rules!` macro. +/// Starts at the macro's definition and ends at the end of the macro's parent module +/// (named or unnamed), or even further if it escapes with `#[macro_use]`. +/// Some macro invocations need to introduce legacy scopes too because they +/// potentially can expand into macro definitions. #[derive(Copy, Clone)] pub enum LegacyScope<'a> { + /// Created when invocation data is allocated in the arena, + /// must be replaced with a proper scope later. + Uninitialized, + /// Empty "root" scope at the crate start containing no names. Empty, - Invocation(&'a InvocationData<'a>), // The scope of the invocation, not including its expansion - Expansion(&'a InvocationData<'a>), // The scope of the invocation, including its expansion + /// Scope introduced by a `macro_rules!` macro definition. Binding(&'a LegacyBinding<'a>), + /// Scope introduced by a macro invocation that can potentially + /// create a `macro_rules!` macro definition. + Invocation(&'a InvocationData<'a>), } -pub struct LegacyBinding<'a> { - pub parent: Cell>, - pub ident: Ident, - def_id: DefId, - pub span: Span, -} - -pub struct ProcMacError { - crate_name: Symbol, - name: Symbol, - module: ast::NodeId, - use_span: Span, - warn_msg: &'static str, -} - -#[derive(Copy, Clone)] -pub enum MacroBinding<'a> { - Legacy(&'a LegacyBinding<'a>), - Global(&'a NameBinding<'a>), - Modern(&'a NameBinding<'a>), +/// Everything you need to resolve a macro path. +#[derive(Clone)] +pub struct ParentScope<'a> { + crate module: Module<'a>, + crate expansion: Mark, + crate legacy: LegacyScope<'a>, + crate derives: Vec, } -impl<'a> MacroBinding<'a> { - pub fn span(self) -> Span { - match self { - MacroBinding::Legacy(binding) => binding.span, - MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding.span, - } - } - - pub fn binding(self) -> &'a NameBinding<'a> { - match self { - MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding, - MacroBinding::Legacy(_) => panic!("unexpected MacroBinding::Legacy"), - } - } - - pub fn def_ignoring_ambiguity(self) -> Def { - match self { - MacroBinding::Legacy(binding) => Def::Macro(binding.def_id, MacroKind::Bang), - MacroBinding::Global(binding) | MacroBinding::Modern(binding) => - binding.def_ignoring_ambiguity(), - } - } +// Macro namespace is separated into two sub-namespaces, one for bang macros and +// one for attribute-like macros (attributes, derives). +// We ignore resolutions from one sub-namespace when searching names in scope for another. +fn sub_namespace_mismatch(requirement: Option, candidate: Option) -> bool { + #[derive(PartialEq)] + enum SubNS { Bang, AttrLike } + let sub_ns = |kind| match kind { + MacroKind::Bang => Some(SubNS::Bang), + MacroKind::Attr | MacroKind::Derive => Some(SubNS::AttrLike), + MacroKind::ProcMacroStub => None, + }; + let requirement = requirement.and_then(|kind| sub_ns(kind)); + let candidate = candidate.and_then(|kind| sub_ns(kind)); + // "No specific sub-namespace" means "matches anything" for both requirements and candidates. + candidate.is_some() && requirement.is_some() && candidate != requirement } -impl<'a> base::Resolver for Resolver<'a> { +impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() } @@ -128,16 +137,18 @@ impl<'a> base::Resolver for Resolver<'a> { self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData { module: Cell::new(module), def_index: module.def_id().unwrap().index, - legacy_scope: Cell::new(LegacyScope::Empty), - expansion: Cell::new(LegacyScope::Empty), + parent_legacy_scope: Cell::new(LegacyScope::Empty), + output_legacy_scope: Cell::new(LegacyScope::Empty), })); mark } fn eliminate_crate_var(&mut self, item: P) -> P { - struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>, Span); + struct EliminateCrateVar<'b, 'a: 'b, 'crateloader: 'a>( + &'b mut Resolver<'a, 'crateloader>, Span + ); - impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> { + impl<'a, 'b, 'crateloader> Folder for EliminateCrateVar<'a, 'b, 'crateloader> { fn fold_path(&mut self, path: ast::Path) -> ast::Path { match self.fold_qpath(None, path) { (None, path) => path, @@ -199,28 +210,31 @@ impl<'a> base::Resolver for Resolver<'a> { } let mut visitor = BuildReducedGraphVisitor { resolver: self, - legacy_scope: LegacyScope::Invocation(invocation), + current_legacy_scope: invocation.parent_legacy_scope.get(), expansion: mark, }; fragment.visit_with(&mut visitor); - invocation.expansion.set(visitor.legacy_scope); + invocation.output_legacy_scope.set(visitor.current_legacy_scope); } fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc) { let def_id = DefId { - krate: BUILTIN_MACROS_CRATE, + krate: CrateNum::BuiltinMacros, index: DefIndex::from_array_index(self.macro_map.len(), DefIndexAddressSpace::Low), }; let kind = ext.kind(); self.macro_map.insert(def_id, ext); let binding = self.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Def(Def::Macro(def_id, kind)), + kind: NameBindingKind::Def(Def::Macro(def_id, kind), false), span: DUMMY_SP, vis: ty::Visibility::Invisible, expansion: Mark::root(), }); - self.macro_prelude.insert(ident.name, binding); + if self.builtin_macros.insert(ident.name, binding).is_some() { + self.session.span_err(ident.span, + &format!("built-in macro `{}` was already defined", ident)); + } } fn resolve_imports(&mut self) { @@ -238,7 +252,7 @@ impl<'a> base::Resolver for Resolver<'a> { attr::mark_known(&attrs[i]); } - match self.macro_prelude.get(&name).cloned() { + match self.builtin_macros.get(&name).cloned() { Some(binding) => match *binding.get_macro(self) { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { return Some(attrs.remove(i)) @@ -274,7 +288,7 @@ impl<'a> base::Resolver for Resolver<'a> { } let trait_name = traits[j].segments[0].ident.name; let legacy_name = Symbol::intern(&format!("derive_{}", trait_name)); - if !self.macro_prelude.contains_key(&legacy_name) { + if !self.builtin_macros.contains_key(&legacy_name) { continue } let span = traits.remove(j).span; @@ -295,7 +309,8 @@ impl<'a> base::Resolver for Resolver<'a> { tokens.push(TokenTree::Token(path.span, tok).into()); } } - attrs[i].tokens = TokenTree::Delimited(attrs[i].span, Delimited { + let delim_span = DelimSpan::from_single(attrs[i].span); + attrs[i].tokens = TokenTree::Delimited(delim_span, Delimited { delim: token::Paren, tts: TokenStream::concat(tokens).into(), }).into(); @@ -315,41 +330,49 @@ impl<'a> base::Resolver for Resolver<'a> { None } - fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool) - -> Result>, Determinacy> { - let def = match invoc.kind { - InvocationKind::Attr { attr: None, .. } => return Ok(None), - _ => self.resolve_invoc_to_def(invoc, scope, force)?, + fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) + -> Result>, Determinacy> { + let (path, kind, derives_in_scope, together_with) = match invoc.kind { + InvocationKind::Attr { attr: None, .. } => + return Ok(None), + InvocationKind::Attr { attr: Some(ref attr), ref traits, together_with, .. } => + (&attr.path, MacroKind::Attr, traits.clone(), together_with), + InvocationKind::Bang { ref mac, .. } => + (&mac.node.path, MacroKind::Bang, Vec::new(), TogetherWith::None), + InvocationKind::Derive { ref path, .. } => + (path, MacroKind::Derive, Vec::new(), TogetherWith::None), }; - if let Def::Macro(_, MacroKind::ProcMacroStub) = def { - self.report_proc_macro_stub(invoc.span()); - return Err(Determinacy::Determined); + + let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope); + let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, force)?; + + if let Def::Macro(def_id, _) = def { + match together_with { + TogetherWith::Derive => + self.session.span_err(invoc.span(), + "macro attributes must be placed before `#[derive]`"), + TogetherWith::TestBench if !self.session.features_untracked().plugin => + self.session.span_err(invoc.span(), + "macro attributes cannot be used together with `#[test]` or `#[bench]`"), + _ => {} + } + self.macro_defs.insert(invoc.expansion_data.mark, def_id); + let normal_module_def_id = + self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; + self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, + normal_module_def_id); + invoc.expansion_data.mark.set_default_transparency(ext.default_transparency()); + invoc.expansion_data.mark.set_is_builtin(def_id.krate == CrateNum::BuiltinMacros); } - let def_id = def.def_id(); - - self.macro_defs.insert(invoc.expansion_data.mark, def_id); - let normal_module_def_id = - self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; - self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, - normal_module_def_id); - - self.unused_macros.remove(&def_id); - let ext = self.get_macro(def); - invoc.expansion_data.mark.set_default_transparency(ext.default_transparency()); - invoc.expansion_data.mark.set_is_builtin(def_id.krate == BUILTIN_MACROS_CRATE); + Ok(Some(ext)) } - fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) - -> Result, Determinacy> { - self.resolve_macro_to_def(scope, path, kind, force).and_then(|def| { - if let Def::Macro(_, MacroKind::ProcMacroStub) = def { - self.report_proc_macro_stub(path.span); - return Err(Determinacy::Determined); - } - self.unused_macros.remove(&def.def_id()); - Ok(self.get_macro(def)) - }) + fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark, + derives_in_scope: Vec, force: bool) + -> Result, Determinacy> { + let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope); + Ok(self.resolve_macro_to_def(path, kind, &parent_scope, force)?.1) } fn check_unused_macros(&self) { @@ -370,134 +393,113 @@ impl<'a> base::Resolver for Resolver<'a> { } } -impl<'a> Resolver<'a> { - fn report_proc_macro_stub(&self, span: Span) { - self.session.span_err(span, - "can't use a procedural macro from the same crate that defines it"); +impl<'a, 'cl> Resolver<'a, 'cl> { + pub fn dummy_parent_scope(&mut self) -> ParentScope<'a> { + self.invoc_parent_scope(Mark::root(), Vec::new()) } - fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool) - -> Result { - let (attr, traits, item) = match invoc.kind { - InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item), - InvocationKind::Bang { ref mac, .. } => { - return self.resolve_macro_to_def(scope, &mac.node.path, MacroKind::Bang, force); - } - InvocationKind::Derive { ref path, .. } => { - return self.resolve_macro_to_def(scope, path, MacroKind::Derive, force); - } - }; - - - let path = attr.as_ref().unwrap().path.clone(); - let mut determinacy = Determinacy::Determined; - match self.resolve_macro_to_def(scope, &path, MacroKind::Attr, force) { - Ok(def) => return Ok(def), - Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined, - Err(Determinacy::Determined) if force => return Err(Determinacy::Determined), - Err(Determinacy::Determined) => {} + fn invoc_parent_scope(&mut self, invoc_id: Mark, derives: Vec) -> ParentScope<'a> { + let invoc = self.invocations[&invoc_id]; + ParentScope { + module: invoc.module.get().nearest_item_scope(), + expansion: invoc_id.parent(), + legacy: invoc.parent_legacy_scope.get(), + derives, } + } - // Ok at this point we've determined that the `attr` above doesn't - // actually resolve at this time, so we may want to report an error. - // It could be the case, though, that `attr` won't ever resolve! If - // there's a custom derive that could be used it might declare `attr` as - // a custom attribute accepted by the derive. In this case we don't want - // to report this particular invocation as unresolved, but rather we'd - // want to move on to the next invocation. - // - // This loop here looks through all of the derive annotations in scope - // and tries to resolve them. If they themselves successfully resolve - // *and* the resolve mentions that this attribute's name is a registered - // custom attribute then we flag this attribute as known and update - // `invoc` above to point to the next invocation. - // - // By then returning `Undetermined` we should continue resolution to - // resolve the next attribute. - let attr_name = match path.segments.len() { - 1 => path.segments[0].ident.name, - _ => return Err(determinacy), - }; - for path in traits { - match self.resolve_macro(scope, path, MacroKind::Derive, force) { - Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext { - if inert_attrs.contains(&attr_name) { - // FIXME(jseyfried) Avoid `mem::replace` here. - let dummy_item = placeholder(AstFragmentKind::Items, ast::DUMMY_NODE_ID) - .make_items().pop().unwrap(); - let dummy_item = Annotatable::Item(dummy_item); - *item = mem::replace(item, dummy_item).map_attrs(|mut attrs| { - let inert_attr = attr.take().unwrap(); - attr::mark_known(&inert_attr); - if self.use_extern_macros { - *attr = expand::find_attr_invoc(&mut attrs); - } - attrs.push(inert_attr); - attrs - }); - return Err(Determinacy::Undetermined) - } - }, - Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined, - Err(Determinacy::Determined) => {} + fn resolve_macro_to_def( + &mut self, + path: &ast::Path, + kind: MacroKind, + parent_scope: &ParentScope<'a>, + force: bool, + ) -> Result<(Def, Lrc), Determinacy> { + let def = self.resolve_macro_to_def_inner(path, kind, parent_scope, force); + + // Report errors and enforce feature gates for the resolved macro. + if def != Err(Determinacy::Undetermined) { + // Do not report duplicated errors on every undetermined resolution. + for segment in &path.segments { + if let Some(args) = &segment.args { + self.session.span_err(args.span(), "generic arguments in macro path"); + } } } - Err(determinacy) - } + let def = def?; - fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) - -> Result { - if kind != MacroKind::Bang && path.segments.len() > 1 { - if !self.session.features_untracked().proc_macro_path_invoc { - emit_feature_err( - &self.session.parse_sess, - "proc_macro_path_invoc", - path.span, - GateIssue::Language, - "paths of length greater than one in macro invocations are \ - currently unstable", - ); + match def { + Def::Macro(def_id, macro_kind) => { + self.unused_macros.remove(&def_id); + if macro_kind == MacroKind::ProcMacroStub { + let msg = "can't use a procedural macro from the same crate that defines it"; + self.session.span_err(path.span, msg); + return Err(Determinacy::Determined); + } + } + Def::NonMacroAttr(attr_kind) => { + if kind == MacroKind::Attr { + let features = self.session.features_untracked(); + if attr_kind == NonMacroAttrKind::Custom { + assert!(path.segments.len() == 1); + let name = path.segments[0].ident.name.as_str(); + if name.starts_with("rustc_") { + if !features.rustc_attrs { + let msg = "unless otherwise specified, attributes with the prefix \ + `rustc_` are reserved for internal compiler diagnostics"; + feature_err(&self.session.parse_sess, "rustc_attrs", path.span, + GateIssue::Language, &msg).emit(); + } + } else if name.starts_with("derive_") { + if !features.custom_derive { + feature_err(&self.session.parse_sess, "custom_derive", path.span, + GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit(); + } + } else if !features.custom_attribute { + let msg = format!("The attribute `{}` is currently unknown to the \ + compiler and may have meaning added to it in the \ + future", path); + feature_err(&self.session.parse_sess, "custom_attribute", path.span, + GateIssue::Language, &msg).emit(); + } + } + } else { + // Not only attributes, but anything in macro namespace can result in + // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report + // an error for those cases. + let msg = format!("expected a macro, found {}", def.kind_name()); + self.session.span_err(path.span, &msg); + return Err(Determinacy::Determined); + } } + _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"), } - let def = self.resolve_macro_to_def_inner(scope, path, kind, force); - if def != Err(Determinacy::Undetermined) { - // Do not report duplicated errors on every undetermined resolution. - path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { - self.session.span_err(segment.args.as_ref().unwrap().span(), - "generic arguments in macro path"); - }); - } - def + Ok((def, self.get_macro(def))) } - pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path, - kind: MacroKind, force: bool) - -> Result { + pub fn resolve_macro_to_def_inner( + &mut self, + path: &ast::Path, + kind: MacroKind, + parent_scope: &ParentScope<'a>, + force: bool, + ) -> Result { let ast::Path { ref segments, span } = *path; let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); - let invocation = self.invocations[&scope]; - let module = invocation.module.get(); - self.current_module = if module.is_trait() { module.parent.unwrap() } else { module }; // Possibly apply the macro helper hack - if self.use_extern_macros && kind == MacroKind::Bang && path.len() == 1 && + if kind == MacroKind::Bang && path.len() == 1 && path[0].span.ctxt().outer().expn_info().map_or(false, |info| info.local_inner_macros) { let root = Ident::new(keywords::DollarCrate.name(), path[0].span); path.insert(0, root); } if path.len() > 1 { - if !self.use_extern_macros && self.gated_errors.insert(span) { - let msg = "non-ident macro paths are experimental"; - let feature = "use_extern_macros"; - emit_feature_err(&self.session.parse_sess, feature, span, GateIssue::Language, msg); - self.found_unresolved_macro = true; - return Err(Determinacy::Determined); - } - - let def = match self.resolve_path(&path, Some(MacroNS), false, span, CrateLint::No) { + let def = match self.resolve_path_with_parent_scope(None, &path, Some(MacroNS), + parent_scope, false, span, + CrateLint::No) { PathResult::NonModule(path_res) => match path_res.base_def() { Def::Err => Err(Determinacy::Determined), def @ _ => { @@ -517,163 +519,392 @@ impl<'a> Resolver<'a> { Err(Determinacy::Determined) }, }; - self.current_module.nearest_item_scope().macro_resolutions.borrow_mut() + parent_scope.module.macro_resolutions.borrow_mut() .push((path.into_boxed_slice(), span)); return def; } - let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false); - let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution { - Ok(Def::Macro(binding.def_id, MacroKind::Bang)) + let result = if let Some(legacy_binding) = self.resolve_legacy_scope(path[0], Some(kind), + parent_scope, false) { + Ok(legacy_binding.def()) } else { - match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, span) { - Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()), - Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), - Err(_) => { + match self.resolve_lexical_macro_path_segment(path[0], MacroNS, Some(kind), + parent_scope, false, force, span) { + Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()), + Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined), + Err(Determinacy::Determined) => { self.found_unresolved_macro = true; Err(Determinacy::Determined) } } }; - self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut() - .push((scope, path[0], kind, result.ok())); + parent_scope.module.legacy_macro_resolutions.borrow_mut() + .push((path[0], kind, parent_scope.clone(), result.ok())); result } - // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`) - pub fn resolve_lexical_macro_path_segment(&mut self, - mut ident: Ident, - ns: Namespace, - record_used: bool, - path_span: Span) - -> Result, Determinacy> { + // Resolve the initial segment of a non-global macro path + // (e.g. `foo` in `foo::bar!(); or `foo!();`). + // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during + // expansion and import resolution (perhaps they can be merged in the future). + crate fn resolve_lexical_macro_path_segment( + &mut self, + mut ident: Ident, + ns: Namespace, + kind: Option, + parent_scope: &ParentScope<'a>, + record_used: bool, + force: bool, + path_span: Span, + ) -> Result<(&'a NameBinding<'a>, FromPrelude), Determinacy> { + // General principles: + // 1. Not controlled (user-defined) names should have higher priority than controlled names + // built into the language or standard library. This way we can add new names into the + // language or standard library without breaking user code. + // 2. "Closed set" below means new names can appear after the current resolution attempt. + // Places to search (in order of decreasing priority): + // (Type NS) + // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet + // (open set, not controlled). + // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents + // (open, not controlled). + // 3. Extern prelude (closed, not controlled). + // 4. Tool modules (closed, controlled right now, but not in the future). + // 5. Standard library prelude (de-facto closed, controlled). + // 6. Language prelude (closed, controlled). + // (Macro NS) + // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents + // (open, not controlled). + // 2. `macro_use` prelude (open, the open part is from macro expansions, not controlled). + // 2a. User-defined prelude from macro-use + // (open, the open part is from macro expansions, not controlled). + // 2b. Standard library prelude is currently implemented as `macro-use` (closed, controlled) + // 3. Language prelude: builtin macros (closed, controlled, except for legacy plugins). + // 4. Language prelude: builtin attributes (closed, controlled). + // N (unordered). Derive helpers (open, not controlled). All ambiguities with other names + // are currently reported as errors. They should be higher in priority than preludes + // and maybe even names in modules according to the "general principles" above. They + // also should be subject to restricted shadowing because are effectively produced by + // derives (you need to resolve the derive first to add helpers into scope), but they + // should be available before the derive is expanded for compatibility. + // It's mess in general, so we are being conservative for now. + + assert!(ns == TypeNS || ns == MacroNS); + assert!(force || !record_used); // `record_used` implies `force` ident = ident.modern(); - let mut module = Some(self.current_module); - let mut potential_illegal_shadower = Err(Determinacy::Determined); - let determinacy = - if record_used { Determinacy::Determined } else { Determinacy::Undetermined }; + + // This is *the* result, resolution from the scope closest to the resolved identifier. + // However, sometimes this result is "weak" because it comes from a glob import or + // a macro expansion, and in this case it cannot shadow names from outer scopes, e.g. + // mod m { ... } // solution in outer scope + // { + // use prefix::*; // imports another `m` - innermost solution + // // weak, cannot shadow the outer `m`, need to report ambiguity error + // m::mac!(); + // } + // So we have to save the innermost solution and continue searching in outer scopes + // to detect potential ambiguities. + let mut innermost_result: Option<(&NameBinding, FromPrelude)> = None; + + enum WhereToResolve<'a> { + Module(Module<'a>), + MacroUsePrelude, + BuiltinMacros, + BuiltinAttrs, + DeriveHelpers, + ExternPrelude, + ToolPrelude, + StdLibPrelude, + BuiltinTypes, + } + + // Go through all the scopes and try to resolve the name. + let mut where_to_resolve = WhereToResolve::Module(parent_scope.module); + let mut use_prelude = !parent_scope.module.no_implicit_prelude; loop { - let orig_current_module = self.current_module; - let result = if let Some(module) = module { - self.current_module = module; // Lexical resolutions can never be a privacy error. - // Since expanded macros may not shadow the lexical scope and - // globs may not shadow global macros (both enforced below), - // we resolve with restricted shadowing (indicated by the penultimate argument). - self.resolve_ident_in_module_unadjusted( - module, ident, ns, true, record_used, path_span, - ).map(MacroBinding::Modern) - } else { - self.macro_prelude.get(&ident.name).cloned().ok_or(determinacy) - .map(MacroBinding::Global) + let result = match where_to_resolve { + WhereToResolve::Module(module) => { + let orig_current_module = mem::replace(&mut self.current_module, module); + let binding = self.resolve_ident_in_module_unadjusted( + ModuleOrUniformRoot::Module(module), + ident, + ns, + true, + record_used, + path_span, + ); + self.current_module = orig_current_module; + binding.map(|binding| (binding, FromPrelude(false))) + } + WhereToResolve::MacroUsePrelude => { + match self.macro_use_prelude.get(&ident.name).cloned() { + Some(binding) => Ok((binding, FromPrelude(true))), + None => Err(Determinacy::Determined), + } + } + WhereToResolve::BuiltinMacros => { + match self.builtin_macros.get(&ident.name).cloned() { + Some(binding) => Ok((binding, FromPrelude(true))), + None => Err(Determinacy::Determined), + } + } + WhereToResolve::BuiltinAttrs => { + if is_builtin_attr_name(ident.name) { + let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin), + ty::Visibility::Public, ident.span, Mark::root()) + .to_name_binding(self.arenas); + Ok((binding, FromPrelude(true))) + } else { + Err(Determinacy::Determined) + } + } + WhereToResolve::DeriveHelpers => { + let mut result = Err(Determinacy::Determined); + for derive in &parent_scope.derives { + let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope }; + if let Ok((_, ext)) = self.resolve_macro_to_def(derive, MacroKind::Derive, + &parent_scope, force) { + if let SyntaxExtension::ProcMacroDerive(_, helper_attrs, _) = &*ext { + if helper_attrs.contains(&ident.name) { + let binding = + (Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper), + ty::Visibility::Public, derive.span, Mark::root()) + .to_name_binding(self.arenas); + result = Ok((binding, FromPrelude(false))); + break; + } + } + } + } + result + } + WhereToResolve::ExternPrelude => { + if use_prelude && self.extern_prelude.contains(&ident.name) { + let crate_id = + self.crate_loader.process_path_extern(ident.name, ident.span); + let crate_root = + self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + self.populate_module_if_necessary(crate_root); + + let binding = (crate_root, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + Ok((binding, FromPrelude(true))) + } else { + Err(Determinacy::Determined) + } + } + WhereToResolve::ToolPrelude => { + if use_prelude && is_known_tool(ident.name) { + let binding = (Def::ToolMod, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + Ok((binding, FromPrelude(true))) + } else { + Err(Determinacy::Determined) + } + } + WhereToResolve::StdLibPrelude => { + let mut result = Err(Determinacy::Determined); + if use_prelude { + if let Some(prelude) = self.prelude { + if let Ok(binding) = self.resolve_ident_in_module_unadjusted( + ModuleOrUniformRoot::Module(prelude), + ident, + ns, + false, + false, + path_span, + ) { + result = Ok((binding, FromPrelude(true))); + } + } + } + result + } + WhereToResolve::BuiltinTypes => { + if let Some(prim_ty) = + self.primitive_type_table.primitive_types.get(&ident.name).cloned() { + let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + Ok((binding, FromPrelude(true))) + } else { + Err(Determinacy::Determined) + } + } }; - self.current_module = orig_current_module; - match result.map(MacroBinding::binding) { - Ok(binding) => { + macro_rules! continue_search { () => { + where_to_resolve = match where_to_resolve { + WhereToResolve::Module(module) => { + match self.hygienic_lexical_parent(module, &mut ident.span) { + Some(parent_module) => WhereToResolve::Module(parent_module), + None => { + use_prelude = !module.no_implicit_prelude; + if ns == MacroNS { + WhereToResolve::MacroUsePrelude + } else { + WhereToResolve::ExternPrelude + } + } + } + } + WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros, + WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs, + WhereToResolve::BuiltinAttrs => WhereToResolve::DeriveHelpers, + WhereToResolve::DeriveHelpers => break, // nowhere else to search + WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude, + WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude, + WhereToResolve::StdLibPrelude => WhereToResolve::BuiltinTypes, + WhereToResolve::BuiltinTypes => break, // nowhere else to search + }; + + continue; + }} + + match result { + Ok(result) => { + if sub_namespace_mismatch(kind, result.0.macro_kind()) { + continue_search!(); + } + if !record_used { - return result; + return Ok(result); } - if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower { - if shadower.def() != binding.def() { - let name = ident.name; + + if let Some(innermost_result) = innermost_result { + // Found another solution, if the first one was "weak", report an error. + let (def, innermost_def) = (result.0.def(), innermost_result.0.def()); + if def != innermost_def && + (innermost_result.0.is_glob_import() || + innermost_result.0.may_appear_after(parent_scope.expansion, result.0) || + innermost_def == Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper) || + def == Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)) { self.ambiguity_errors.push(AmbiguityError { - span: path_span, - name, - b1: shadower, - b2: binding, - lexical: true, + ident, + b1: innermost_result.0, + b2: result.0, }); - return potential_illegal_shadower; + return Ok(innermost_result); } - } - if binding.is_glob_import() || binding.expansion != Mark::root() { - potential_illegal_shadower = result; } else { - return result; + // Found the first solution. + innermost_result = Some(result); } + + continue_search!(); }, - Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined), - Err(Determinacy::Determined) => {} + Err(Determinacy::Determined) => { + continue_search!(); + } + Err(Determinacy::Undetermined) => return Err(Determinacy::determined(force)), } + } - module = match module { - Some(module) => self.hygienic_lexical_parent(module, &mut ident.span), - None => return potential_illegal_shadower, - } + // The first found solution was the only one, return it. + if let Some(innermost_result) = innermost_result { + return Ok(innermost_result); + } + + let determinacy = Determinacy::determined(force); + if determinacy == Determinacy::Determined && kind == Some(MacroKind::Attr) { + // For single-segment attributes interpret determinate "no resolution" as a custom + // attribute. (Lexical resolution implies the first segment and attr kind should imply + // the last segment, so we are certainly working with a single-segment attribute here.) + assert!(ns == MacroNS); + let binding = (Def::NonMacroAttr(NonMacroAttrKind::Custom), + ty::Visibility::Public, ident.span, Mark::root()) + .to_name_binding(self.arenas); + Ok((binding, FromPrelude(true))) + } else { + Err(determinacy) } } - pub fn resolve_legacy_scope(&mut self, - mut scope: &'a Cell>, - ident: Ident, - record_used: bool) - -> Option> { + fn resolve_legacy_scope( + &mut self, + ident: Ident, + kind: Option, + parent_scope: &ParentScope<'a>, + record_used: bool, + ) -> Option<&'a NameBinding<'a>> { + if sub_namespace_mismatch(kind, Some(MacroKind::Bang)) { + return None; + } + let ident = ident.modern(); - let mut possible_time_travel = None; - let mut relative_depth: u32 = 0; - let mut binding = None; + + // This is *the* result, resolution from the scope closest to the resolved identifier. + // However, sometimes this result is "weak" because it comes from a macro expansion, + // and in this case it cannot shadow names from outer scopes, e.g. + // macro_rules! m { ... } // solution in outer scope + // { + // define_m!(); // generates another `macro_rules! m` - innermost solution + // // weak, cannot shadow the outer `m`, need to report ambiguity error + // m!(); + // } + // So we have to save the innermost solution and continue searching in outer scopes + // to detect potential ambiguities. + let mut innermost_result: Option<&NameBinding> = None; + + // Go through all the scopes and try to resolve the name. + let mut where_to_resolve = parent_scope.legacy; loop { - match scope.get() { - LegacyScope::Empty => break, - LegacyScope::Expansion(invocation) => { - match invocation.expansion.get() { - LegacyScope::Invocation(_) => scope.set(invocation.legacy_scope.get()), - LegacyScope::Empty => { - if possible_time_travel.is_none() { - possible_time_travel = Some(scope); - } - scope = &invocation.legacy_scope; - } - _ => { - relative_depth += 1; - scope = &invocation.expansion; - } + let result = match where_to_resolve { + LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => + Some(legacy_binding.binding), + _ => None, + }; + + macro_rules! continue_search { () => { + where_to_resolve = match where_to_resolve { + LegacyScope::Empty => break, // nowhere else to search + LegacyScope::Binding(binding) => binding.parent_legacy_scope, + LegacyScope::Invocation(invocation) => invocation.output_legacy_scope.get(), + LegacyScope::Uninitialized => unreachable!(), + }; + + continue; + }} + + match result { + Some(result) => { + if !record_used { + return Some(result); } - } - LegacyScope::Invocation(invocation) => { - relative_depth = relative_depth.saturating_sub(1); - scope = &invocation.legacy_scope; - } - LegacyScope::Binding(potential_binding) => { - if potential_binding.ident == ident { - if (!self.use_extern_macros || record_used) && relative_depth > 0 { - self.disallowed_shadowing.push(potential_binding); + + if let Some(innermost_result) = innermost_result { + // Found another solution, if the first one was "weak", report an error. + if result.def() != innermost_result.def() && + innermost_result.may_appear_after(parent_scope.expansion, result) { + self.ambiguity_errors.push(AmbiguityError { + ident, + b1: innermost_result, + b2: result, + }); + return Some(innermost_result); } - binding = Some(potential_binding); - break + } else { + // Found the first solution. + innermost_result = Some(result); } - scope = &potential_binding.parent; - } - }; - } - - let binding = if let Some(binding) = binding { - MacroBinding::Legacy(binding) - } else if let Some(binding) = self.macro_prelude.get(&ident.name).cloned() { - if !self.use_extern_macros { - self.record_use(ident, MacroNS, binding, DUMMY_SP); - } - MacroBinding::Global(binding) - } else { - return None; - }; - if !self.use_extern_macros { - if let Some(scope) = possible_time_travel { - // Check for disallowed shadowing later - self.lexical_macro_resolutions.push((ident, scope)); + continue_search!(); + } + None => { + continue_search!(); + } } } - Some(binding) + // The first found solution was the only one (or there was no solution at all), return it. + innermost_result } pub fn finalize_current_module_macro_resolutions(&mut self) { let module = self.current_module; for &(ref path, span) in module.macro_resolutions.borrow().iter() { - match self.resolve_path(&path, Some(MacroNS), true, span, CrateLint::No) { + match self.resolve_path(None, &path, Some(MacroNS), true, span, CrateLint::No) { PathResult::NonModule(_) => {}, PathResult::Failed(span, msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); @@ -682,16 +913,20 @@ impl<'a> Resolver<'a> { } } - for &(mark, ident, kind, def) in module.legacy_macro_resolutions.borrow().iter() { + let legacy_macro_resolutions = + mem::replace(&mut *module.legacy_macro_resolutions.borrow_mut(), Vec::new()); + for (ident, kind, parent_scope, def) in legacy_macro_resolutions { let span = ident.span; - let legacy_scope = &self.invocations[&mark].legacy_scope; - let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident, true); - let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, span); - - let check_consistency = |this: &Self, binding: MacroBinding| { + let legacy_resolution = self.resolve_legacy_scope( + ident, Some(kind), &parent_scope, true + ); + let resolution = self.resolve_lexical_macro_path_segment( + ident, MacroNS, Some(kind), &parent_scope, true, true, span + ); + + let check_consistency = |this: &Self, new_def: Def| { if let Some(def) = def { - if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() && - binding.def_ignoring_ambiguity() != def { + if this.ambiguity_errors.is_empty() && new_def != def && new_def != Def::Err { // Make sure compilation does not succeed if preferred macro resolution // has changed after the macro had been expanded. In theory all such // situations should be reported as ambiguity errors, so this is span-bug. @@ -710,14 +945,6 @@ impl<'a> Resolver<'a> { }; match (legacy_resolution, resolution) { - (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => { - let msg1 = format!("`{}` could refer to the macro defined here", ident); - let msg2 = format!("`{}` could also refer to the macro imported here", ident); - self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident)) - .span_note(legacy_binding.span, &msg1) - .span_note(binding.span, &msg2) - .emit(); - }, (None, Err(_)) => { assert!(def.is_none()); let bang = if kind == MacroKind::Bang { "!" } else { "" }; @@ -727,28 +954,48 @@ impl<'a> Resolver<'a> { self.suggest_macro_name(&ident.as_str(), kind, &mut err, span); err.emit(); }, - (Some(MacroBinding::Modern(_)), _) | (_, Ok(MacroBinding::Legacy(_))) => { - span_bug!(span, "impossible macro resolution result"); - } + (Some(legacy_binding), Ok((binding, FromPrelude(from_prelude)))) + if legacy_binding.def() != binding.def_ignoring_ambiguity() && + (!from_prelude || + legacy_binding.may_appear_after(parent_scope.expansion, binding)) => { + self.report_ambiguity_error(ident, legacy_binding, binding); + }, + // OK, non-macro-expanded legacy wins over prelude even if defs are different + // Also, legacy and modern can co-exist if their defs are same + (Some(legacy_binding), Ok(_)) | // OK, unambiguous resolution - (Some(binding), Err(_)) | (None, Ok(binding)) | - // OK, legacy wins over global even if their definitions are different - (Some(binding @ MacroBinding::Legacy(_)), Ok(MacroBinding::Global(_))) | - // OK, modern wins over global even if their definitions are different - (Some(MacroBinding::Global(_)), Ok(binding @ MacroBinding::Modern(_))) => { - check_consistency(self, binding); + (Some(legacy_binding), Err(_)) => { + check_consistency(self, legacy_binding.def()); } - (Some(MacroBinding::Global(binding1)), Ok(MacroBinding::Global(binding2))) => { - if binding1.def() != binding2.def() { - span_bug!(span, "mismatch between same global macro resolutions"); + // OK, unambiguous resolution + (None, Ok((binding, FromPrelude(from_prelude)))) => { + check_consistency(self, binding.def_ignoring_ambiguity()); + if from_prelude { + self.record_use(ident, MacroNS, binding); } - check_consistency(self, MacroBinding::Global(binding1)); - - self.record_use(ident, MacroNS, binding1, span); - self.err_if_macro_use_proc_macro(ident.name, span, binding1); - }, + } }; } + + let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new()); + for (ident, parent_scope) in builtin_attrs { + let resolve_legacy = |this: &mut Self| this.resolve_legacy_scope( + ident, Some(MacroKind::Attr), &parent_scope, true + ); + let resolve_modern = |this: &mut Self| this.resolve_lexical_macro_path_segment( + ident, MacroNS, Some(MacroKind::Attr), &parent_scope, true, true, ident.span + ).map(|(binding, _)| binding).ok(); + + if let Some(binding) = resolve_legacy(self).or_else(|| resolve_modern(self)) { + if binding.def_ignoring_ambiguity() != + Def::NonMacroAttr(NonMacroAttrKind::Builtin) { + let builtin_binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin), + ty::Visibility::Public, ident.span, Mark::root()) + .to_name_binding(self.arenas); + self.report_ambiguity_error(ident, binding, builtin_binding); + } + } + } } fn suggest_macro_name(&mut self, name: &str, kind: MacroKind, @@ -760,21 +1007,13 @@ impl<'a> Resolver<'a> { None // Then check global macros. }.or_else(|| { - // FIXME: get_macro needs an &mut Resolver, can we do it without cloning? - let macro_prelude = self.macro_prelude.clone(); - let names = macro_prelude.iter().filter_map(|(name, binding)| { - if binding.get_macro(self).kind() == kind { - Some(name) - } else { - None - } + let names = self.builtin_macros.iter().chain(self.macro_use_prelude.iter()) + .filter_map(|(name, binding)| { + if binding.macro_kind() == Some(kind) { Some(name) } else { None } }); find_best_match_for_name(names, name, None) // Then check modules. }).or_else(|| { - if !self.use_extern_macros { - return None; - } let is_macro = |def| { if let Def::Macro(_, def_kind) = def { def_kind == kind @@ -789,9 +1028,19 @@ impl<'a> Resolver<'a> { if let Some(suggestion) = suggestion { if suggestion != name { if let MacroKind::Bang = kind { - err.span_suggestion(span, "you could try the macro", suggestion.to_string()); + err.span_suggestion_with_applicability( + span, + "you could try the macro", + suggestion.to_string(), + Applicability::MaybeIncorrect + ); } else { - err.span_suggestion(span, "try", suggestion.to_string()); + err.span_suggestion_with_applicability( + span, + "try", + suggestion.to_string(), + Applicability::MaybeIncorrect + ); } } else { err.help("have you added the `#[macro_use]` on the module/import?"); @@ -811,8 +1060,8 @@ impl<'a> Resolver<'a> { arenas.alloc_invocation_data(InvocationData { def_index: invoc.def_index, module: Cell::new(graph_root), - expansion: Cell::new(LegacyScope::Empty), - legacy_scope: Cell::new(LegacyScope::Empty), + parent_legacy_scope: Cell::new(LegacyScope::Uninitialized), + output_legacy_scope: Cell::new(LegacyScope::Uninitialized), }) }); }; @@ -827,7 +1076,7 @@ impl<'a> Resolver<'a> { pub fn define_macro(&mut self, item: &ast::Item, expansion: Mark, - legacy_scope: &mut LegacyScope<'a>) { + current_legacy_scope: &mut LegacyScope<'a>) { self.local_macro_def_scopes.insert(item.id, self.current_module); let ident = item.ident; if ident.name == "macro_rules" { @@ -844,19 +1093,23 @@ impl<'a> Resolver<'a> { if def.legacy { let ident = ident.modern(); self.macro_names.insert(ident); - *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding { - parent: Cell::new(*legacy_scope), ident: ident, def_id: def_id, span: item.span, - })); let def = Def::Macro(def_id, MacroKind::Bang); + let vis = ty::Visibility::Invisible; // Doesn't matter for legacy bindings + let binding = (def, vis, item.span, expansion).to_name_binding(self.arenas); + let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding { + parent_legacy_scope: *current_legacy_scope, binding, ident + }); + *current_legacy_scope = LegacyScope::Binding(legacy_binding); self.all_macros.insert(ident.name, def); if attr::contains_name(&item.attrs, "macro_export") { - self.macro_exports.push(Export { - ident: ident.modern(), - def: def, - vis: ty::Visibility::Public, - span: item.span, - }); + let module = self.graph_root; + let vis = ty::Visibility::Public; + self.define(module, ident, MacroNS, + (def, vis, item.span, expansion, IsMacroExport)); } else { + if !attr::contains_name(&item.attrs, "rustc_doc_only_macro") { + self.check_reserved_macro_name(ident, MacroNS); + } self.unused_macros.insert(def_id); } } else { @@ -870,64 +1123,6 @@ impl<'a> Resolver<'a> { } } - /// Error if `ext` is a Macros 1.1 procedural macro being imported by `#[macro_use]` - fn err_if_macro_use_proc_macro(&mut self, name: Name, use_span: Span, - binding: &NameBinding<'a>) { - let krate = binding.def().def_id().krate; - - // Plugin-based syntax extensions are exempt from this check - if krate == BUILTIN_MACROS_CRATE { return; } - - let ext = binding.get_macro(self); - - match *ext { - // If `ext` is a procedural macro, check if we've already warned about it - SyntaxExtension::AttrProcMacro(..) | SyntaxExtension::ProcMacro { .. } => - if !self.warned_proc_macros.insert(name) { return; }, - _ => return, - } - - let warn_msg = match *ext { - SyntaxExtension::AttrProcMacro(..) => - "attribute procedural macros cannot be imported with `#[macro_use]`", - SyntaxExtension::ProcMacro { .. } => - "procedural macros cannot be imported with `#[macro_use]`", - _ => return, - }; - - let def_id = self.current_module.normal_ancestor_id; - let node_id = self.definitions.as_local_node_id(def_id).unwrap(); - - self.proc_mac_errors.push(ProcMacError { - crate_name: self.cstore.crate_name_untracked(krate), - name, - module: node_id, - use_span, - warn_msg, - }); - } - - pub fn report_proc_macro_import(&mut self, krate: &ast::Crate) { - for err in self.proc_mac_errors.drain(..) { - let (span, found_use) = ::UsePlacementFinder::check(krate, err.module); - - if let Some(span) = span { - let found_use = if found_use { "" } else { "\n" }; - self.session.struct_span_err(err.use_span, err.warn_msg) - .span_suggestion( - span, - "instead, import the procedural macro like any other item", - format!("use {}::{};{}", err.crate_name, err.name, found_use), - ).emit(); - } else { - self.session.struct_span_err(err.use_span, err.warn_msg) - .help(&format!("instead, import the procedural macro like any other item: \ - `use {}::{};`", err.crate_name, err.name)) - .emit(); - } - } - } - fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) { if !self.session.features_untracked().custom_derive { let sess = &self.session.parse_sess; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index afeb8c122b..dc4a76db69 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -10,7 +10,7 @@ use self::ImportDirectiveSubclass::*; -use {AmbiguityError, CrateLint, Module, PerNS}; +use {AmbiguityError, CrateLint, Module, ModuleOrUniformRoot, PerNS}; use Namespace::{self, TypeNS, MacroNS}; use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; use Resolver; @@ -24,16 +24,18 @@ use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CR use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::def::*; use rustc::session::DiagnosticMessageId; -use rustc::util::nodemap::{FxHashMap, FxHashSet}; +use rustc::util::nodemap::FxHashSet; use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; use syntax::symbol::keywords; use syntax::util::lev_distance::find_best_match_for_name; -use syntax_pos::Span; +use syntax_pos::{MultiSpan, Span}; use std::cell::{Cell, RefCell}; +use std::collections::BTreeMap; +use std::fmt::Write; use std::{mem, ptr}; /// Contains data for specific types of import directives. @@ -85,11 +87,19 @@ pub struct ImportDirective<'a> { pub parent: Module<'a>, pub module_path: Vec, - pub imported_module: Cell>>, // the resolution of `module_path` + /// The resolution of `module_path`. + pub imported_module: Cell>>, pub subclass: ImportDirectiveSubclass<'a>, pub vis: Cell, pub expansion: Mark, pub used: Cell, + + /// Whether this import is a "canary" for the `uniform_paths` feature, + /// i.e. `use x::...;` results in an `use self::x as _;` canary. + /// This flag affects diagnostics: an error is reported if and only if + /// the import resolves successfully and an external crate with the same + /// name (`x` above) also exists; any resolution failures are ignored. + pub is_uniform_paths_canary: bool, } impl<'a> ImportDirective<'a> { @@ -123,7 +133,7 @@ impl<'a> NameResolution<'a> { } } -impl<'a> Resolver<'a> { +impl<'a, 'crateloader> Resolver<'a, 'crateloader> { fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace) -> &'a RefCell> { *module.resolutions.borrow_mut().entry((ident.modern(), ns)) @@ -133,38 +143,126 @@ impl<'a> Resolver<'a> { /// Attempts to resolve `ident` in namespaces `ns` of `module`. /// Invariant: if `record_used` is `Some`, expansion and import resolution must be complete. pub fn resolve_ident_in_module_unadjusted(&mut self, - module: Module<'a>, + module: ModuleOrUniformRoot<'a>, ident: Ident, ns: Namespace, restricted_shadowing: bool, record_used: bool, path_span: Span) -> Result<&'a NameBinding<'a>, Determinacy> { + let module = match module { + ModuleOrUniformRoot::Module(module) => module, + ModuleOrUniformRoot::UniformRoot(root) => { + // HACK(eddyb): `resolve_path` uses `keywords::Invalid` to indicate + // paths of length 0, and currently these are relative `use` paths. + let can_be_relative = !ident.is_path_segment_keyword() && + root == keywords::Invalid.name(); + if can_be_relative { + // Relative paths should only get here if the feature-gate is on. + assert!(self.session.rust_2018() && + self.session.features_untracked().uniform_paths); + + // Try first to resolve relatively. + let mut ctxt = ident.span.ctxt().modern(); + let self_module = self.resolve_self(&mut ctxt, self.current_module); + + let binding = self.resolve_ident_in_module_unadjusted( + ModuleOrUniformRoot::Module(self_module), + ident, + ns, + restricted_shadowing, + record_used, + path_span, + ); + + // FIXME(eddyb) This may give false negatives, specifically + // if a crate with the same name is found in `extern_prelude`, + // preventing the check below this one from returning `binding` + // in all cases. + // + // That is, if there's no crate with the same name, `binding` + // is always returned, which is the result of doing the exact + // same lookup of `ident`, in the `self` module. + // But when a crate does exist, it will get chosen even when + // macro expansion could result in a success from the lookup + // in the `self` module, later on. + // + // NB. This is currently alleviated by the "ambiguity canaries" + // (see `is_uniform_paths_canary`) that get introduced for the + // maybe-relative imports handled here: if the false negative + // case were to arise, it would *also* cause an ambiguity error. + if binding.is_ok() { + return binding; + } + + // Fall back to resolving to an external crate. + if !( + ns == TypeNS && + !ident.is_path_segment_keyword() && + self.extern_prelude.contains(&ident.name) + ) { + // ... unless the crate name is not in the `extern_prelude`. + return binding; + } + } + + let crate_root = if + ns == TypeNS && + root != keywords::Extern.name() && + ( + ident.name == keywords::Crate.name() || + ident.name == keywords::DollarCrate.name() + ) + { + self.resolve_crate_root(ident) + } else if + ns == TypeNS && + !ident.is_path_segment_keyword() && + self.extern_prelude.contains(&ident.name) + { + let crate_id = + self.crate_loader.process_path_extern(ident.name, ident.span); + self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) + } else { + return Err(Determined); + }; + self.populate_module_if_necessary(crate_root); + let binding = (crate_root, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + return Ok(binding); + } + }; + self.populate_module_if_necessary(module); let resolution = self.resolution(module, ident, ns) .try_borrow_mut() .map_err(|_| Determined)?; // This happens when there is a cycle of imports + if let Some(binding) = resolution.binding { + if !restricted_shadowing && binding.expansion != Mark::root() { + if let NameBindingKind::Def(_, true) = binding.kind { + self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); + } + } + } + if record_used { if let Some(binding) = resolution.binding { if let Some(shadowed_glob) = resolution.shadowed_glob { - let name = ident.name; // Forbid expanded shadowing to avoid time travel. if restricted_shadowing && binding.expansion != Mark::root() && ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing binding.def() != shadowed_glob.def() { self.ambiguity_errors.push(AmbiguityError { - span: path_span, - name, - lexical: false, + ident, b1: binding, b2: shadowed_glob, }); } } - if self.record_use(ident, ns, binding, path_span) { + if self.record_use(ident, ns, binding) { return Ok(self.dummy_binding); } if !self.is_accessible(binding.vis) { @@ -213,6 +311,14 @@ impl<'a> Resolver<'a> { // if it cannot be shadowed by some new item/import expanded from a macro. // This happens either if there are no unexpanded macros, or expanded names cannot // shadow globs (that happens in macro namespace or with restricted shadowing). + // + // Additionally, any macro in any module can plant names in the root module if it creates + // `macro_export` macros, so the root module effectively has unresolved invocations if any + // module has unresolved invocations. + // However, it causes resolution/expansion to stuck too often (#53144), so, to make + // progress, we have to ignore those potential unresolved invocations from other modules + // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted + // shadowing is enabled, see `macro_expanded_macro_export_errors`). let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty(); if let Some(binding) = resolution.binding { if !unexpanded_macros || ns == MacroNS || restricted_shadowing { @@ -246,7 +352,11 @@ impl<'a> Resolver<'a> { if !self.is_accessible(glob_import.vis.get()) { continue } - let module = unwrap_or!(glob_import.imported_module.get(), return Err(Undetermined)); + let module = match glob_import.imported_module.get() { + Some(ModuleOrUniformRoot::Module(module)) => module, + Some(ModuleOrUniformRoot::UniformRoot(_)) => continue, + None => return Err(Undetermined), + }; let (orig_current_module, mut ident) = (self.current_module, ident.modern()); match ident.span.glob_adjust(module.expansion, glob_import.span.ctxt().modern()) { Some(Some(def)) => self.current_module = self.macro_def_scope(def), @@ -254,7 +364,12 @@ impl<'a> Resolver<'a> { None => continue, }; let result = self.resolve_ident_in_module_unadjusted( - module, ident, ns, false, false, path_span, + ModuleOrUniformRoot::Module(module), + ident, + ns, + false, + false, + path_span, ); self.current_module = orig_current_module; @@ -279,7 +394,8 @@ impl<'a> Resolver<'a> { root_span: Span, root_id: NodeId, vis: ty::Visibility, - expansion: Mark) { + expansion: Mark, + is_uniform_paths_canary: bool) { let current_module = self.current_module; let directive = self.arenas.alloc_import_directive(ImportDirective { parent: current_module, @@ -293,8 +409,11 @@ impl<'a> Resolver<'a> { vis: Cell::new(vis), expansion, used: Cell::new(false), + is_uniform_paths_canary, }); + debug!("add_import_directive({:?})", directive); + self.indeterminate_imports.push(directive); match directive.subclass { SingleImport { target, type_ns_only, .. } => { @@ -341,6 +460,16 @@ impl<'a> Resolver<'a> { }) } + crate fn check_reserved_macro_name(&self, ident: Ident, ns: Namespace) { + // Reserve some names that are not quite covered by the general check + // performed on `Resolver::builtin_attrs`. + if ns == MacroNS && + (ident.name == "cfg" || ident.name == "cfg_attr" || ident.name == "derive") { + self.session.span_err(ident.span, + &format!("name `{}` is reserved in macro namespace", ident)); + } + } + // Define the name or return the existing binding if there is a collision. pub fn try_define(&mut self, module: Module<'a>, @@ -348,6 +477,7 @@ impl<'a> Resolver<'a> { ns: Namespace, binding: &'a NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> { + self.check_reserved_macro_name(ident, ns); self.update_resolution(module, ident, ns, |this, resolution| { if let Some(old_binding) = resolution.binding { if binding.is_glob_import() { @@ -368,6 +498,18 @@ impl<'a> Resolver<'a> { resolution.binding = Some(binding); resolution.shadowed_glob = Some(old_binding); } + } else if let (&NameBindingKind::Def(_, true), &NameBindingKind::Def(_, true)) = + (&old_binding.kind, &binding.kind) { + + this.session.buffer_lint_with_diagnostic( + DUPLICATE_MACRO_EXPORTS, + CRATE_NODE_ID, + binding.span, + &format!("a macro named `{}` has already been exported", ident), + BuiltinLintDiagnostics::DuplicatedMacroExports( + ident, old_binding.span, binding.span)); + + resolution.binding = Some(binding); } else { return Err(old_binding); } @@ -393,7 +535,7 @@ impl<'a> Resolver<'a> { // If the resolution becomes a success, define it in the module's glob importers. fn update_resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F) -> T - where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T + where F: FnOnce(&mut Resolver<'a, 'crateloader>, &mut NameResolution<'a>) -> T { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. @@ -444,30 +586,30 @@ impl<'a> Resolver<'a> { } } -pub struct ImportResolver<'a, 'b: 'a> { - pub resolver: &'a mut Resolver<'b>, +pub struct ImportResolver<'a, 'b: 'a, 'c: 'a + 'b> { + pub resolver: &'a mut Resolver<'b, 'c>, } -impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> { - type Target = Resolver<'b>; - fn deref(&self) -> &Resolver<'b> { +impl<'a, 'b: 'a, 'c: 'a + 'b> ::std::ops::Deref for ImportResolver<'a, 'b, 'c> { + type Target = Resolver<'b, 'c>; + fn deref(&self) -> &Resolver<'b, 'c> { self.resolver } } -impl<'a, 'b: 'a> ::std::ops::DerefMut for ImportResolver<'a, 'b> { - fn deref_mut(&mut self) -> &mut Resolver<'b> { +impl<'a, 'b: 'a, 'c: 'a + 'b> ::std::ops::DerefMut for ImportResolver<'a, 'b, 'c> { + fn deref_mut(&mut self) -> &mut Resolver<'b, 'c> { self.resolver } } -impl<'a, 'b: 'a> ty::DefIdTree for &'a ImportResolver<'a, 'b> { +impl<'a, 'b: 'a, 'c: 'a + 'b> ty::DefIdTree for &'a ImportResolver<'a, 'b, 'c> { fn parent(self, id: DefId) -> Option { self.resolver.parent(id) } } -impl<'a, 'b:'a> ImportResolver<'a, 'b> { +impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // Import resolution // // This is a fixed-point algorithm. We resolve imports until our efforts @@ -496,11 +638,65 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { self.finalize_resolutions_in(module); } + struct UniformPathsCanaryResults<'a> { + name: Name, + module_scope: Option<&'a NameBinding<'a>>, + block_scopes: Vec<&'a NameBinding<'a>>, + } + + // Collect all tripped `uniform_paths` canaries separately. + let mut uniform_paths_canaries: BTreeMap< + (Span, NodeId, Namespace), + UniformPathsCanaryResults, + > = BTreeMap::new(); + let mut errors = false; let mut seen_spans = FxHashSet(); + let mut error_vec = Vec::new(); + let mut prev_root_id: NodeId = NodeId::new(0); for i in 0 .. self.determined_imports.len() { let import = self.determined_imports[i]; - if let Some((span, err)) = self.finalize_import(import) { + let error = self.finalize_import(import); + + // For a `#![feature(uniform_paths)]` `use self::x as _` canary, + // failure is ignored, while success may cause an ambiguity error. + if import.is_uniform_paths_canary { + if error.is_some() { + continue; + } + + let (name, result) = match import.subclass { + SingleImport { source, ref result, .. } => (source.name, result), + _ => bug!(), + }; + + let has_explicit_self = + import.module_path.len() > 0 && + import.module_path[0].name == keywords::SelfValue.name(); + + self.per_ns(|_, ns| { + if let Some(result) = result[ns].get().ok() { + let canary_results = + uniform_paths_canaries.entry((import.span, import.id, ns)) + .or_insert(UniformPathsCanaryResults { + name, + module_scope: None, + block_scopes: vec![], + }); + + // All the canaries with the same `id` should have the same `name`. + assert_eq!(canary_results.name, name); + + if has_explicit_self { + // There should only be one `self::x` (module-scoped) canary. + assert!(canary_results.module_scope.is_none()); + canary_results.module_scope = Some(result); + } else { + canary_results.block_scopes.push(result); + } + } + }); + } else if let Some((span, err)) = error { errors = true; if let SingleImport { source, ref result, .. } = import.subclass { @@ -516,25 +712,135 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // If the error is a single failed import then create a "fake" import // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(import); + if prev_root_id.as_u32() != 0 && + prev_root_id.as_u32() != import.root_id.as_u32() && + !error_vec.is_empty(){ + // in case of new import line, throw diagnostic message + // for previous line. + let mut empty_vec = vec![]; + mem::swap(&mut empty_vec, &mut error_vec); + self.throw_unresolved_import_error(empty_vec, None); + } if !seen_spans.contains(&span) { let path = import_path_to_string(&import.module_path[..], &import.subclass, span); - let error = ResolutionError::UnresolvedImport(Some((span, &path, &err))); - resolve_error(self.resolver, span, error); + error_vec.push((span, path, err)); seen_spans.insert(span); + prev_root_id = import.root_id; } } } + let uniform_paths_feature = self.session.features_untracked().uniform_paths; + for ((span, _, ns), results) in uniform_paths_canaries { + let name = results.name; + let external_crate = if ns == TypeNS && self.extern_prelude.contains(&name) { + let crate_id = + self.crate_loader.process_path_extern(name, span); + Some(Def::Mod(DefId { krate: crate_id, index: CRATE_DEF_INDEX })) + } else { + None + }; + + // Currently imports can't resolve in non-module scopes, + // we only have canaries in them for future-proofing. + if external_crate.is_none() && results.module_scope.is_none() { + continue; + } + + { + let mut all_results = external_crate.into_iter().chain( + results.module_scope.iter() + .chain(&results.block_scopes) + .map(|binding| binding.def()) + ); + let first = all_results.next().unwrap(); + + // An ambiguity requires more than one *distinct* possible resolution. + let possible_resultions = + 1 + all_results.filter(|&def| def != first).count(); + if possible_resultions <= 1 { + continue; + } + } + + errors = true; + + let msg = format!("`{}` import is ambiguous", name); + let mut err = self.session.struct_span_err(span, &msg); + let mut suggestion_choices = String::new(); + if external_crate.is_some() { + write!(suggestion_choices, "`::{}`", name); + err.span_label(span, + format!("can refer to external crate `::{}`", name)); + } + if let Some(result) = results.module_scope { + if !suggestion_choices.is_empty() { + suggestion_choices.push_str(" or "); + } + write!(suggestion_choices, "`self::{}`", name); + if uniform_paths_feature { + err.span_label(result.span, + format!("can refer to `self::{}`", name)); + } else { + err.span_label(result.span, + format!("may refer to `self::{}` in the future", name)); + } + } + for result in results.block_scopes { + err.span_label(result.span, + format!("shadowed by block-scoped `{}`", name)); + } + err.help(&format!("write {} explicitly instead", suggestion_choices)); + if uniform_paths_feature { + err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`"); + } else { + err.note("in the future, `#![feature(uniform_paths)]` may become the default"); + } + err.emit(); + } + + if !error_vec.is_empty() { + self.throw_unresolved_import_error(error_vec.clone(), None); + } + // Report unresolved imports only if no hard error was already reported // to avoid generating multiple errors on the same import. if !errors { - if let Some(import) = self.indeterminate_imports.iter().next() { - let error = ResolutionError::UnresolvedImport(None); - resolve_error(self.resolver, import.span, error); + for import in &self.indeterminate_imports { + if import.is_uniform_paths_canary { + continue; + } + self.throw_unresolved_import_error(error_vec, Some(MultiSpan::from(import.span))); + break; + } + } + } + + fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>, + span: Option) { + let max_span_label_msg_count = 10; // upper limit on number of span_label message. + let (span,msg) = match error_vec.is_empty() { + true => (span.unwrap(), "unresolved import".to_string()), + false => { + let span = MultiSpan::from_spans(error_vec.clone().into_iter() + .map(|elem: (Span, String, String)| { elem.0 } + ).collect()); + let path_vec: Vec = error_vec.clone().into_iter() + .map(|elem: (Span, String, String)| { format!("`{}`", elem.1) } + ).collect(); + let path = path_vec.join(", "); + let msg = format!("unresolved import{} {}", + if path_vec.len() > 1 { "s" } else { "" }, path); + (span, msg) } + }; + let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg); + for span_error in error_vec.into_iter().take(max_span_label_msg_count) { + err.span_label(span_error.0, span_error.2); } + err.emit(); } /// Attempts to resolve the given import, returning true if its resolution is determined. @@ -553,8 +859,18 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // For better failure detection, pretend that the import will not define any names // while resolving its module path. directive.vis.set(ty::Visibility::Invisible); - let result = self.resolve_path(&directive.module_path[..], None, false, - directive.span, directive.crate_lint()); + let result = self.resolve_path( + Some(if directive.is_uniform_paths_canary { + ModuleOrUniformRoot::Module(directive.parent) + } else { + ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name()) + }), + &directive.module_path[..], + None, + false, + directive.span, + directive.crate_lint(), + ); directive.vis.set(vis); match result { @@ -621,75 +937,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> { self.current_module = directive.parent; let ImportDirective { ref module_path, span, .. } = *directive; - let mut warn_if_binding_comes_from_local_crate = false; - - // FIXME: Last path segment is treated specially in import resolution, so extern crate - // mode for absolute paths needs some special support for single-segment imports. - if module_path.len() == 1 && (module_path[0].name == keywords::CrateRoot.name() || - module_path[0].name == keywords::Extern.name()) { - let is_extern = module_path[0].name == keywords::Extern.name() || - (self.session.features_untracked().extern_absolute_paths && - self.session.rust_2018()); - match directive.subclass { - GlobImport { .. } if is_extern => { - return Some((directive.span, - "cannot glob-import all possible crates".to_string())); - } - GlobImport { .. } if self.session.features_untracked().extern_absolute_paths => { - self.lint_path_starts_with_module( - directive.root_id, - directive.root_span, - ); - } - SingleImport { source, target, .. } => { - let crate_root = if source.name == keywords::Crate.name() && - module_path[0].name != keywords::Extern.name() { - if target.name == keywords::Crate.name() { - return Some((directive.span, - "crate root imports need to be explicitly named: \ - `use crate as name;`".to_string())); - } else { - Some(self.resolve_crate_root(source)) - } - } else if is_extern && !source.is_path_segment_keyword() { - let crate_id = - self.resolver.crate_loader.process_use_extern( - source.name, - directive.span, - directive.id, - &self.resolver.definitions, - ); - let crate_root = - self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(crate_root); - Some(crate_root) - } else { - warn_if_binding_comes_from_local_crate = true; - None - }; - - if let Some(crate_root) = crate_root { - let binding = (crate_root, ty::Visibility::Public, directive.span, - directive.expansion).to_name_binding(self.arenas); - let binding = self.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Import { - binding, - directive, - used: Cell::new(false), - }, - vis: directive.vis.get(), - span: directive.span, - expansion: directive.expansion, - }); - let _ = self.try_define(directive.parent, target, TypeNS, binding); - return None; - } - } - _ => {} - } - } let module_result = self.resolve_path( + Some(if directive.is_uniform_paths_canary { + ModuleOrUniformRoot::Module(directive.parent) + } else { + ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name()) + }), &module_path, None, true, @@ -709,7 +963,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if !self_path.is_empty() && !is_special(self_path[0]) && !(self_path.len() > 1 && is_special(self_path[1])) { self_path[0].name = keywords::SelfValue.name(); - self_result = Some(self.resolve_path(&self_path, None, false, + self_result = Some(self.resolve_path(None, &self_path, None, false, span, CrateLint::No)); } return if let Some(PathResult::Module(..)) = self_result { @@ -723,12 +977,27 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let (ident, result, type_ns_only) = match directive.subclass { SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only), - GlobImport { .. } if module.def_id() == directive.parent.def_id() => { - // Importing a module into itself is not allowed. - return Some((directive.span, - "Cannot glob-import a module into itself.".to_string())); - } GlobImport { is_prelude, ref max_vis } => { + if module_path.len() <= 1 { + // HACK(eddyb) `lint_if_path_starts_with_module` needs at least + // 2 segments, so the `resolve_path` above won't trigger it. + let mut full_path = module_path.clone(); + full_path.push(keywords::Invalid.ident()); + self.lint_if_path_starts_with_module( + directive.crate_lint(), + &full_path, + directive.span, + None, + ); + } + + if let ModuleOrUniformRoot::Module(module) = module { + if module.def_id() == directive.parent.def_id() { + // Importing a module into itself is not allowed. + return Some((directive.span, + "Cannot glob-import a module into itself.".to_string())); + } + } if !is_prelude && max_vis.get() != ty::Visibility::Invisible && // Allow empty globs. !max_vis.get().is_at_least(directive.vis.get(), &*self) { @@ -740,13 +1009,19 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { _ => unreachable!(), }; + // Do not record uses from canaries, to avoid interfering with other + // diagnostics or suggestions that rely on some items not being used. + let record_used = !directive.is_uniform_paths_canary; + let mut all_ns_err = true; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { if let Ok(binding) = result[ns].get() { all_ns_err = false; - if this.record_use(ident, ns, binding, directive.span) { - this.resolution(module, ident, ns).borrow_mut().binding = - Some(this.dummy_binding); + if record_used && this.record_use(ident, ns, binding) { + if let ModuleOrUniformRoot::Module(module) = module { + this.resolution(module, ident, ns).borrow_mut().binding = + Some(this.dummy_binding); + } } } }); @@ -754,15 +1029,20 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if all_ns_err { let mut all_ns_failed = true; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { - match this.resolve_ident_in_module(module, ident, ns, true, span) { + match this.resolve_ident_in_module(module, ident, ns, record_used, span) { Ok(_) => all_ns_failed = false, _ => {} } }); return if all_ns_failed { - let resolutions = module.resolutions.borrow(); - let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| { + let resolutions = match module { + ModuleOrUniformRoot::Module(module) => + Some(module.resolutions.borrow()), + ModuleOrUniformRoot::UniformRoot(_) => None, + }; + let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter()); + let names = resolutions.filter_map(|(&(ref i, _), resolution)| { if *i == ident { return None; } // Never suggest the same name match *resolution.borrow() { NameResolution { binding: Some(name_binding), .. } => { @@ -771,7 +1051,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { match binding.kind { // Never suggest the name that has binding error // i.e. the name that cannot be previously resolved - NameBindingKind::Def(Def::Err) => return None, + NameBindingKind::Def(Def::Err, _) => return None, _ => Some(&i.name), } }, @@ -786,13 +1066,26 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let lev_suggestion = match find_best_match_for_name(names, &ident.as_str(), None) { Some(name) => format!(". Did you mean to use `{}`?", name), - None => "".to_owned(), + None => String::new(), }; - let module_str = module_to_string(module); - let msg = if let Some(module_str) = module_str { - format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion) - } else { - format!("no `{}` in the root{}", ident, lev_suggestion) + let msg = match module { + ModuleOrUniformRoot::Module(module) => { + let module_str = module_to_string(module); + if let Some(module_str) = module_str { + format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion) + } else { + format!("no `{}` in the root{}", ident, lev_suggestion) + } + } + ModuleOrUniformRoot::UniformRoot(_) => { + if !ident.is_path_segment_keyword() { + format!("no `{}` external crate{}", ident, lev_suggestion) + } else { + // HACK(eddyb) this shows up for `self` & `super`, which + // should work instead - for now keep the same error message. + format!("no `{}` in the root{}", ident, lev_suggestion) + } + } }; Some((span, msg)) } else { @@ -843,26 +1136,20 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } - if warn_if_binding_comes_from_local_crate { - let mut warned = false; + if module_path.len() <= 1 { + // HACK(eddyb) `lint_if_path_starts_with_module` needs at least + // 2 segments, so the `resolve_path` above won't trigger it. + let mut full_path = module_path.clone(); + full_path.push(ident); self.per_ns(|this, ns| { - let binding = match result[ns].get().ok() { - Some(b) => b, - None => return - }; - if let NameBindingKind::Import { directive: d, .. } = binding.kind { - if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass { - return - } - } - if warned { - return + if let Ok(binding) = result[ns].get() { + this.lint_if_path_starts_with_module( + directive.crate_lint(), + &full_path, + directive.span, + Some(binding), + ); } - warned = true; - this.lint_path_starts_with_module( - directive.root_id, - directive.root_span, - ); }); } @@ -879,7 +1166,15 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { - let module = directive.imported_module.get().unwrap(); + let module = match directive.imported_module.get().unwrap() { + ModuleOrUniformRoot::Module(module) => module, + ModuleOrUniformRoot::UniformRoot(_) => { + self.session.span_err(directive.span, + "cannot glob-import all possible crates"); + return; + } + }; + self.populate_module_if_necessary(module); if let Some(Def::Trait(_)) = module.def() { @@ -924,24 +1219,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { *module.globs.borrow_mut() = Vec::new(); let mut reexports = Vec::new(); - let mut exported_macro_names = FxHashMap(); - if ptr::eq(module, self.graph_root) { - let macro_exports = mem::replace(&mut self.macro_exports, Vec::new()); - for export in macro_exports.into_iter().rev() { - if let Some(later_span) = exported_macro_names.insert(export.ident.modern(), - export.span) { - self.session.buffer_lint_with_diagnostic( - DUPLICATE_MACRO_EXPORTS, - CRATE_NODE_ID, - later_span, - &format!("a macro named `{}` has already been exported", export.ident), - BuiltinLintDiagnostics::DuplicatedMacroExports( - export.ident, export.span, later_span)); - } else { - reexports.push(export); - } - } - } for (&(ident, ns), resolution) in module.resolutions.borrow().iter() { let resolution = &mut *resolution.borrow_mut(); @@ -950,22 +1227,20 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { None => continue, }; - if binding.is_import() || binding.is_macro_def() { + // Don't reexport `uniform_path` canaries. + let non_canary_import = match binding.kind { + NameBindingKind::Import { directive, .. } => { + !directive.is_uniform_paths_canary + } + _ => false, + }; + + if non_canary_import || binding.is_macro_def() { let def = binding.def(); if def != Def::Err { if !def.def_id().is_local() { self.cstore.export_macros_untracked(def.def_id().krate); } - if let Def::Macro(..) = def { - if let Some(&span) = exported_macro_names.get(&ident.modern()) { - let msg = - format!("a macro named `{}` has already been exported", ident); - self.session.struct_span_err(span, &msg) - .span_label(span, format!("`{}` already exported", ident)) - .span_note(binding.span, "previous macro export here") - .emit(); - } - } reexports.push(Export { ident: ident.modern(), def: def, @@ -1001,8 +1276,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { }; let mut err = self.session.struct_span_err(binding.span, &msg); - let imported_module = directive.imported_module.get() - .expect("module should exist"); + let imported_module = match directive.imported_module.get() { + Some(ModuleOrUniformRoot::Module(module)) => module, + _ => bug!("module should exist"), + }; let resolutions = imported_module.parent.expect("parent should exist") .resolutions.borrow(); let enum_path_segment_index = directive.module_path.len() - 1; @@ -1013,8 +1290,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let enum_span = enum_resolution.borrow() .binding.expect("binding should exist") .span; - let enum_def_span = self.session.codemap().def_span(enum_span); - let enum_def_snippet = self.session.codemap() + let enum_def_span = self.session.source_map().def_span(enum_span); + let enum_def_snippet = self.session.source_map() .span_to_snippet(enum_def_span).expect("snippet should exist"); // potentially need to strip extant `crate`/`pub(path)` for suggestion let after_vis_index = enum_def_snippet.find("enum") diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 7b94170ef6..2dbea2155a 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -16,7 +16,7 @@ rustc_target = { path = "../librustc_target" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rls-data = "0.16" +rls-data = "0.18" rls-span = "0.4" # FIXME(#40527) should move rustc serialize out of tree rustc-serialize = "0.3" diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 04a4bca4ff..d719d257f3 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -41,7 +41,7 @@ use syntax::print::pprust::{ ty_to_string }; use syntax::ptr::P; -use syntax::codemap::{Spanned, DUMMY_SP, respan}; +use syntax::source_map::{Spanned, DUMMY_SP, respan}; use syntax_pos::*; use {escape, generated_code, lower_attributes, PathCollector, SaveContext}; @@ -91,7 +91,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> { // of macro use (callsite) spans. We store these to ensure // we only write one macro def per unique macro definition, and // one macro use per unique callsite span. - // mac_defs: HashSet, + // mac_defs: FxHashSet, macro_calls: FxHashSet, } @@ -107,7 +107,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { dumper, span: span_utils.clone(), cur_scope: CRATE_NODE_ID, - // mac_defs: HashSet::new(), + // mac_defs: FxHashSet::default(), macro_calls: FxHashSet(), } } @@ -147,9 +147,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let crate_root = source_file.map(|source_file| { let source_file = Path::new(source_file); match source_file.file_name() { - Some(_) => source_file.parent().unwrap().display().to_string(), - None => source_file.display().to_string(), - } + Some(_) => source_file.parent().unwrap().display(), + None => source_file.display(), + }.to_string() }); let data = CratePreludeData { @@ -176,8 +176,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let segments = &path.segments[if path.is_global() { 1 } else { 0 }..]; let mut result = Vec::with_capacity(segments.len()); + let mut segs = Vec::with_capacity(segments.len()); - let mut segs = vec![]; for (i, seg) in segments.iter().enumerate() { segs.push(seg.clone()); let sub_path = ast::Path { @@ -591,9 +591,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { for variant in &enum_definition.variants { let name = variant.node.ident.name.to_string(); - let mut qualname = enum_data.qualname.clone(); - qualname.push_str("::"); - qualname.push_str(&name); + let qualname = format!("{}::{}", enum_data.qualname, name); match variant.node.data { ast::VariantData::Struct(ref fields, _) => { @@ -824,10 +822,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { if let Some(ref generic_args) = seg.args { match **generic_args { ast::GenericArgs::AngleBracketed(ref data) => { - data.args.iter().for_each(|arg| match arg { - ast::GenericArg::Type(ty) => self.visit_ty(ty), - _ => {} - }); + for arg in &data.args { + match arg { + ast::GenericArg::Type(ty) => self.visit_ty(ty), + _ => {} + } + } } ast::GenericArgs::Parenthesized(ref data) => { for t in &data.inputs { @@ -911,10 +911,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { // Explicit types in the turbo-fish. if let Some(ref generic_args) = seg.args { if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { - data.args.iter().for_each(|arg| match arg { - ast::GenericArg::Type(ty) => self.visit_ty(ty), - _ => {} - }); + for arg in &data.args { + match arg { + ast::GenericArg::Type(ty) => self.visit_ty(ty), + _ => {} + } + } } } @@ -969,9 +971,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { match self.save_ctxt.get_path_def(id) { HirDef::Local(id) => { let mut value = if immut == ast::Mutability::Immutable { - self.span.snippet(ident.span).to_string() + self.span.snippet(ident.span) } else { - "".to_string() + "".to_owned() }; let hir_id = self.tcx.hir.node_to_hir_id(id); let typ = self.save_ctxt @@ -1099,10 +1101,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { /// mac_uses and mac_defs sets to prevent multiples. fn process_macro_use(&mut self, span: Span) { let source_span = span.source_callsite(); - if self.macro_calls.contains(&source_span) { + if !self.macro_calls.insert(source_span) { return; } - self.macro_calls.insert(source_span); let data = match self.save_ctxt.get_macro_use_data(span) { None => return, @@ -1358,6 +1359,14 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } } } + + fn process_bounds(&mut self, bounds: &'l ast::GenericBounds) { + for bound in bounds { + if let ast::GenericBound::Trait(ref trait_ref, _) = *bound { + self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path) + } + } + } } impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, O> { @@ -1368,7 +1377,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc let qualname = format!("::{}", self.tcx.node_path_str(id)); - let cm = self.tcx.sess.codemap(); + let cm = self.tcx.sess.source_map(); let filename = cm.span_to_filename(span); let data_id = ::id_from_node_id(id, &self.save_ctxt); let children = m.items @@ -1522,19 +1531,20 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } fn visit_generics(&mut self, generics: &'l ast::Generics) { - generics.params.iter().for_each(|param| match param.kind { - ast::GenericParamKind::Lifetime { .. } => {} - ast::GenericParamKind::Type { ref default, .. } => { - for bound in ¶m.bounds { - if let ast::GenericBound::Trait(ref trait_ref, _) = *bound { - self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path) - } - } + for param in &generics.params { + if let ast::GenericParamKind::Type { ref default, .. } = param.kind { + self.process_bounds(¶m.bounds); if let Some(ref ty) = default { self.visit_ty(&ty); } } - }); + } + for pred in &generics.where_clause.predicates { + if let ast::WherePredicate::BoundPredicate(ref wbp) = *pred { + self.process_bounds(&wbp.bounds); + self.visit_ty(&wbp.bounded_ty); + } + } } fn visit_ty(&mut self, t: &'l ast::Ty) { @@ -1595,8 +1605,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } } ast::ExprKind::Closure(_, _, _, ref decl, ref body, _fn_decl_span) => { - let mut id = String::from("$"); - id.push_str(&ex.id.to_string()); + let id = format!("${}", ex.id); // walk arg and return types for arg in &decl.inputs { @@ -1657,7 +1666,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc fn visit_arm(&mut self, arm: &'l ast::Arm) { self.process_var_decl_multi(&arm.pats); - walk_list!(self, visit_expr, &arm.guard); + match arm.guard { + Some(ast::Guard::If(ref expr)) => self.visit_expr(expr), + _ => {} + } self.visit_expr(&arm.body); } diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 2fe7d73de8..d2e52f9823 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -39,7 +39,7 @@ pub struct WriteOutput<'b, W: Write + 'b> { impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> { fn dump(&mut self, result: &Analysis) { - if let Err(_) = write!(self.output, "{}", as_json(&result)) { + if write!(self.output, "{}", as_json(&result)).is_err() { error!("Error writing output"); } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 761521c880..c9bae29703 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -12,6 +12,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(custom_attribute)] +#![cfg_attr(not(stage0), feature(nll))] #![allow(unused_attributes)] #![recursion_limit="256"] @@ -41,10 +42,10 @@ mod sig; use rustc::hir; use rustc::hir::def::Def as HirDef; -use rustc::hir::map::{Node, NodeTraitItem, NodeImplItem}; +use rustc::hir::Node; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::cstore::ExternCrate; -use rustc::session::config::CrateType::CrateTypeExecutable; +use rustc::session::config::CrateType; use rustc::ty::{self, TyCtxt}; use rustc_typeck::hir_ty_to_ty; @@ -55,14 +56,14 @@ use std::fs::File; use std::path::{Path, PathBuf}; use syntax::ast::{self, Attribute, NodeId, PatKind}; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use syntax::parse::lexer::comments::strip_doc_comment_decoration; use syntax::parse::token; use syntax::print::pprust; use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{arg_to_string, ty_to_string}; -use syntax::codemap::MacroAttribute; +use syntax::source_map::MacroAttribute; use syntax_pos::*; use json_dumper::JsonDumper; @@ -94,12 +95,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { fn span_from_span(&self, span: Span) -> SpanData { use rls_span::{Column, Row}; - let cm = self.tcx.sess.codemap(); + let cm = self.tcx.sess.source_map(); let start = cm.lookup_char_pos(span.lo()); let end = cm.lookup_char_pos(span.hi()); SpanData { - file_name: start.file.name.clone().to_string().into(), + file_name: start.file.name.to_string().into(), byte_start: span.lo().0, byte_end: span.hi().0, line_start: Row::new_one_indexed(start.line as u32), @@ -111,7 +112,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // List external crates used by the current crate. pub fn get_external_crates(&self) -> Vec { - let mut result = Vec::new(); + let mut result = Vec::with_capacity(self.tcx.crates().len()); for &n in self.tcx.crates().iter() { let span = match *self.tcx.extern_crate(n.as_def_id()) { @@ -121,11 +122,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { continue; } }; - let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo()); + let lo_loc = self.span_utils.sess.source_map().lookup_char_pos(span.lo()); result.push(ExternalCrateData { // FIXME: change file_name field to PathBuf in rls-data // https://github.com/nrc/rls-data/issues/7 - file_name: SpanUtils::make_path_string(&lo_loc.file.name), + file_name: self.span_utils.make_path_string(&lo_loc.file.name), num: n.as_u32(), id: GlobalCrateId { name: self.tcx.crate_name(n).to_string(), @@ -146,7 +147,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { filter!(self.span_utils, sub_span, item.span, None); Some(Data::DefData(Def { - kind: DefKind::Function, + kind: DefKind::ForeignFunction, id: id_from_node_id(item.id, self), span: self.span_from_span(sub_span.unwrap()), name: item.ident.to_string(), @@ -169,7 +170,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let span = self.span_from_span(sub_span.unwrap()); Some(Data::DefData(Def { - kind: DefKind::Static, + kind: DefKind::ForeignStatic, id, span, name: item.ident.to_string(), @@ -267,7 +268,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ast::ItemKind::Mod(ref m) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let cm = self.tcx.sess.codemap(); + let cm = self.tcx.sess.source_map(); let filename = cm.span_to_filename(m.inner); let sub_span = self.span_utils @@ -319,7 +320,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { decl_id: None, docs: self.docs_for_attrs(&item.attrs), sig: sig::item_signature(item, self), - attributes: lower_attributes(item.attrs.to_owned(), self), + attributes: lower_attributes(item.attrs.clone(), self), })) } ast::ItemKind::Impl(.., ref trait_ref, ref typ, ref impls) => { @@ -418,7 +419,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let (qualname, parent_scope, decl_id, docs, attributes) = match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) { Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) { - Some(Node::NodeItem(item)) => match item.node { + Some(Node::Item(item)) => match item.node { hir::ItemKind::Impl(.., ref ty, _) => { let mut qualname = String::from("<"); qualname.push_str(&self.tcx.hir.node_to_pretty_string(ty.id)); @@ -427,7 +428,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut decl_id = None; let mut docs = String::new(); let mut attrs = vec![]; - if let Some(NodeImplItem(item)) = self.tcx.hir.find(id) { + if let Some(Node::ImplItem(item)) = self.tcx.hir.find(id) { docs = self.docs_for_attrs(&item.attrs); attrs = item.attrs.to_vec(); } @@ -469,7 +470,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut docs = String::new(); let mut attrs = vec![]; - if let Some(NodeTraitItem(item)) = self.tcx.hir.find(id) { + if let Some(Node::TraitItem(item)) = self.tcx.hir.find(id) { docs = self.docs_for_attrs(&item.attrs); attrs = item.attrs.to_vec(); } @@ -533,13 +534,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_expr_data(&self, expr: &ast::Expr) -> Option { let hir_node = self.tcx.hir.expect_expr(expr.id); let ty = self.tables.expr_ty_adjusted_opt(&hir_node); - if ty.is_none() || ty.unwrap().sty == ty::TyError { + if ty.is_none() || ty.unwrap().sty == ty::Error { return None; } match expr.node { ast::ExprKind::Field(ref sub_ex, ident) => { let hir_node = match self.tcx.hir.find(sub_ex.id) { - Some(Node::NodeExpr(expr)) => expr, + Some(Node::Expr(expr)) => expr, _ => { debug!( "Missing or weird node for sub-expression {} in {:?}", @@ -550,7 +551,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } }; match self.tables.expr_ty_adjusted(&hir_node).sty { - ty::TyAdt(def, _) if !def.is_enum() => { + ty::Adt(def, _) if !def.is_enum() => { let variant = &def.non_enum_variant(); let index = self.tcx.find_field_index(ident, variant).unwrap(); let sub_span = self.span_utils.span_for_last_ident(expr.span); @@ -562,7 +563,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ref_id: id_from_def_id(variant.fields[index].did), })); } - ty::TyTuple(..) => None, + ty::Tuple(..) => None, _ => { debug!("Expected struct or union type, found {:?}", ty); None @@ -571,7 +572,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ExprKind::Struct(ref path, ..) => { match self.tables.expr_ty_adjusted(&hir_node).sty { - ty::TyAdt(def, _) if !def.is_enum() => { + ty::Adt(def, _) if !def.is_enum() => { let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); let span = self.span_from_span(sub_span.unwrap()); @@ -626,32 +627,32 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_path_def(&self, id: NodeId) -> HirDef { match self.tcx.hir.get(id) { - Node::NodeTraitRef(tr) => tr.path.def, + Node::TraitRef(tr) => tr.path.def, - Node::NodeItem(&hir::Item { + Node::Item(&hir::Item { node: hir::ItemKind::Use(ref path, _), .. }) | - Node::NodeVisibility(&Spanned { + Node::Visibility(&Spanned { node: hir::VisibilityKind::Restricted { ref path, .. }, .. }) => path.def, - Node::NodeExpr(&hir::Expr { + Node::Expr(&hir::Expr { node: hir::ExprKind::Struct(ref qpath, ..), .. }) | - Node::NodeExpr(&hir::Expr { + Node::Expr(&hir::Expr { node: hir::ExprKind::Path(ref qpath), .. }) | - Node::NodePat(&hir::Pat { + Node::Pat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) | - Node::NodePat(&hir::Pat { + Node::Pat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) | - Node::NodePat(&hir::Pat { + Node::Pat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => { @@ -659,12 +660,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { self.tables.qpath_def(qpath, hir_id) } - Node::NodeBinding(&hir::Pat { + Node::Binding(&hir::Pat { node: hir::PatKind::Binding(_, canonical_id, ..), .. }) => HirDef::Local(canonical_id), - Node::NodeTy(ty) => if let hir::Ty { + Node::Ty(ty) => if let hir::Ty { node: hir::TyKind::Path(ref qpath), .. } = *ty @@ -673,7 +674,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { hir::QPath::Resolved(_, ref path) => path.def, hir::QPath::TypeRelative(..) => { let ty = hir_ty_to_ty(self.tcx, ty); - if let ty::TyProjection(proj) = ty.sty { + if let ty::Projection(proj) = ty.sty { return HirDef::AssociatedTy(proj.item_def_id); } HirDef::Err @@ -746,7 +747,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Union(def_id) | HirDef::Enum(def_id) | HirDef::TyAlias(def_id) | - HirDef::TyForeign(def_id) | + HirDef::ForeignTy(def_id) | HirDef::TraitAlias(def_id) | HirDef::AssociatedExistential(def_id) | HirDef::AssociatedTy(def_id) | @@ -810,7 +811,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::SelfTy(..) | HirDef::Label(..) | HirDef::Macro(..) | - HirDef::GlobalAsm(..) | + HirDef::ToolMod | + HirDef::NonMacroAttr(..) | + HirDef::SelfCtor(..) | HirDef::Err => None, } } @@ -1046,9 +1049,9 @@ impl<'a> DumpHandler<'a> { let executable = sess.crate_types .borrow() .iter() - .any(|ct| *ct == CrateTypeExecutable); + .any(|ct| *ct == CrateType::Executable); let mut out_name = if executable { - "".to_owned() + String::new() } else { "lib".to_owned() }; diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 1303256287..9cf64a9d1c 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -435,7 +435,7 @@ impl Sig for ast::Item { }, ]; text.push_str(&name); - // Could be either `mod foo;` or `mod foo { ... }`, but we'll just puck one. + // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one. text.push(';'); Ok(Signature { @@ -630,7 +630,7 @@ impl Sig for ast::Generics { let mut text = "<".to_owned(); - let mut defs = vec![]; + let mut defs = Vec::with_capacity(self.params.len()); for param in &self.params { let mut param_text = param.ident.to_string(); defs.push(SigElement { diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 4d93e81a78..2550a312c5 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -13,7 +13,6 @@ use rustc::session::Session; use generated_code; use std::cell::Cell; -use std::env; use syntax::parse::lexer::{self, StringReader}; use syntax::parse::token::{self, Token}; @@ -36,11 +35,10 @@ impl<'a> SpanUtils<'a> { } } - pub fn make_path_string(path: &FileName) -> String { + pub fn make_path_string(&self, path: &FileName) -> String { match *path { FileName::Real(ref path) if !path.is_absolute() => - env::current_dir() - .unwrap() + self.sess.working_dir.0 .join(&path) .display() .to_string(), @@ -49,7 +47,7 @@ impl<'a> SpanUtils<'a> { } pub fn snippet(&self, span: Span) -> String { - match self.sess.codemap().span_to_snippet(span) { + match self.sess.source_map().span_to_snippet(span) { Ok(s) => s, Err(_) => String::new(), } @@ -153,11 +151,10 @@ impl<'a> SpanUtils<'a> { } #[cfg(debug_assertions)] { if angle_count != 0 || bracket_count != 0 { - let loc = self.sess.codemap().lookup_char_pos(span.lo()); + let loc = self.sess.source_map().lookup_char_pos(span.lo()); span_bug!( span, - "Mis-counted brackets when breaking path? Parsing '{}' \ - in {}, line {}", + "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}", self.snippet(span), loc.file.name, loc.line @@ -266,11 +263,8 @@ impl<'a> SpanUtils<'a> { /// such as references to macro internal variables. pub fn filter_generated(&self, sub_span: Option, parent: Span) -> bool { if !generated_code(parent) { - if sub_span.is_none() { - // Edge case - this occurs on generated code with incorrect expansion info. - return true; - } - return false; + // Edge case - this occurs on generated code with incorrect expansion info. + return sub_span.is_none() } // If sub_span is none, filter out generated code. let sub_span = match sub_span { @@ -278,9 +272,9 @@ impl<'a> SpanUtils<'a> { None => return true, }; - //If the span comes from a fake filemap, filter it. + //If the span comes from a fake source_file, filter it. if !self.sess - .codemap() + .source_map() .lookup_char_pos(parent.lo()) .file .is_real_file() diff --git a/src/librustc_target/abi/call/amdgpu.rs b/src/librustc_target/abi/call/amdgpu.rs new file mode 100644 index 0000000000..62462f04d8 --- /dev/null +++ b/src/librustc_target/abi/call/amdgpu.rs @@ -0,0 +1,42 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use abi::call::{ArgType, FnType, }; +use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; + +fn classify_ret_ty<'a, Ty, C>(_tuncx: C, ret: &mut ArgType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + ret.extend_integer_width_to(32); +} + +fn classify_arg_ty<'a, Ty, C>(_cx: C, arg: &mut ArgType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + arg.extend_integer_width_to(32); +} + +pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + if !fty.ret.is_ignore() { + classify_ret_ty(cx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(cx, arg); + } +} diff --git a/src/librustc_target/abi/call/mips64.rs b/src/librustc_target/abi/call/mips64.rs index 3734e563d5..8e2dd99696 100644 --- a/src/librustc_target/abi/call/mips64.rs +++ b/src/librustc_target/abi/call/mips64.rs @@ -145,7 +145,7 @@ fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>) // Extract first 8 chunks as the prefix let rest_size = size - Size::from_bytes(8) * prefix_index as u64; arg.cast_to(CastTarget { - prefix: prefix, + prefix, prefix_chunk: Size::from_bytes(8), rest: Uniform { unit: Reg::i64(), total: rest_size } }); diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index ca5aba5b64..788497a378 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -13,6 +13,7 @@ use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; use spec::HasTargetSpec; mod aarch64; +mod amdgpu; mod arm; mod asmjs; mod hexagon; @@ -23,6 +24,7 @@ mod nvptx; mod nvptx64; mod powerpc; mod powerpc64; +mod riscv; mod s390x; mod sparc; mod sparc64; @@ -43,7 +45,9 @@ pub enum PassMode { /// a single uniform or a pair of registers. Cast(CastTarget), /// Pass the argument indirectly via a hidden pointer. - Indirect(ArgAttributes), + /// The second value, if any, is for the extra data (vtable or length) + /// which indicates that it refers to an unsized rvalue. + Indirect(ArgAttributes, Option), } // Hack to disable non_upper_case_globals only for the bitflags! and not for the rest @@ -89,7 +93,7 @@ impl ArgAttributes { } pub fn set(&mut self, attr: ArgAttribute) -> &mut Self { - self.regular = self.regular | attr; + self.regular |= attr; self } @@ -228,7 +232,7 @@ impl CastTarget { pub fn align(&self, cx: C) -> Align { self.prefix.iter() - .filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx))) + .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk }.align(cx))) .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)), |acc, align| acc.max(align)) } @@ -367,13 +371,19 @@ impl<'a, Ty> ArgType<'a, Ty> { // i686-pc-windows-msvc, it results in wrong stack offsets. // attrs.pointee_align = Some(self.layout.align); - self.mode = PassMode::Indirect(attrs); + let extra_attrs = if self.layout.is_unsized() { + Some(ArgAttributes::new()) + } else { + None + }; + + self.mode = PassMode::Indirect(attrs, extra_attrs); } pub fn make_indirect_byval(&mut self) { self.make_indirect(); match self.mode { - PassMode::Indirect(ref mut attrs) => { + PassMode::Indirect(ref mut attrs, _) => { attrs.set(ArgAttribute::ByVal); } _ => unreachable!() @@ -408,7 +418,21 @@ impl<'a, Ty> ArgType<'a, Ty> { pub fn is_indirect(&self) -> bool { match self.mode { - PassMode::Indirect(_) => true, + PassMode::Indirect(..) => true, + _ => false + } + } + + pub fn is_sized_indirect(&self) -> bool { + match self.mode { + PassMode::Indirect(_, None) => true, + _ => false + } + } + + pub fn is_unsized_indirect(&self) -> bool { + match self.mode { + PassMode::Indirect(_, Some(_)) => true, _ => false } } @@ -480,6 +504,7 @@ impl<'a, Ty> FnType<'a, Ty> { x86_64::compute_abi_info(cx, self); }, "aarch64" => aarch64::compute_abi_info(cx, self), + "amdgpu" => amdgpu::compute_abi_info(cx, self), "arm" => arm::compute_abi_info(cx, self), "mips" => mips::compute_abi_info(cx, self), "mips64" => mips64::compute_abi_info(cx, self), @@ -500,10 +525,12 @@ impl<'a, Ty> FnType<'a, Ty> { "nvptx" => nvptx::compute_abi_info(self), "nvptx64" => nvptx64::compute_abi_info(self), "hexagon" => hexagon::compute_abi_info(self), + "riscv32" => riscv::compute_abi_info(self, 32), + "riscv64" => riscv::compute_abi_info(self, 64), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)) } - if let PassMode::Indirect(ref mut attrs) = self.ret.mode { + if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode { attrs.set(ArgAttribute::StructRet); } diff --git a/src/librustc_target/abi/call/riscv.rs b/src/librustc_target/abi/call/riscv.rs new file mode 100644 index 0000000000..fe0d7485c1 --- /dev/null +++ b/src/librustc_target/abi/call/riscv.rs @@ -0,0 +1,59 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Reference: RISC-V ELF psABI specification +// https://github.com/riscv/riscv-elf-psabi-doc + +use abi::call::{ArgType, FnType}; + +fn classify_ret_ty(arg: &mut ArgType, xlen: u64) { + // "Scalars wider than 2✕XLEN are passed by reference and are replaced in + // the argument list with the address." + // "Aggregates larger than 2✕XLEN bits are passed by reference and are + // replaced in the argument list with the address, as are C++ aggregates + // with nontrivial copy constructors, destructors, or vtables." + if arg.layout.size.bits() > 2 * xlen { + arg.make_indirect(); + } + + // "When passed in registers, scalars narrower than XLEN bits are widened + // according to the sign of their type up to 32 bits, then sign-extended to + // XLEN bits." + arg.extend_integer_width_to(xlen); // this method only affects integer scalars +} + +fn classify_arg_ty(arg: &mut ArgType, xlen: u64) { + // "Scalars wider than 2✕XLEN are passed by reference and are replaced in + // the argument list with the address." + // "Aggregates larger than 2✕XLEN bits are passed by reference and are + // replaced in the argument list with the address, as are C++ aggregates + // with nontrivial copy constructors, destructors, or vtables." + if arg.layout.size.bits() > 2 * xlen { + arg.make_indirect(); + } + + // "When passed in registers, scalars narrower than XLEN bits are widened + // according to the sign of their type up to 32 bits, then sign-extended to + // XLEN bits." + arg.extend_integer_width_to(xlen); // this method only affects integer scalars +} + +pub fn compute_abi_info(fty: &mut FnType, xlen: u64) { + if !fty.ret.is_ignore() { + classify_ret_ty(&mut fty.ret, xlen); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(arg, xlen); + } +} diff --git a/src/librustc_target/abi/call/x86.rs b/src/librustc_target/abi/call/x86.rs index 0c0040de9d..1dcaafcf77 100644 --- a/src/librustc_target/abi/call/x86.rs +++ b/src/librustc_target/abi/call/x86.rs @@ -99,9 +99,10 @@ pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>, flavor: Flav for arg in &mut fty.args { let attrs = match arg.mode { PassMode::Ignore | - PassMode::Indirect(_) => continue, + PassMode::Indirect(_, None) => continue, PassMode::Direct(ref mut attrs) => attrs, PassMode::Pair(..) | + PassMode::Indirect(_, Some(_)) | PassMode::Cast(_) => { unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode) } diff --git a/src/librustc_target/abi/call/x86_64.rs b/src/librustc_target/abi/call/x86_64.rs index a443255b97..eade086ec4 100644 --- a/src/librustc_target/abi/call/x86_64.rs +++ b/src/librustc_target/abi/call/x86_64.rs @@ -199,10 +199,8 @@ pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>) _ => {} } } - if arg.layout.is_aggregate() { - if int_regs < needed_int || sse_regs < needed_sse { - cls_or_mem = Err(Memory); - } + if arg.layout.is_aggregate() && (int_regs < needed_int || sse_regs < needed_sse) { + cls_or_mem = Err(Memory); } } } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index dac4738e2b..5c4cd849f8 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -93,17 +93,17 @@ impl TargetDataLayout { let mut dl = TargetDataLayout::default(); let mut i128_align_src = 64; for spec in target.data_layout.split('-') { - match &spec.split(':').collect::>()[..] { - &["e"] => dl.endian = Endian::Little, - &["E"] => dl.endian = Endian::Big, - &["a", ref a..] => dl.aggregate_align = align(a, "a")?, - &["f32", ref a..] => dl.f32_align = align(a, "f32")?, - &["f64", ref a..] => dl.f64_align = align(a, "f64")?, - &[p @ "p", s, ref a..] | &[p @ "p0", s, ref a..] => { + match spec.split(':').collect::>()[..] { + ["e"] => dl.endian = Endian::Little, + ["E"] => dl.endian = Endian::Big, + ["a", ref a..] => dl.aggregate_align = align(a, "a")?, + ["f32", ref a..] => dl.f32_align = align(a, "f32")?, + ["f64", ref a..] => dl.f64_align = align(a, "f64")?, + [p @ "p", s, ref a..] | [p @ "p0", s, ref a..] => { dl.pointer_size = size(s, p)?; dl.pointer_align = align(a, p)?; } - &[s, ref a..] if s.starts_with("i") => { + [s, ref a..] if s.starts_with("i") => { let bits = match s[1..].parse::() { Ok(bits) => bits, Err(_) => { @@ -127,7 +127,7 @@ impl TargetDataLayout { dl.i128_align = a; } } - &[s, ref a..] if s.starts_with("v") => { + [s, ref a..] if s.starts_with("v") => { let v_size = size(&s[1..], "v")?; let a = align(a, s)?; if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { @@ -416,6 +416,24 @@ impl Align { pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2), } } + + /// Compute the best alignment possible for the given offset + /// (the largest power of two that the offset is a multiple of). + /// + /// NB: for an offset of `0`, this happens to return `2^64`. + pub fn max_for_offset(offset: Size) -> Align { + let pow2 = offset.bytes().trailing_zeros() as u8; + Align { + abi_pow2: pow2, + pref_pow2: pow2, + } + } + + /// Lower the alignment, if necessary, such that the given offset + /// is aligned to it (the offset is a multiple of the aligment). + pub fn restrict_for_offset(self, offset: Size) -> Align { + self.min(Align::max_for_offset(offset)) + } } /// Integers, also used for enum discriminants. @@ -429,8 +447,8 @@ pub enum Integer { } impl Integer { - pub fn size(&self) -> Size { - match *self { + pub fn size(self) -> Size { + match self { I8 => Size::from_bytes(1), I16 => Size::from_bytes(2), I32 => Size::from_bytes(4), @@ -439,10 +457,10 @@ impl Integer { } } - pub fn align(&self, cx: C) -> Align { + pub fn align(self, cx: C) -> Align { let dl = cx.data_layout(); - match *self { + match self { I8 => dl.i8_align, I16 => dl.i16_align, I32 => dl.i32_align, @@ -522,15 +540,15 @@ impl fmt::Display for FloatTy { } impl FloatTy { - pub fn ty_to_string(&self) -> &'static str { - match *self { + pub fn ty_to_string(self) -> &'static str { + match self { FloatTy::F32 => "f32", FloatTy::F64 => "f64", } } - pub fn bit_width(&self) -> usize { - match *self { + pub fn bit_width(self) -> usize { + match self { FloatTy::F32 => 32, FloatTy::F64 => 64, } @@ -596,7 +614,16 @@ pub struct Scalar { pub value: Primitive, /// Inclusive wrap-around range of valid values, that is, if - /// min > max, it represents min..=u128::MAX followed by 0..=max. + /// start > end, it represents `start..=max_value()`, + /// followed by `0..=end`. + /// + /// That is, for an i8 primitive, a range of `254..=2` means following + /// sequence: + /// + /// 254 (-2), 255 (-1), 0, 1, 2 + /// + /// This is intended specifically to mirror LLVM’s `!range` metadata, + /// semantics. // FIXME(eddyb) always use the shortest range, e.g. by finding // the largest space between two consecutive valid values and // taking everything else as the (shortest) valid range. diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 8f49115743..c198b19ce6 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -15,20 +15,16 @@ //! is really just odds-and-ends relating to code gen and linking. //! This crate mostly exists to make rustc smaller, so we might put //! more 'stuff' here in the future. It does not have a dependency on -//! rustc_llvm. -//! -//! FIXME: Split this into two crates: one that has deps on syntax, and -//! one that doesn't; the one that doesn't might get decent parallel -//! build speedups. +//! LLVM. #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(box_syntax)] -#![feature(const_fn)] -#![feature(fs_read_write)] -#![feature(inclusive_range)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] +#![cfg_attr(not(stage0), feature(nll))] #![feature(slice_patterns)] #[macro_use] diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index 90f8cd90c6..16dd27887f 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -21,7 +21,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), target_os: "ios".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/aarch64_fuchsia.rs b/src/librustc_target/spec/aarch64_fuchsia.rs index 28baf6f66e..8f7ee11d57 100644 --- a/src/librustc_target/spec/aarch64_fuchsia.rs +++ b/src/librustc_target/spec/aarch64_fuchsia.rs @@ -22,8 +22,8 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), target_os: "fuchsia".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), + target_env: String::new(), + target_vendor: String::new(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), diff --git a/src/librustc_target/spec/aarch64_linux_android.rs b/src/librustc_target/spec/aarch64_linux_android.rs index afd67112f0..540aac2c33 100644 --- a/src/librustc_target/spec/aarch64_linux_android.rs +++ b/src/librustc_target/spec/aarch64_linux_android.rs @@ -27,7 +27,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), target_os: "android".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs new file mode 100644 index 0000000000..8747f239d3 --- /dev/null +++ b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs @@ -0,0 +1,35 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor}; + +pub fn target() -> TargetResult { + let mut base = super::windows_msvc_base::opts(); + base.max_atomic_width = Some(64); + base.has_elf_tls = true; + + // FIXME: this shouldn't be panic=abort, it should be panic=unwind + base.panic_strategy = PanicStrategy::Abort; + base.linker = Some("rust-lld".to_owned()); + + Ok(Target { + llvm_target: "aarch64-pc-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "pc".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Link), + options: base, + }) +} diff --git a/src/librustc_target/spec/aarch64_unknown_cloudabi.rs b/src/librustc_target/spec/aarch64_unknown_cloudabi.rs index ffdb7decd0..087b0fa543 100644 --- a/src/librustc_target/spec/aarch64_unknown_cloudabi.rs +++ b/src/librustc_target/spec/aarch64_unknown_cloudabi.rs @@ -24,7 +24,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), target_os: "cloudabi".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/aarch64_unknown_freebsd.rs b/src/librustc_target/spec/aarch64_unknown_freebsd.rs index 48177b8c79..541f0564a0 100644 --- a/src/librustc_target/spec/aarch64_unknown_freebsd.rs +++ b/src/librustc_target/spec/aarch64_unknown_freebsd.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), target_os: "freebsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/aarch64_unknown_hermit.rs b/src/librustc_target/spec/aarch64_unknown_hermit.rs new file mode 100644 index 0000000000..32fb700202 --- /dev/null +++ b/src/librustc_target/spec/aarch64_unknown_hermit.rs @@ -0,0 +1,32 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::hermit_base::opts(); + base.max_atomic_width = Some(128); + base.abi_blacklist = super::arm_base::abi_blacklist(); + base.linker = Some("aarch64-hermit-gcc".to_string()); + + Ok(Target { + llvm_target: "aarch64-unknown-hermit".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "hermit".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_target/spec/aarch64_unknown_netbsd.rs b/src/librustc_target/spec/aarch64_unknown_netbsd.rs new file mode 100644 index 0000000000..c4afd1143f --- /dev/null +++ b/src/librustc_target/spec/aarch64_unknown_netbsd.rs @@ -0,0 +1,31 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::netbsd_base::opts(); + base.max_atomic_width = Some(128); + base.abi_blacklist = super::arm_base::abi_blacklist(); + + Ok(Target { + llvm_target: "aarch64-unknown-netbsd".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "netbsd".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_target/spec/aarch64_unknown_none.rs b/src/librustc_target/spec/aarch64_unknown_none.rs new file mode 100644 index 0000000000..1cf214d09c --- /dev/null +++ b/src/librustc_target/spec/aarch64_unknown_none.rs @@ -0,0 +1,46 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Generic AArch64 target for bare-metal code +// +// Can be used in conjunction with the `target-feature` and +// `target-cpu` compiler flags to opt-in more hardware-specific +// features. +// +// For example, `-C target-cpu=cortex-a53`. + +use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy}; + +pub fn target() -> Result { + let opts = TargetOptions { + linker: Some("rust-lld".to_owned()), + executables: true, + relocation_model: "static".to_string(), + disable_redzone: true, + linker_is_gnu: true, + max_atomic_width: Some(128), + panic_strategy: PanicStrategy::Abort, + abi_blacklist: super::arm_base::abi_blacklist(), + .. Default::default() + }; + Ok(Target { + llvm_target: "aarch64-unknown-none".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: String::new(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + options: opts, + }) +} diff --git a/src/librustc_target/spec/aarch64_unknown_openbsd.rs b/src/librustc_target/spec/aarch64_unknown_openbsd.rs index 25817fce5c..81c24fa10f 100644 --- a/src/librustc_target/spec/aarch64_unknown_openbsd.rs +++ b/src/librustc_target/spec/aarch64_unknown_openbsd.rs @@ -23,7 +23,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), target_os: "openbsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/abi.rs b/src/librustc_target/spec/abi.rs index 317cdb4006..6d8c8eb19f 100644 --- a/src/librustc_target/spec/abi.rs +++ b/src/librustc_target/spec/abi.rs @@ -51,7 +51,7 @@ pub struct AbiData { } #[allow(non_upper_case_globals)] -const AbiDatas: &'static [AbiData] = &[ +const AbiDatas: &[AbiData] = &[ // Platform-specific ABIs AbiData {abi: Abi::Cdecl, name: "cdecl", generic: false }, AbiData {abi: Abi::Stdcall, name: "stdcall", generic: false }, @@ -87,20 +87,20 @@ pub fn all_names() -> Vec<&'static str> { impl Abi { #[inline] - pub fn index(&self) -> usize { - *self as usize + pub fn index(self) -> usize { + self as usize } #[inline] - pub fn data(&self) -> &'static AbiData { + pub fn data(self) -> &'static AbiData { &AbiDatas[self.index()] } - pub fn name(&self) -> &'static str { + pub fn name(self) -> &'static str { self.data().name } - pub fn generic(&self) -> bool { + pub fn generic(self) -> bool { self.data().generic } } diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index 4b66891e36..38b3f2528f 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -26,7 +26,7 @@ pub fn opts() -> TargetOptions { // TLS is flagged as enabled if it looks to be supported. let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok(); let version = deployment_target.as_ref().and_then(|s| { - let mut i = s.splitn(2, "."); + let mut i = s.splitn(2, '.'); i.next().and_then(|a| i.next().map(|b| (a, b))) }).and_then(|(a, b)| { a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok() diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index 46bb01e7c4..296eaca7c7 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -25,13 +25,13 @@ pub enum Arch { } impl Arch { - pub fn to_string(&self) -> &'static str { + pub fn to_string(self) -> &'static str { match self { - &Armv7 => "armv7", - &Armv7s => "armv7s", - &Arm64 => "arm64", - &I386 => "i386", - &X86_64 => "x86_64" + Armv7 => "armv7", + Armv7s => "armv7s", + Arm64 => "arm64", + I386 => "i386", + X86_64 => "x86_64" } } } diff --git a/src/librustc_target/spec/arm_linux_androideabi.rs b/src/librustc_target/spec/arm_linux_androideabi.rs index ffd242b2bc..c5e3385a91 100644 --- a/src/librustc_target/spec/arm_linux_androideabi.rs +++ b/src/librustc_target/spec/arm_linux_androideabi.rs @@ -24,7 +24,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), target_os: "android".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/armebv7r_none_eabi.rs b/src/librustc_target/spec/armebv7r_none_eabi.rs new file mode 100644 index 0000000000..8d3ff1b800 --- /dev/null +++ b/src/librustc_target/spec/armebv7r_none_eabi.rs @@ -0,0 +1,40 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Targets the Big endian Cortex-R4/R5 processor (ARMv7-R) + +use std::default::Default; +use spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "armebv7r-unknown-none-eabi".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "none".to_string(), + target_env: "".to_string(), + target_vendor: "".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + executables: true, + linker: Some("rust-lld".to_owned()), + relocation_model: "static".to_string(), + panic_strategy: PanicStrategy::Abort, + max_atomic_width: Some(32), + abi_blacklist: super::arm_base::abi_blacklist(), + emit_debug_gdb_scripts: false, + .. Default::default() + }, + }) +} diff --git a/src/librustc_target/spec/armebv7r_none_eabihf.rs b/src/librustc_target/spec/armebv7r_none_eabihf.rs index 8bd08d355a..0343ea7bd1 100644 --- a/src/librustc_target/spec/armebv7r_none_eabihf.rs +++ b/src/librustc_target/spec/armebv7r_none_eabihf.rs @@ -11,26 +11,27 @@ // Targets the Cortex-R4F/R5F processor (ARMv7-R) use std::default::Default; -use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { - llvm_target: "armebv7r-none-eabihf".to_string(), + llvm_target: "armebv7r-unknown-none-eabihf".to_string(), target_endian: "big".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), target_os: "none".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), - linker_flavor: LinkerFlavor::Gcc, + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), options: TargetOptions { executables: true, + linker: Some("rust-lld".to_owned()), relocation_model: "static".to_string(), panic_strategy: PanicStrategy::Abort, - features: "+v7,+vfp3,+d16,+fp-only-sp".to_string(), + features: "+vfp3,+d16,+fp-only-sp".to_string(), max_atomic_width: Some(32), abi_blacklist: super::arm_base::abi_blacklist(), emit_debug_gdb_scripts: false, diff --git a/src/librustc_target/spec/armv7_apple_ios.rs b/src/librustc_target/spec/armv7_apple_ios.rs index da7cbb918b..0f7b2ad763 100644 --- a/src/librustc_target/spec/armv7_apple_ios.rs +++ b/src/librustc_target/spec/armv7_apple_ios.rs @@ -21,7 +21,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(), arch: "arm".to_string(), target_os: "ios".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/armv7_linux_androideabi.rs b/src/librustc_target/spec/armv7_linux_androideabi.rs index cfdc5cddcf..06abe0b2c9 100644 --- a/src/librustc_target/spec/armv7_linux_androideabi.rs +++ b/src/librustc_target/spec/armv7_linux_androideabi.rs @@ -28,7 +28,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), target_os: "android".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs index 393c45e434..44e611f04b 100644 --- a/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs +++ b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs @@ -26,7 +26,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), target_os: "cloudabi".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/armv7r_none_eabi.rs b/src/librustc_target/spec/armv7r_none_eabi.rs new file mode 100644 index 0000000000..43148d593f --- /dev/null +++ b/src/librustc_target/spec/armv7r_none_eabi.rs @@ -0,0 +1,40 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R) + +use std::default::Default; +use spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "armv7r-unknown-none-eabi".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "none".to_string(), + target_env: "".to_string(), + target_vendor: "".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + executables: true, + linker: Some("rust-lld".to_owned()), + relocation_model: "static".to_string(), + panic_strategy: PanicStrategy::Abort, + max_atomic_width: Some(32), + abi_blacklist: super::arm_base::abi_blacklist(), + emit_debug_gdb_scripts: false, + .. Default::default() + }, + }) +} diff --git a/src/librustc_target/spec/armv7r_none_eabihf.rs b/src/librustc_target/spec/armv7r_none_eabihf.rs new file mode 100644 index 0000000000..036b0544c5 --- /dev/null +++ b/src/librustc_target/spec/armv7r_none_eabihf.rs @@ -0,0 +1,41 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R) + +use std::default::Default; +use spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "armv7r-unknown-none-eabihf".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "none".to_string(), + target_env: "".to_string(), + target_vendor: "".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + executables: true, + linker: Some("rust-lld".to_owned()), + relocation_model: "static".to_string(), + panic_strategy: PanicStrategy::Abort, + features: "+vfp3,+d16,+fp-only-sp".to_string(), + max_atomic_width: Some(32), + abi_blacklist: super::arm_base::abi_blacklist(), + emit_debug_gdb_scripts: false, + .. Default::default() + }, + }) +} diff --git a/src/librustc_target/spec/armv7s_apple_ios.rs b/src/librustc_target/spec/armv7s_apple_ios.rs index c0c577c3b8..a5f35d0a77 100644 --- a/src/librustc_target/spec/armv7s_apple_ios.rs +++ b/src/librustc_target/spec/armv7s_apple_ios.rs @@ -21,7 +21,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(), arch: "arm".to_string(), target_os: "ios".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/asmjs_unknown_emscripten.rs b/src/librustc_target/spec/asmjs_unknown_emscripten.rs index 4e716fb207..da70a3ad04 100644 --- a/src/librustc_target/spec/asmjs_unknown_emscripten.rs +++ b/src/librustc_target/spec/asmjs_unknown_emscripten.rs @@ -40,7 +40,7 @@ pub fn target() -> Result { target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), target_os: "emscripten".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), arch: "asmjs".to_string(), diff --git a/src/librustc_target/spec/hermit_base.rs b/src/librustc_target/spec/hermit_base.rs new file mode 100644 index 0000000000..2a24f771e9 --- /dev/null +++ b/src/librustc_target/spec/hermit_base.rs @@ -0,0 +1,37 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions}; +use std::default::Default; + +pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + "-Wl,-Bstatic".to_string(), + "-Wl,--no-dynamic-linker".to_string(), + "-Wl,--gc-sections".to_string(), + "-Wl,--as-needed".to_string(), + ]); + + TargetOptions { + exe_allocation_crate: None, + executables: true, + has_elf_tls: true, + linker_is_gnu: true, + no_default_libraries: false, + panic_strategy: PanicStrategy::Abort, + position_independent_executables: false, + pre_link_args: args, + relocation_model: "static".to_string(), + target_family: Some("unix".to_string()), + tls_model: "local-exec".to_string(), + .. Default::default() + } +} diff --git a/src/librustc_target/spec/i386_apple_ios.rs b/src/librustc_target/spec/i386_apple_ios.rs index 9eb0327f62..15fd384f9c 100644 --- a/src/librustc_target/spec/i386_apple_ios.rs +++ b/src/librustc_target/spec/i386_apple_ios.rs @@ -21,7 +21,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "ios".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index d17789dfcc..a298b550fe 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -26,7 +26,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "macos".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/i686_linux_android.rs b/src/librustc_target/spec/i686_linux_android.rs index 171e089959..6aa139893e 100644 --- a/src/librustc_target/spec/i686_linux_android.rs +++ b/src/librustc_target/spec/i686_linux_android.rs @@ -31,7 +31,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "android".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/i686_unknown_cloudabi.rs b/src/librustc_target/spec/i686_unknown_cloudabi.rs index 335105bb1a..637bca71ad 100644 --- a/src/librustc_target/spec/i686_unknown_cloudabi.rs +++ b/src/librustc_target/spec/i686_unknown_cloudabi.rs @@ -26,7 +26,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "cloudabi".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/i686_unknown_dragonfly.rs b/src/librustc_target/spec/i686_unknown_dragonfly.rs index cb0c471353..fa02f0dd63 100644 --- a/src/librustc_target/spec/i686_unknown_dragonfly.rs +++ b/src/librustc_target/spec/i686_unknown_dragonfly.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "dragonfly".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/i686_unknown_freebsd.rs b/src/librustc_target/spec/i686_unknown_freebsd.rs index 3838a157d1..e11a455911 100644 --- a/src/librustc_target/spec/i686_unknown_freebsd.rs +++ b/src/librustc_target/spec/i686_unknown_freebsd.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "freebsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/i686_unknown_haiku.rs b/src/librustc_target/spec/i686_unknown_haiku.rs index 98f0787beb..775d80b0cf 100644 --- a/src/librustc_target/spec/i686_unknown_haiku.rs +++ b/src/librustc_target/spec/i686_unknown_haiku.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "haiku".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/i686_unknown_netbsd.rs b/src/librustc_target/spec/i686_unknown_netbsd.rs index d60ed98859..a9c0c11aab 100644 --- a/src/librustc_target/spec/i686_unknown_netbsd.rs +++ b/src/librustc_target/spec/i686_unknown_netbsd.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "netbsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/i686_unknown_openbsd.rs b/src/librustc_target/spec/i686_unknown_openbsd.rs index f22bf2abe4..471d6bd475 100644 --- a/src/librustc_target/spec/i686_unknown_openbsd.rs +++ b/src/librustc_target/spec/i686_unknown_openbsd.rs @@ -26,7 +26,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128".to_string(), arch: "x86".to_string(), target_os: "openbsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index c5d21cdc46..3c68b5a7ab 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -62,6 +62,7 @@ mod cloudabi_base; mod dragonfly_base; mod freebsd_base; mod haiku_base; +mod hermit_base; mod linux_base; mod linux_musl_base; mod openbsd_base; @@ -73,6 +74,7 @@ mod thumb_base; mod l4re_base; mod fuchsia_base; mod redox_base; +mod riscv_base; #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, RustcEncodable, RustcDecodable)] @@ -93,6 +95,29 @@ pub enum LldFlavor { Link, } +impl LldFlavor { + fn from_str(s: &str) -> Option { + Some(match s { + "darwin" => LldFlavor::Ld64, + "gnu" => LldFlavor::Ld, + "link" => LldFlavor::Link, + "wasm" => LldFlavor::Wasm, + _ => return None, + }) + } +} + +impl ToJson for LldFlavor { + fn to_json(&self) -> Json { + match *self { + LldFlavor::Ld64 => "darwin", + LldFlavor::Ld => "gnu", + LldFlavor::Link => "link", + LldFlavor::Wasm => "wasm", + }.to_json() + } +} + impl ToJson for LinkerFlavor { fn to_json(&self) -> Json { self.desc().to_json() @@ -318,6 +343,7 @@ supported_targets! { ("i686-unknown-openbsd", i686_unknown_openbsd), ("x86_64-unknown-openbsd", x86_64_unknown_openbsd), + ("aarch64-unknown-netbsd", aarch64_unknown_netbsd), ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf), ("armv7-unknown-netbsd-eabihf", armv7_unknown_netbsd_eabihf), ("i686-unknown-netbsd", i686_unknown_netbsd), @@ -345,7 +371,10 @@ supported_targets! { ("armv7-apple-ios", armv7_apple_ios), ("armv7s-apple-ios", armv7s_apple_ios), + ("armebv7r-none-eabi", armebv7r_none_eabi), ("armebv7r-none-eabihf", armebv7r_none_eabihf), + ("armv7r-none-eabi", armv7r_none_eabi), + ("armv7r-none-eabihf", armv7r_none_eabihf), ("x86_64-sun-solaris", x86_64_sun_solaris), ("sparcv9-sun-solaris", sparcv9_sun_solaris), @@ -353,9 +382,11 @@ supported_targets! { ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu), ("i686-pc-windows-gnu", i686_pc_windows_gnu), + ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc), ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc), ("i686-pc-windows-msvc", i686_pc_windows_msvc), ("i586-pc-windows-msvc", i586_pc_windows_msvc), + ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc), ("asmjs-unknown-emscripten", asmjs_unknown_emscripten), ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), @@ -373,6 +404,14 @@ supported_targets! { ("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf), ("i686-unknown-cloudabi", i686_unknown_cloudabi), ("x86_64-unknown-cloudabi", x86_64_unknown_cloudabi), + + ("aarch64-unknown-hermit", aarch64_unknown_hermit), + ("x86_64-unknown-hermit", x86_64_unknown_hermit), + + ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf), + ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf), + + ("aarch64-unknown-none", aarch64_unknown_none), } /// Everything `rustc` knows about how to compile for a specific target. @@ -427,6 +466,9 @@ pub struct TargetOptions { /// Linker to invoke pub linker: Option, + /// LLD flavor + pub lld_flavor: LldFlavor, + /// Linker arguments that are passed *before* any user-defined libraries. pub pre_link_args: LinkArgs, // ... unconditionally pub pre_link_args_crt: LinkArgs, // ... when linking with a bundled crt @@ -644,12 +686,13 @@ impl Default for TargetOptions { TargetOptions { is_builtin: false, linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()), + lld_flavor: LldFlavor::Ld, pre_link_args: LinkArgs::new(), pre_link_args_crt: LinkArgs::new(), post_link_args: LinkArgs::new(), asm_args: Vec::new(), cpu: "generic".to_string(), - features: "".to_string(), + features: String::new(), dynamic_linking: false, only_cdylib: false, executables: false, @@ -661,7 +704,7 @@ impl Default for TargetOptions { function_sections: true, dll_prefix: "lib".to_string(), dll_suffix: ".so".to_string(), - exe_suffix: "".to_string(), + exe_suffix: String::new(), staticlib_prefix: "lib".to_string(), staticlib_suffix: ".a".to_string(), target_family: None, @@ -741,7 +784,7 @@ impl Target { /// Maximum integer size in bits that this target can perform atomic /// operations on. pub fn max_atomic_width(&self) -> u64 { - self.options.max_atomic_width.unwrap_or(self.target_pointer_width.parse().unwrap()) + self.options.max_atomic_width.unwrap_or_else(|| self.target_pointer_width.parse().unwrap()) } pub fn is_abi_supported(&self, abi: Abi) -> bool { @@ -758,20 +801,16 @@ impl Target { // the JSON parser is not updated to match the structs. let get_req_field = |name: &str| { - match obj.find(name) - .map(|s| s.as_string()) - .and_then(|os| os.map(|s| s.to_string())) { - Some(val) => Ok(val), - None => { - return Err(format!("Field {} in target specification is required", name)) - } - } + obj.find(name) + .map(|s| s.as_string()) + .and_then(|os| os.map(|s| s.to_string())) + .ok_or_else(|| format!("Field {} in target specification is required", name)) }; let get_opt_field = |name: &str, default: &str| { obj.find(name).and_then(|s| s.as_string()) .map(|s| s.to_string()) - .unwrap_or(default.to_string()) + .unwrap_or_else(|| default.to_string()) }; let mut base = Target { @@ -850,6 +889,20 @@ impl Target { .map(|s| s.to_string() ); } } ); + ($key_name:ident, LldFlavor) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + if let Some(flavor) = LldFlavor::from_str(&s) { + base.options.$key_name = flavor; + } else { + return Some(Err(format!( + "'{}' is not a valid value for lld-flavor. \ + Use 'darwin', 'gnu', 'link' or 'wasm.", + s))) + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); ($key_name:ident, LinkerFlavor) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().map(|s| { @@ -905,6 +958,7 @@ impl Target { key!(is_builtin, bool); key!(linker, optional); + try!(key!(lld_flavor, LldFlavor)); key!(pre_link_args, link_args); key!(pre_link_args_crt, link_args); key!(pre_link_objects_exe, list); @@ -1001,7 +1055,6 @@ impl Target { /// filesystem access and JSON decoding. pub fn search(target_triple: &TargetTriple) -> Result { use std::env; - use std::ffi::OsString; use std::fs; use serialize::json; @@ -1012,8 +1065,8 @@ impl Target { Target::from_json(obj) } - match target_triple { - &TargetTriple::TargetTriple(ref target_triple) => { + match *target_triple { + TargetTriple::TargetTriple(ref target_triple) => { // check if triple is in list of supported targets if let Ok(t) = load_specific(target_triple) { return Ok(t) @@ -1026,8 +1079,7 @@ impl Target { PathBuf::from(target) }; - let target_path = env::var_os("RUST_TARGET_PATH") - .unwrap_or(OsString::new()); + let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or_default(); // FIXME 16351: add a sane default search path? @@ -1039,7 +1091,7 @@ impl Target { } Err(format!("Could not find specification for target {:?}", target_triple)) } - &TargetTriple::TargetPath(ref target_path) => { + TargetTriple::TargetPath(ref target_path) => { if target_path.is_file() { return load_file(&target_path); } @@ -1114,6 +1166,7 @@ impl ToJson for Target { target_option_val!(is_builtin); target_option_val!(linker); + target_option_val!(lld_flavor); target_option_val!(link_args - pre_link_args); target_option_val!(link_args - pre_link_args_crt); target_option_val!(pre_link_objects_exe); @@ -1184,7 +1237,7 @@ impl ToJson for Target { if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() - .map(Abi::name).map(|name| name.to_json()) + .map(|&name| Abi::name(name).to_json()) .collect::>().to_json()); } @@ -1223,9 +1276,9 @@ impl TargetTriple { /// /// If this target is a path, the file name (without extension) is returned. pub fn triple(&self) -> &str { - match self { - &TargetTriple::TargetTriple(ref triple) => triple, - &TargetTriple::TargetPath(ref path) => { + match *self { + TargetTriple::TargetTriple(ref triple) => triple, + TargetTriple::TargetPath(ref path) => { path.file_stem().expect("target path must not be empty").to_str() .expect("target path must be valid unicode") } @@ -1241,7 +1294,7 @@ impl TargetTriple { use std::collections::hash_map::DefaultHasher; let triple = self.triple(); - if let &TargetTriple::TargetPath(ref path) = self { + if let TargetTriple::TargetPath(ref path) = *self { let mut hasher = DefaultHasher::new(); path.hash(&mut hasher); let hash = hasher.finish(); diff --git a/src/librustc_target/spec/msp430_none_elf.rs b/src/librustc_target/spec/msp430_none_elf.rs index 3ac4c459c6..0958a95898 100644 --- a/src/librustc_target/spec/msp430_none_elf.rs +++ b/src/librustc_target/spec/msp430_none_elf.rs @@ -19,8 +19,8 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16".to_string(), arch: "msp430".to_string(), target_os: "none".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), + target_env: String::new(), + target_vendor: String::new(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/powerpc_unknown_netbsd.rs b/src/librustc_target/spec/powerpc_unknown_netbsd.rs index c05e40b9c2..740222c960 100644 --- a/src/librustc_target/spec/powerpc_unknown_netbsd.rs +++ b/src/librustc_target/spec/powerpc_unknown_netbsd.rs @@ -26,7 +26,7 @@ pub fn target() -> TargetResult { data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), target_os: "netbsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs new file mode 100644 index 0000000000..b199a50f0c --- /dev/null +++ b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs @@ -0,0 +1,41 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, LldFlavor, PanicStrategy, + Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(), + llvm_target: "riscv32".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + arch: "riscv32".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + linker: Some("rust-lld".to_string()), + cpu: "generic-rv32".to_string(), + max_atomic_width: Some(32), + atomic_cas: false, // incomplete +a extension + features: "+m,+a,+c".to_string(), + executables: true, + panic_strategy: PanicStrategy::Abort, + relocation_model: "static".to_string(), + emit_debug_gdb_scripts: false, + abi_blacklist: super::riscv_base::abi_blacklist(), + .. Default::default() + }, + }) +} diff --git a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs new file mode 100644 index 0000000000..68da1b61ad --- /dev/null +++ b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs @@ -0,0 +1,42 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, LldFlavor, PanicStrategy, + Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + Ok(Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(), + llvm_target: "riscv32".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + arch: "riscv32".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + linker: Some("rust-lld".to_string()), + cpu: "generic-rv32".to_string(), + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86005 + max_atomic_width: None, //Some(32), + atomic_cas: false, + features: "+m,+c".to_string(), + executables: true, + panic_strategy: PanicStrategy::Abort, + relocation_model: "static".to_string(), + emit_debug_gdb_scripts: false, + abi_blacklist: super::riscv_base::abi_blacklist(), + .. Default::default() + }, + }) +} diff --git a/src/librustc_target/spec/riscv_base.rs b/src/librustc_target/spec/riscv_base.rs new file mode 100644 index 0000000000..701ddf57b3 --- /dev/null +++ b/src/librustc_target/spec/riscv_base.rs @@ -0,0 +1,30 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::abi::Abi; + +// All the calling conventions trigger an assertion(Unsupported calling +// convention) in llvm on RISCV +pub fn abi_blacklist() -> Vec { + vec![ + Abi::Cdecl, + Abi::Stdcall, + Abi::Fastcall, + Abi::Vectorcall, + Abi::Thiscall, + Abi::Aapcs, + Abi::Win64, + Abi::SysV64, + Abi::PtxKernel, + Abi::Msp430Interrupt, + Abi::X86Interrupt, + Abi::AmdGpuKernel, + ] +} diff --git a/src/librustc_target/spec/sparc64_unknown_netbsd.rs b/src/librustc_target/spec/sparc64_unknown_netbsd.rs index 1c1bca9b2b..c663aa344d 100644 --- a/src/librustc_target/spec/sparc64_unknown_netbsd.rs +++ b/src/librustc_target/spec/sparc64_unknown_netbsd.rs @@ -24,7 +24,7 @@ pub fn target() -> TargetResult { data_layout: "E-m:e-i64:64-n32:64-S128".to_string(), arch: "sparc64".to_string(), target_os: "netbsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/sparcv9_sun_solaris.rs b/src/librustc_target/spec/sparcv9_sun_solaris.rs index 7dea1b75a3..8bc233107b 100644 --- a/src/librustc_target/spec/sparcv9_sun_solaris.rs +++ b/src/librustc_target/spec/sparcv9_sun_solaris.rs @@ -30,7 +30,7 @@ pub fn target() -> TargetResult { // just be confusing. arch: "sparc64".to_string(), target_os: "solaris".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "sun".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs index fdaf1dc611..4c9a4764ef 100644 --- a/src/librustc_target/spec/thumb_base.rs +++ b/src/librustc_target/spec/thumb_base.rs @@ -42,9 +42,8 @@ pub fn opts() -> TargetOptions { // See rust-lang/rfcs#1645 for a discussion about these defaults TargetOptions { executables: true, - // In 99%+ of cases, we want to use the `arm-none-eabi-gcc` compiler (there aren't many - // options around) - linker: Some("arm-none-eabi-gcc".to_string()), + // In most cases, LLD is good enough + linker: Some("rust-lld".to_string()), // Because these devices have very little resources having an unwinder is too onerous so we // default to "abort" because the "unwind" strategy is very rare. panic_strategy: PanicStrategy::Abort, diff --git a/src/librustc_target/spec/thumbv6m_none_eabi.rs b/src/librustc_target/spec/thumbv6m_none_eabi.rs index 2681250181..99034277ab 100644 --- a/src/librustc_target/spec/thumbv6m_none_eabi.rs +++ b/src/librustc_target/spec/thumbv6m_none_eabi.rs @@ -10,7 +10,7 @@ // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture) -use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; +use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -21,9 +21,9 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), target_os: "none".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), - linker_flavor: LinkerFlavor::Gcc, + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), options: TargetOptions { // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them diff --git a/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs b/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs new file mode 100644 index 0000000000..dab10ca241 --- /dev/null +++ b/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs @@ -0,0 +1,50 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetOptions, TargetResult, PanicStrategy}; + +pub fn target() -> TargetResult { + let mut base = super::windows_msvc_base::opts(); + + // Prevent error LNK2013: BRANCH24(T) fixup overflow + // The LBR optimization tries to eliminate branch islands, + // but if the displacement is larger than can fit + // in the instruction, this error will occur. The linker + // should be smart enough to insert branch islands only + // where necessary, but this is not the observed behavior. + // Disabling the LBR optimization works around the issue. + base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push( + "/OPT:NOLBR".to_string()); + + // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is + // implemented for windows/arm in LLVM + base.panic_strategy = PanicStrategy::Abort; + + Ok(Target { + llvm_target: "thumbv7a-pc-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "pc".to_string(), + linker_flavor: LinkerFlavor::Msvc, + + options: TargetOptions { + features: "+vfp3,+neon".to_string(), + cpu: "generic".to_string(), + max_atomic_width: Some(64), + abi_blacklist: super::arm_base::abi_blacklist(), + .. base + } + }) +} diff --git a/src/librustc_target/spec/thumbv7em_none_eabi.rs b/src/librustc_target/spec/thumbv7em_none_eabi.rs index ab85c97b1b..17fad29dd2 100644 --- a/src/librustc_target/spec/thumbv7em_none_eabi.rs +++ b/src/librustc_target/spec/thumbv7em_none_eabi.rs @@ -19,7 +19,7 @@ // To opt-in to hardware accelerated floating point operations, you can use, for example, // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`. -use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; +use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -30,9 +30,9 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), target_os: "none".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), - linker_flavor: LinkerFlavor::Gcc, + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), options: TargetOptions { max_atomic_width: Some(32), diff --git a/src/librustc_target/spec/thumbv7em_none_eabihf.rs b/src/librustc_target/spec/thumbv7em_none_eabihf.rs index 4e62f29134..02ede112ed 100644 --- a/src/librustc_target/spec/thumbv7em_none_eabihf.rs +++ b/src/librustc_target/spec/thumbv7em_none_eabihf.rs @@ -18,7 +18,7 @@ // // To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag. -use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; +use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -29,9 +29,9 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), target_os: "none".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), - linker_flavor: LinkerFlavor::Gcc, + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), options: TargetOptions { // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the diff --git a/src/librustc_target/spec/thumbv7m_none_eabi.rs b/src/librustc_target/spec/thumbv7m_none_eabi.rs index 10dc503388..f4fffade16 100644 --- a/src/librustc_target/spec/thumbv7m_none_eabi.rs +++ b/src/librustc_target/spec/thumbv7m_none_eabi.rs @@ -10,7 +10,7 @@ // Targets the Cortex-M3 processor (ARMv7-M) -use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; +use spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { Ok(Target { @@ -21,9 +21,9 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), target_os: "none".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), - linker_flavor: LinkerFlavor::Gcc, + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), options: TargetOptions { max_atomic_width: Some(32), diff --git a/src/librustc_target/spec/wasm32_experimental_emscripten.rs b/src/librustc_target/spec/wasm32_experimental_emscripten.rs index 164df20f84..60ad2d2324 100644 --- a/src/librustc_target/spec/wasm32_experimental_emscripten.rs +++ b/src/librustc_target/spec/wasm32_experimental_emscripten.rs @@ -43,7 +43,7 @@ pub fn target() -> Result { target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), target_os: "emscripten".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), arch: "wasm32".to_string(), diff --git a/src/librustc_target/spec/wasm32_unknown_emscripten.rs b/src/librustc_target/spec/wasm32_unknown_emscripten.rs index 5077abf1e0..b4c09f86b8 100644 --- a/src/librustc_target/spec/wasm32_unknown_emscripten.rs +++ b/src/librustc_target/spec/wasm32_unknown_emscripten.rs @@ -40,7 +40,7 @@ pub fn target() -> Result { target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), target_os: "emscripten".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), arch: "wasm32".to_string(), diff --git a/src/librustc_target/spec/wasm32_unknown_unknown.rs b/src/librustc_target/spec/wasm32_unknown_unknown.rs index 51d402e197..c0455ceb83 100644 --- a/src/librustc_target/spec/wasm32_unknown_unknown.rs +++ b/src/librustc_target/spec/wasm32_unknown_unknown.rs @@ -32,12 +32,11 @@ pub fn target() -> Result { // relatively self-explanatory! exe_suffix: ".wasm".to_string(), - dll_prefix: "".to_string(), + dll_prefix: String::new(), dll_suffix: ".wasm".to_string(), linker_is_gnu: false, - // A bit of a lie, but "eh" - max_atomic_width: Some(32), + max_atomic_width: Some(64), // Unwinding doesn't work right now, so the whole target unconditionally // defaults to panic=abort. Note that this is guaranteed to change in @@ -53,6 +52,7 @@ pub fn target() -> Result { // we use the LLD shipped with the Rust toolchain by default linker: Some("rust-lld".to_owned()), + lld_flavor: LldFlavor::Wasm, .. Default::default() }; @@ -64,7 +64,7 @@ pub fn target() -> Result { // This is basically guaranteed to change in the future, don't rely on // this. Use `not(target_os = "emscripten")` for now. target_os: "unknown".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), arch: "wasm32".to_string(), diff --git a/src/librustc_target/spec/windows_base.rs b/src/librustc_target/spec/windows_base.rs index 176df9f132..29049b1427 100644 --- a/src/librustc_target/spec/windows_base.rs +++ b/src/librustc_target/spec/windows_base.rs @@ -77,10 +77,10 @@ pub fn opts() -> TargetOptions { linker: Some("gcc".to_string()), dynamic_linking: true, executables: true, - dll_prefix: "".to_string(), + dll_prefix: String::new(), dll_suffix: ".dll".to_string(), exe_suffix: ".exe".to_string(), - staticlib_prefix: "".to_string(), + staticlib_prefix: String::new(), staticlib_suffix: ".lib".to_string(), no_default_libraries: true, target_family: Some("windows".to_string()), diff --git a/src/librustc_target/spec/windows_msvc_base.rs b/src/librustc_target/spec/windows_msvc_base.rs index 1f00e690cd..27879de9ab 100644 --- a/src/librustc_target/spec/windows_msvc_base.rs +++ b/src/librustc_target/spec/windows_msvc_base.rs @@ -21,10 +21,10 @@ pub fn opts() -> TargetOptions { function_sections: true, dynamic_linking: true, executables: true, - dll_prefix: "".to_string(), + dll_prefix: String::new(), dll_suffix: ".dll".to_string(), exe_suffix: ".exe".to_string(), - staticlib_prefix: "".to_string(), + staticlib_prefix: String::new(), staticlib_suffix: ".lib".to_string(), target_family: Some("windows".to_string()), is_like_windows: true, diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index a4efd7e006..150590ba68 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -26,7 +26,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "macos".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_apple_ios.rs b/src/librustc_target/spec/x86_64_apple_ios.rs index eeb53d72fe..e184ec2435 100644 --- a/src/librustc_target/spec/x86_64_apple_ios.rs +++ b/src/librustc_target/spec/x86_64_apple_ios.rs @@ -21,7 +21,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "ios".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "apple".to_string(), linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { diff --git a/src/librustc_target/spec/x86_64_fuchsia.rs b/src/librustc_target/spec/x86_64_fuchsia.rs index e8fa179887..62148a740d 100644 --- a/src/librustc_target/spec/x86_64_fuchsia.rs +++ b/src/librustc_target/spec/x86_64_fuchsia.rs @@ -25,8 +25,8 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "fuchsia".to_string(), - target_env: "".to_string(), - target_vendor: "".to_string(), + target_env: String::new(), + target_vendor: String::new(), linker_flavor: LinkerFlavor::Gcc, options: base, }) diff --git a/src/librustc_target/spec/x86_64_linux_android.rs b/src/librustc_target/spec/x86_64_linux_android.rs index 06abe91678..ea67dc6bde 100644 --- a/src/librustc_target/spec/x86_64_linux_android.rs +++ b/src/librustc_target/spec/x86_64_linux_android.rs @@ -27,7 +27,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "android".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs index ed15cfd903..af846653af 100644 --- a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs +++ b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs @@ -33,7 +33,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "netbsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "rumprun".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_sun_solaris.rs b/src/librustc_target/spec/x86_64_sun_solaris.rs index e84f21c500..beb23dce06 100644 --- a/src/librustc_target/spec/x86_64_sun_solaris.rs +++ b/src/librustc_target/spec/x86_64_sun_solaris.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "solaris".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "sun".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_unknown_bitrig.rs b/src/librustc_target/spec/x86_64_unknown_bitrig.rs index 21ec6dffcb..a98fc80716 100644 --- a/src/librustc_target/spec/x86_64_unknown_bitrig.rs +++ b/src/librustc_target/spec/x86_64_unknown_bitrig.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "bitrig".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_unknown_cloudabi.rs b/src/librustc_target/spec/x86_64_unknown_cloudabi.rs index 8dc8bd7a7f..16df900068 100644 --- a/src/librustc_target/spec/x86_64_unknown_cloudabi.rs +++ b/src/librustc_target/spec/x86_64_unknown_cloudabi.rs @@ -26,7 +26,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "cloudabi".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_unknown_dragonfly.rs b/src/librustc_target/spec/x86_64_unknown_dragonfly.rs index 50b2871c2e..4c14a321fe 100644 --- a/src/librustc_target/spec/x86_64_unknown_dragonfly.rs +++ b/src/librustc_target/spec/x86_64_unknown_dragonfly.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "dragonfly".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_unknown_freebsd.rs b/src/librustc_target/spec/x86_64_unknown_freebsd.rs index f0aa81ed45..4515b33087 100644 --- a/src/librustc_target/spec/x86_64_unknown_freebsd.rs +++ b/src/librustc_target/spec/x86_64_unknown_freebsd.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "freebsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_unknown_haiku.rs b/src/librustc_target/spec/x86_64_unknown_haiku.rs index 68fa58b922..7e6b56866e 100644 --- a/src/librustc_target/spec/x86_64_unknown_haiku.rs +++ b/src/librustc_target/spec/x86_64_unknown_haiku.rs @@ -27,7 +27,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "haiku".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_unknown_hermit.rs b/src/librustc_target/spec/x86_64_unknown_hermit.rs new file mode 100644 index 0000000000..c879e94e6e --- /dev/null +++ b/src/librustc_target/spec/x86_64_unknown_hermit.rs @@ -0,0 +1,33 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::hermit_base::opts(); + base.cpu = "x86-64".to_string(); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.linker = Some("x86_64-hermit-gcc".to_string()); + base.max_atomic_width = Some(64); + + Ok(Target { + llvm_target: "x86_64-unknown-hermit".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "hermit".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_target/spec/x86_64_unknown_netbsd.rs b/src/librustc_target/spec/x86_64_unknown_netbsd.rs index 6e8ca6b9e1..de53c9e99e 100644 --- a/src/librustc_target/spec/x86_64_unknown_netbsd.rs +++ b/src/librustc_target/spec/x86_64_unknown_netbsd.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "netbsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_unknown_openbsd.rs b/src/librustc_target/spec/x86_64_unknown_openbsd.rs index c60b7c8668..de22c77d1e 100644 --- a/src/librustc_target/spec/x86_64_unknown_openbsd.rs +++ b/src/librustc_target/spec/x86_64_unknown_openbsd.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "openbsd".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_target/spec/x86_64_unknown_redox.rs b/src/librustc_target/spec/x86_64_unknown_redox.rs index 548dfb0610..12a354b499 100644 --- a/src/librustc_target/spec/x86_64_unknown_redox.rs +++ b/src/librustc_target/spec/x86_64_unknown_redox.rs @@ -25,7 +25,7 @@ pub fn target() -> TargetResult { data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), arch: "x86_64".to_string(), target_os: "redox".to_string(), - target_env: "".to_string(), + target_env: String::new(), target_vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, options: base, diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index 1349839111..cd21ee601a 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -16,4 +16,5 @@ rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -chalk-engine = { version = "0.6.0", default-features=false } +chalk-engine = { version = "0.7.0", default-features=false } +smallvec = { version = "0.6.5", features = ["union"] } diff --git a/src/librustc_traits/chalk_context.rs b/src/librustc_traits/chalk_context.rs index b0f0b105f3..4c28df97bd 100644 --- a/src/librustc_traits/chalk_context.rs +++ b/src/librustc_traits/chalk_context.rs @@ -25,7 +25,7 @@ use rustc::traits::{ use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use rustc::ty::subst::Kind; use rustc::ty::{self, TyCtxt}; -use rustc_data_structures::small_vec::SmallVec; +use smallvec::SmallVec; use std::fmt::{self, Debug}; use std::marker::PhantomData; @@ -237,7 +237,7 @@ impl context::ContextOps> for ChalkContext<'cx, 'gcx> { // _ => false, // }, // Kind::Type(ty) => match ty.sty { -// ty::TyInfer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1, +// ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1, // _ => false, // }, // }) diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 5f9060b362..e3ec2e6b9c 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -18,7 +18,7 @@ use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt}; use rustc::util::nodemap::FxHashSet; use rustc_data_structures::sync::Lrc; -use syntax::codemap::{Span, DUMMY_SP}; +use syntax::source_map::{Span, DUMMY_SP}; crate fn provide(p: &mut Providers) { *p = Providers { @@ -81,7 +81,7 @@ fn dropck_outlives<'tcx>( // into the types of its fields `(B, Vec
)`. These will get // pushed onto the stack. Eventually, expanding `Vec` will // lead to us trying to push `A` a second time -- to prevent - // infinite recusion, we notice that `A` was already pushed + // infinite recursion, we notice that `A` was already pushed // once and stop. let mut ty_stack = vec![(for_ty, 0)]; @@ -119,11 +119,11 @@ fn dropck_outlives<'tcx>( match ty.sty { // All parameters live for the duration of the // function. - ty::TyParam(..) => {} + ty::Param(..) => {} // A projection that we couldn't resolve - it // might have a destructor. - ty::TyProjection(..) | ty::TyAnon(..) => { + ty::Projection(..) | ty::Opaque(..) => { result.kinds.push(ty.into()); } @@ -173,39 +173,39 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( } let result = match ty.sty { - ty::TyBool - | ty::TyChar - | ty::TyInt(_) - | ty::TyUint(_) - | ty::TyFloat(_) - | ty::TyStr - | ty::TyNever - | ty::TyForeign(..) - | ty::TyRawPtr(..) - | ty::TyRef(..) - | ty::TyFnDef(..) - | ty::TyFnPtr(_) - | ty::TyGeneratorWitness(..) => { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Never + | ty::Foreign(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::GeneratorWitness(..) => { // these types never have a destructor Ok(DtorckConstraint::empty()) } - ty::TyArray(ety, _) | ty::TySlice(ety) => { + ty::Array(ety, _) | ty::Slice(ety) => { // single-element containers, behave like their element dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety) } - ty::TyTuple(tys) => tys + ty::Tuple(tys) => tys .iter() .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) .collect(), - ty::TyClosure(def_id, substs) => substs + ty::Closure(def_id, substs) => substs .upvar_tys(def_id, tcx) .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) .collect(), - ty::TyGenerator(def_id, substs, _movability) => { + ty::Generator(def_id, substs, _movability) => { // rust-lang/rust#49918: types can be constructed, stored // in the interior, and sit idle when generator yields // (and is subsequently dropped). @@ -216,7 +216,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( // its interior). // // However, the interior's representation uses things like - // TyGeneratorWitness that explicitly assume they are not + // GeneratorWitness that explicitly assume they are not // traversed in such a manner. So instead, we will // simplify things for now by treating all generators as // if they were like trait objects, where its upvars must @@ -242,7 +242,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( Ok(constraint) } - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { let DtorckConstraint { dtorck_types, outlives, @@ -259,20 +259,20 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( // Objects must be alive in order for their destructor // to be called. - ty::TyDynamic(..) => Ok(DtorckConstraint { + ty::Dynamic(..) => Ok(DtorckConstraint { outlives: vec![ty.into()], dtorck_types: vec![], overflows: vec![], }), // Types that can't be resolved. Pass them forward. - ty::TyProjection(..) | ty::TyAnon(..) | ty::TyParam(..) => Ok(DtorckConstraint { + ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => Ok(DtorckConstraint { outlives: vec![], dtorck_types: vec![ty], overflows: vec![], }), - ty::TyInfer(..) | ty::TyError => { + ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. Err(NoSolution) diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index e8a3447902..b5ee346569 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -13,7 +13,7 @@ use rustc::traits::{EvaluationResult, Obligation, ObligationCause, use rustc::traits::query::CanonicalPredicateGoal; use rustc::ty::query::Providers; use rustc::ty::{ParamEnvAnd, TyCtxt}; -use syntax::codemap::DUMMY_SP; +use syntax::source_map::DUMMY_SP; crate fn provide(p: &mut Providers) { *p = Providers { diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index b6560fae11..7b31518c07 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -21,7 +21,7 @@ use rustc::ty::outlives::Component; use rustc::ty::query::Providers; use rustc::ty::wf; use syntax::ast::DUMMY_NODE_ID; -use syntax::codemap::DUMMY_SP; +use syntax::source_map::DUMMY_SP; use rustc::traits::FulfillmentContext; use rustc_data_structures::sync::Lrc; diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index d17cf35f18..a6618efebb 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -11,11 +11,11 @@ //! New recursive solver modeled on Chalk's recursive solver. Most of //! the guts are broken up into modules; see the comments in those modules. -#![feature(crate_in_paths)] +#![cfg_attr(stage0, feature(crate_in_paths))] #![feature(crate_visibility_modifier)] -#![feature(extern_prelude)] -#![feature(iterator_find_map)] +#![cfg_attr(stage0, feature(extern_prelude))] #![feature(in_band_lifetimes)] +#![cfg_attr(not(stage0), feature(nll))] #![recursion_limit="256"] @@ -27,6 +27,7 @@ extern crate rustc; extern crate rustc_data_structures; extern crate syntax; extern crate syntax_pos; +extern crate smallvec; mod chalk_context; mod dropck_outlives; diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index a3c24f8af2..9fd3b318ec 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -17,7 +17,7 @@ use rustc::traits::{ WhereClause, }; use rustc::ty::query::Providers; -use rustc::ty::{self, Slice, TyCtxt}; +use rustc::ty::{self, List, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use std::mem; use syntax::ast; @@ -162,7 +162,7 @@ crate fn program_clauses_for<'a, 'tcx>( DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id), DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id), DefPathData::TypeNs(..) => program_clauses_for_type_def(tcx, def_id), - _ => Slice::empty(), + _ => List::empty(), } } @@ -319,7 +319,7 @@ fn program_clauses_for_trait<'a, 'tcx>( fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> { if let ImplPolarity::Negative = tcx.impl_polarity(def_id) { - return Slice::empty(); + return List::empty(); } // Rule Implemented-From-Impl (see rustc guide) diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs index 0c78fd74a2..b3ba86ad8a 100644 --- a/src/librustc_tsan/lib.rs +++ b/src/librustc_tsan/lib.rs @@ -10,6 +10,7 @@ #![sanitizer_runtime] #![feature(alloc_system)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 184cb9826b..881fa2604b 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -10,12 +10,13 @@ crate-type = ["dylib"] test = false [dependencies] -log = "0.4" -syntax = { path = "../libsyntax" } arena = { path = "../libarena" } +log = "0.4" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_errors = { path = "../librustc_errors" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } rustc_target = { path = "../librustc_target" } +smallvec = { version = "0.6.5", features = ["union"] } +syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0bc7ae0418..72502cda6e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -12,28 +12,32 @@ //! representation. The main routine here is `ast_ty_to_ty()`: each use //! is parameterized by an instance of `AstConv`. -use rustc_data_structures::accumulate_vec::AccumulateVec; -use hir::{self, GenericArg}; +use smallvec::SmallVec; +use hir::{self, GenericArg, GenericArgs}; use hir::def::Def; use hir::def_id::DefId; +use hir::HirVec; use middle::resolve_lifetime as rl; use namespace::Namespace; -use rustc::ty::subst::{Subst, Substs}; +use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; -use rustc::ty::GenericParamDefKind; +use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::wf::object_region_bounds; use rustc_target::spec::abi; +use std::collections::BTreeSet; use std::slice; use require_c_abi_if_variadic; use util::common::ErrorReported; -use util::nodemap::{FxHashSet, FxHashMap}; -use errors::FatalError; +use util::nodemap::FxHashMap; +use errors::{FatalError, DiagnosticId}; +use lint; use std::iter; use syntax::ast; +use syntax::ptr::P; use syntax::feature_gate::{GateIssue, emit_feature_err}; -use syntax_pos::Span; +use syntax_pos::{Span, MultiSpan}; pub trait AstConv<'gcx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; @@ -88,15 +92,17 @@ struct ConvertedBinding<'tcx> { span: Span, } -struct ParamRange { - required: usize, - accepted: usize +#[derive(PartialEq)] +enum GenericArgPosition { + Type, + Value, // e.g. functions + MethodCall, } /// Dummy type used for the `Self` of a `TraitRef` created for converting /// a trait object, and which gets removed in `ExistentialTraitRef`. /// This type must not appear anywhere in other converted types. -const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::FreshTy(0)); +const TRAIT_OBJECT_DUMMY_SELF: ty::TyKind<'static> = ty::Infer(ty::FreshTy(0)); impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { pub fn ast_region_to_region(&self, @@ -176,21 +182,345 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { -> &'tcx Substs<'tcx> { - let (substs, assoc_bindings) = - item_segment.with_generic_args(|generic_args| { - self.create_substs_for_ast_path( - span, - def_id, - generic_args, - item_segment.infer_types, - None) - }); + let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| { + self.create_substs_for_ast_path( + span, + def_id, + generic_args, + item_segment.infer_types, + None, + ) + }); - assoc_bindings.first().map(|b| self.prohibit_projection(b.span)); + assoc_bindings.first().map(|b| Self::prohibit_assoc_ty_binding(self.tcx(), b.span)); substs } + /// Report error if there is an explicit type parameter when using `impl Trait`. + fn check_impl_trait( + tcx: TyCtxt, + span: Span, + seg: &hir::PathSegment, + generics: &ty::Generics, + ) -> bool { + let explicit = !seg.infer_types; + let impl_trait = generics.params.iter().any(|param| match param.kind { + ty::GenericParamDefKind::Type { + synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. + } => true, + _ => false, + }); + + if explicit && impl_trait { + let mut err = struct_span_err! { + tcx.sess, + span, + E0632, + "cannot provide explicit type parameters when `impl Trait` is \ + used in argument position." + }; + + err.emit(); + } + + impl_trait + } + + /// Check that the correct number of generic arguments have been provided. + /// Used specifically for function calls. + pub fn check_generic_arg_count_for_call( + tcx: TyCtxt, + span: Span, + def: &ty::Generics, + seg: &hir::PathSegment, + is_method_call: bool, + ) -> bool { + let empty_args = P(hir::GenericArgs { + args: HirVec::new(), bindings: HirVec::new(), parenthesized: false, + }); + let suppress_mismatch = Self::check_impl_trait(tcx, span, seg, &def); + Self::check_generic_arg_count( + tcx, + span, + def, + if let Some(ref args) = seg.args { + args + } else { + &empty_args + }, + if is_method_call { + GenericArgPosition::MethodCall + } else { + GenericArgPosition::Value + }, + def.parent.is_none() && def.has_self, // `has_self` + seg.infer_types || suppress_mismatch, // `infer_types` + ) + } + + /// Check that the correct number of generic arguments have been provided. + /// This is used both for datatypes and function calls. + fn check_generic_arg_count( + tcx: TyCtxt, + span: Span, + def: &ty::Generics, + args: &hir::GenericArgs, + position: GenericArgPosition, + has_self: bool, + infer_types: bool, + ) -> bool { + // At this stage we are guaranteed that the generic arguments are in the correct order, e.g. + // that lifetimes will proceed types. So it suffices to check the number of each generic + // arguments in order to validate them with respect to the generic parameters. + let param_counts = def.own_counts(); + let arg_counts = args.own_counts(); + let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0; + + let mut defaults: ty::GenericParamCount = Default::default(); + for param in &def.params { + match param.kind { + GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Type { has_default, .. } => { + defaults.types += has_default as usize + } + }; + } + + if position != GenericArgPosition::Type && !args.bindings.is_empty() { + AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span); + } + + // Prohibit explicit lifetime arguments if late-bound lifetime parameters are present. + if !infer_lifetimes { + if let Some(span_late) = def.has_late_bound_regions { + let msg = "cannot specify lifetime arguments explicitly \ + if late bound lifetime parameters are present"; + let note = "the late bound lifetime parameter is introduced here"; + let span = args.args[0].span(); + if position == GenericArgPosition::Value + && arg_counts.lifetimes != param_counts.lifetimes { + let mut err = tcx.sess.struct_span_err(span, msg); + err.span_note(span_late, note); + err.emit(); + return true; + } else { + let mut multispan = MultiSpan::from_span(span); + multispan.push_span_label(span_late, note.to_string()); + tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, + args.args[0].id(), multispan, msg); + return false; + } + } + } + + let check_kind_count = |kind, + required, + permitted, + provided, + offset| { + // We enforce the following: `required` <= `provided` <= `permitted`. + // For kinds without defaults (i.e. lifetimes), `required == permitted`. + // For other kinds (i.e. types), `permitted` may be greater than `required`. + if required <= provided && provided <= permitted { + return false; + } + + // Unfortunately lifetime and type parameter mismatches are typically styled + // differently in diagnostics, which means we have a few cases to consider here. + let (bound, quantifier) = if required != permitted { + if provided < required { + (required, "at least ") + } else { // provided > permitted + (permitted, "at most ") + } + } else { + (required, "") + }; + + let mut span = span; + let label = if required == permitted && provided > permitted { + let diff = provided - permitted; + if diff == 1 { + // In the case when the user has provided too many arguments, + // we want to point to the first unexpected argument. + let first_superfluous_arg: &GenericArg = &args.args[offset + permitted]; + span = first_superfluous_arg.span(); + } + format!( + "{}unexpected {} argument{}", + if diff != 1 { format!("{} ", diff) } else { String::new() }, + kind, + if diff != 1 { "s" } else { "" }, + ) + } else { + format!( + "expected {}{} {} argument{}", + quantifier, + bound, + kind, + if bound != 1 { "s" } else { "" }, + ) + }; + + tcx.sess.struct_span_err_with_code( + span, + &format!( + "wrong number of {} arguments: expected {}{}, found {}", + kind, + quantifier, + bound, + provided, + ), + DiagnosticId::Error("E0107".into()) + ).span_label(span, label).emit(); + + provided > required // `suppress_error` + }; + + if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes { + check_kind_count( + "lifetime", + param_counts.lifetimes, + param_counts.lifetimes, + arg_counts.lifetimes, + 0, + ); + } + if !infer_types + || arg_counts.types > param_counts.types - defaults.types - has_self as usize { + check_kind_count( + "type", + param_counts.types - defaults.types - has_self as usize, + param_counts.types - has_self as usize, + arg_counts.types, + arg_counts.lifetimes, + ) + } else { + false + } + } + + /// Creates the relevant generic argument substitutions + /// corresponding to a set of generic parameters. + pub fn create_substs_for_generic_args<'a, 'b, A, P, I>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + def_id: DefId, + parent_substs: &[Kind<'tcx>], + has_self: bool, + self_ty: Option>, + args_for_def_id: A, + provided_kind: P, + inferred_kind: I, + ) -> &'tcx Substs<'tcx> where + A: Fn(DefId) -> (Option<&'b GenericArgs>, bool), + P: Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>, + I: Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx> + { + // Collect the segments of the path: we need to substitute arguments + // for parameters throughout the entire path (wherever there are + // generic parameters). + let mut parent_defs = tcx.generics_of(def_id); + let count = parent_defs.count(); + let mut stack = vec![(def_id, parent_defs)]; + while let Some(def_id) = parent_defs.parent { + parent_defs = tcx.generics_of(def_id); + stack.push((def_id, parent_defs)); + } + + // We manually build up the substitution, rather than using convenience + // methods in subst.rs so that we can iterate over the arguments and + // parameters in lock-step linearly, rather than trying to match each pair. + let mut substs: SmallVec<[Kind<'tcx>; 8]> = SmallVec::with_capacity(count); + + // Iterate over each segment of the path. + while let Some((def_id, defs)) = stack.pop() { + let mut params = defs.params.iter().peekable(); + + // If we have already computed substitutions for parents, we can use those directly. + while let Some(¶m) = params.peek() { + if let Some(&kind) = parent_substs.get(param.index as usize) { + substs.push(kind); + params.next(); + } else { + break; + } + } + + // (Unless it's been handled in `parent_substs`) `Self` is handled first. + if has_self { + if let Some(¶m) = params.peek() { + if param.index == 0 { + if let GenericParamDefKind::Type { .. } = param.kind { + substs.push(self_ty.map(|ty| ty.into()) + .unwrap_or_else(|| inferred_kind(None, param, true))); + params.next(); + } + } + } + } + + // Check whether this segment takes generic arguments and the user has provided any. + let (generic_args, infer_types) = args_for_def_id(def_id); + + let mut args = generic_args.iter().flat_map(|generic_args| generic_args.args.iter()) + .peekable(); + + loop { + // We're going to iterate through the generic arguments that the user + // provided, matching them with the generic parameters we expect. + // Mismatches can occur as a result of elided lifetimes, or for malformed + // input. We try to handle both sensibly. + match (args.peek(), params.peek()) { + (Some(&arg), Some(¶m)) => { + match (arg, ¶m.kind) { + (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime) + | (GenericArg::Type(_), GenericParamDefKind::Type { .. }) => { + substs.push(provided_kind(param, arg)); + args.next(); + params.next(); + } + (GenericArg::Lifetime(_), GenericParamDefKind::Type { .. }) => { + // We expected a type argument, but got a lifetime + // argument. This is an error, but we need to handle it + // gracefully so we can report sensible errors. In this + // case, we're simply going to infer this argument. + args.next(); + } + (GenericArg::Type(_), GenericParamDefKind::Lifetime) => { + // We expected a lifetime argument, but got a type + // argument. That means we're inferring the lifetimes. + substs.push(inferred_kind(None, param, infer_types)); + params.next(); + } + } + } + (Some(_), None) => { + // We should never be able to reach this point with well-formed input. + // Getting to this point means the user supplied more arguments than + // there are parameters. + args.next(); + } + (None, Some(¶m)) => { + // If there are fewer arguments than parameters, it means + // we're inferring the remaining arguments. + match param.kind { + GenericParamDefKind::Lifetime | GenericParamDefKind::Type { .. } => { + let kind = inferred_kind(Some(&substs), param, infer_types); + substs.push(kind); + } + } + args.next(); + params.next(); + } + (None, None) => break, + } + } + } + + tcx.intern_substs(&substs) + } + /// Given the type/region arguments provided to some path (along with /// an implicit Self, if this is a trait reference) returns the complete /// set of substitutions. This may involve applying defaulted type parameters. @@ -204,60 +534,29 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { self_ty: Option>) -> (&'tcx Substs<'tcx>, Vec>) { - let tcx = self.tcx(); - - debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ - generic_args={:?})", - def_id, self_ty, generic_args); - // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). + debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ + generic_args={:?})", + def_id, self_ty, generic_args); - // FIXME(varkor): Separating out the parameters is messy. - let lifetimes: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg { - GenericArg::Lifetime(lt) => Some(lt), - _ => None, - }).collect(); - let types: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }).collect(); - let lt_provided = lifetimes.len(); - let ty_provided = types.len(); - - let decl_generics = tcx.generics_of(def_id); - let mut lt_accepted = 0; - let mut ty_params = ParamRange { required: 0, accepted: 0 }; - for param in &decl_generics.params { - match param.kind { - GenericParamDefKind::Lifetime => { - lt_accepted += 1; - } - GenericParamDefKind::Type { has_default, .. } => { - ty_params.accepted += 1; - if !has_default { - ty_params.required += 1; - } - } - }; - } - if self_ty.is_some() { - ty_params.required -= 1; - ty_params.accepted -= 1; - } - - if lt_accepted != lt_provided { - report_lifetime_number_error(tcx, span, lt_provided, lt_accepted); - } + let tcx = self.tcx(); + let generic_params = tcx.generics_of(def_id); // If a self-type was declared, one should be provided. - assert_eq!(decl_generics.has_self, self_ty.is_some()); + assert_eq!(generic_params.has_self, self_ty.is_some()); - // Check the number of type parameters supplied by the user. - if !infer_types || ty_provided > ty_params.required { - check_type_argument_count(tcx, span, ty_provided, ty_params); - } + let has_self = generic_params.has_self; + Self::check_generic_arg_count( + self.tcx(), + span, + &generic_params, + &generic_args, + GenericArgPosition::Type, + has_self, + infer_types, + ); let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); let default_needs_object_self = |param: &ty::GenericParamDef| { @@ -274,71 +573,74 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { false }; - let own_self = self_ty.is_some() as usize; - let substs = Substs::for_item(tcx, def_id, |param, substs| { - match param.kind { - GenericParamDefKind::Lifetime => { - let i = param.index as usize - own_self; - if let Some(lt) = lifetimes.get(i) { - self.ast_region_to_region(lt, Some(param)).into() - } else { - tcx.types.re_static.into() + let substs = Self::create_substs_for_generic_args( + self.tcx(), + def_id, + &[][..], + self_ty.is_some(), + self_ty, + // Provide the generic args, and whether types should be inferred. + |_| (Some(generic_args), infer_types), + // Provide substitutions for parameters for which (valid) arguments have been provided. + |param, arg| { + match (¶m.kind, arg) { + (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { + self.ast_region_to_region(<, Some(param)).into() } - } - GenericParamDefKind::Type { has_default, .. } => { - let i = param.index as usize; - - // Handle Self first, so we can adjust the index to match the AST. - if let (0, Some(ty)) = (i, self_ty) { - return ty.into(); + (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { + self.ast_ty_to_ty(&ty).into() } - - let i = i - (lt_accepted + own_self); - if i < ty_provided { - // A provided type parameter. - self.ast_ty_to_ty(&types[i]).into() - } else if infer_types { - // No type parameters were provided, we can infer all. - if !default_needs_object_self(param) { - self.ty_infer_for_def(param, span).into() + _ => unreachable!(), + } + }, + // Provide substitutions for parameters for which arguments are inferred. + |substs, param, infer_types| { + match param.kind { + GenericParamDefKind::Lifetime => tcx.types.re_static.into(), + GenericParamDefKind::Type { has_default, .. } => { + if !infer_types && has_default { + // No type parameter provided, but a default exists. + + // If we are converting an object type, then the + // `Self` parameter is unknown. However, some of the + // other type parameters may reference `Self` in their + // defaults. This will lead to an ICE if we are not + // careful! + if default_needs_object_self(param) { + struct_span_err!(tcx.sess, span, E0393, + "the type parameter `{}` must be explicitly \ + specified", + param.name) + .span_label(span, + format!("missing reference to `{}`", param.name)) + .note(&format!("because of the default `Self` reference, \ + type parameters must be specified on object \ + types")) + .emit(); + tcx.types.err.into() + } else { + // This is a default type parameter. + self.normalize_ty( + span, + tcx.at(span).type_of(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(span)) + ).into() + } + } else if infer_types { + // No type parameters were provided, we can infer all. + if !default_needs_object_self(param) { + self.ty_infer_for_def(param, span).into() + } else { + self.ty_infer(span).into() + } } else { - self.ty_infer(span).into() - } - } else if has_default { - // No type parameter provided, but a default exists. - - // If we are converting an object type, then the - // `Self` parameter is unknown. However, some of the - // other type parameters may reference `Self` in their - // defaults. This will lead to an ICE if we are not - // careful! - if default_needs_object_self(param) { - struct_span_err!(tcx.sess, span, E0393, - "the type parameter `{}` must be explicitly \ - specified", - param.name) - .span_label(span, - format!("missing reference to `{}`", param.name)) - .note(&format!("because of the default `Self` reference, \ - type parameters must be specified on object \ - types")) - .emit(); + // We've already errored above about the mismatch. tcx.types.err.into() - } else { - // This is a default type parameter. - self.normalize_ty( - span, - tcx.at(span).type_of(param.def_id) - .subst_spanned(tcx, substs, Some(span)) - ).into() } - } else { - // We've already errored above about the mismatch. - tcx.types.err.into() } } - } - }); + }, + ); let assoc_bindings = generic_args.bindings.iter().map(|binding| { ConvertedBinding { @@ -348,8 +650,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } }).collect(); - debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", - decl_generics, self_ty, substs); + debug!("create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", + generic_params, self_ty, substs); (substs, assoc_bindings) } @@ -444,7 +746,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { trait_def_id, self_ty, trait_segment); - assoc_bindings.first().map(|b| self.prohibit_projection(b.span)); + assoc_bindings.first().map(|b| AstConv::prohibit_assoc_ty_binding(self.tcx(), b.span)); ty::TraitRef::new(trait_def_id, substs) } @@ -695,7 +997,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { return tcx.types.err; } - let mut associated_types = FxHashSet::default(); + // use a btreeset to keep output in a more consistent order + let mut associated_types = BTreeSet::default(); + for tr in traits::supertraits(tcx, principal) { associated_types.extend(tcx.associated_items(tr.def_id()) .filter(|item| item.kind == ty::AssociatedKind::Type) @@ -728,7 +1032,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait)) .chain(existential_projections .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder()))) - .collect::>(); + .collect::>(); v.sort_by(|a, b| a.stable_cmp(tcx, b)); let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter())); @@ -902,8 +1206,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { Err(ErrorReported) => return (tcx.types.err, Def::Err), } } - (&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) | - (&ty::TyParam(_), Def::TyParam(param_did)) => { + (&ty::Param(_), Def::SelfTy(Some(param_did), None)) | + (&ty::Param(_), Def::TyParam(param_did)) => { match self.find_bound_for_assoc_item(param_did, assoc_name, span) { Ok(bound) => bound, Err(ErrorReported) => return (tcx.types.err, Def::Err), @@ -978,7 +1282,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs)) } - pub fn prohibit_generics(&self, segments: &[hir::PathSegment]) { + pub fn prohibit_generics<'a, T: IntoIterator>(&self, segments: T) { for segment in segments { segment.with_generic_args(|generic_args| { let (mut err_for_lt, mut err_for_ty) = (false, false); @@ -1009,15 +1313,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } } for binding in &generic_args.bindings { - self.prohibit_projection(binding.span); + Self::prohibit_assoc_ty_binding(self.tcx(), binding.span); break; } }) } } - pub fn prohibit_projection(&self, span: Span) { - let mut err = struct_span_err!(self.tcx().sess, span, E0229, + pub fn prohibit_assoc_ty_binding(tcx: TyCtxt, span: Span) { + let mut err = struct_span_err!(tcx.sess, span, E0229, "associated type bindings are not allowed here"); err.span_label(span, "associated type not allowed here").emit(); } @@ -1030,7 +1334,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { -> Ty<'tcx> { let tcx = self.tcx(); - debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})", + debug!("def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})", path.def, opt_self_ty, path.segments); let span = path.span; @@ -1046,11 +1350,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let substs = self.ast_path_substs_for_ty(span, did, item_segment.0); self.normalize_ty( span, - tcx.mk_anon(did, substs), + tcx.mk_opaque(did, substs), ) } Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | - Def::Union(did) | Def::TyForeign(did) => { + Def::Union(did) | Def::ForeignTy(did) => { assert_eq!(opt_self_ty, None); self.prohibit_generics(path.segments.split_last().unwrap().1); self.ast_path_to_ty(span, did, path.segments.last().unwrap()) @@ -1101,12 +1405,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); match prim_ty { - hir::TyBool => tcx.types.bool, - hir::TyChar => tcx.types.char, - hir::TyInt(it) => tcx.mk_mach_int(it), - hir::TyUint(uit) => tcx.mk_mach_uint(uit), - hir::TyFloat(ft) => tcx.mk_mach_float(ft), - hir::TyStr => tcx.mk_str() + hir::Bool => tcx.types.bool, + hir::Char => tcx.types.char, + hir::Int(it) => tcx.mk_mach_int(it), + hir::Uint(uit) => tcx.mk_mach_uint(uit), + hir::Float(ft) => tcx.mk_mach_float(ft), + hir::Str => tcx.mk_str() } } Def::Err => { @@ -1137,7 +1441,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); - debug!("TyRef r={:?}", r); + debug!("Ref r={:?}", r); let t = self.ast_ty_to_ty(&mt.ty); tcx.mk_ref(r, ty::TypeAndMut {ty: t, mutbl: mt.mutbl}) } @@ -1176,7 +1480,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let length_def_id = tcx.hir.local_def_id(length.id); let substs = Substs::identity_for_item(tcx, length_def_id); let length = ty::Const::unevaluated(tcx, length_def_id, substs, tcx.types.usize); - let array_ty = tcx.mk_ty(ty::TyArray(self.ast_ty_to_ty(&ty), length)); + let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) } hir::TyKind::Typeof(ref _e) => { @@ -1188,7 +1492,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { tcx.types.err } hir::TyKind::Infer => { - // TyInfer also appears as the type of arguments or return + // Infer also appears as the type of arguments or return // values in a ExprKind::Closure, or as // the type of local variables. Both of these cases are // handled specially and will not descend into this routine. @@ -1239,7 +1543,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { }); debug!("impl_trait_ty_to_ty: final substs = {:?}", substs); - let ty = tcx.mk_anon(def_id, substs); + let ty = tcx.mk_opaque(def_id, substs); debug!("impl_trait_ty_to_ty: {}", ty); ty } @@ -1271,7 +1575,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let output_ty = match decl.output { hir::Return(ref output) => self.ast_ty_to_ty(output), - hir::DefaultReturn(..) => tcx.mk_nil(), + hir::DefaultReturn(..) => tcx.mk_unit(), }; debug!("ty_of_fn: output_ty={:?}", output_ty); @@ -1329,7 +1633,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { /// we return `None`. fn compute_object_lifetime_bound(&self, span: Span, - existential_predicates: ty::Binder<&'tcx ty::Slice>>) + existential_predicates: ty::Binder<&'tcx ty::List>>) -> Option> // if None, use the default { let tcx = self.tcx(); @@ -1393,72 +1697,6 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, (auto_traits, trait_bounds) } -fn check_type_argument_count(tcx: TyCtxt, - span: Span, - supplied: usize, - ty_params: ParamRange) -{ - let (required, accepted) = (ty_params.required, ty_params.accepted); - if supplied < required { - let expected = if required < accepted { - "expected at least" - } else { - "expected" - }; - let arguments_plural = if required == 1 { "" } else { "s" }; - - struct_span_err!(tcx.sess, span, E0243, - "wrong number of type arguments: {} {}, found {}", - expected, required, supplied) - .span_label(span, - format!("{} {} type argument{}", - expected, - required, - arguments_plural)) - .emit(); - } else if supplied > accepted { - let expected = if required < accepted { - format!("expected at most {}", accepted) - } else { - format!("expected {}", accepted) - }; - let arguments_plural = if accepted == 1 { "" } else { "s" }; - - struct_span_err!(tcx.sess, span, E0244, - "wrong number of type arguments: {}, found {}", - expected, supplied) - .span_label( - span, - format!("{} type argument{}", - if accepted == 0 { "expected no" } else { &expected }, - arguments_plural) - ) - .emit(); - } -} - -fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected: usize) { - let label = if number < expected { - if expected == 1 { - format!("expected {} lifetime parameter", expected) - } else { - format!("expected {} lifetime parameters", expected) - } - } else { - let additional = number - expected; - if additional == 1 { - "unexpected lifetime parameter".to_string() - } else { - format!("{} unexpected lifetime parameters", additional) - } - }; - struct_span_err!(tcx.sess, span, E0107, - "wrong number of lifetime parameters: expected {}, found {}", - expected, number) - .span_label(span, label) - .emit(); -} - // A helper struct for conveniently grouping a set of bounds which we pass to // and return from functions in multiple places. #[derive(PartialEq, Eq, Clone, Debug)] diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index c9b5fd525d..0d2bc57540 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -22,7 +22,7 @@ use util::nodemap::FxHashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::cmp; use syntax::ast; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use syntax::ptr::P; use syntax_pos::Span; @@ -53,7 +53,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { PatKind::Lit(ref lt) => { let ty = self.check_expr(lt); match ty.sty { - ty::TypeVariants::TyRef(..) => false, + ty::Ref(..) => false, _ => true, } } @@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Peel off as many `&` or `&mut` from the discriminant as possible. For example, // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches - // the `Some(5)` which is not of type TyRef. + // the `Some(5)` which is not of type Ref. // // For each ampersand peeled off, update the binding mode and push the original // type into the adjustments vector. @@ -84,8 +84,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected = loop { debug!("inspecting {:?} with type {:?}", exp_ty, exp_ty.sty); match exp_ty.sty { - ty::TypeVariants::TyRef(_, inner_ty, inner_mutability) => { - debug!("current discriminant is TyRef, inserting implicit deref"); + ty::Ref(_, inner_ty, inner_mutability) => { + debug!("current discriminant is Ref, inserting implicit deref"); // Preserve the reference type. We'll need it later during HAIR lowering. pat_adjustments.push(exp_ty); @@ -150,8 +150,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let hir::ExprKind::Lit(ref lt) = lt.node { if let ast::LitKind::ByteStr(_) = lt.node { let expected_ty = self.structurally_resolved_type(pat.span, expected); - if let ty::TyRef(_, r_ty, _) = expected_ty.sty { - if let ty::TySlice(_) = r_ty.sty { + if let ty::Ref(_, r_ty, _) = expected_ty.sty { + if let ty::Slice(_) = r_ty.sty { pat_ty = tcx.mk_imm_ref(tcx.types.re_static, tcx.mk_slice(tcx.types.u8)) } @@ -285,7 +285,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut expected_len = elements.len(); if ddpos.is_some() { // Require known type only when `..` is present - if let ty::TyTuple(ref tys) = + if let ty::Tuple(ref tys) = self.structurally_resolved_type(pat.span, expected).sty { expected_len = tys.len(); } @@ -297,12 +297,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // from all tuple elements isn't trivial. TypeVariableOrigin::TypeInference(pat.span))); let element_tys = tcx.mk_type_list(element_tys_iter); - let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys)); - self.demand_eqtype(pat.span, expected, pat_ty); - for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &element_tys[i], def_bm, true); + let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); + if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) { + err.emit(); + // Walk subpatterns with an expected type of `err` in this case to silence + // further errors being emitted when using the bindings. #50333 + let element_tys_iter = (0..max_len).map(|_| tcx.types.err); + for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &tcx.types.err, def_bm, true); + } + tcx.mk_tup(element_tys_iter) + } else { + for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &element_tys[i], def_bm, true); + } + pat_ty } - pat_ty } PatKind::Box(ref inner) => { let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span)); @@ -333,7 +343,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // hack detailed in (*) below. debug!("check_pat_walk: expected={:?}", expected); let (rptr_ty, inner_ty) = match expected.sty { - ty::TyRef(_, r_ty, r_mutbl) if r_mutbl == mutbl => { + ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => { (expected, r_ty) } _ => { @@ -350,7 +360,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(mut err) = err { if is_arg { if let PatKind::Binding(..) = inner.node { - if let Ok(snippet) = tcx.sess.codemap() + if let Ok(snippet) = tcx.sess.source_map() .span_to_snippet(pat.span) { err.help(&format!("did you mean `{}: &{}`?", @@ -375,7 +385,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { PatKind::Slice(ref before, ref slice, ref after) => { let expected_ty = self.structurally_resolved_type(pat.span, expected); let (inner_ty, slice_ty) = match expected_ty.sty { - ty::TyArray(inner_ty, size) => { + ty::Array(inner_ty, size) => { let size = size.unwrap_usize(tcx); let min_len = before.len() as u64 + after.len() as u64; if slice.is_none() { @@ -400,16 +410,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (inner_ty, tcx.types.err) } } - ty::TySlice(inner_ty) => (inner_ty, expected_ty), + ty::Slice(inner_ty) => (inner_ty, expected_ty), _ => { if !expected_ty.references_error() { let mut err = struct_span_err!( tcx.sess, pat.span, E0529, "expected an array or slice, found `{}`", expected_ty); - if let ty::TyRef(_, ty, _) = expected_ty.sty { + if let ty::Ref(_, ty, _) = expected_ty.sty { match ty.sty { - ty::TyArray(..) | ty::TySlice(..) => { + ty::Array(..) | ty::Slice(..) => { err.help("the semantics of slice patterns changed \ recently; see issue #23121"); } @@ -493,7 +503,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool { if let PatKind::Binding(..) = inner.node { if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { - if let ty::TyDynamic(..) = mt.ty.sty { + if let ty::Dynamic(..) = mt.ty.sty { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. let type_str = self.ty_to_string(expected); @@ -656,16 +666,18 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // us to give better error messages (pointing to a usually better // arm for inconsistent arms or to the whole match when a `()` type // is required). - Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety, + Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety, _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)), }; CoerceMany::with_coercion_sites(coerce_first, arms) }; for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() { - if let Some(ref e) = arm.guard { + if let Some(ref g) = arm.guard { self.diverges.set(pats_diverge); - self.check_expr_has_type_or_error(e, tcx.types.bool); + match g { + hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool), + }; } self.diverges.set(pats_diverge); @@ -675,14 +687,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // Handle the fallback arm of a desugared if-let like a missing else. let is_if_let_fallback = match match_src { hir::MatchSource::IfLetDesugar { contains_else_clause: false } => { - i == arms.len() - 1 && arm_ty.is_nil() + i == arms.len() - 1 && arm_ty.is_unit() } _ => false }; if is_if_let_fallback { let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse); - assert!(arm_ty.is_nil()); + assert!(arm_ty.is_unit()); coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); } else { let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm { @@ -754,12 +766,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } Def::VariantCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Const) | + Def::SelfCtor(..) | Def::Const(..) | Def::AssociatedConst(..) => {} // OK _ => bug!("unexpected pattern definition: {:?}", def) } // Type check the path. - let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); + let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id).0; self.demand_suptype(pat.span, expected, pat_ty); pat_ty } @@ -789,6 +802,24 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // Resolve the path and check the definition for errors. let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span); + if def == Def::Err { + self.set_tainted_by_errors(); + on_error(); + return self.tcx.types.err; + } + + // Type check the path. + let (pat_ty, def) = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); + if !pat_ty.is_fn() { + report_unexpected_def(def); + return self.tcx.types.err; + } + // Replace constructor type with constructed type for tuple struct patterns. + let pat_ty = pat_ty.fn_sig(tcx).output(); + let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type"); + + self.demand_eqtype(pat.span, expected, pat_ty); + let variant = match def { Def::Err => { self.set_tainted_by_errors(); @@ -805,20 +836,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } _ => bug!("unexpected pattern definition: {:?}", def) }; - - // Type check the path. - let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); - // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig(tcx).output(); - let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type"); - - self.demand_eqtype(pat.span, expected, pat_ty); - // Type check subpatterns. if subpats.len() == variant.fields.len() || subpats.len() < variant.fields.len() && ddpos.is_some() { let substs = match pat_ty.sty { - ty::TyAdt(_, substs) => substs, + ty::Adt(_, substs) => substs, ref ty => bug!("unexpected pattern type {:?}", ty), }; for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { @@ -854,7 +876,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let tcx = self.tcx; let (substs, adt) = match adt_ty.sty { - ty::TyAdt(adt, substs) => (substs, adt), + ty::Adt(adt, substs) => (substs, adt), _ => span_bug!(span, "struct pattern is not an ADT") }; let kind_name = adt.variant_descr(); @@ -948,7 +970,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } // Require `..` if struct has non_exhaustive attribute. - if adt.is_struct() && adt.is_non_exhaustive() && !adt.did.is_local() && !etc { + if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { span_err!(tcx.sess, span, E0638, "`..` required with {} marked as non-exhaustive", kind_name); diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 0956261498..743a2390ec 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -177,7 +177,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { self.fcx.try_overloaded_deref(self.span, source, needs) .and_then(|InferOk { value: method, obligations: o }| { obligations.extend(o); - if let ty::TyRef(region, _, mutbl) = method.sig.output().sty { + if let ty::Ref(region, _, mutbl) = method.sig.output().sty { Some(OverloadedDeref { region, mutbl, diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index ec127d26ab..53186c64be 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -20,6 +20,7 @@ use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoB use rustc_target::spec::abi; use syntax::ast::Ident; use syntax_pos::Span; +use errors::Applicability; use rustc::hir; @@ -95,13 +96,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the callee is a bare function or a closure, then we're all set. match adjusted_ty.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => { + ty::FnDef(..) | ty::FnPtr(_) => { let adjustments = autoderef.adjust_steps(Needs::None); self.apply_adjustments(callee_expr, adjustments); return Some(CallStep::Builtin(adjusted_ty)); } - ty::TyClosure(def_id, substs) => { + ty::Closure(def_id, substs) => { assert_eq!(def_id.krate, LOCAL_CRATE); // Check whether this is a call to a closure where we @@ -135,7 +136,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // over the top. The simplest fix by far is to just ignore // this case and deref again, so we wind up with // `FnMut::call_mut(&mut *x, ())`. - ty::TyRef(..) if autoderef.step_count() == 0 => { + ty::Ref(..) if autoderef.step_count() == 0 => { return None; } @@ -175,7 +176,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let method = self.register_infer_ok_obligations(ok); let mut autoref = None; if borrow { - if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[0].sty { + if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty { let mutbl = match mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -206,13 +207,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected: Expectation<'tcx>) -> Ty<'tcx> { let (fn_sig, def_span) = match callee_ty.sty { - ty::TyFnDef(def_id, _) => { + ty::FnDef(def_id, _) => { (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id)) } - ty::TyFnPtr(sig) => (sig, None), + ty::FnPtr(sig) => (sig, None), ref t => { let mut unit_variant = None; - if let &ty::TyAdt(adt_def, ..) = t { + if let &ty::Adt(adt_def, ..) = t { if adt_def.is_enum() { if let hir::ExprKind::Call(ref expr, _) = call_expr.node { unit_variant = Some(self.tcx.hir.node_to_pretty_string(expr.id)) @@ -234,10 +235,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.span_label(call_expr.span, "not a function"); if let Some(ref path) = unit_variant { - err.span_suggestion(call_expr.span, - &format!("`{}` is a unit variant, you need to write it \ - without the parenthesis", path), - path.to_string()); + err.span_suggestion_with_applicability( + call_expr.span, + &format!("`{}` is a unit variant, you need to write it \ + without the parenthesis", path), + path.to_string(), + Applicability::MachineApplicable + ); } if let hir::ExprKind::Call(ref expr, _) = call_expr.node { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 07e19c84a9..ebe0c279aa 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -78,8 +78,8 @@ enum PointerKind<'tcx> { Length, /// The unsize info of this projection OfProjection(&'tcx ty::ProjectionTy<'tcx>), - /// The unsize info of this anon ty - OfAnon(DefId, &'tcx Substs<'tcx>), + /// The unsize info of this opaque ty + OfOpaque(DefId, &'tcx Substs<'tcx>), /// The unsize info of this parameter OfParam(&'tcx ty::ParamTy), } @@ -103,10 +103,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } Ok(match t.sty { - ty::TySlice(_) | ty::TyStr => Some(PointerKind::Length), - ty::TyDynamic(ref tty, ..) => + ty::Slice(_) | ty::Str => Some(PointerKind::Length), + ty::Dynamic(ref tty, ..) => Some(PointerKind::Vtable(tty.principal().map(|p| p.def_id()))), - ty::TyAdt(def, substs) if def.is_struct() => { + ty::Adt(def, substs) if def.is_struct() => { match def.non_enum_variant().fields.last() { None => Some(PointerKind::Thin), Some(f) => { @@ -115,25 +115,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - ty::TyTuple(fields) => match fields.last() { + ty::Tuple(fields) => match fields.last() { None => Some(PointerKind::Thin), Some(f) => self.pointer_kind(f, span)? }, // Pointers to foreign types are thin, despite being unsized - ty::TyForeign(..) => Some(PointerKind::Thin), + ty::Foreign(..) => Some(PointerKind::Thin), // We should really try to normalize here. - ty::TyProjection(ref pi) => Some(PointerKind::OfProjection(pi)), - ty::TyAnon(def_id, substs) => Some(PointerKind::OfAnon(def_id, substs)), - ty::TyParam(ref p) => Some(PointerKind::OfParam(p)), + ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)), + ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)), + ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. - ty::TyInfer(_) => None, + ty::Infer(_) => None, - ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | - ty::TyFloat(_) | ty::TyArray(..) | ty::TyGeneratorWitness(..) | - ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyFnDef(..) | - ty::TyFnPtr(..) | ty::TyClosure(..) | ty::TyGenerator(..) | - ty::TyAdt(..) | ty::TyNever | ty::TyError => { + ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | + ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) | + ty::RawPtr(_) | ty::Ref(..) | ty::FnDef(..) | + ty::FnPtr(..) | ty::Closure(..) | ty::Generator(..) | + ty::Adt(..) | ty::Never | ty::Error => { self.tcx.sess.delay_span_bug( span, &format!("`{:?}` should be sized but is not?", t)); return Err(ErrorReported); @@ -199,7 +199,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { // cases now. We do a more thorough check at the end, once // inference is more completely known. match cast_ty.sty { - ty::TyDynamic(..) | ty::TySlice(..) => { + ty::Dynamic(..) | ty::Slice(..) => { check.report_cast_to_unsized_type(fcx); Err(ErrorReported) } @@ -221,7 +221,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty)); - if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) { + if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr.span) { err.span_help(self.expr.span, &format!("did you mean `*{}`?", snippet)); } @@ -319,13 +319,13 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { fcx.resolve_type_vars_if_possible(&self.expr_ty), tstr); match self.expr_ty.sty { - ty::TyRef(_, _, mt) => { + ty::Ref(_, _, mt) => { let mtstr = match mt { hir::MutMutable => "mut ", hir::MutImmutable => "", }; if self.cast_ty.is_trait() { - match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) { + match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) { Ok(s) => { err.span_suggestion(self.cast_span, "try casting to a reference instead", @@ -343,8 +343,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { tstr); } } - ty::TyAdt(def, ..) if def.is_box() => { - match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) { + ty::Adt(def, ..) if def.is_box() => { + match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) { Ok(s) => { err.span_suggestion(self.cast_span, "try casting to a `Box` instead", @@ -429,7 +429,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::TyFnDef(..) = self.expr_ty.sty { + if let ty::FnDef(..) = self.expr_ty.sty { // Attempt a coercion to a fn pointer type. let f = self.expr_ty.fn_sig(fcx.tcx); let res = fcx.try_coerce(self.expr, @@ -477,12 +477,12 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { (RPtr(p), Int(_)) | (RPtr(p), Float) => { match p.ty.sty { - ty::TypeVariants::TyInt(_) | - ty::TypeVariants::TyUint(_) | - ty::TypeVariants::TyFloat(_) => { + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) => { Err(CastError::NeedDeref) } - ty::TypeVariants::TyInfer(t) => { + ty::Infer(t) => { match t { ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref), @@ -583,7 +583,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { // array-ptr-cast. if m_expr.mutbl == hir::MutImmutable && m_cast.mutbl == hir::MutImmutable { - if let ty::TyArray(ety, _) = m_expr.ty.sty { + if let ty::Array(ety, _) = m_expr.ty.sty { // Due to the limitations of LLVM global constants, // region pointers end up pointing at copies of // vector elements instead of the original values. diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index f2745d0639..a283e032e0 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -24,7 +24,7 @@ use rustc::ty::subst::Substs; use std::cmp; use std::iter; use rustc_target::spec::abi::Abi; -use syntax::codemap::Span; +use syntax::source_map::Span; use rustc::hir; /// What signature do we *expect* the closure to have from context? @@ -190,7 +190,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ); match expected_ty.sty { - ty::TyDynamic(ref object_type, ..) => { + ty::Dynamic(ref object_type, ..) => { let sig = object_type .projection_bounds() .filter_map(|pb| { @@ -203,8 +203,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .and_then(|p| self.tcx.lang_items().fn_trait_kind(p.def_id())); (sig, kind) } - ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), - ty::TyFnPtr(sig) => { + ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), + ty::FnPtr(sig) => { let expected_sig = ExpectedSig { cause_span: None, sig: sig.skip_binder().clone(), @@ -269,9 +269,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // NB: This predicate is created by breaking down a // `ClosureType: FnFoo()` predicate, where - // `ClosureType` represents some `TyClosure`. It can't + // `ClosureType` represents some `Closure`. It can't // possibly be referring to the current closure, - // because we haven't produced the `TyClosure` for + // because we haven't produced the `Closure` for // this closure yet; this is exactly why the other // code is looking for a self type of a unresolved // inference variable. @@ -317,7 +317,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ); let input_tys = match arg_param_ty.sty { - ty::TyTuple(tys) => tys.into_iter(), + ty::Tuple(tys) => tys.into_iter(), _ => { return None; } @@ -353,7 +353,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { trait_ref, self_ty ); match self_ty.sty { - ty::TyInfer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref), + ty::Infer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref), _ => None, } } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index e3b0b8cccf..9604eb3420 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -210,11 +210,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // Note: does not attempt to resolve type variables we encounter. // See above for details. match b.sty { - ty::TyRawPtr(mt_b) => { + ty::RawPtr(mt_b) => { return self.coerce_unsafe_ptr(a, b, mt_b.mutbl); } - ty::TyRef(r_b, ty, mutbl) => { + ty::Ref(r_b, ty, mutbl) => { let mt_b = ty::TypeAndMut { ty, mutbl }; return self.coerce_borrowed_pointer(a, b, r_b, mt_b); } @@ -223,7 +223,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } match a.sty { - ty::TyFnDef(..) => { + ty::FnDef(..) => { // Function items are coercible to any closure // type; function pointers are not (that would // require double indirection). @@ -231,12 +231,12 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // items to drop the unsafe qualifier. self.coerce_from_fn_item(a, b) } - ty::TyFnPtr(a_f) => { + ty::FnPtr(a_f) => { // We permit coercion of fn pointers to drop the // unsafe qualifier. self.coerce_from_fn_pointer(a, a_f, b) } - ty::TyClosure(def_id_a, substs_a) => { + ty::Closure(def_id_a, substs_a) => { // Non-capturing closures are coercible to // function pointers self.coerce_closure_to_fn(a, def_id_a, substs_a, b) @@ -267,7 +267,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // yield. let (r_a, mt_a) = match a.sty { - ty::TyRef(r_a, ty, mutbl) => { + ty::Ref(r_a, ty, mutbl) => { let mt_a = ty::TypeAndMut { ty, mutbl }; coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?; (r_a, mt_a) @@ -429,7 +429,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // Now apply the autoref. We have to extract the region out of // the final ref type we got. let r_borrow = match ty.sty { - ty::TyRef(r_borrow, _, _) => r_borrow, + ty::Ref(r_borrow, _, _) => r_borrow, _ => span_bug!(span, "expected a ref type, got {:?}", ty), }; let mutbl = match mt_b.mutbl { @@ -473,7 +473,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // Handle reborrows before selecting `Source: CoerceUnsized`. let reborrow = match (&source.sty, &target.sty) { - (&ty::TyRef(_, ty_a, mutbl_a), &ty::TyRef(_, _, mutbl_b)) => { + (&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => { coerce_mutbls(mutbl_a, mutbl_b)?; let coercion = Coercion(self.cause.span); @@ -498,7 +498,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { }) })) } - (&ty::TyRef(_, ty_a, mt_a), &ty::TyRawPtr(ty::TypeAndMut { mutbl: mt_b, .. })) => { + (&ty::Ref(_, ty_a, mt_a), &ty::RawPtr(ty::TypeAndMut { mutbl: mt_b, .. })) => { coerce_mutbls(mt_a, mt_b)?; Some((Adjustment { @@ -562,7 +562,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { if unsize_did == tr.def_id() { let sty = &tr.skip_binder().input_types().nth(1).unwrap().sty; - if let ty::TyTuple(..) = sty { + if let ty::Tuple(..) = sty { debug!("coerce_unsized: found unsized tuple coercion"); has_unsized_tuple_coercion = true; } @@ -619,7 +619,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { where F: FnOnce(Ty<'tcx>) -> Vec>, G: FnOnce(Ty<'tcx>) -> Vec> { - if let ty::TyFnPtr(fn_ty_b) = b.sty { + if let ty::FnPtr(fn_ty_b) = b.sty { match (fn_ty_a.unsafety(), fn_ty_b.unsafety()) { (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); @@ -659,7 +659,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b); match b.sty { - ty::TyFnPtr(_) => { + ty::FnPtr(_) => { let a_sig = a.fn_sig(self.tcx); let InferOk { value: a_sig, mut obligations } = self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig); @@ -699,7 +699,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let node_id_a = self.tcx.hir.as_local_node_id(def_id_a).unwrap(); match b.sty { - ty::TyFnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => { + ty::FnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => { // We coerce the closure, which has fn type // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to @@ -722,8 +722,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { debug!("coerce_unsafe_ptr(a={:?}, b={:?})", a, b); let (is_ref, mt_a) = match a.sty { - ty::TyRef(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }), - ty::TyRawPtr(mt) => (false, mt), + ty::Ref(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }), + ty::RawPtr(mt) => (false, mt), _ => { return self.unify_and(a, b, identity); } @@ -811,7 +811,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or Substs. - if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) { + if let (&ty::FnDef(..), &ty::FnDef(..)) = (&prev_ty.sty, &new_ty.sty) { // Don't reify if the function types have a LUB, i.e. they // are the same function and their parameters have a LUB. let lub_ty = self.commit_if_ok(|_| { @@ -881,7 +881,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. } ] => { match self.node_ty(expr.hir_id).sty { - ty::TyRef(_, _, mt_orig) => { + ty::Ref(_, _, mt_orig) => { let mutbl_adj: hir::Mutability = mutbl_adj.into(); // Reborrow that we can safely ignore, because // the next adjustment can only be a Deref @@ -1077,7 +1077,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> self.coerce_inner(fcx, cause, None, - fcx.tcx.mk_nil(), + fcx.tcx.mk_unit(), Some(augment_error), label_unit_as_expected) } @@ -1146,8 +1146,8 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> // `expression_ty` will be unit). // // Another example is `break` with no argument expression. - assert!(expression_ty.is_nil()); - assert!(expression_ty.is_nil(), "if let hack without unit type"); + assert!(expression_ty.is_unit()); + assert!(expression_ty.is_unit(), "if let hack without unit type"); fcx.at(cause, fcx.param_env) .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty()) .map(|infer_ok| { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 0ca92d724b..9aa2ba363e 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -40,7 +40,7 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref); - let impl_m_span = tcx.sess.codemap().def_span(impl_m_span); + let impl_m_span = tcx.sess.source_map().def_span(impl_m_span); if let Err(ErrorReported) = compare_self_type(tcx, impl_m, @@ -68,9 +68,7 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Err(ErrorReported) = compare_synthetic_generics(tcx, impl_m, - impl_m_span, - trait_m, - trait_item_span) { + trait_m) { return; } @@ -321,7 +319,8 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_m.ident); if let TypeError::Mutability = terr { if let Some(trait_err_span) = trait_err_span { - if let Ok(trait_err_str) = tcx.sess.codemap().span_to_snippet(trait_err_span) { + if let Ok(trait_err_str) = tcx.sess.source_map(). + span_to_snippet(trait_err_span) { diag.span_suggestion( impl_err_span, "consider change the type to match the mutability in trait", @@ -388,7 +387,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // are zero. Since I don't quite know how to phrase things at // the moment, give a kind of vague error message. if trait_params != impl_params { - let def_span = tcx.sess.codemap().def_span(span); + let def_span = tcx.sess.source_map().def_span(span); let span = tcx.hir.get_generics_span(impl_m.def_id).unwrap_or(def_span); let mut err = struct_span_err!( tcx.sess, @@ -399,7 +398,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ); err.span_label(span, "lifetimes do not match method in trait"); if let Some(sp) = tcx.hir.span_if_local(trait_m.def_id) { - let def_sp = tcx.sess.codemap().def_span(sp); + let def_sp = tcx.sess.source_map().def_span(sp); let sp = tcx.hir.get_generics_span(trait_m.def_id).unwrap_or(def_sp); err.span_label(sp, "lifetimes in impl do not match this method in trait"); } @@ -729,14 +728,11 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_m: &ty::AssociatedItem, - _impl_m_span: Span, // FIXME necessary? - trait_m: &ty::AssociatedItem, - _trait_item_span: Option) // FIXME necessary? + trait_m: &ty::AssociatedItem) -> Result<(), ErrorReported> { // FIXME(chrisvittal) Clean up this function, list of FIXME items: // 1. Better messages for the span labels // 2. Explanation as to what is going on - // 3. Correct the function signature for what we actually use // If we get here, we already have the same number of generics, so the zip will // be okay. let mut error_found = false; @@ -775,7 +771,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // as another generic argument let new_name = tcx .sess - .codemap() + .source_map() .span_to_snippet(trait_span) .ok()?; let trait_m = tcx.hir.as_local_node_id(trait_m.def_id)?; @@ -788,7 +784,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // and the opening paren of the argument list let new_generics_span = tcx .sess - .codemap() + .source_map() .generate_fn_name_span(impl_span)? .shrink_to_hi(); // in case there are generics, just replace them @@ -799,7 +795,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // replace with the generics from the trait let new_generics = tcx .sess - .codemap() + .source_map() .span_to_snippet(trait_m.generics.span) .ok()?; @@ -870,7 +866,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let bounds = bounds.first()?.span().to(bounds.last()?.span()); let bounds = tcx .sess - .codemap() + .source_map() .span_to_snippet(bounds) .ok()?; diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 92b35bd50f..4e22ead8db 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -17,11 +17,11 @@ use syntax::util::parser::PREC_POSTFIX; use syntax_pos::Span; use rustc::hir; use rustc::hir::def::Def; -use rustc::hir::map::{NodeItem, NodeExpr}; +use rustc::hir::Node; use rustc::hir::{Item, ItemKind, print}; use rustc::ty::{self, Ty, AssociatedItem}; use rustc::ty::adjustment::AllowTwoPhase; -use errors::{DiagnosticBuilder, CodeMapper}; +use errors::{Applicability, DiagnosticBuilder, SourceMapper}; use super::method::probe; @@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the expected type is an enum with any variants whose sole // field is of the found type, suggest such variants. See Issue // #42764. - if let ty::TyAdt(expected_adt, substs) = expected.sty { + if let ty::Adt(expected_adt, substs) = expected.sty { let mut compatible_variants = vec![]; for variant in &expected_adt.variants { if variant.fields.len() == 1 { @@ -199,13 +199,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node { if let hir::def::Def::Local(id) = path.def { let parent = self.tcx.hir.get_parent_node(id); - if let Some(NodeExpr(hir::Expr { + if let Some(Node::Expr(hir::Expr { id, node: hir::ExprKind::Closure(_, decl, ..), .. })) = self.tcx.hir.find(parent) { let parent = self.tcx.hir.get_parent_node(*id); - if let (Some(NodeExpr(hir::Expr { + if let (Some(Node::Expr(hir::Expr { node: hir::ExprKind::MethodCall(path, span, expr), .. })), 1) = (self.tcx.hir.find(parent), decl.inputs.len()) { @@ -251,7 +251,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { checked_ty: Ty<'tcx>, expected: Ty<'tcx>) -> Option<(Span, &'static str, String)> { - let cm = self.sess().codemap(); + let cm = self.sess().source_map(); // Use the callsite's span if this is a macro call. #41858 let sp = cm.call_span_if_macro(expr.span); if !cm.span_to_filename(sp).is_real() { @@ -259,9 +259,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } match (&expected.sty, &checked_ty.sty) { - (&ty::TyRef(_, exp, _), &ty::TyRef(_, check, _)) => match (&exp.sty, &check.sty) { - (&ty::TyStr, &ty::TyArray(arr, _)) | - (&ty::TyStr, &ty::TySlice(arr)) if arr == self.tcx.types.u8 => { + (&ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) { + (&ty::Str, &ty::Array(arr, _)) | + (&ty::Str, &ty::Slice(arr)) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.node { if let Ok(src) = cm.span_to_snippet(sp) { if src.starts_with("b\"") { @@ -272,8 +272,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } }, - (&ty::TyArray(arr, _), &ty::TyStr) | - (&ty::TySlice(arr), &ty::TyStr) if arr == self.tcx.types.u8 => { + (&ty::Array(arr, _), &ty::Str) | + (&ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.node { if let Ok(src) = cm.span_to_snippet(sp) { if src.starts_with("\"") { @@ -286,7 +286,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } _ => {} }, - (&ty::TyRef(_, _, mutability), _) => { + (&ty::Ref(_, _, mutability), _) => { // Check if it can work when put into a ref. For example: // // ``` @@ -325,7 +325,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - (_, &ty::TyRef(_, checked, _)) => { + (_, &ty::Ref(_, checked, _)) => { // We have `&T`, check if what was expected was `T`. If so, // we may want to suggest adding a `*`, or removing // a `&`. @@ -351,11 +351,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !self.infcx.type_moves_by_default(self.param_env, checked, sp) { - let sp = cm.call_span_if_macro(sp); - if let Ok(code) = cm.span_to_snippet(sp) { - return Some((sp, - "consider dereferencing the borrow", - format!("*{}", code))); + // do not suggest if the span comes from a macro (#52783) + if let (Ok(code), + true) = (cm.span_to_snippet(sp), sp == expr.span) { + return Some(( + sp, + "consider dereferencing the borrow", + format!("*{}", code), + )); } } } @@ -377,7 +380,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match self.tcx.hir.find(parent_id) { Some(parent) => { // Shouldn't suggest `.into()` on `const`s. - if let NodeItem(Item { node: ItemKind::Const(_, _), .. }) = parent { + if let Node::Item(Item { node: ItemKind::Const(_, _), .. }) = parent { // FIXME(estebank): modify once we decide to suggest `as` casts return false; } @@ -405,7 +408,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8); - if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) { + if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) { let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty); let cast_suggestion = format!("{}{}{} as {}", if needs_paren { "(" } else { "" }, @@ -418,189 +421,240 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if needs_paren { ")" } else { "" }); match (&expected_ty.sty, &checked_ty.sty) { - (&ty::TyInt(ref exp), &ty::TyInt(ref found)) => { + (&ty::Int(ref exp), &ty::Int(ref found)) => { match (found.bit_width(), exp.bit_width()) { (Some(found), Some(exp)) if found > exp => { if can_cast { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_truncate), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_truncate), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } } (None, _) | (_, None) => { if can_cast { - err.span_suggestion(expr.span, - &format!("{}, which {}", - msg, - depending_on_isize), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, depending_on_isize), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } } _ => { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_sign_extend), - into_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_sign_extend), + into_suggestion, + Applicability::MachineApplicable + ); } } true } - (&ty::TyUint(ref exp), &ty::TyUint(ref found)) => { + (&ty::Uint(ref exp), &ty::Uint(ref found)) => { match (found.bit_width(), exp.bit_width()) { (Some(found), Some(exp)) if found > exp => { if can_cast { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_truncate), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_truncate), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } } (None, _) | (_, None) => { if can_cast { - err.span_suggestion(expr.span, - &format!("{}, which {}", - msg, - depending_on_usize), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, depending_on_usize), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } } _ => { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_zero_extend), - into_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_zero_extend), + into_suggestion, + Applicability::MachineApplicable + ); } } true } - (&ty::TyInt(ref exp), &ty::TyUint(ref found)) => { + (&ty::Int(ref exp), &ty::Uint(ref found)) => { if can_cast { match (found.bit_width(), exp.bit_width()) { (Some(found), Some(exp)) if found > exp - 1 => { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_truncate), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_truncate), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } (None, None) => { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_truncate), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_truncate), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } (None, _) => { - err.span_suggestion(expr.span, - &format!("{}, which {}", - msg, - depending_on_isize), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, depending_on_isize), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } (_, None) => { - err.span_suggestion(expr.span, - &format!("{}, which {}", - msg, - depending_on_usize), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, depending_on_usize), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } _ => { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_zero_extend), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_zero_extend), + cast_suggestion, + Applicability::MachineApplicable + ); } } } true } - (&ty::TyUint(ref exp), &ty::TyInt(ref found)) => { + (&ty::Uint(ref exp), &ty::Int(ref found)) => { if can_cast { match (found.bit_width(), exp.bit_width()) { (Some(found), Some(exp)) if found - 1 > exp => { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_truncate), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_truncate), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } (None, None) => { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_sign_extend), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_sign_extend), + cast_suggestion, + Applicability::MachineApplicable // lossy conversion + ); } (None, _) => { - err.span_suggestion(expr.span, - &format!("{}, which {}", - msg, - depending_on_usize), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, depending_on_usize), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } (_, None) => { - err.span_suggestion(expr.span, - &format!("{}, which {}", - msg, - depending_on_isize), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, depending_on_isize), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } _ => { - err.span_suggestion(expr.span, - &format!("{}, which {}", msg, will_sign_extend), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, which {}", msg, will_sign_extend), + cast_suggestion, + Applicability::MachineApplicable + ); } } } true } - (&ty::TyFloat(ref exp), &ty::TyFloat(ref found)) => { + (&ty::Float(ref exp), &ty::Float(ref found)) => { if found.bit_width() < exp.bit_width() { - err.span_suggestion(expr.span, - &format!("{} in a lossless way", - msg), - into_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{} in a lossless way", msg), + into_suggestion, + Applicability::MachineApplicable + ); } else if can_cast { - err.span_suggestion(expr.span, - &format!("{}, producing the closest possible value", - msg), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, producing the closest possible value", msg), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } true } - (&ty::TyUint(_), &ty::TyFloat(_)) | (&ty::TyInt(_), &ty::TyFloat(_)) => { + (&ty::Uint(_), &ty::Float(_)) | (&ty::Int(_), &ty::Float(_)) => { if can_cast { - err.span_suggestion(expr.span, - &format!("{}, rounding the float towards zero", - msg), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, rounding the float towards zero", msg), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); err.warn("casting here will cause undefined behavior if the rounded value \ cannot be represented by the target integer type, including \ `Inf` and `NaN` (this is a bug and will be fixed)"); } true } - (&ty::TyFloat(ref exp), &ty::TyUint(ref found)) => { + (&ty::Float(ref exp), &ty::Uint(ref found)) => { // if `found` is `None` (meaning found is `usize`), don't suggest `.into()` if exp.bit_width() > found.bit_width().unwrap_or(256) { - err.span_suggestion(expr.span, - &format!("{}, producing the floating point \ - representation of the integer", - msg), - into_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, producing the floating point representation of the \ + integer", + msg), + into_suggestion, + Applicability::MachineApplicable + ); } else if can_cast { - err.span_suggestion(expr.span, - &format!("{}, producing the floating point \ - representation of the integer, rounded if \ - necessary", - msg), - cast_suggestion); + err.span_suggestion_with_applicability(expr.span, + &format!("{}, producing the floating point representation of the \ + integer, rounded if necessary", + msg), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } true } - (&ty::TyFloat(ref exp), &ty::TyInt(ref found)) => { + (&ty::Float(ref exp), &ty::Int(ref found)) => { // if `found` is `None` (meaning found is `isize`), don't suggest `.into()` if exp.bit_width() > found.bit_width().unwrap_or(256) { - err.span_suggestion(expr.span, - &format!("{}, producing the floating point \ - representation of the integer", - msg), - into_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, producing the floating point representation of the \ + integer", + msg), + into_suggestion, + Applicability::MachineApplicable + ); } else if can_cast { - err.span_suggestion(expr.span, - &format!("{}, producing the floating point \ - representation of the integer, rounded if \ - necessary", - msg), - cast_suggestion); + err.span_suggestion_with_applicability( + expr.span, + &format!("{}, producing the floating point representation of the \ + integer, rounded if necessary", + msg), + cast_suggestion, + Applicability::MaybeIncorrect // lossy conversion + ); } true } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index f9166851f6..9d3cbf910e 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -45,7 +45,7 @@ pub fn check_drop_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let dtor_self_type = tcx.type_of(drop_impl_did); let dtor_predicates = tcx.predicates_of(drop_impl_did); match dtor_self_type.sty { - ty::TyAdt(adt_def, self_to_impl_substs) => { + ty::Adt(adt_def, self_to_impl_substs) => { ensure_drop_params_and_item_params_correspond(tcx, drop_impl_did, dtor_self_type, diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index e209049307..f0afc58b3c 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -121,7 +121,7 @@ pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, // Replace all regions inside the generator interior with late bound regions // Note that each region slot in the types gets a new fresh late bound region, // which means that none of the regions inside relate to any other, even if - // typeck had previously found contraints that would cause them to be related. + // typeck had previously found constraints that would cause them to be related. let mut counter = 0; let type_list = fcx.tcx.fold_regions(&type_list, &mut false, |_, current_depth| { counter += 1; @@ -167,7 +167,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'gcx, 'tcx> { let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let ty = self.fcx.tables.borrow().expr_ty_adjusted(expr); + // Record the unadjusted type + let ty = self.fcx.tables.borrow().expr_ty(expr); self.record(ty, scope, Some(expr), expr.span); + + // Also include the adjusted types, since these can result in MIR locals + for adjustment in self.fcx.tables.borrow().expr_adjustments(expr) { + self.record(adjustment.target, scope, Some(expr), expr.span); + } } } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index af4356dc8d..8215ae211c 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -26,12 +26,15 @@ use rustc::hir; use std::iter; -fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - it: &hir::ForeignItem, - n_tps: usize, - abi: Abi, - inputs: Vec>, - output: Ty<'tcx>) { +fn equate_intrinsic_type<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + it: &hir::ForeignItem, + n_tps: usize, + abi: Abi, + safety: hir::Unsafety, + inputs: Vec>, + output: Ty<'tcx>, +) { let def_id = tcx.hir.local_def_id(it.id); match it.node { @@ -65,7 +68,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, inputs.into_iter(), output, false, - hir::Unsafety::Unsafe, + safety, abi ))); let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType); @@ -78,7 +81,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str()); let name = it.name.as_str(); - let (n_tps, inputs, output) = if name.starts_with("atomic_") { + let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") { let split : Vec<&str> = name.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic not correct format"); @@ -91,7 +94,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "load" => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)), "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], - tcx.mk_nil()), + tcx.mk_unit()), "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax" | "umin" => { @@ -99,7 +102,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param(0)) } "fence" | "singlethreadfence" => { - (0, Vec::new(), tcx.mk_nil()) + (0, Vec::new(), tcx.mk_unit()) } op => { struct_span_err!(tcx.sess, it.span, E0092, @@ -109,12 +112,16 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } }; - (n_tps, inputs, output) + (n_tps, inputs, output, hir::Unsafety::Unsafe) } else if &name[..] == "abort" || &name[..] == "unreachable" { - (0, Vec::new(), tcx.types.never) + (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe) } else { + let unsafety = match &name[..] { + "size_of" | "min_align_of" => hir::Unsafety::Normal, + _ => hir::Unsafety::Unsafe, + }; let (n_tps, inputs, output) = match &name[..] { - "breakpoint" => (0, Vec::new(), tcx.mk_nil()), + "breakpoint" => (0, Vec::new(), tcx.mk_unit()), "size_of" | "pref_align_of" | "min_align_of" => (1, Vec::new(), tcx.types.usize), "size_of_val" | "min_align_of_val" => { @@ -134,7 +141,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.mk_mut_ptr(param(0)), param(0) ], - tcx.mk_nil()) + tcx.mk_unit()) } "prefetch_read_data" | "prefetch_write_data" | "prefetch_read_instruction" | "prefetch_write_instruction" => { @@ -142,10 +149,10 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: param(0), mutbl: hir::MutImmutable }), tcx.types.i32], - tcx.mk_nil()) + tcx.mk_unit()) } "drop_in_place" => { - (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_nil()) + (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()) } "needs_drop" => (1, Vec::new(), tcx.types.bool), @@ -178,7 +185,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }), tcx.types.usize, ], - tcx.mk_nil()) + tcx.mk_unit()) } "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => { (1, @@ -193,7 +200,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }), tcx.types.usize, ], - tcx.mk_nil()) + tcx.mk_unit()) } "write_bytes" | "volatile_set_memory" => { (1, @@ -205,7 +212,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.types.u8, tcx.types.usize, ], - tcx.mk_nil()) + tcx.mk_unit()) } "sqrtf32" => (0, vec![ tcx.types.f32 ], tcx.types.f32), "sqrtf64" => (0, vec![ tcx.types.f64 ], tcx.types.f64), @@ -273,7 +280,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "volatile_load" | "unaligned_volatile_load" => (1, vec![ tcx.mk_imm_ptr(param(0)) ], param(0)), "volatile_store" | "unaligned_volatile_store" => - (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil()), + (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_unit()), "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap" | "bitreverse" => @@ -293,7 +300,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => (1, vec![param(0), param(0)], param(0)), - "assume" => (0, vec![tcx.types.bool], tcx.mk_nil()), + "assume" => (0, vec![tcx.types.bool], tcx.mk_unit()), "likely" => (0, vec![tcx.types.bool], tcx.types.bool), "unlikely" => (0, vec![tcx.types.bool], tcx.types.bool), @@ -306,7 +313,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); let fn_ty = ty::Binder::bind(tcx.mk_fn_sig( iter::once(mut_u8), - tcx.mk_nil(), + tcx.mk_unit(), false, hir::Unsafety::Normal, Abi::Rust, @@ -315,7 +322,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } "nontemporal_store" => { - (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil()) + (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_unit()) } ref other => { @@ -327,9 +334,9 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } }; - (n_tps, inputs, output) + (n_tps, inputs, output, unsafety) }; - equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, inputs, output) + equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -369,7 +376,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (3, vec![param(0), param(1), param(2)], param(0)) } "simd_scatter" => { - (3, vec![param(0), param(1), param(2)], tcx.mk_nil()) + (3, vec![param(0), param(1), param(2)], tcx.mk_unit()) } "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)), "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)), @@ -439,7 +446,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; - equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic, + equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic, hir::Unsafety::Unsafe, inputs, output) } @@ -463,35 +470,35 @@ fn match_intrinsic_type_to_type<'a, 'tcx>( match *expected { Void => match t.sty { - ty::TyTuple(ref v) if v.is_empty() => {}, + ty::Tuple(ref v) if v.is_empty() => {}, _ => simple_error(&format!("`{}`", t), "()"), }, // (The width we pass to LLVM doesn't concern the type checker.) Integer(signed, bits, _llvm_width) => match (signed, bits, &t.sty) { - (true, 8, &ty::TyInt(ast::IntTy::I8)) | - (false, 8, &ty::TyUint(ast::UintTy::U8)) | - (true, 16, &ty::TyInt(ast::IntTy::I16)) | - (false, 16, &ty::TyUint(ast::UintTy::U16)) | - (true, 32, &ty::TyInt(ast::IntTy::I32)) | - (false, 32, &ty::TyUint(ast::UintTy::U32)) | - (true, 64, &ty::TyInt(ast::IntTy::I64)) | - (false, 64, &ty::TyUint(ast::UintTy::U64)) | - (true, 128, &ty::TyInt(ast::IntTy::I128)) | - (false, 128, &ty::TyUint(ast::UintTy::U128)) => {}, + (true, 8, &ty::Int(ast::IntTy::I8)) | + (false, 8, &ty::Uint(ast::UintTy::U8)) | + (true, 16, &ty::Int(ast::IntTy::I16)) | + (false, 16, &ty::Uint(ast::UintTy::U16)) | + (true, 32, &ty::Int(ast::IntTy::I32)) | + (false, 32, &ty::Uint(ast::UintTy::U32)) | + (true, 64, &ty::Int(ast::IntTy::I64)) | + (false, 64, &ty::Uint(ast::UintTy::U64)) | + (true, 128, &ty::Int(ast::IntTy::I128)) | + (false, 128, &ty::Uint(ast::UintTy::U128)) => {}, _ => simple_error(&format!("`{}`", t), &format!("`{}{n}`", if signed {"i"} else {"u"}, n = bits)), }, Float(bits) => match (bits, &t.sty) { - (32, &ty::TyFloat(ast::FloatTy::F32)) | - (64, &ty::TyFloat(ast::FloatTy::F64)) => {}, + (32, &ty::Float(ast::FloatTy::F32)) | + (64, &ty::Float(ast::FloatTy::F64)) => {}, _ => simple_error(&format!("`{}`", t), &format!("`f{n}`", n = bits)), }, Pointer(ref inner_expected, ref _llvm_type, const_) => { match t.sty { - ty::TyRawPtr(ty::TypeAndMut { ty, mutbl }) => { + ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => { if (mutbl == hir::MutImmutable) != const_ { simple_error(&format!("`{}`", t), if const_ {"const pointer"} else {"mut pointer"}) @@ -537,7 +544,7 @@ fn match_intrinsic_type_to_type<'a, 'tcx>( } Aggregate(_flatten, ref expected_contents) => { match t.sty { - ty::TyTuple(contents) => { + ty::Tuple(contents) => { if contents.len() != expected_contents.len() { simple_error(&format!("tuple with length {}", contents.len()), &format!("tuple with length {}", expected_contents.len())); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 6c3e265619..6057c18663 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -22,8 +22,8 @@ use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref}; use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::infer::{self, InferOk}; -use syntax_pos::Span; use rustc::hir; +use syntax_pos::Span; use std::ops::Deref; @@ -293,7 +293,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { .include_raw_pointers() .filter_map(|(ty, _)| { match ty.sty { - ty::TyDynamic(ref data, ..) => data.principal().map(|p| closure(self, ty, p)), + ty::Dynamic(ref data, ..) => data.principal().map(|p| closure(self, ty, p)), _ => None, } }) @@ -308,55 +308,55 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_substs( &mut self, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment, + seg: &hir::PathSegment, parent_substs: &Substs<'tcx>, ) -> &'tcx Substs<'tcx> { // Determine the values for the generic parameters of the method. // If they were not explicitly supplied, just construct fresh // variables. - let method_generics = self.tcx.generics_of(pick.item.def_id); - let mut fn_segment = Some((segment, method_generics)); - let supress_mismatch = self.fcx.check_impl_trait(self.span, fn_segment); - self.fcx.check_generic_arg_count(self.span, &mut fn_segment, true, supress_mismatch); + let generics = self.tcx.generics_of(pick.item.def_id); + AstConv::check_generic_arg_count_for_call( + self.tcx, + self.span, + &generics, + &seg, + true, // `is_method_call` + ); // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. - assert_eq!(method_generics.parent_count, parent_substs.len()); - let provided = &segment.args; - let own_counts = method_generics.own_counts(); - Substs::for_item(self.tcx, pick.item.def_id, |param, _| { - let mut i = param.index as usize; - if i < parent_substs.len() { - parent_substs[i] - } else { - let (is_lt, is_ty) = match param.kind { - GenericParamDefKind::Lifetime => (true, false), - GenericParamDefKind::Type { .. } => (false, true), - }; - provided.as_ref().and_then(|data| { - for arg in &data.args { - match arg { - GenericArg::Lifetime(lt) if is_lt => { - if i == parent_substs.len() { - return Some(AstConv::ast_region_to_region( - self.fcx, lt, Some(param)).into()); - } - i -= 1; - } - GenericArg::Lifetime(_) => {} - GenericArg::Type(ty) if is_ty => { - if i == parent_substs.len() + own_counts.lifetimes { - return Some(self.to_ty(ty).into()); - } - i -= 1; - } - GenericArg::Type(_) => {} - } + assert_eq!(generics.parent_count, parent_substs.len()); + + AstConv::create_substs_for_generic_args( + self.tcx, + pick.item.def_id, + parent_substs, + false, + None, + // Provide the generic args, and whether types should be inferred. + |_| { + // The last argument of the returned tuple here is unimportant. + if let Some(ref data) = seg.args { + (Some(data), false) + } else { + (None, false) + } + }, + // Provide substitutions for parameters for which (valid) arguments have been provided. + |param, arg| { + match (¶m.kind, arg) { + (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { + AstConv::ast_region_to_region(self.fcx, lt, Some(param)).into() } - None - }).unwrap_or_else(|| self.var_for_def(self.span, param)) - } - }) + (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { + self.to_ty(ty).into() + } + _ => unreachable!(), + } + }, + // Provide substitutions for parameters for which arguments are inferred. + |_, param, _| self.var_for_def(self.span, param), + ) } fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) { @@ -479,7 +479,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind { if let Some(ok) = self.try_overloaded_deref(expr.span, source, needs) { let method = self.register_infer_ok_obligations(ok); - if let ty::TyRef(region, _, mutbl) = method.sig.output().sty { + if let ty::Ref(region, _, mutbl) = method.sig.output().sty { *deref = OverloadedDeref { region, mutbl, @@ -538,7 +538,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("convert_place_op_to_mutable: method={:?}", method); self.write_method_call(expr.hir_id, method); - let (region, mutbl) = if let ty::TyRef(r, _, mutbl) = method.sig.inputs()[0].sty { + let (region, mutbl) = if let ty::Ref(r, _, mutbl) = method.sig.inputs()[0].sty { (r, mutbl) } else { span_bug!(expr.span, "input to place op is not a ref?"); @@ -605,7 +605,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { }) .any(|trait_pred| { match trait_pred.skip_binder().self_ty().sty { - ty::TyDynamic(..) => true, + ty::Dynamic(..) => true, _ => false, } }) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 8d8482208b..85a437283f 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -314,7 +314,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { from_unsafe_deref: reached_raw_pointer, unsize: false, }; - if let ty::TyRawPtr(_) = ty.sty { + if let ty::RawPtr(_) = ty.sty { // all the subsequent steps will be from_unsafe_deref reached_raw_pointer = true; } @@ -324,7 +324,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let final_ty = autoderef.maybe_ambiguous_final_ty(); match final_ty.sty { - ty::TyInfer(ty::TyVar(_)) => { + ty::Infer(ty::TyVar(_)) => { // Ended in an inference variable. If we are doing // a real method lookup, this is a hard error because it's // possible that there will be multiple applicable methods. @@ -356,7 +356,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // just ignore it. } } - ty::TyArray(elem_ty, _) => { + ty::Array(elem_ty, _) => { let dereferences = steps.len() - 1; steps.push(CandidateStep { @@ -368,7 +368,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { unsize: true, }); } - ty::TyError => return None, + ty::Error => return None, _ => (), } @@ -450,33 +450,33 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let lang_items = self.tcx.lang_items(); match self_ty.sty { - ty::TyDynamic(ref data, ..) => { + ty::Dynamic(ref data, ..) => { if let Some(p) = data.principal() { self.assemble_inherent_candidates_from_object(self_ty, p); self.assemble_inherent_impl_candidates_for_type(p.def_id()); } } - ty::TyAdt(def, _) => { + ty::Adt(def, _) => { self.assemble_inherent_impl_candidates_for_type(def.did); } - ty::TyForeign(did) => { + ty::Foreign(did) => { self.assemble_inherent_impl_candidates_for_type(did); } - ty::TyParam(p) => { + ty::Param(p) => { self.assemble_inherent_candidates_from_param(self_ty, p); } - ty::TyChar => { + ty::Char => { let lang_def_id = lang_items.char_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyStr => { + ty::Str => { let lang_def_id = lang_items.str_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); let lang_def_id = lang_items.str_alloc_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TySlice(_) => { + ty::Slice(_) => { let lang_def_id = lang_items.slice_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); @@ -489,70 +489,70 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let lang_def_id = lang_items.slice_u8_alloc_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { let lang_def_id = lang_items.const_ptr_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { let lang_def_id = lang_items.mut_ptr_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyInt(ast::IntTy::I8) => { + ty::Int(ast::IntTy::I8) => { let lang_def_id = lang_items.i8_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyInt(ast::IntTy::I16) => { + ty::Int(ast::IntTy::I16) => { let lang_def_id = lang_items.i16_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyInt(ast::IntTy::I32) => { + ty::Int(ast::IntTy::I32) => { let lang_def_id = lang_items.i32_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyInt(ast::IntTy::I64) => { + ty::Int(ast::IntTy::I64) => { let lang_def_id = lang_items.i64_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyInt(ast::IntTy::I128) => { + ty::Int(ast::IntTy::I128) => { let lang_def_id = lang_items.i128_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyInt(ast::IntTy::Isize) => { + ty::Int(ast::IntTy::Isize) => { let lang_def_id = lang_items.isize_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyUint(ast::UintTy::U8) => { + ty::Uint(ast::UintTy::U8) => { let lang_def_id = lang_items.u8_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyUint(ast::UintTy::U16) => { + ty::Uint(ast::UintTy::U16) => { let lang_def_id = lang_items.u16_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyUint(ast::UintTy::U32) => { + ty::Uint(ast::UintTy::U32) => { let lang_def_id = lang_items.u32_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyUint(ast::UintTy::U64) => { + ty::Uint(ast::UintTy::U64) => { let lang_def_id = lang_items.u64_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyUint(ast::UintTy::U128) => { + ty::Uint(ast::UintTy::U128) => { let lang_def_id = lang_items.u128_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyUint(ast::UintTy::Usize) => { + ty::Uint(ast::UintTy::Usize) => { let lang_def_id = lang_items.usize_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyFloat(ast::FloatTy::F32) => { + ty::Float(ast::FloatTy::F32) => { let lang_def_id = lang_items.f32_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); let lang_def_id = lang_items.f32_runtime_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::TyFloat(ast::FloatTy::F64) => { + ty::Float(ast::FloatTy::F64) => { let lang_def_id = lang_items.f64_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); @@ -652,7 +652,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { match *predicate { ty::Predicate::Trait(ref trait_predicate) => { match trait_predicate.skip_binder().trait_ref.self_ty().sty { - ty::TyParam(ref p) if *p == param_ty => { + ty::Param(ref p) if *p == param_ty => { Some(trait_predicate.to_poly_trait_ref()) } _ => None, @@ -758,8 +758,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.span, infer::FnCall, &fty); if let Some(self_ty) = self_ty { - if let Err(_) = self.at(&ObligationCause::dummy(), self.param_env) - .sup(fty.inputs()[0], self_ty) + if self.at(&ObligationCause::dummy(), self.param_env) + .sup(fty.inputs()[0], self_ty) + .is_err() { return false } @@ -918,7 +919,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { pick.autoderefs = step.autoderefs; // Insert a `&*` or `&mut *` if this is a reference type: - if let ty::TyRef(_, _, mutbl) = step.self_ty.sty { + if let ty::Ref(_, _, mutbl) = step.self_ty.sty { pick.autoderefs += 1; pick.autoref = Some(mutbl); } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 0fbdecffb8..abc32ed2ea 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -13,6 +13,7 @@ use check::FnCtxt; use rustc::hir::map as hir_map; +use hir::Node; use rustc_data_structures::sync::Lrc; use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable}; use hir::def::Def; @@ -24,7 +25,7 @@ use util::nodemap::FxHashSet; use syntax::ast; use syntax::util::lev_distance::find_best_match_for_name; -use errors::DiagnosticBuilder; +use errors::{Applicability, DiagnosticBuilder}; use syntax_pos::{Span, FileName}; @@ -32,7 +33,7 @@ use rustc::hir::def_id::LOCAL_CRATE; use rustc::hir; use rustc::hir::print; use rustc::infer::type_variable::TypeVariableOrigin; -use rustc::ty::TyAdt; +use rustc::ty::Adt; use std::cmp::Ordering; @@ -45,9 +46,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match ty.sty { // Not all of these (e.g. unsafe fns) implement FnOnce // so we look for these beforehand - ty::TyClosure(..) | - ty::TyFnDef(..) | - ty::TyFnPtr(_) => true, + ty::Closure(..) | + ty::FnDef(..) | + ty::FnPtr(_) => true, // If it's not a simple function, look for things which implement FnOnce _ => { let fn_once = match tcx.lang_items().require(FnOnceTraitLangItem) { @@ -132,7 +133,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if let Some(note_span) = note_span { // We have a span pointing to the method. Show note with snippet. - err.span_note(self.tcx.sess.codemap().def_span(note_span), ¬e_str); + err.span_note(self.tcx.sess.source_map().def_span(note_span), + ¬e_str); } else { err.note(¬e_str); } @@ -141,7 +143,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let item = self .associated_item(trait_did, item_name, Namespace::Value) .unwrap(); - let item_span = self.tcx.sess.codemap() + let item_span = self.tcx.sess.source_map() .def_span(self.tcx.def_span(item.def_id)); if sources.len() > 1 { span_note!(err, @@ -198,7 +200,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let item_kind = if is_method { "method" } else if actual.is_enum() { - if let TyAdt(ref adt_def, _) = actual.sty { + if let Adt(ref adt_def, _) = actual.sty { let names = adt_def.variants.iter().map(|s| &s.name); suggestion = find_best_match_for_name(names, &item_name.as_str(), @@ -246,7 +248,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; match expr.node { hir::ExprKind::Lit(ref lit) => { // numeric literal - let snippet = tcx.sess.codemap().span_to_snippet(lit.span) + let snippet = tcx.sess.source_map().span_to_snippet(lit.span) .unwrap_or("".to_string()); err.span_suggestion(lit.span, @@ -261,9 +263,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let &hir::QPath::Resolved(_, ref path) = &qpath { if let hir::def::Def::Local(node_id) = path.def { let span = tcx.hir.span(node_id); - let snippet = tcx.sess.codemap().span_to_snippet(span) + let snippet = tcx.sess.source_map().span_to_snippet(span) .unwrap(); - let filename = tcx.sess.codemap().span_to_filename(span); + let filename = tcx.sess.source_map().span_to_filename(span); let parent_node = self.tcx.hir.get( self.tcx.hir.get_parent_node(node_id), @@ -274,7 +276,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ); match (filename, parent_node) { - (FileName::Real(_), hir_map::NodeLocal(hir::Local { + (FileName::Real(_), Node::Local(hir::Local { source: hir::LocalSource::Normal, ty, .. @@ -320,7 +322,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(def) = actual.ty_adt_def() { if let Some(full_sp) = tcx.hir.span_if_local(def.did) { - let def_sp = tcx.sess.codemap().def_span(full_sp); + let def_sp = tcx.sess.source_map().def_span(full_sp); err.span_label(def_sp, format!("{} `{}` not found {}", item_kind, item_name, @@ -337,11 +339,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(expr) = rcvr_expr { for (ty, _) in self.autoderef(span, rcvr_ty) { match ty.sty { - ty::TyAdt(def, substs) if !def.is_enum() => { + ty::Adt(def, substs) if !def.is_enum() => { let variant = &def.non_enum_variant(); if let Some(index) = self.tcx.find_field_index(item_name, variant) { let field = &variant.fields[index]; - let snippet = tcx.sess.codemap().span_to_snippet(expr.span); + let snippet = tcx.sess.source_map().span_to_snippet(expr.span); let expr_string = match snippet { Ok(expr_string) => expr_string, _ => "s".into(), // Default to a generic placeholder for the @@ -387,7 +389,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if let Some(expr) = rcvr_expr { - if let Ok(expr_string) = tcx.sess.codemap().span_to_snippet(expr.span) { + if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) { report_function!(expr.span, expr_string); } else if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node @@ -406,11 +408,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if static_sources.len() == 1 { if let Some(expr) = rcvr_expr { - err.span_suggestion(expr.span.to(span), + err.span_suggestion_with_applicability(expr.span.to(span), "use associated function syntax instead", format!("{}::{}", self.ty_to_string(actual), - item_name)); + item_name), + Applicability::MachineApplicable); } else { err.help(&format!("try with `{}::{}`", self.ty_to_string(actual), item_name)); @@ -637,13 +640,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> bool { fn is_local(ty: Ty) -> bool { match ty.sty { - ty::TyAdt(def, _) => def.did.is_local(), - ty::TyForeign(did) => did.is_local(), + ty::Adt(def, _) => def.did.is_local(), + ty::Foreign(did) => did.is_local(), - ty::TyDynamic(ref tr, ..) => tr.principal() + ty::Dynamic(ref tr, ..) => tr.principal() .map_or(false, |p| p.def_id().is_local()), - ty::TyParam(_) => true, + ty::Param(_) => true, // everything else (primitive types etc.) is effectively // non-local (there are "edge" cases, e.g. (LocalType,), but diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4cde171f1b..db0c4fdb03 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -91,25 +91,25 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use std::slice; use namespace::Namespace; use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; -use rustc::infer::anon_types::AnonTypeDecl; +use rustc::infer::opaque_types::OpaqueTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; -use rustc::mir::interpret::{GlobalId}; -use rustc::ty::subst::{UnpackedKind, Subst, Substs}; +use rustc::mir::interpret::{ConstValue, GlobalId}; +use rustc::ty::subst::{CanonicalSubsts, UnpackedKind, Subst, Substs}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; use rustc::ty::util::{Representability, IntTypeExt, Discr}; -use errors::{DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use require_c_abi_if_variadic; use session::{CompileIncomplete, config, Session}; use TypeAndSubsts; use lint; use util::common::{ErrorReported, indenter}; -use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, NodeMap}; +use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap}; use std::cell::{Cell, RefCell, Ref, RefMut}; use rustc_data_structures::sync::Lrc; @@ -122,7 +122,8 @@ use std::ops::{self, Deref}; use rustc_target::spec::abi::Abi; use syntax::ast; use syntax::attr; -use syntax::codemap::original_sp; +use syntax::source_map::DUMMY_SP; +use syntax::source_map::original_sp; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; use syntax::symbol::{Symbol, LocalInternedString, keywords}; @@ -131,7 +132,7 @@ use syntax_pos::{self, BytePos, Span, MultiSpan}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::hir::map::Node; +use rustc::hir::Node; use rustc::hir::{self, PatKind, ItemKind}; use rustc::middle::lang_items; @@ -211,11 +212,11 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { deferred_generator_interiors: RefCell)>>, - // Anonymized types found in explicit return types and their + // Opaque types found in explicit return types and their // associated fresh inference variable. Writeback resolves these // variables to get the concrete type, which can be used to - // deanonymize TyAnon, after typeck is done with all functions. - anon_types: RefCell>>, + // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions. + opaque_types: RefCell>>, /// Each type parameter has an implicit region bound that /// indicates it must outlive at least the function body (the user @@ -311,7 +312,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { /// for examples of where this comes up,. fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> { match fcx.tcx.struct_tail(ty).sty { - ty::TySlice(_) | ty::TyStr | ty::TyDynamic(..) => { + ty::Slice(_) | ty::Str | ty::Dynamic(..) => { ExpectRvalueLikeUnsized(ty) } _ => ExpectHasType(ty) @@ -505,6 +506,9 @@ impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> { } } +#[derive(Debug)] +struct PathSeg(DefId, usize); + pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { body_id: ast::NodeId, @@ -618,7 +622,10 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id)); let implicit_region_bound = body_id.map(|body_id| { let body = tcx.hir.body(body_id); - tcx.mk_region(ty::ReScope(region::Scope::CallSite(body.value.hir_id.local_id))) + tcx.mk_region(ty::ReScope(region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite + })) }); Inherited { @@ -631,7 +638,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { deferred_call_resolutions: RefCell::new(DefIdMap()), deferred_cast_checks: RefCell::new(Vec::new()), deferred_generator_interiors: RefCell::new(Vec::new()), - anon_types: RefCell::new(DefIdMap()), + opaque_types: RefCell::new(DefIdMap()), implicit_region_bound, body_id, } @@ -757,7 +764,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> Option<(hir::BodyId, Option<&'tcx hir::FnDecl>)> { match tcx.hir.get(id) { - hir::map::NodeItem(item) => { + Node::Item(item) => { match item.node { hir::ItemKind::Const(_, body) | hir::ItemKind::Static(_, _, body) => @@ -768,7 +775,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, None, } } - hir::map::NodeTraitItem(item) => { + Node::TraitItem(item) => { match item.node { hir::TraitItemKind::Const(_, Some(body)) => Some((body, None)), @@ -778,7 +785,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, None, } } - hir::map::NodeImplItem(item) => { + Node::ImplItem(item) => { match item.node { hir::ImplItemKind::Const(_, body) => Some((body, None)), @@ -788,7 +795,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, None, } } - hir::map::NodeAnonConst(constant) => Some((constant.body, None)), + Node::AnonConst(constant) => Some((constant.body, None)), _ => None, } } @@ -876,7 +883,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. fcx.check_casts(); - // Closure and generater analysis may run after fallback + // Closure and generator analysis may run after fallback // because they don't constrain other type variables. fcx.closure_analyze(body); assert!(fcx.deferred_call_resolutions.borrow().is_empty()); @@ -961,8 +968,10 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { if let PatKind::Binding(_, _, ident, _) = p.node { let var_ty = self.assign(p.span, p.id, None); - self.fcx.require_type_is_sized(var_ty, p.span, - traits::VariableType(p.id)); + if !self.fcx.tcx.features().unsized_locals { + self.fcx.require_type_is_sized(var_ty, p.span, + traits::VariableType(p.id)); + } debug!("Pattern binding {} is assigned to {} with type {:?}", ident, @@ -1018,7 +1027,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let declared_ret_ty = fn_sig.output(); fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); - let revealed_ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &declared_ret_ty); + let revealed_ret_ty = fcx.instantiate_opaque_types_from_return_value(fn_id, &declared_ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty))); fn_sig = fcx.tcx.mk_fn_sig( fn_sig.inputs().iter().cloned(), @@ -1048,8 +1057,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // The check for a non-trivial pattern is a hack to avoid duplicate warnings // for simple cases like `fn foo(x: Trait)`, // where we would error once on the parameter as a whole, and once on the binding `x`. - if arg.pat.simple_ident().is_none() { - fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation); + if arg.pat.simple_ident().is_none() && !fcx.tcx.features().unsized_locals { + fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::SizedArgumentType); } fcx.write_ty(arg.hir_id, arg_ty); @@ -1111,7 +1120,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() { if id == fn_id { match entry_type { - config::EntryMain => { + config::EntryFnType::Main => { let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]); let trait_ref = ty::TraitRef::new(term_id, substs); let return_ty_span = decl.output.span(); @@ -1122,7 +1131,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, traits::Obligation::new( cause, param_env, trait_ref.to_predicate())); }, - config::EntryStart => {}, + config::EntryFnType::Start => {}, } } } @@ -1132,7 +1141,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() { if panic_impl_did == fcx.tcx.hir.local_def_id(fn_id) { if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() { - if declared_ret_ty.sty != ty::TyNever { + // at this point we don't care if there are duplicate handlers or if the handler has + // the wrong signature as this value we'll be used when writing metadata and that + // only happens if compilation succeeded + fcx.tcx.sess.has_panic_handler.try_set_same(true); + + if declared_ret_ty.sty != ty::Never { fcx.tcx.sess.span_err( decl.output.span(), "return type should be `!`", @@ -1143,8 +1157,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let span = fcx.tcx.hir.span(fn_id); if inputs.len() == 1 { let arg_is_panic_info = match inputs[0].sty { - ty::TyRef(region, ty, mutbl) => match ty.sty { - ty::TyAdt(ref adt, _) => { + ty::Ref(region, ty, mutbl) => match ty.sty { + ty::Adt(ref adt, _) => { adt.did == panic_info_did && mutbl == hir::Mutability::MutImmutable && *region != RegionKind::ReStatic @@ -1161,18 +1175,18 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, ); } - if let Node::NodeItem(item) = fcx.tcx.hir.get(fn_id) { + if let Node::Item(item) = fcx.tcx.hir.get(fn_id) { if let ItemKind::Fn(_, _, ref generics, _) = item.node { if !generics.params.is_empty() { fcx.tcx.sess.span_err( span, - "`#[panic_implementation]` function should have no type \ - parameters", + "should have no type parameters", ); } } } } else { + let span = fcx.tcx.sess.source_map().def_span(span); fcx.tcx.sess.span_err(span, "function should have one argument"); } } else { @@ -1185,7 +1199,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, if let Some(alloc_error_handler_did) = fcx.tcx.lang_items().oom() { if alloc_error_handler_did == fcx.tcx.hir.local_def_id(fn_id) { if let Some(alloc_layout_did) = fcx.tcx.lang_items().alloc_layout() { - if declared_ret_ty.sty != ty::TyNever { + if declared_ret_ty.sty != ty::Never { fcx.tcx.sess.span_err( decl.output.span(), "return type should be `!`", @@ -1196,7 +1210,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let span = fcx.tcx.hir.span(fn_id); if inputs.len() == 1 { let arg_is_alloc_layout = match inputs[0].sty { - ty::TyAdt(ref adt, _) => { + ty::Adt(ref adt, _) => { adt.did == alloc_layout_did }, _ => false, @@ -1209,7 +1223,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, ); } - if let Node::NodeItem(item) = fcx.tcx.hir.get(fn_id) { + if let Node::Item(item) = fcx.tcx.hir.get(fn_id) { if let ItemKind::Fn(_, _, ref generics, _) = item.node { if !generics.params.is_empty() { fcx.tcx.sess.span_err( @@ -1221,6 +1235,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } } } else { + let span = fcx.tcx.sess.source_map().def_span(span); fcx.tcx.sess.span_err(span, "function should have one argument"); } } else { @@ -1370,7 +1385,11 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt, id: DefId, span: Span) { }; let param_env = ty::ParamEnv::reveal_all(); if let Ok(static_) = tcx.const_eval(param_env.and(cid)) { - let alloc = tcx.const_value_to_allocation(static_); + let alloc = if let ConstValue::ByRef(_, allocation, _) = static_.val { + allocation + } else { + bug!("Matching on non-ByRef static") + }; if alloc.relocations.len() != 0 { let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ @@ -1429,7 +1448,7 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir::ImplItemKind::Type(_) => ty::AssociatedKind::Type }; - let parent = ancestors.defs(tcx, trait_item.ident, kind, trait_def.def_id).skip(1).next() + let parent = ancestors.defs(tcx, trait_item.ident, kind, trait_def.def_id).nth(1) .map(|node_item| node_item.map(|parent| parent.defaultness)); if let Some(parent) = parent { @@ -1445,7 +1464,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_id: DefId, impl_trait_ref: ty::TraitRef<'tcx>, impl_item_refs: &[hir::ImplItemRef]) { - let impl_span = tcx.sess.codemap().def_span(impl_span); + let impl_span = tcx.sess.source_map().def_span(impl_span); // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` @@ -1628,7 +1647,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) { let t = tcx.type_of(def_id); match t.sty { - ty::TyAdt(def, substs) if def.is_struct() => { + ty::Adt(def, substs) if def.is_struct() => { let fields = &def.non_enum_variant().fields; if fields.is_empty() { span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty"); @@ -1642,7 +1661,7 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId return; } match e.sty { - ty::TyParam(_) => { /* struct(T, T, T, T) is ok */ } + ty::Param(_) => { /* struct(T, T, T, T) is ok */ } _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ } _ => { span_err!(tcx.sess, sp, E0077, @@ -1688,7 +1707,7 @@ fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return false; } match t.sty { - ty::TyAdt(def, substs) if def.is_struct() || def.is_union() => { + ty::Adt(def, substs) if def.is_struct() || def.is_union() => { if tcx.adt_def(def.did).repr.align > 0 { return true; } @@ -1697,7 +1716,7 @@ fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for field in &def.non_enum_variant().fields { let f = field.ty(tcx, substs); match f.sty { - ty::TyAdt(def, _) => { + ty::Adt(def, _) => { if check_packed_inner(tcx, def.did, stack) { return true; } @@ -1977,7 +1996,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn resolve_type_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> { debug!("resolve_type_vars_with_obligations(ty={:?})", ty); - // No TyInfer()? Nothing needs doing. + // No Infer()? Nothing needs doing. if !ty.has_infer_types() { debug!("resolve_type_vars_with_obligations: ty={:?}", ty); return ty; @@ -2005,7 +2024,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { closure_def_id: DefId, r: DeferredCallResolution<'gcx, 'tcx>) { let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut(); - deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r); + deferred_call_resolutions.entry(closure_def_id).or_default().push(r); } fn remove_deferred_call_resolutions(&self, @@ -2053,11 +2072,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { + debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method); self.tables .borrow_mut() .type_dependent_defs_mut() .insert(hir_id, Def::Method(method.def_id)); + self.write_substs(hir_id, method.substs); + + // When the method is confirmed, the `method.substs` includes + // parameters from not just the method, but also the impl of + // the method -- in particular, the `Self` type will be fully + // resolved. However, those are not something that the "user + // specified" -- i.e., those types come from the inferred type + // of the receiver, not something the user wrote. So when we + // create the user-substs, we want to replace those earlier + // types with just the types that the user actually wrote -- + // that is, those that appear on the *method itself*. + // + // As an example, if the user wrote something like + // `foo.bar::(...)` -- the `Self` type here will be the + // type of `foo` (possibly adjusted), but we don't want to + // include that. We want just the `[_, u32]` part. + if !method.substs.is_noop() { + let method_generics = self.tcx.generics_of(method.def_id); + if !method_generics.params.is_empty() { + let user_substs = self.infcx.probe(|_| { + let just_method_substs = Substs::for_item(self.tcx, method.def_id, |param, _| { + let i = param.index as usize; + if i < method_generics.parent_count { + self.infcx.var_for_def(DUMMY_SP, param) + } else { + method.substs[i] + } + }); + self.infcx.canonicalize_response(&just_method_substs) + }); + + debug!("write_method_call: user_substs = {:?}", user_substs); + self.write_user_substs(hir_id, user_substs); + } + } } pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) { @@ -2071,6 +2126,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + /// Given the substs that we just converted from the HIR, try to + /// canonicalize them and store them as user-given substitutions + /// (i.e., substitutions that must be respected by the NLL check). + /// + /// This should be invoked **before any unifications have + /// occurred**, so that annotations like `Vec<_>` are preserved + /// properly. + pub fn write_user_substs_from_substs(&self, hir_id: hir::HirId, substs: &'tcx Substs<'tcx>) { + if !substs.is_noop() { + let user_substs = self.infcx.canonicalize_response(&substs); + debug!("instantiate_value_path: user_substs = {:?}", user_substs); + self.write_user_substs(hir_id, user_substs); + } + } + + pub fn write_user_substs(&self, hir_id: hir::HirId, substs: CanonicalSubsts<'tcx>) { + debug!( + "write_user_substs({:?}, {:?}) in fcx {}", + hir_id, + substs, + self.tag(), + ); + + if !substs.is_identity() { + self.tables.borrow_mut().user_substs_mut().insert(hir_id, substs); + } else { + debug!("write_user_substs: skipping identity substs"); + } + } + pub fn apply_adjustments(&self, expr: &hir::Expr, adj: Vec>) { debug!("apply_adjustments(expr={:?}, adj={:?})", expr, adj); @@ -2140,24 +2225,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { result } - /// Replace the anonymized types from the return value of the - /// function with type variables and records the `AnonTypeMap` for + /// Replace the opaque types from the return value of the + /// function with type variables and records the `OpaqueTypeMap` for /// later use during writeback. See - /// `InferCtxt::instantiate_anon_types` for more details. - fn instantiate_anon_types_from_return_value>( + /// `InferCtxt::instantiate_opaque_types` for more details. + fn instantiate_opaque_types_from_return_value>( &self, fn_id: ast::NodeId, value: &T, ) -> T { let fn_def_id = self.tcx.hir.local_def_id(fn_id); debug!( - "instantiate_anon_types_from_return_value(fn_def_id={:?}, value={:?})", + "instantiate_opaque_types_from_return_value(fn_def_id={:?}, value={:?})", fn_def_id, value ); - let (value, anon_type_map) = self.register_infer_ok_obligations( - self.instantiate_anon_types( + let (value, opaque_type_map) = self.register_infer_ok_obligations( + self.instantiate_opaque_types( fn_def_id, self.body_id, self.param_env, @@ -2165,9 +2250,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ) ); - let mut anon_types = self.anon_types.borrow_mut(); - for (ty, decl) in anon_type_map { - let old_value = anon_types.insert(ty, decl); + let mut opaque_types = self.opaque_types.borrow_mut(); + for (ty, decl) in opaque_type_map { + let old_value = opaque_types.insert(ty, decl); assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl); } @@ -2326,8 +2411,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // feature(never_type) is enabled, unconstrained ints with i32, // unconstrained floats with f64. // Fallback becomes very dubious if we have encountered type-checking errors. - // In that case, fallback to TyError. - // The return value indicates whether fallback has occured. + // In that case, fallback to Error. + // The return value indicates whether fallback has occurred. fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool { use rustc::ty::error::UnconstrainedNumeric::Neither; use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; @@ -2476,7 +2561,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut self_ty = adjusted_ty; if unsize { // We only unsize arrays here. - if let ty::TyArray(element_ty, _) = adjusted_ty.sty { + if let ty::Array(element_ty, _) = adjusted_ty.sty { self_ty = self.tcx.mk_slice(element_ty); } else { continue; @@ -2495,7 +2580,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let method = self.register_infer_ok_obligations(ok); let mut adjustments = autoderef.adjust_steps(needs); - if let ty::TyRef(region, _, r_mutbl) = method.sig.inputs()[0].sty { + if let ty::Ref(region, _, r_mutbl) = method.sig.inputs()[0].sty { let mutbl = match r_mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -2666,17 +2751,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if arg_count == 1 {" was"} else {"s were"}), DiagnosticId::Error(error_code.to_owned())); - if let Some(def_s) = def_span.map(|sp| tcx.sess.codemap().def_span(sp)) { + if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().def_span(sp)) { err.span_label(def_s, "defined here"); } if sugg_unit { - let sugg_span = tcx.sess.codemap().end_point(expr_sp); + let sugg_span = tcx.sess.source_map().end_point(expr_sp); // remove closing `)` from the span let sugg_span = sugg_span.shrink_to_lo(); - err.span_suggestion( + err.span_suggestion_with_applicability( sugg_span, "expected the unit value `()`; create it with empty parentheses", - String::from("()")); + String::from("()"), + Applicability::MachineApplicable); } else { err.span_label(sp, format!("expected {}{} parameter{}", if variadic {"at least "} else {""}, @@ -2689,15 +2775,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let formal_tys = if tuple_arguments == TupleArguments { let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); match tuple_type.sty { - ty::TyTuple(arg_types) if arg_types.len() != args.len() => { + ty::Tuple(arg_types) if arg_types.len() != args.len() => { param_count_error(arg_types.len(), args.len(), "E0057", false, false); expected_arg_tys = &[]; self.err_args(args.len()) } - ty::TyTuple(arg_types) => { + ty::Tuple(arg_types) => { expected_arg_tys = match expected_arg_tys.get(0) { Some(&ty) => match ty.sty { - ty::TyTuple(ref tys) => &tys, + ty::Tuple(ref tys) => &tys, _ => &[] }, None => &[] @@ -2725,9 +2811,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { // is the missing argument of type `()`? let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 { - self.resolve_type_vars_if_possible(&expected_arg_tys[0]).is_nil() + self.resolve_type_vars_if_possible(&expected_arg_tys[0]).is_unit() } else if fn_inputs.len() == 1 && supplied_arg_count == 0 { - self.resolve_type_vars_if_possible(&fn_inputs[0]).is_nil() + self.resolve_type_vars_if_possible(&fn_inputs[0]).is_unit() } else { false }; @@ -2826,16 +2912,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // in C but we just error out instead and require explicit casts. let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); match arg_ty.sty { - ty::TyFloat(ast::FloatTy::F32) => { + ty::Float(ast::FloatTy::F32) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); } - ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => { + ty::Int(ast::IntTy::I8) | ty::Int(ast::IntTy::I16) | ty::Bool => { variadic_error(tcx.sess, arg.span, arg_ty, "c_int"); } - ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => { + ty::Uint(ast::UintTy::U8) | ty::Uint(ast::UintTy::U16) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } - ty::TyFnDef(..) => { + ty::FnDef(..) => { let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx)); let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty); variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string()); @@ -2871,10 +2957,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { let opt_ty = expected.to_option(self).and_then(|ty| { match ty.sty { - ty::TyInt(_) | ty::TyUint(_) => Some(ty), - ty::TyChar => Some(tcx.types.u8), - ty::TyRawPtr(..) => Some(tcx.types.usize), - ty::TyFnDef(..) | ty::TyFnPtr(_) => Some(tcx.types.usize), + ty::Int(_) | ty::Uint(_) => Some(ty), + ty::Char => Some(tcx.types.u8), + ty::RawPtr(..) => Some(tcx.types.usize), + ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize), _ => None } }); @@ -2885,7 +2971,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ast::LitKind::FloatUnsuffixed(_) => { let opt_ty = expected.to_option(self).and_then(|ty| { match ty.sty { - ty::TyFloat(_) => Some(ty), + ty::Float(_) => Some(ty), _ => None } }); @@ -2935,10 +3021,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (ExpectIfCondition, &hir::ExprKind::Assign(ref lhs, ref rhs)) => { let msg = "try comparing for equality"; if let (Ok(left), Ok(right)) = ( - self.tcx.sess.codemap().span_to_snippet(lhs.span), - self.tcx.sess.codemap().span_to_snippet(rhs.span)) + self.tcx.sess.source_map().span_to_snippet(lhs.span), + self.tcx.sess.source_map().span_to_snippet(rhs.span)) { - err.span_suggestion(expr.span, msg, format!("{} == {}", left, right)); + err.span_suggestion_with_applicability( + expr.span, + msg, + format!("{} == {}", left, right), + Applicability::MaybeIncorrect); } else { err.help(msg); } @@ -3174,7 +3264,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut autoderef = self.autoderef(expr.span, expr_t); while let Some((base_t, _)) = autoderef.next() { match base_t.sty { - ty::TyAdt(base_def, substs) if !base_def.is_enum() => { + ty::Adt(base_def, substs) if !base_def.is_enum() => { debug!("struct named {:?}", base_t); let (ident, def_scope) = self.tcx.adjust_ident(field, base_def.did, self.body_id); @@ -3196,7 +3286,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { private_candidate = Some((base_def.did, field_ty)); } } - ty::TyTuple(ref tys) => { + ty::Tuple(ref tys) => { let fstr = field.as_str(); if let Ok(index) = fstr.parse::() { if fstr == index.to_string() { @@ -3241,7 +3331,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut err = self.no_such_field_err(field.span, field, expr_t); match expr_t.sty { - ty::TyAdt(def, _) if !def.is_enum() => { + ty::Adt(def, _) if !def.is_enum() => { if let Some(suggested_field_name) = Self::suggest_field_name(def.non_enum_variant(), &field.as_str(), vec![]) { @@ -3257,7 +3347,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; } - ty::TyRawPtr(..) => { + ty::RawPtr(..) => { let base = self.tcx.hir.node_to_pretty_string(base.id); let msg = format!("`{}` is a native pointer; try dereferencing it", base); let suggestion = format!("(*{}).{}", base, field); @@ -3331,7 +3421,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut err = self.type_error_struct_with_diag( field.ident.span, |actual| match ty.sty { - ty::TyAdt(adt, ..) if adt.is_enum() => { + ty::Adt(adt, ..) if adt.is_enum() => { struct_span_err!(self.tcx.sess, field.ident.span, E0559, "{} `{}::{}` has no field named `{}`", kind_name, actual, variant.name, field.ident) @@ -3352,7 +3442,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { format!("field does not exist - did you mean `{}`?", field_name)); } else { match ty.sty { - ty::TyAdt(adt, ..) => { + ty::Adt(adt, ..) => { if adt.is_enum() { err.span_label(field.ident.span, format!("`{}::{}` does not have this field", @@ -3389,8 +3479,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // re-link the regions that EIfEO can erase. self.demand_eqtype(span, adt_ty_hint, adt_ty); - let (substs, adt_kind, kind_name) = match &adt_ty.sty{ - &ty::TyAdt(adt, substs) => { + let (substs, adt_kind, kind_name) = match &adt_ty.sty { + &ty::Adt(adt, substs) => { (substs, adt.adt_kind(), adt.variant_descr()) } _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields") @@ -3461,7 +3551,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { displayable_field_names.sort(); let truncated_fields_error = if len <= 3 { - "".to_string() + String::new() } else { format!(" and {} other field{}", (len - 3), if len - 3 == 1 {""} else {"s"}) }; @@ -3515,7 +3605,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } Def::Variant(..) => { match ty.sty { - ty::TyAdt(adt, substs) => { + ty::Adt(adt, substs) => { Some((adt.variant_of_def(def), adt.did, substs)) } _ => bug!("unexpected type: {:?}", ty.sty) @@ -3524,7 +3614,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { match ty.sty { - ty::TyAdt(adt, substs) if !adt.is_enum() => { + ty::Adt(adt, substs) if !adt.is_enum() => { Some((adt.non_enum_variant(), adt.did, substs)) } _ => None, @@ -3534,6 +3624,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if let Some((variant, did, substs)) = variant { + debug!("check_struct_path: did={:?} substs={:?}", did, substs); + let hir_id = self.tcx.hir.node_to_hir_id(node_id); + self.write_user_substs_from_substs(hir_id, substs); + // Check bounds on type arguments used in the path. let bounds = self.instantiate_bounds(path_span, did, substs); let cause = traits::ObligationCause::new(path_span, self.body_id, @@ -3559,13 +3653,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { base_expr: &'gcx Option>) -> Ty<'tcx> { // Find the relevant variant - let (variant, struct_ty) = - if let Some(variant_ty) = self.check_struct_path(qpath, expr.id) { - variant_ty - } else { - self.check_struct_fields_on_error(fields, base_expr); - return self.tcx.types.err; - }; + let (variant, adt_ty) = + if let Some(variant_ty) = self.check_struct_path(qpath, expr.id) { + variant_ty + } else { + self.check_struct_fields_on_error(fields, base_expr); + return self.tcx.types.err; + }; let path_span = match *qpath { hir::QPath::Resolved(_, ref path) => path.span, @@ -3573,24 +3667,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Prohibit struct expressions when non exhaustive flag is set. - if let ty::TyAdt(adt, _) = struct_ty.sty { - if !adt.did.is_local() && adt.is_non_exhaustive() { - span_err!(self.tcx.sess, expr.span, E0639, - "cannot create non-exhaustive {} using struct expression", - adt.variant_descr()); - } + let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type"); + if !adt.did.is_local() && variant.is_field_list_non_exhaustive() { + span_err!(self.tcx.sess, expr.span, E0639, + "cannot create non-exhaustive {} using struct expression", + adt.variant_descr()); } - let error_happened = self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, + let error_happened = self.check_expr_struct_fields(adt_ty, expected, expr.id, path_span, variant, fields, base_expr.is_none()); if let &Some(ref base_expr) = base_expr { // If check_expr_struct_fields hit an error, do not attempt to populate // the fields with the base_expr. This could cause us to hit errors later // when certain fields are assumed to exist that in fact do not. if !error_happened { - self.check_expr_has_type_or_error(base_expr, struct_ty); - match struct_ty.sty { - ty::TyAdt(adt, substs) if adt.is_struct() => { + self.check_expr_has_type_or_error(base_expr, adt_ty); + match adt_ty.sty { + ty::Adt(adt, substs) if adt.is_struct() => { let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| { self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) }).collect(); @@ -3607,8 +3700,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - self.require_type_is_sized(struct_ty, expr.span, traits::StructInitializerSized); - struct_ty + self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized); + adt_ty } @@ -3620,7 +3713,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// strict, _|_ can appear in the type of an expression that does not, /// itself, diverge: for example, fn() -> _|_.) /// Note that inspecting a type's structure *directly* may expose the fact - /// that there are actually multiple representations for `TyError`, so avoid + /// that there are actually multiple representations for `Error`, so avoid /// that when err needs to be handled differently. fn check_expr_with_expectation_and_needs(&self, expr: &'gcx hir::Expr, @@ -3679,7 +3772,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprKind::Box(ref subexpr) => { let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| { match ty.sty { - ty::TyAdt(def, _) if def.is_box() + ty::Adt(def, _) if def.is_box() => Expectation::rvalue_hint(self, ty.boxed_ty()), _ => NoExpectation } @@ -3723,7 +3816,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else if let Some(ok) = self.try_overloaded_deref( expr.span, oprnd_t, needs) { let method = self.register_infer_ok_obligations(ok); - if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[0].sty { + if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty { let mutbl = match mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -3750,7 +3843,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::UnNot => { let result = self.check_user_unop(expr, oprnd_t, unop); // If it's builtin, we can reuse the type, this helps inference. - if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) { + if !(oprnd_t.is_integral() || oprnd_t.sty == ty::Bool) { oprnd_t = result; } } @@ -3768,7 +3861,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprKind::AddrOf(mutbl, ref oprnd) => { let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { match ty.sty { - ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => { + ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { if self.is_place_expr(&oprnd) { // Places may legitimately have unsized types. // For example, dereferences of a fat pointer and @@ -3808,7 +3901,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprKind::Path(ref qpath) => { let (def, opt_ty, segs) = self.resolve_ty_and_def_ufcs(qpath, expr.id, expr.span); let ty = if def != Def::Err { - self.instantiate_value_path(segs, opt_ty, def, expr.span, id) + self.instantiate_value_path(segs, opt_ty, def, expr.span, id).0 } else { self.set_tainted_by_errors(); tcx.types.err @@ -3828,7 +3921,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for input in inputs { self.check_expr(input); } - tcx.mk_nil() + tcx.mk_unit() } hir::ExprKind::Break(destination, ref expr_opt) => { if let Ok(target_id) = destination.target_id { @@ -3855,7 +3948,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { // Otherwise, this is a break *without* a value. That's // always legal, and is equivalent to `break ()`. - e_ty = tcx.mk_nil(); + e_ty = tcx.mk_unit(); cause = self.misc(expr.span); } @@ -3868,7 +3961,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(ref e) = *expr_opt { coerce.coerce(self, &cause, e, e_ty); } else { - assert!(e_ty.is_nil()); + assert!(e_ty.is_unit()); coerce.coerce_forced_unit(self, &cause, &mut |_| (), true); } } else { @@ -3915,7 +4008,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } hir::ExprKind::Continue(destination) => { - if let Ok(_) = destination.target_id { + if destination.target_id.is_ok() { tcx.types.never } else { // There was an error, make typecheck fail @@ -3962,7 +4055,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if lhs_ty.references_error() || rhs_ty.references_error() { tcx.types.err } else { - tcx.mk_nil() + tcx.mk_unit() } } hir::ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => { @@ -3991,7 +4084,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(Diverges::Maybe); } - self.tcx.mk_nil() + self.tcx.mk_unit() } hir::ExprKind::Loop(ref body, _, source) => { let coerce = match source { @@ -4031,7 +4124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // [1] self.tcx.sess.delay_span_bug(body.span, "no coercion, but loop may not break"); } - ctxt.coerce.map(|c| c.complete(self)).unwrap_or(self.tcx.mk_nil()) + ctxt.coerce.map(|c| c.complete(self)).unwrap_or(self.tcx.mk_unit()) } hir::ExprKind::Match(ref discrim, ref arms, match_src) => { self.check_match(expr, &discrim, arms, expected, match_src) @@ -4081,7 +4174,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprKind::Array(ref args) => { let uty = expected.to_option(self).and_then(|uty| { match uty.sty { - ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty), + ty::Array(ty, _) | ty::Slice(ty) => Some(ty), _ => None } }); @@ -4128,7 +4221,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let uty = match expected { ExpectHasType(uty) => { match uty.sty { - ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty), + ty::Array(ty, _) | ty::Slice(ty) => Some(ty), _ => None } } @@ -4160,7 +4253,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if element_ty.references_error() { tcx.types.err } else if let Ok(count) = count { - tcx.mk_ty(ty::TyArray(t, count)) + tcx.mk_ty(ty::Array(t, count)) } else { tcx.types.err } @@ -4169,7 +4262,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let flds = expected.only_has_type(self).and_then(|ty| { let ty = self.resolve_type_vars_with_obligations(ty); match ty.sty { - ty::TyTuple(ref flds) => Some(&flds[..]), + ty::Tuple(ref flds) => Some(&flds[..]), _ => None } }); @@ -4223,18 +4316,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "cannot index into a value of type `{}`", base_t); // Try to give some advice about indexing tuples. - if let ty::TyTuple(..) = base_t.sty { + if let ty::Tuple(..) = base_t.sty { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: if let hir::ExprKind::Lit(ref lit) = idx.node { if let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node { - let snip = tcx.sess.codemap().span_to_snippet(base.span); + let snip = tcx.sess.source_map().span_to_snippet(base.span); if let Ok(snip) = snip { - err.span_suggestion(expr.span, - "to access tuple elements, use", - format!("{}.{}", snip, i)); + err.span_suggestion_with_applicability( + expr.span, + "to access tuple elements, use", + format!("{}.{}", snip, i), + Applicability::MachineApplicable); needs_note = false; } } @@ -4260,7 +4355,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "yield statement outside of generator literal").emit(); } } - tcx.mk_nil() + tcx.mk_unit() } } } @@ -4275,8 +4370,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { { match *qpath { hir::QPath::Resolved(ref maybe_qself, ref path) => { - let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); - let ty = AstConv::def_to_ty(self, opt_self_ty, path, true); + let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); + let ty = AstConv::def_to_ty(self, self_ty, path, true); (path.def, ty) } hir::QPath::TypeRelative(ref qself, ref segment) => { @@ -4424,7 +4519,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } hir::StmtKind::Expr(ref expr, _) => { // Check with expected type of () - self.check_expr_has_type_or_error(&expr, self.tcx.mk_nil()); + self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit()); } hir::StmtKind::Semi(ref expr, _) => { self.check_expr(&expr); @@ -4437,7 +4532,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_block_no_value(&self, blk: &'gcx hir::Block) { - let unit = self.tcx.mk_nil(); + let unit = self.tcx.mk_unit(); let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); // if the block produces a `!` value, that can always be @@ -4459,7 +4554,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // In some cases, blocks have just one exit, but other blocks // can be targeted by multiple breaks. This can happen both // with labeled blocks as well as when we desugar - // a `do catch { ... }` expression. + // a `try { ... }` expression. // // Example 1: // @@ -4564,7 +4659,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) { let parent = self.tcx.hir.get(fn_id); - if let Node::NodeItem(&hir::Item { + if let Node::Item(&hir::Item { name, node: hir::ItemKind::Fn(ref decl, ..), .. }) = parent { decl.clone().and_then(|decl| { @@ -4573,7 +4668,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // but it will still present it as the reason for the expected type. Some((decl, name != Symbol::intern("main"))) }) - } else if let Node::NodeTraitItem(&hir::TraitItem { + } else if let Node::TraitItem(&hir::TraitItem { node: hir::TraitItemKind::Method(hir::MethodSig { ref decl, .. }, ..), .. @@ -4581,7 +4676,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { decl.clone().and_then(|decl| { Some((decl, true)) }) - } else if let Node::NodeImplItem(&hir::ImplItem { + } else if let Node::ImplItem(&hir::ImplItem { node: hir::ImplItemKind::Method(hir::MethodSig { ref decl, .. }, ..), .. @@ -4627,10 +4722,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.span_suggestion(sp, msg, suggestion); } else if !self.check_for_cast(err, expr, found, expected) { let methods = self.get_conversion_methods(expr.span, expected, found); - if let Ok(expr_text) = self.sess().codemap().span_to_snippet(expr.span) { + if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { let suggestions = iter::repeat(expr_text).zip(methods.iter()) - .map(|(receiver, method)| format!("{}.{}()", receiver, method.ident)) - .collect::>(); + .filter_map(|(receiver, method)| { + let method_call = format!(".{}()", method.ident); + if receiver.ends_with(&method_call) { + None // do not suggest code that is already there (#53348) + } else { + /* + methods defined in `method_call_list` will overwrite + `.clone()` in copy of `receiver` + */ + let method_call_list = [".to_vec()", ".to_string()"]; + if receiver.ends_with(".clone()") + && method_call_list.contains(&method_call.as_str()){ + // created copy of `receiver` because we don't want other + // suggestion to get affected + let mut new_receiver = receiver.clone(); + let max_len = new_receiver.rfind(".").unwrap(); + new_receiver.truncate(max_len); + Some(format!("{}{}", new_receiver, method_call)) + } + else { + Some(format!("{}{}", receiver, method_call)) + } + } + }) .collect::>(); if !suggestions.is_empty() { err.span_suggestions(expr.span, "try using a conversion method", suggestions); } @@ -4654,7 +4771,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expression: &'gcx hir::Expr, expected: Ty<'tcx>, cause_span: Span) { - if expected.is_nil() { + if expected.is_unit() { // `BlockTailExpression` only relevant if the tail expr would be // useful on its own. match expression.node { @@ -4665,10 +4782,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) | hir::ExprKind::Block(..) => { - let sp = self.tcx.sess.codemap().next_point(cause_span); - err.span_suggestion(sp, - "try adding a semicolon", - ";".to_string()); + let sp = self.tcx.sess.source_map().next_point(cause_span); + err.span_suggestion_with_applicability( + sp, + "try adding a semicolon", + ";".to_string(), + Applicability::MachineApplicable); } _ => (), } @@ -4695,12 +4814,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { can_suggest: bool) { // Only suggest changing the return type for methods that // haven't set a return type at all (and aren't `fn main()` or an impl). - match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_nil()) { + match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) { (&hir::FunctionRetTy::DefaultReturn(span), true, true, true) => { - err.span_suggestion(span, - "try adding a return type", - format!("-> {} ", - self.resolve_type_vars_with_obligations(found))); + err.span_suggestion_with_applicability( + span, + "try adding a return type", + format!("-> {} ", self.resolve_type_vars_with_obligations(found)), + Applicability::MachineApplicable); } (&hir::FunctionRetTy::DefaultReturn(span), false, true, true) => { err.span_label(span, "possibly return type missing here?"); @@ -4759,23 +4879,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } let original_span = original_sp(last_stmt.span, blk.span); let span_semi = original_span.with_lo(original_span.hi() - BytePos(1)); - err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string()); + err.span_suggestion_with_applicability( + span_semi, + "consider removing this semicolon", + String::new(), + Applicability::MachineApplicable); } - // Instantiates the given path, which must refer to an item with the given - // number of type parameters and type. - pub fn instantiate_value_path(&self, - segments: &[hir::PathSegment], - opt_self_ty: Option>, - def: Def, - span: Span, - node_id: ast::NodeId) - -> Ty<'tcx> { - debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})", - segments, - def, - node_id); - + fn def_ids_for_path_segments(&self, + segments: &[hir::PathSegment], + def: Def) + -> Vec { // We need to extract the type parameters supplied by the user in // the path `path`. Due to the current setup, this is a bit of a // tricky-process; the problem is that resolve only tells us the @@ -4821,33 +4935,70 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The first step then is to categorize the segments appropriately. assert!(!segments.is_empty()); + let last = segments.len() - 1; + + let mut path_segs = vec![]; - let mut ufcs_associated = None; - let mut type_segment = None; - let mut fn_segment = None; match def { // Case 1. Reference to a struct/variant constructor. Def::StructCtor(def_id, ..) | - Def::VariantCtor(def_id, ..) => { + Def::VariantCtor(def_id, ..) | + Def::SelfCtor(.., def_id) => { // Everything but the final segment should have no // parameters at all. - let mut generics = self.tcx.generics_of(def_id); - if let Some(def_id) = generics.parent { - // Variant and struct constructors use the - // generics of their parent type definition. - generics = self.tcx.generics_of(def_id); - } - type_segment = Some((segments.last().unwrap(), generics)); + let generics = self.tcx.generics_of(def_id); + // Variant and struct constructors use the + // generics of their parent type definition. + let generics_def_id = generics.parent.unwrap_or(def_id); + path_segs.push(PathSeg(generics_def_id, last)); } // Case 2. Reference to a top-level value. Def::Fn(def_id) | Def::Const(def_id) | Def::Static(def_id, _) => { - fn_segment = Some((segments.last().unwrap(), self.tcx.generics_of(def_id))); + path_segs.push(PathSeg(def_id, last)); } // Case 3. Reference to a method or associated const. + Def::Method(def_id) | + Def::AssociatedConst(def_id) => { + if segments.len() >= 2 { + let generics = self.tcx.generics_of(def_id); + path_segs.push(PathSeg(generics.parent.unwrap(), last - 1)); + } + path_segs.push(PathSeg(def_id, last)); + } + + // Case 4. Local variable, no generics. + Def::Local(..) | Def::Upvar(..) => {} + + _ => bug!("unexpected definition: {:?}", def), + } + + debug!("path_segs = {:?}", path_segs); + + path_segs + } + + // Instantiates the given path, which must refer to an item with the given + // number of type parameters and type. + pub fn instantiate_value_path(&self, + segments: &[hir::PathSegment], + self_ty: Option>, + def: Def, + span: Span, + node_id: ast::NodeId) + -> (Ty<'tcx>, Def) { + debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})", + segments, + def, + node_id); + + let path_segs = self.def_ids_for_path_segments(segments, def); + + let mut ufcs_associated = None; + match def { Def::Method(def_id) | Def::AssociatedConst(def_id) => { let container = self.tcx.associated_item(def_id).container; @@ -4857,41 +5008,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } ty::ImplContainer(_) => {} } - - let generics = self.tcx.generics_of(def_id); - if segments.len() >= 2 { - let parent_generics = self.tcx.generics_of(generics.parent.unwrap()); - type_segment = Some((&segments[segments.len() - 2], parent_generics)); - } else { + if segments.len() == 1 { // `::assoc` will end up here, and so can `T::assoc`. - let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self"); + let self_ty = self_ty.expect("UFCS sugared assoc missing Self"); ufcs_associated = Some((container, self_ty)); } - fn_segment = Some((segments.last().unwrap(), generics)); } - - // Case 4. Local variable, no generics. - Def::Local(..) | Def::Upvar(..) => {} - - _ => bug!("unexpected definition: {:?}", def), + _ => {} } - debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment); - // Now that we have categorized what space the parameters for each // segment belong to, let's sort out the parameters that the user // provided (if any) into their appropriate spaces. We'll also report // errors if type parameters are provided in an inappropriate place. - let poly_segments = type_segment.is_some() as usize + - fn_segment.is_some() as usize; - AstConv::prohibit_generics(self, &segments[..segments.len() - poly_segments]); + + let mut generic_segs = FxHashSet::default(); + for PathSeg(_, index) in &path_segs { + generic_segs.insert(index); + } + AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| { + if !generic_segs.contains(&index) { + Some(seg) + } else { + None + } + })); match def { Def::Local(nid) | Def::Upvar(nid, ..) => { let ty = self.local_ty(span, nid); let ty = self.normalize_associated_types_in(span, &ty); self.write_ty(self.tcx.hir.node_to_hir_id(node_id), ty); - return ty; + return (ty, def); } _ => {} } @@ -4902,120 +5050,126 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // variables. If the user provided some types, we may still need // to add defaults. If the user provided *too many* types, that's // a problem. - let supress_mismatch = self.check_impl_trait(span, fn_segment); - self.check_generic_arg_count(span, &mut type_segment, false, supress_mismatch); - self.check_generic_arg_count(span, &mut fn_segment, false, supress_mismatch); - let (fn_start, has_self) = match (type_segment, fn_segment) { - (_, Some((_, generics))) => { - (generics.parent_count, generics.has_self) - } - (Some((_, generics)), None) => { - (generics.params.len(), generics.has_self) - } - (None, None) => (0, false) - }; - // FIXME(varkor): Separating out the parameters is messy. - let mut lifetimes_type_seg = vec![]; - let mut types_type_seg = vec![]; - let mut infer_types_type_seg = true; - if let Some((seg, _)) = type_segment { - if let Some(ref data) = seg.args { - for arg in &data.args { - match arg { - GenericArg::Lifetime(lt) => lifetimes_type_seg.push(lt), - GenericArg::Type(ty) => types_type_seg.push(ty), - } - } + let mut infer_args_for_err = FxHashSet::default(); + for &PathSeg(def_id, index) in &path_segs { + let seg = &segments[index]; + let generics = self.tcx.generics_of(def_id); + // Argument-position `impl Trait` is treated as a normal generic + // parameter internally, but we don't allow users to specify the + // parameter's value explicitly, so we have to do some error- + // checking here. + let suppress_errors = AstConv::check_generic_arg_count_for_call( + self.tcx, + span, + &generics, + &seg, + false, // `is_method_call` + ); + if suppress_errors { + infer_args_for_err.insert(index); + self.set_tainted_by_errors(); // See issue #53251. } - infer_types_type_seg = seg.infer_types; } - let mut lifetimes_fn_seg = vec![]; - let mut types_fn_seg = vec![]; - let mut infer_types_fn_seg = true; - if let Some((seg, _)) = fn_segment { - if let Some(ref data) = seg.args { - for arg in &data.args { - match arg { - GenericArg::Lifetime(lt) => lifetimes_fn_seg.push(lt), - GenericArg::Type(ty) => types_fn_seg.push(ty), - } + let has_self = path_segs.last().map(|PathSeg(def_id, _)| { + self.tcx.generics_of(*def_id).has_self + }).unwrap_or(false); + + let mut new_def = def; + let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def { + let ty = self.impl_self_ty(span, impl_def_id).ty; + + match ty.ty_adt_def() { + Some(adt_def) if adt_def.is_struct() => { + let variant = adt_def.non_enum_variant(); + new_def = Def::StructCtor(variant.did, variant.ctor_kind); + (variant.did, self.tcx.type_of(variant.did)) + } + _ => { + (impl_def_id, self.tcx.types.err) } } - infer_types_fn_seg = seg.infer_types; - } + } else { + let def_id = def.def_id(); - let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| { - let mut i = param.index as usize; + // The things we are substituting into the type should not contain + // escaping late-bound regions, and nor should the base type scheme. + let ty = self.tcx.type_of(def_id); + (def_id, ty) + }; - let (segment, lifetimes, types, infer_types) = if i < fn_start { - if let GenericParamDefKind::Type { .. } = param.kind { - // Handle Self first, so we can adjust the index to match the AST. - if has_self && i == 0 { - return opt_self_ty.map(|ty| ty.into()).unwrap_or_else(|| { - self.var_for_def(span, param) - }); + let substs = AstConv::create_substs_for_generic_args( + self.tcx, + def_id, + &[][..], + has_self, + self_ty, + // Provide the generic args, and whether types should be inferred. + |def_id| { + if let Some(&PathSeg(_, index)) = path_segs.iter().find(|&PathSeg(did, _)| { + *did == def_id + }) { + // If we've encountered an `impl Trait`-related error, we're just + // going to infer the arguments for better error messages. + if !infer_args_for_err.contains(&index) { + // Check whether the user has provided generic arguments. + if let Some(ref data) = segments[index].args { + return (Some(data), segments[index].infer_types); + } } + return (None, segments[index].infer_types); } - i -= has_self as usize; - (type_segment, &lifetimes_type_seg, &types_type_seg, infer_types_type_seg) - } else { - i -= fn_start; - (fn_segment, &lifetimes_fn_seg, &types_fn_seg, infer_types_fn_seg) - }; - match param.kind { - GenericParamDefKind::Lifetime => { - if let Some(lifetime) = lifetimes.get(i) { - AstConv::ast_region_to_region(self, lifetime, Some(param)).into() - } else { - self.re_infer(span, Some(param)).unwrap().into() + (None, true) + }, + // Provide substitutions for parameters for which (valid) arguments have been provided. + |param, arg| { + match (¶m.kind, arg) { + (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { + AstConv::ast_region_to_region(self, lt, Some(param)).into() } + (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { + self.to_ty(ty).into() + } + _ => unreachable!(), } - GenericParamDefKind::Type { .. } => { - // Skip over the lifetimes in the same segment. - if let Some((_, generics)) = segment { - i -= generics.own_counts().lifetimes; + }, + // Provide substitutions for parameters for which arguments are inferred. + |substs, param, infer_types| { + match param.kind { + GenericParamDefKind::Lifetime => { + self.re_infer(span, Some(param)).unwrap().into() } - - let has_default = match param.kind { - GenericParamDefKind::Type { has_default, .. } => has_default, - _ => unreachable!() - }; - - if let Some(ast_ty) = types.get(i) { - // A provided type parameter. - self.to_ty(ast_ty).into() - } else if !infer_types && has_default { - // No type parameter provided, but a default exists. - let default = self.tcx.type_of(param.def_id); - self.normalize_ty( - span, - default.subst_spanned(self.tcx, substs, Some(span)) - ).into() - } else { - // No type parameters were provided, we can infer all. - // This can also be reached in some error cases: - // We prefer to use inference variables instead of - // TyError to let type inference recover somewhat. - self.var_for_def(span, param) + GenericParamDefKind::Type { has_default, .. } => { + if !infer_types && has_default { + // If we have a default, then we it doesn't matter that we're not + // inferring the type arguments: we provide the default where any + // is missing. + let default = self.tcx.type_of(param.def_id); + self.normalize_ty( + span, + default.subst_spanned(self.tcx, substs.unwrap(), Some(span)) + ).into() + } else { + // If no type arguments were provided, we have to infer them. + // This case also occurs as a result of some malformed input, e.g. + // a lifetime argument being given instead of a type paramter. + // Using inference instead of `Error` gives better error messages. + self.var_for_def(span, param) + } } } - } - }); - - // The things we are substituting into the type should not contain - // escaping late-bound regions, and nor should the base type scheme. - let ty = self.tcx.type_of(def.def_id()); + }, + ); assert!(!substs.has_escaping_regions()); assert!(!ty.has_escaping_regions()); // Add all the obligations that are required, substituting and // normalized appropriately. - let bounds = self.instantiate_bounds(span, def.def_id(), &substs); + let bounds = self.instantiate_bounds(span, def_id, &substs); self.add_obligations_for_parameters( - traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def.def_id())), + traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)), &bounds); // Substitute the values for the type parameters into the type of @@ -5041,13 +5195,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - self.check_rustc_args_require_const(def.def_id(), node_id, span); + self.check_rustc_args_require_const(def_id, node_id, span); debug!("instantiate_value_path: type of {:?} is {:?}", node_id, ty_substituted); - self.write_substs(self.tcx.hir.node_to_hir_id(node_id), substs); - ty_substituted + let hir_id = self.tcx.hir.node_to_hir_id(node_id); + self.write_substs(hir_id, substs); + + self.write_user_substs_from_substs(hir_id, substs); + + (ty_substituted, new_def) } fn check_rustc_args_require_const(&self, @@ -5063,7 +5221,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If our calling expression is indeed the function itself, we're good! // If not, generate an error that this can only be called directly. match self.tcx.hir.get(self.tcx.hir.get_parent_node(node_id)) { - Node::NodeExpr(expr) => { + Node::Expr(expr) => { match expr.node { hir::ExprKind::Call(ref callee, ..) => { if callee.id == node_id { @@ -5080,166 +5238,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { directly, not through a function pointer"); } - /// Report errors if the provided parameters are too few or too many. - fn check_generic_arg_count(&self, - span: Span, - segment: &mut Option<(&hir::PathSegment, &ty::Generics)>, - is_method_call: bool, - supress_mismatch_error: bool) { - let (lifetimes, types, infer_types, bindings) = segment.map_or( - (vec![], vec![], true, &[][..]), - |(s, _)| { - s.args.as_ref().map_or( - (vec![], vec![], s.infer_types, &[][..]), - |data| { - let (mut lifetimes, mut types) = (vec![], vec![]); - data.args.iter().for_each(|arg| match arg { - GenericArg::Lifetime(lt) => lifetimes.push(lt), - GenericArg::Type(ty) => types.push(ty), - }); - (lifetimes, types, s.infer_types, &data.bindings[..]) - } - ) - }); - - // Check provided parameters. - let ((ty_required, ty_accepted), lt_accepted) = - segment.map_or(((0, 0), 0), |(_, generics)| { - struct ParamRange { - required: usize, - accepted: usize - }; - - let mut lt_accepted = 0; - let mut ty_params = ParamRange { required: 0, accepted: 0 }; - for param in &generics.params { - match param.kind { - GenericParamDefKind::Lifetime => lt_accepted += 1, - GenericParamDefKind::Type { has_default, .. } => { - ty_params.accepted += 1; - if !has_default { - ty_params.required += 1; - } - } - }; - } - if generics.parent.is_none() && generics.has_self { - ty_params.required -= 1; - ty_params.accepted -= 1; - } - - ((ty_params.required, ty_params.accepted), lt_accepted) - }); - - let count_type_params = |n| { - format!("{} type parameter{}", n, if n == 1 { "" } else { "s" }) - }; - let expected_text = count_type_params(ty_accepted); - let actual_text = count_type_params(types.len()); - if let Some((mut err, span)) = if types.len() > ty_accepted { - // To prevent derived errors to accumulate due to extra - // type parameters, we force instantiate_value_path to - // use inference variables instead of the provided types. - *segment = None; - let span = types[ty_accepted].span; - Some((struct_span_err!(self.tcx.sess, span, E0087, - "too many type parameters provided: \ - expected at most {}, found {}", - expected_text, actual_text), span)) - } else if types.len() < ty_required && !infer_types && !supress_mismatch_error { - Some((struct_span_err!(self.tcx.sess, span, E0089, - "too few type parameters provided: \ - expected {}, found {}", - expected_text, actual_text), span)) - } else { - None - } { - err.span_label(span, format!("expected {}", expected_text)).emit(); - } - - if !bindings.is_empty() { - AstConv::prohibit_projection(self, bindings[0].span); - } - - let infer_lifetimes = lifetimes.len() == 0; - // Prohibit explicit lifetime arguments if late bound lifetime parameters are present. - let has_late_bound_lifetime_defs = - segment.map_or(None, |(_, generics)| generics.has_late_bound_regions); - if let (Some(span_late), false) = (has_late_bound_lifetime_defs, lifetimes.is_empty()) { - // Report this as a lint only if no error was reported previously. - let primary_msg = "cannot specify lifetime arguments explicitly \ - if late bound lifetime parameters are present"; - let note_msg = "the late bound lifetime parameter is introduced here"; - if !is_method_call && (lifetimes.len() > lt_accepted || - lifetimes.len() < lt_accepted && !infer_lifetimes) { - let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg); - err.span_note(span_late, note_msg); - err.emit(); - *segment = None; - } else { - let mut multispan = MultiSpan::from_span(lifetimes[0].span); - multispan.push_span_label(span_late, note_msg.to_string()); - self.tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, - lifetimes[0].id, multispan, primary_msg); - } - return; - } - - let count_lifetime_params = |n| { - format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" }) - }; - let expected_text = count_lifetime_params(lt_accepted); - let actual_text = count_lifetime_params(lifetimes.len()); - if let Some((mut err, span)) = if lifetimes.len() > lt_accepted { - let span = lifetimes[lt_accepted].span; - Some((struct_span_err!(self.tcx.sess, span, E0088, - "too many lifetime parameters provided: \ - expected at most {}, found {}", - expected_text, actual_text), span)) - } else if lifetimes.len() < lt_accepted && !infer_lifetimes { - Some((struct_span_err!(self.tcx.sess, span, E0090, - "too few lifetime parameters provided: \ - expected {}, found {}", - expected_text, actual_text), span)) - } else { - None - } { - err.span_label(span, format!("expected {}", expected_text)).emit(); - } - } - - /// Report error if there is an explicit type parameter when using `impl Trait`. - fn check_impl_trait(&self, - span: Span, - segment: Option<(&hir::PathSegment, &ty::Generics)>) - -> bool { - let segment = segment.map(|(path_segment, generics)| { - let explicit = !path_segment.infer_types; - let impl_trait = generics.params.iter().any(|param| match param.kind { - ty::GenericParamDefKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. - } => true, - _ => false, - }); - - if explicit && impl_trait { - let mut err = struct_span_err! { - self.tcx.sess, - span, - E0632, - "cannot provide explicit type parameters when `impl Trait` is \ - used in argument position." - }; - - err.emit(); - } - - impl_trait - }); - - segment.unwrap_or(false) - } - // Resolves `typ` by a single level if `typ` is a type variable. // If no resolution is possible, then an error is reported. // Numeric inference variables may be left unresolved. @@ -5292,10 +5290,10 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut types_used = vec![false; own_counts.types]; for leaf_ty in ty.walk() { - if let ty::TyParam(ty::ParamTy { idx, .. }) = leaf_ty.sty { + if let ty::Param(ty::ParamTy { idx, .. }) = leaf_ty.sty { debug!("Found use of ty param num {}", idx); types_used[idx as usize - own_counts.lifetimes] = true; - } else if let ty::TyError = leaf_ty.sty { + } else if let ty::Error = leaf_ty.sty { // If there is already another error, do not emit // an error for not using a type Parameter. assert!(tcx.sess.err_count() > 0); diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index cdf2b6ae44..5004880ce4 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -13,7 +13,7 @@ use super::{FnCtxt, Needs}; use super::method::MethodCallee; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::TypeVariants::{TyRef, TyAdt, TyStr, TyUint, TyNever, TyTuple, TyChar, TyArray}; +use rustc::ty::TyKind::{Ref, Adt, Str, Uint, Never, Tuple, Char, Array}; use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::infer::type_variable::TypeVariableOrigin; use errors; @@ -35,7 +35,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ty = if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); - self.tcx.mk_nil() + self.tcx.mk_unit() } else { return_ty }; @@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(method) => { let by_ref_binop = !op.node.is_by_value(); if is_assign == IsAssign::Yes || by_ref_binop { - if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[0].sty { + if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty { let mutbl = match mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -221,7 +221,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } if by_ref_binop { - if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[1].sty { + if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].sty { let mutbl = match mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -242,7 +242,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .borrow_mut() .adjustments_mut() .entry(rhs_expr.hir_id) - .or_insert(vec![]) + .or_default() .push(autoref); } } @@ -253,19 +253,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Err(()) => { // error types are considered "builtin" if !lhs_ty.references_error() { - let codemap = self.tcx.sess.codemap(); + let source_map = self.tcx.sess.source_map(); match is_assign { IsAssign::Yes => { - let mut err = struct_span_err!(self.tcx.sess, expr.span, E0368, - "binary assignment operation `{}=` \ - cannot be applied to type `{}`", - op.node.as_str(), - lhs_ty); - err.span_label(lhs_expr.span, - format!("cannot use `{}=` on type `{}`", - op.node.as_str(), lhs_ty)); + let mut err = struct_span_err!( + self.tcx.sess, + expr.span, + E0368, + "binary assignment operation `{}=` cannot be applied to type `{}`", + op.node.as_str(), + lhs_ty, + ); + err.span_label( + lhs_expr.span, + format!("cannot use `{}=` on type `{}`", + op.node.as_str(), lhs_ty), + ); let mut suggested_deref = false; - if let TyRef(_, mut rty, _) = lhs_ty.sty { + if let Ref(_, mut rty, _) = lhs_ty.sty { if { !self.infcx.type_moves_by_default(self.param_env, rty, @@ -275,18 +280,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Op::Binary(op, is_assign)) .is_ok() } { - if let Ok(lstring) = codemap.span_to_snippet(lhs_expr.span) { - while let TyRef(_, rty_inner, _) = rty.sty { + if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) { + while let Ref(_, rty_inner, _) = rty.sty { rty = rty_inner; } let msg = &format!( - "`{}=` can be used on '{}', you can \ - dereference `{2}`: `*{2}`", - op.node.as_str(), - rty, - lstring + "`{}=` can be used on '{}', you can dereference `{}`", + op.node.as_str(), + rty, + lstring, + ); + err.span_suggestion_with_applicability( + lhs_expr.span, + msg, + format!("*{}", lstring), + errors::Applicability::MachineApplicable, ); - err.help(msg); suggested_deref = true; } } @@ -311,7 +320,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This has nothing here because it means we did string // concatenation (e.g. "Hello " += "World!"). This means // we don't want the note in the else clause to be emitted - } else if let ty::TyParam(_) = lhs_ty.sty { + } else if let ty::Param(_) = lhs_ty.sty { // FIXME: point to span of param err.note(&format!( "`{}` might need a bound for `{}`", @@ -333,7 +342,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { op.node.as_str(), lhs_ty); let mut suggested_deref = false; - if let TyRef(_, mut rty, _) = lhs_ty.sty { + if let Ref(_, mut rty, _) = lhs_ty.sty { if { !self.infcx.type_moves_by_default(self.param_env, rty, @@ -343,8 +352,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Op::Binary(op, is_assign)) .is_ok() } { - if let Ok(lstring) = codemap.span_to_snippet(lhs_expr.span) { - while let TyRef(_, rty_inner, _) = rty.sty { + if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) { + while let Ref(_, rty_inner, _) = rty.sty { rty = rty_inner; } let msg = &format!( @@ -385,7 +394,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This has nothing here because it means we did string // concatenation (e.g. "Hello " + "World!"). This means // we don't want the note in the else clause to be emitted - } else if let ty::TyParam(_) = lhs_ty.sty { + } else if let ty::Param(_) = lhs_ty.sty { // FIXME: point to span of param err.note(&format!( "`{}` might need a bound for `{}`", @@ -420,7 +429,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err: &mut errors::DiagnosticBuilder, is_assign: bool, ) -> bool { - let codemap = self.tcx.sess.codemap(); + let source_map = self.tcx.sess.source_map(); let msg = "`to_owned()` can be used to create an owned `String` \ from a string reference. String concatenation \ appends the string on the right to the string \ @@ -429,12 +438,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If this function returns true it means a note was printed, so we don't need // to print the normal "implementation of `std::ops::Add` might be missing" note match (&lhs_ty.sty, &rhs_ty.sty) { - (&TyRef(_, l_ty, _), &TyRef(_, r_ty, _)) - if l_ty.sty == TyStr && r_ty.sty == TyStr => { + (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) + if l_ty.sty == Str && r_ty.sty == Str => { if !is_assign { err.span_label(expr.span, "`+` can't be used to concatenate two `&str` strings"); - match codemap.span_to_snippet(lhs_expr.span) { + match source_map.span_to_snippet(lhs_expr.span) { Ok(lstring) => err.span_suggestion(lhs_expr.span, msg, format!("{}.to_owned()", lstring)), @@ -443,13 +452,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } true } - (&TyRef(_, l_ty, _), &TyAdt(..)) - if l_ty.sty == TyStr && &format!("{:?}", rhs_ty) == "std::string::String" => { + (&Ref(_, l_ty, _), &Adt(..)) + if l_ty.sty == Str && &format!("{:?}", rhs_ty) == "std::string::String" => { err.span_label(expr.span, "`+` can't be used to concatenate a `&str` with a `String`"); match ( - codemap.span_to_snippet(lhs_expr.span), - codemap.span_to_snippet(rhs_expr.span), + source_map.span_to_snippet(lhs_expr.span), + source_map.span_to_snippet(rhs_expr.span), is_assign, ) { (Ok(l), Ok(r), false) => { @@ -489,11 +498,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.span_label(ex.span, format!("cannot apply unary \ operator `{}`", op.as_str())); match actual.sty { - TyUint(_) if op == hir::UnNeg => { + Uint(_) if op == hir::UnNeg => { err.note("unsigned values cannot be negated"); }, - TyStr | TyNever | TyChar | TyTuple(_) | TyArray(_,_) => {}, - TyRef(_, ref lty, _) if lty.sty == TyStr => {}, + Str | Never | Char | Tuple(_) | Array(_,_) => {}, + Ref(_, ref lty, _) if lty.sty == Str => {}, _ => { let missing_trait = match op { hir::UnNeg => "std::ops::Neg", diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 8aa5658d29..fbf8afc3be 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -307,7 +307,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let body_id = body.id(); self.body_id = body_id.node_id; - let call_site = region::Scope::CallSite(body.value.hir_id.local_id); + let call_site = region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite + }; self.call_site_scope = Some(call_site); let fn_sig = { @@ -333,7 +336,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { &fn_sig_tys[..], body_id.node_id, span); - self.link_fn_args(region::Scope::Node(body.value.hir_id.local_id), &body.arguments); + self.link_fn_args( + region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Node + }, + &body.arguments); self.visit_body(body); self.visit_region_obligations(body_id.node_id); @@ -347,8 +355,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { body_hir_id, call_site_region); - self.constrain_anon_types( - &self.fcx.anon_types.borrow(), + self.constrain_opaque_types( + &self.fcx.opaque_types.borrow(), self.outlives_environment.free_region_map(), ); } @@ -483,7 +491,10 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { let expr_ty = self.resolve_node_type(expr.hir_id); // the region corresponding to this expression let expr_region = self.tcx.mk_region(ty::ReScope( - region::Scope::Node(expr.hir_id.local_id))); + region::Scope { + id: expr.hir_id.local_id, + data: region::ScopeData::Node + })); self.type_must_outlive(infer::ExprTypeIsNotInScope(expr_ty, expr.span), expr_ty, expr_region); @@ -589,7 +600,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { // For overloaded derefs, base_ty is the input to `Deref::deref`, // but it's a reference type uing the same region as the output. let base_ty = self.resolve_expr_type_adjusted(base); - if let ty::TyRef(r_ptr, _, _) = base_ty.sty { + if let ty::Ref(r_ptr, _, _) = base_ty.sty { self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr); } @@ -702,22 +713,22 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { from_ty, to_ty); match (&from_ty.sty, &to_ty.sty) { - /*From:*/ (&ty::TyRef(from_r, from_ty, _), - /*To: */ &ty::TyRef(to_r, to_ty, _)) => { + /*From:*/ (&ty::Ref(from_r, from_ty, _), + /*To: */ &ty::Ref(to_r, to_ty, _)) => { // Target cannot outlive source, naturally. self.sub_regions(infer::Reborrow(cast_expr.span), to_r, from_r); self.walk_cast(cast_expr, from_ty, to_ty); } /*From:*/ (_, - /*To: */ &ty::TyDynamic(.., r)) => { + /*To: */ &ty::Dynamic(.., r)) => { // When T is existentially quantified as a trait // `Foo+'to`, it must outlive the region bound `'to`. self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r); } - /*From:*/ (&ty::TyAdt(from_def, _), - /*To: */ &ty::TyAdt(to_def, _)) if from_def.is_box() && to_def.is_box() => { + /*From:*/ (&ty::Adt(from_def, _), + /*To: */ &ty::Adt(to_def, _)) if from_def.is_box() && to_def.is_box() => { self.walk_cast(cast_expr, from_ty.boxed_ty(), to_ty.boxed_ty()); } @@ -736,7 +747,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn constrain_callee(&mut self, callee_expr: &hir::Expr) { let callee_ty = self.resolve_node_type(callee_expr.hir_id); match callee_ty.sty { - ty::TyFnDef(..) | ty::TyFnPtr(_) => { } + ty::FnDef(..) | ty::FnPtr(_) => { } _ => { // this should not happen, but it does if the program is // erroneous @@ -766,7 +777,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // call occurs. // // FIXME(#6268) to support nested method calls, should be callee_id - let callee_scope = region::Scope::Node(call_expr.hir_id.local_id); + let callee_scope = region::Scope { + id: call_expr.hir_id.local_id, + data: region::ScopeData::Node + }; let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope)); debug!("callee_region={:?}", callee_region); @@ -819,7 +833,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span); let expr_region = self.tcx.mk_region(ty::ReScope( - region::Scope::Node(expr.hir_id.local_id))); + region::Scope { + id: expr.hir_id.local_id, + data: region::ScopeData::Node + })); for adjustment in adjustments { debug!("constrain_adjustments: adjustment={:?}, cmt={:?}", adjustment, cmt); @@ -913,10 +930,13 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { debug!("constrain_index(index_expr=?, indexed_ty={}", self.ty_to_string(indexed_ty)); - let r_index_expr = ty::ReScope(region::Scope::Node(index_expr.hir_id.local_id)); - if let ty::TyRef(r_ptr, r_ty, _) = indexed_ty.sty { + let r_index_expr = ty::ReScope(region::Scope { + id: index_expr.hir_id.local_id, + data: region::ScopeData::Node + }); + if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.sty { match r_ty.sty { - ty::TySlice(_) | ty::TyStr => { + ty::Slice(_) | ty::Str => { self.sub_regions(infer::IndexSlice(index_expr.span), self.tcx.mk_region(r_index_expr), r_ptr); } @@ -1072,7 +1092,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } adjustment::AutoBorrow::RawPtr(m) => { - let r = self.tcx.mk_region(ty::ReScope(region::Scope::Node(expr.hir_id.local_id))); + let r = self.tcx.mk_region(ty::ReScope(region::Scope { + id: expr.hir_id.local_id, + data: region::ScopeData::Node + })); self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt); } } @@ -1089,7 +1112,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { id, mutbl, cmt_borrowed); let rptr_ty = self.resolve_node_type(id); - if let ty::TyRef(r, _, _) = rptr_ty.sty { + if let ty::Ref(r, _, _) = rptr_ty.sty { debug!("rptr_ty={}", rptr_ty); self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed); } @@ -1284,7 +1307,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // how all the types get adjusted.) match ref_kind { ty::ImmBorrow => { - // The reference being reborrowed is a sharable ref of + // The reference being reborrowed is a shareable ref of // type `&'a T`. In this case, it doesn't matter where we // *found* the `&T` pointer, the memory it references will // be valid and immutable for `'a`. So we can stop here. diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 61fe90be21..41df937980 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -109,9 +109,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Extract the type of the closure. let (closure_def_id, substs) = match self.node_ty(closure_hir_id).sty { - ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), - ty::TyGenerator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), - ty::TyError => { + ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), + ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), + ty::Error => { // #51714: skip analysis when we have already encountered type errors return; } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 38743cc9cf..9e09f2cd18 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -18,7 +18,7 @@ use rustc::ty::subst::{Subst, Substs}; use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::middle::lang_items; -use rustc::infer::anon_types::may_define_existential_type; +use rustc::infer::opaque_types::may_define_existential_type; use syntax::ast; use syntax::feature_gate::{self, GateIssue}; @@ -258,25 +258,35 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)) } }; - let unsized_len = if + let all_sized = all_sized || variant.fields.is_empty() || - needs_drop_copy() - { + needs_drop_copy(); + let unsized_len = if all_sized { 0 } else { 1 }; - for field in &variant.fields[..variant.fields.len() - unsized_len] { + for (idx, field) in variant.fields[..variant.fields.len() - unsized_len] + .iter() + .enumerate() + { + let last = idx == variant.fields.len() - 1; fcx.register_bound( field.ty, fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new(field.span, - fcx.body_id, - traits::FieldSized(match item.node.adt_kind() { - Some(i) => i, - None => bug!(), - }))); + traits::ObligationCause::new( + field.span, + fcx.body_id, + traits::FieldSized { + adt_kind: match item.node.adt_kind() { + Some(i) => i, + None => bug!(), + }, + last + } + ) + ); } // All field types must be well-formed. @@ -444,7 +454,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { match t.sty { - ty::TyParam(p) => { + ty::Param(p) => { self.params.insert(p.idx); t.super_visit_with(self) } @@ -566,19 +576,19 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( ty.fold_with(&mut ty::fold::BottomUpFolder { tcx: fcx.tcx, fldop: |ty| { - if let ty::TyAnon(def_id, substs) = ty.sty { - trace!("check_existential_types: anon_ty, {:?}, {:?}", def_id, substs); + if let ty::Opaque(def_id, substs) = ty.sty { + trace!("check_existential_types: opaque_ty, {:?}, {:?}", def_id, substs); let generics = tcx.generics_of(def_id); // only check named existential types if generics.parent.is_none() { - let anon_node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - if may_define_existential_type(tcx, fn_def_id, anon_node_id) { + let opaque_node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + if may_define_existential_type(tcx, fn_def_id, opaque_node_id) { trace!("check_existential_types may define. Generics: {:#?}", generics); let mut seen: FxHashMap<_, Vec<_>> = FxHashMap(); for (subst, param) in substs.iter().zip(&generics.params) { match subst.unpack() { ty::subst::UnpackedKind::Type(ty) => match ty.sty { - ty::TyParam(..) => {}, + ty::Param(..) => {}, // prevent `fn foo() -> Foo` from being defining _ => { tcx @@ -664,7 +674,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( } } } // if is_named_existential_type - } // if let TyAnon + } // if let Opaque ty }, reg_op: |reg| reg, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b37f489b2c..0b2f92ac4b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -17,15 +17,15 @@ use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::infer::InferCtxt; +use rustc::ty::adjustment::{Adjust, Adjustment}; +use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder}; use rustc::ty::subst::UnpackedKind; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::adjustment::{Adjust, Adjustment}; -use rustc::ty::fold::{TypeFoldable, TypeFolder, BottomUpFolder}; use rustc::util::nodemap::DefIdSet; +use rustc_data_structures::sync::Lrc; +use std::mem; use syntax::ast; use syntax_pos::Span; -use std::mem; -use rustc_data_structures::sync::Lrc; /////////////////////////////////////////////////////////////////////////// // Entry point @@ -35,7 +35,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let item_id = self.tcx.hir.body_owner(body.id()); let item_def_id = self.tcx.hir.local_def_id(item_id); - let mut wbcx = WritebackCx::new(self, body); + // This attribute causes us to dump some writeback information + // in the form of errors, which is used for unit tests. + let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, "rustc_dump_user_substs"); + + let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs); for arg in &body.arguments { wbcx.visit_node_id(arg.pat.span, arg.hir_id); } @@ -44,7 +48,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); wbcx.visit_fru_field_types(); - wbcx.visit_anon_types(body.value.span); + wbcx.visit_opaque_types(body.value.span); wbcx.visit_cast_types(); wbcx.visit_free_region_map(); wbcx.visit_user_provided_tys(); @@ -55,8 +59,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ); debug!( "used_trait_imports({:?}) = {:?}", - item_def_id, - used_trait_imports + item_def_id, used_trait_imports ); wbcx.tables.used_trait_imports = used_trait_imports; @@ -64,8 +67,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!( "writeback: tables for {:?} are {:#?}", - item_def_id, - wbcx.tables + item_def_id, wbcx.tables ); self.tcx.alloc_tables(wbcx.tables) @@ -86,12 +88,15 @@ struct WritebackCx<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> { tables: ty::TypeckTables<'gcx>, body: &'gcx hir::Body, + + rustc_dump_user_substs: bool, } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn new( fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body, + rustc_dump_user_substs: bool, ) -> WritebackCx<'cx, 'gcx, 'tcx> { let owner = fcx.tcx.hir.definitions().node_to_hir_id(body.id().node_id); @@ -99,6 +104,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fcx, tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))), body, + rustc_dump_user_substs, } } @@ -118,8 +124,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { // operating on scalars, we clear the overload. fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr) { match e.node { - hir::ExprKind::Unary(hir::UnNeg, ref inner) | - hir::ExprKind::Unary(hir::UnNot, ref inner) => { + hir::ExprKind::Unary(hir::UnNeg, ref inner) + | hir::ExprKind::Unary(hir::UnNot, ref inner) => { let inner_ty = self.fcx.node_ty(inner.hir_id); let inner_ty = self.fcx.resolve_type_vars_if_possible(&inner_ty); @@ -174,12 +180,11 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { match tables.expr_ty_adjusted(&base).sty { // All valid indexing looks like this - ty::TyRef(_, base_ty, _) => { + ty::Ref(_, base_ty, _) => { let index_ty = tables.expr_ty_adjusted(&index); let index_ty = self.fcx.resolve_type_vars_if_possible(&index_ty); - if base_ty.builtin_index().is_some() - && index_ty == self.fcx.tcx.types.usize { + if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize { // Remove the method call record tables.type_dependent_defs_mut().remove(e.hir_id); tables.node_substs_mut().remove(e.hir_id); @@ -191,24 +196,26 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { // of size information - we need to get rid of it // Since this is "after" the other adjustment to be // discarded, we do an extra `pop()` - Some(Adjustment { kind: Adjust::Unsize, .. }) => { + Some(Adjustment { + kind: Adjust::Unsize, + .. + }) => { // So the borrow discard actually happens here a.pop(); - }, + } _ => {} } }); } - }, + } // Might encounter non-valid indexes at this point, so there // has to be a fall-through - _ => {}, + _ => {} } } } } - /////////////////////////////////////////////////////////////////////////// // Impl of Visitor for Resolver // @@ -262,7 +269,9 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { if let Some(&bm) = self.fcx.tables.borrow().pat_binding_modes().get(p.hir_id) { self.tables.pat_binding_modes_mut().insert(p.hir_id, bm); } else { - self.tcx().sess.delay_span_bug(p.span, "missing binding mode"); + self.tcx() + .sess + .delay_span_bug(p.span, "missing binding mode"); } } hir::PatKind::Struct(_, ref fields, _) => { @@ -310,8 +319,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { }; debug!( "Upvar capture for {:?} resolved to {:?}", - upvar_id, - new_upvar_capture + upvar_id, new_upvar_capture ); self.tables .upvar_capture_map @@ -385,18 +393,18 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_anon_types(&mut self, span: Span) { - for (&def_id, anon_defn) in self.fcx.anon_types.borrow().iter() { + fn visit_opaque_types(&mut self, span: Span) { + for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - let instantiated_ty = self.resolve(&anon_defn.concrete_ty, &node_id); + let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &node_id); let generics = self.tcx().generics_of(def_id); let definition_ty = if generics.parent.is_some() { // impl trait - self.fcx.infer_anon_definition_from_instantiation( + self.fcx.infer_opaque_definition_from_instantiation( def_id, - anon_defn, + opaque_defn, instantiated_ty, ) } else { @@ -417,16 +425,15 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fldop: |ty| { trace!("checking type {:?}: {:#?}", ty, ty.sty); // find a type parameter - if let ty::TyParam(..) = ty.sty { + if let ty::Param(..) = ty.sty { // look it up in the substitution list - assert_eq!(anon_defn.substs.len(), generics.params.len()); - for (subst, param) in anon_defn.substs.iter().zip(&generics.params) { + assert_eq!(opaque_defn.substs.len(), generics.params.len()); + for (subst, param) in opaque_defn.substs.iter().zip(&generics.params) { if let UnpackedKind::Type(subst) = subst.unpack() { if subst == ty { // found it in the substitution list, replace with the // parameter from the existential type - return self - .tcx() + return self.tcx() .global_tcx() .mk_ty_param(param.index, param.name); } @@ -453,7 +460,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { ty::ReStatic => region, _ => { trace!("checking {:?}", region); - for (subst, p) in anon_defn.substs.iter().zip(&generics.params) { + for (subst, p) in opaque_defn.substs.iter().zip(&generics.params) { if let UnpackedKind::Lifetime(subst) = subst.unpack() { if subst == region { // found it in the substitution list, replace with the @@ -464,14 +471,16 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { name: p.name, }; trace!("replace {:?} with {:?}", region, reg); - return self.tcx().global_tcx() + return self.tcx() + .global_tcx() .mk_region(ty::ReEarlyBound(reg)); } } } - trace!("anon_defn: {:#?}", anon_defn); + trace!("opaque_defn: {:#?}", opaque_defn); trace!("generics: {:#?}", generics); - self.tcx().sess + self.tcx() + .sess .struct_span_err( span, "non-defining existential type use in defining scope", @@ -480,7 +489,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { span, format!( "lifetime `{}` is part of concrete type but not used \ - in parameter list of existential type", + in parameter list of existential type", region, ), ) @@ -488,16 +497,26 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { self.tcx().global_tcx().mk_region(ty::ReStatic) } } - } + }, }) }; - let old = self.tables.concrete_existential_types.insert(def_id, definition_ty); + if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.sty { + if def_id == defin_ty_def_id { + // Concrete type resolved to the existential type itself + // Force a cycle error + self.tcx().at(span).type_of(defin_ty_def_id); + } + } + + let old = self.tables + .concrete_existential_types + .insert(def_id, definition_ty); if let Some(old) = old { if old != definition_ty { span_bug!( span, - "visit_anon_types tried to write \ + "visit_opaque_types tried to write \ different types for the same existential type: {:?}, {:?}, {:?}", def_id, definition_ty, @@ -510,13 +529,18 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn visit_field_id(&mut self, node_id: ast::NodeId) { let hir_id = self.tcx().hir.node_to_hir_id(node_id); - if let Some(index) = self.fcx.tables.borrow_mut().field_indices_mut().remove(hir_id) { + if let Some(index) = self.fcx + .tables + .borrow_mut() + .field_indices_mut() + .remove(hir_id) + { self.tables.field_indices_mut().insert(hir_id, index); } } fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) { - // Export associated path extensions and method resultions. + // Export associated path extensions and method resolutions. if let Some(def) = self.fcx .tables .borrow_mut() @@ -542,6 +566,22 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { assert!(!substs.needs_infer() && !substs.has_skol()); self.tables.node_substs_mut().insert(hir_id, substs); } + + // Copy over any user-substs + if let Some(user_substs) = self.fcx.tables.borrow().user_substs(hir_id) { + let user_substs = self.tcx().lift_to_global(&user_substs).unwrap(); + self.tables.user_substs_mut().insert(hir_id, user_substs); + + // Unit-testing mechanism: + if self.rustc_dump_user_substs { + let node_id = self.tcx().hir.hir_to_node_id(hir_id); + let span = self.tcx().hir.span(node_id); + self.tcx().sess.span_err( + span, + &format!("user substs: {:?}", user_substs), + ); + } + } } fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) { @@ -559,8 +599,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let resolved_adjustment = self.resolve(&adjustment, &span); debug!( "Adjustments for node {:?}: {:?}", - hir_id, - resolved_adjustment + hir_id, resolved_adjustment ); self.tables .adjustments_mut() @@ -584,8 +623,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let resolved_adjustment = self.resolve(&adjustment, &span); debug!( "pat_adjustments for node {:?}: {:?}", - hir_id, - resolved_adjustment + hir_id, resolved_adjustment ); self.tables .pat_adjustments_mut() @@ -701,7 +739,8 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info_err(Some(self.body.id()), self.span.to_span(&self.tcx), t).emit(); + .need_type_info_err(Some(self.body.id()), self.span.to_span(&self.tcx), t) + .emit(); } } } diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 1a57dfd745..5967bd1ba3 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -11,6 +11,7 @@ use lint; use rustc::ty::TyCtxt; +use errors::Applicability; use syntax::ast; use syntax_pos::Span; @@ -71,7 +72,7 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> { return; } - let msg = if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { format!("unused import: `{}`", snippet) } else { "unused import".to_string() @@ -116,6 +117,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { !tcx.is_compiler_builtins(cnum) && !tcx.is_panic_runtime(cnum) && !tcx.has_global_allocator(cnum) + && !tcx.has_panic_handler(cnum) }) .cloned() .collect(); @@ -132,15 +134,21 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { // If the crate is fully unused, we suggest removing it altogether. // We do this in any edition. - if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) { - assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE); - let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index); - let id = tcx.hir.hir_to_node_id(hir_id); - let msg = "unused extern crate"; - tcx.struct_span_lint_node(lint, id, span, msg) - .span_suggestion_short(span, "remove it", "".to_string()) - .emit(); - continue; + if extern_crate.warn_if_unused { + if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) { + assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE); + let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index); + let id = tcx.hir.hir_to_node_id(hir_id); + let msg = "unused extern crate"; + tcx.struct_span_lint_node(lint, id, span, msg) + .span_suggestion_short_with_applicability( + span, + "remove it", + String::new(), + Applicability::MachineApplicable) + .emit(); + continue; + } } // If we are not in Rust 2018 edition, then we don't make any further @@ -171,7 +179,12 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { }; let replacement = visibility_qualified(&item.vis, &base_replacement); tcx.struct_span_lint_node(lint, id, extern_crate.span, msg) - .span_suggestion_short(extern_crate.span, &help, replacement) + .span_suggestion_short_with_applicability( + extern_crate.span, + &help, + replacement, + Applicability::MachineApplicable, + ) .emit(); } } @@ -192,6 +205,10 @@ struct ExternCrateToLint { /// crate_name`), and -- perhaps surprisingly -- this stores the /// *original* name (`item.name` will contain the new name) orig_name: Option, + + /// if `false`, the original name started with `_`, so we shouldn't lint + /// about it going unused (but we should still emit idiom lints). + warn_if_unused: bool, } impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> { @@ -203,6 +220,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> { def_id: extern_crate_def_id, span: item.span, orig_name, + warn_if_unused: !item.name.as_str().starts_with('_'), } ); } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 4d9a4a03a6..efc35fad82 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -23,7 +23,7 @@ use rustc::ty::util::CopyImplementationError; use rustc::infer; use rustc::hir::def_id::DefId; -use rustc::hir::map as hir_map; +use hir::Node; use rustc::hir::{self, ItemKind}; pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) { @@ -41,28 +41,26 @@ struct Checker<'a, 'tcx: 'a> { impl<'a, 'tcx> Checker<'a, 'tcx> { fn check(&self, trait_def_id: Option, mut f: F) -> &Self - where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId, DefId) + where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId) { if Some(self.trait_def_id) == trait_def_id { for &impl_id in self.tcx.hir.trait_impls(self.trait_def_id) { let impl_def_id = self.tcx.hir.local_def_id(impl_id); - f(self.tcx, self.trait_def_id, impl_def_id); + f(self.tcx, impl_def_id); } } self } } -fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - _drop_did: DefId, - impl_did: DefId) { +fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) { match tcx.type_of(impl_did).sty { - ty::TyAdt(..) => {} + ty::Adt(..) => {} _ => { // Destructors only work on nominal types. if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) { match tcx.hir.find(impl_node_id) { - Some(hir_map::NodeItem(item)) => { + Some(Node::Item(item)) => { let span = match item.node { ItemKind::Impl(.., ref ty, _) => ty.span, _ => item.span, @@ -87,9 +85,7 @@ fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - _copy_did: DefId, - impl_did: DefId) { +fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) { debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); let impl_node_id = if let Some(n) = tcx.hir.as_local_node_id(impl_did) { @@ -157,9 +153,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - _: DefId, - impl_did: DefId) { +fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) { debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did); @@ -223,23 +217,23 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, (mt_a.ty, mt_b.ty, unsize_trait, None) }; let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) { - (&ty::TyRef(r_a, ty_a, mutbl_a), &ty::TyRef(r_b, ty_b, mutbl_b)) => { + (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => { infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b }; check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ref(r_b, ty)) } - (&ty::TyRef(_, ty_a, mutbl_a), &ty::TyRawPtr(mt_b)) => { + (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => { let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ptr(ty)) } - (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => { + (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => { check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ptr(ty)) } - (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) if def_a.is_struct() && + (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => { if def_a != def_b { let source_path = gcx.item_path_str(def_a.did); diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index 02a18fa47d..52e37b8d0c 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -102,16 +102,16 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { let self_ty = self.tcx.type_of(def_id); let lang_items = self.tcx.lang_items(); match self_ty.sty { - ty::TyAdt(def, _) => { + ty::Adt(def, _) => { self.check_def_id(item, def.did); } - ty::TyForeign(did) => { + ty::Foreign(did) => { self.check_def_id(item, did); } - ty::TyDynamic(ref data, ..) if data.principal().is_some() => { + ty::Dynamic(ref data, ..) if data.principal().is_some() => { self.check_def_id(item, data.principal().unwrap().def_id()); } - ty::TyChar => { + ty::Char => { self.check_primitive_impl(def_id, lang_items.char_impl(), None, @@ -119,7 +119,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "char", item.span); } - ty::TyStr => { + ty::Str => { self.check_primitive_impl(def_id, lang_items.str_impl(), lang_items.str_alloc_impl(), @@ -127,7 +127,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "str", item.span); } - ty::TySlice(slice_item) if slice_item == self.tcx.types.u8 => { + ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => { self.check_primitive_impl(def_id, lang_items.slice_u8_impl(), lang_items.slice_u8_alloc_impl(), @@ -135,7 +135,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "[u8]", item.span); } - ty::TySlice(_) => { + ty::Slice(_) => { self.check_primitive_impl(def_id, lang_items.slice_impl(), lang_items.slice_alloc_impl(), @@ -143,7 +143,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "[T]", item.span); } - ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { self.check_primitive_impl(def_id, lang_items.const_ptr_impl(), None, @@ -151,7 +151,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "*const T", item.span); } - ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { self.check_primitive_impl(def_id, lang_items.mut_ptr_impl(), None, @@ -159,7 +159,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "*mut T", item.span); } - ty::TyInt(ast::IntTy::I8) => { + ty::Int(ast::IntTy::I8) => { self.check_primitive_impl(def_id, lang_items.i8_impl(), None, @@ -167,7 +167,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "i8", item.span); } - ty::TyInt(ast::IntTy::I16) => { + ty::Int(ast::IntTy::I16) => { self.check_primitive_impl(def_id, lang_items.i16_impl(), None, @@ -175,7 +175,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "i16", item.span); } - ty::TyInt(ast::IntTy::I32) => { + ty::Int(ast::IntTy::I32) => { self.check_primitive_impl(def_id, lang_items.i32_impl(), None, @@ -183,7 +183,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "i32", item.span); } - ty::TyInt(ast::IntTy::I64) => { + ty::Int(ast::IntTy::I64) => { self.check_primitive_impl(def_id, lang_items.i64_impl(), None, @@ -191,7 +191,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "i64", item.span); } - ty::TyInt(ast::IntTy::I128) => { + ty::Int(ast::IntTy::I128) => { self.check_primitive_impl(def_id, lang_items.i128_impl(), None, @@ -199,7 +199,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "i128", item.span); } - ty::TyInt(ast::IntTy::Isize) => { + ty::Int(ast::IntTy::Isize) => { self.check_primitive_impl(def_id, lang_items.isize_impl(), None, @@ -207,7 +207,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "isize", item.span); } - ty::TyUint(ast::UintTy::U8) => { + ty::Uint(ast::UintTy::U8) => { self.check_primitive_impl(def_id, lang_items.u8_impl(), None, @@ -215,7 +215,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "u8", item.span); } - ty::TyUint(ast::UintTy::U16) => { + ty::Uint(ast::UintTy::U16) => { self.check_primitive_impl(def_id, lang_items.u16_impl(), None, @@ -223,7 +223,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "u16", item.span); } - ty::TyUint(ast::UintTy::U32) => { + ty::Uint(ast::UintTy::U32) => { self.check_primitive_impl(def_id, lang_items.u32_impl(), None, @@ -231,7 +231,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "u32", item.span); } - ty::TyUint(ast::UintTy::U64) => { + ty::Uint(ast::UintTy::U64) => { self.check_primitive_impl(def_id, lang_items.u64_impl(), None, @@ -239,7 +239,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "u64", item.span); } - ty::TyUint(ast::UintTy::U128) => { + ty::Uint(ast::UintTy::U128) => { self.check_primitive_impl(def_id, lang_items.u128_impl(), None, @@ -247,7 +247,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "u128", item.span); } - ty::TyUint(ast::UintTy::Usize) => { + ty::Uint(ast::UintTy::Usize) => { self.check_primitive_impl(def_id, lang_items.usize_impl(), None, @@ -255,7 +255,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "usize", item.span); } - ty::TyFloat(ast::FloatTy::F32) => { + ty::Float(ast::FloatTy::F32) => { self.check_primitive_impl(def_id, lang_items.f32_impl(), lang_items.f32_runtime_impl(), @@ -263,7 +263,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "f32", item.span); } - ty::TyFloat(ast::FloatTy::F64) => { + ty::Float(ast::FloatTy::F64) => { self.check_primitive_impl(def_id, lang_items.f64_impl(), lang_items.f64_runtime_impl(), @@ -271,7 +271,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { "f64", item.span); } - ty::TyError => { + ty::Error => { return; } _ => { @@ -304,7 +304,7 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> { let impl_def_id = self.tcx.hir.local_def_id(item.id); let mut rc_vec = self.impls_map.inherent_impls .entry(def_id) - .or_insert_with(|| Lrc::new(vec![])); + .or_default(); // At this point, there should not be any clones of the // `Lrc`, so we can still safely push into it in place: diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index e92349040e..168cf47fb5 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -52,7 +52,7 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_def_id: DefId) { let did = Some(trait_def_id); let li = tcx.lang_items(); - let span = tcx.sess.codemap().def_span(tcx.span_of_impl(impl_def_id).unwrap()); + let span = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); // Disallow *all* explicit impls of `Sized` and `Unsize` for now. if did == li.sized_trait() { @@ -157,7 +157,7 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI tcx.specialization_graph_of(trait_def_id); // check for overlap with the automatic `impl Trait for Trait` - if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty { + if let ty::Dynamic(ref data, ..) = trait_ref.self_ty().sty { // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. @@ -169,7 +169,7 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI traits::supertrait_def_ids(tcx, data.principal().unwrap().def_id()); if supertrait_def_ids.any(|d| d == trait_def_id) { - let sp = tcx.sess.codemap().def_span(tcx.span_of_impl(impl_def_id).unwrap()); + let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); struct_span_err!(tcx.sess, sp, E0371, diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 9be509b358..f9b8948823 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -40,7 +40,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { self.tcx.hir.node_to_string(item.id)); let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); let trait_def_id = trait_ref.def_id; - let cm = self.tcx.sess.codemap(); + let cm = self.tcx.sess.source_map(); let sp = cm.def_span(item.span); match traits::orphan_check(self.tcx, def_id) { Ok(()) => {} @@ -114,8 +114,8 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { !trait_def_id.is_local() { let self_ty = trait_ref.self_ty(); let opt_self_def_id = match self_ty.sty { - ty::TyAdt(self_def, _) => Some(self_def.did), - ty::TyForeign(did) => Some(did), + ty::Adt(self_def, _) => Some(self_def.did), + ty::Foreign(did) => Some(did), _ => None, }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 77b02d9ff5..5309be2176 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -25,17 +25,18 @@ //! crate as a kind of pass. This should eventually be factored away. use astconv::{AstConv, Bounds}; -use lint; use constrained_type_params as ctp; +use lint; use middle::lang_items::SizedTraitLangItem; use middle::resolve_lifetime as rl; +use middle::weak_lang_items; use rustc::mir::mono::Linkage; -use rustc::ty::subst::Substs; -use rustc::ty::{ToPredicate, ReprOptions}; -use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::query::Providers; -use rustc::ty::util::IntTypeExt; +use rustc::ty::subst::Substs; use rustc::ty::util::Discr; +use rustc::ty::util::IntTypeExt; +use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; +use rustc::ty::{ReprOptions, ToPredicate}; use rustc::util::captures::Captures; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::abi; @@ -43,23 +44,26 @@ use rustc_target::spec::abi; use syntax::ast; use syntax::ast::MetaItemKind; use syntax::attr::{InlineAttr, list_contains_name, mark_used}; -use syntax::codemap::Spanned; -use syntax::symbol::{Symbol, keywords}; +use syntax::source_map::Spanned; use syntax::feature_gate; +use syntax::symbol::{keywords, Symbol}; use syntax_pos::{Span, DUMMY_SP}; -use rustc::hir::{self, map as hir_map, CodegenFnAttrs, CodegenFnAttrFlags, Unsafety}; -use rustc::hir::GenericParamKind; -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::def::{Def, CtorKind}; +use rustc::hir::def::{CtorKind, Def}; +use rustc::hir::Node; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc::hir::GenericParamKind; +use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; /////////////////////////////////////////////////////////////////////////// // Main entry point pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = CollectItemTypesVisitor { tcx: tcx }; - tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + tcx.hir + .krate() + .visit_all_item_likes(&mut visitor.as_deep_visitor()); } pub fn provide(providers: &mut Providers) { @@ -93,7 +97,7 @@ pub fn provide(providers: &mut Providers) { /// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy /// `get_type_parameter_bounds` requests, drawing the information from /// the AST (`hir::Generics`), recursively. -pub struct ItemCtxt<'a,'tcx:'a> { +pub struct ItemCtxt<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId, } @@ -101,7 +105,7 @@ pub struct ItemCtxt<'a,'tcx:'a> { /////////////////////////////////////////////////////////////////////////// struct CollectItemTypesVisitor<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx> + tcx: TyCtxt<'a, 'tcx, 'tcx>, } impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { @@ -118,7 +122,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { for param in &generics.params { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} - hir::GenericParamKind::Type { default: Some(_), .. } => { + hir::GenericParamKind::Type { + default: Some(_), .. + } => { let def_id = self.tcx.hir.local_def_id(param.id); self.tcx.type_of(def_id); } @@ -152,34 +158,33 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { // Utility types and common code for the above passes. impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) - -> ItemCtxt<'a,'tcx> { - ItemCtxt { - tcx, - item_def_id, - } + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) -> ItemCtxt<'a, 'tcx> { + ItemCtxt { tcx, item_def_id } } } -impl<'a,'tcx> ItemCtxt<'a,'tcx> { +impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { pub fn to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { AstConv::ast_ty_to_ty(self, ast_ty) } } impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx } + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { + self.tcx + } - fn get_type_parameter_bounds(&self, - span: Span, - def_id: DefId) - -> ty::GenericPredicates<'tcx> - { - self.tcx.at(span).type_param_predicates((self.item_def_id, def_id)) + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { + self.tcx + .at(span) + .type_param_predicates((self.item_def_id, def_id)) } - fn re_infer(&self, _span: Span, _def: Option<&ty::GenericParamDef>) - -> Option> { + fn re_infer( + &self, + _span: Span, + _def: Option<&ty::GenericParamDef>, + ) -> Option> { None } @@ -190,23 +195,27 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { E0121, "the type placeholder `_` is not allowed within types on item signatures" ).span_label(span, "not allowed in type signatures") - .emit(); + .emit(); self.tcx().types.err } - fn projected_ty_from_poly_trait_ref(&self, - span: Span, - item_def_id: DefId, - poly_trait_ref: ty::PolyTraitRef<'tcx>) - -> Ty<'tcx> - { + fn projected_ty_from_poly_trait_ref( + &self, + span: Span, + item_def_id: DefId, + poly_trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Ty<'tcx> { if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() { self.tcx().mk_projection(item_def_id, trait_ref.substs) } else { // no late-bound regions, we can just ignore the binder - span_err!(self.tcx().sess, span, E0212, + span_err!( + self.tcx().sess, + span, + E0212, "cannot extract an associated type from a higher-ranked trait bound \ - in this context"); + in this context" + ); self.tcx().types.err } } @@ -226,10 +235,10 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } } -fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - (item_def_id, def_id): (DefId, DefId)) - -> ty::GenericPredicates<'tcx> { - use rustc::hir::map::*; +fn type_param_predicates<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + (item_def_id, def_id): (DefId, DefId), +) -> ty::GenericPredicates<'tcx> { use rustc::hir::*; // In the AST, bounds can derive from two places. Either @@ -250,55 +259,61 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.generics_of(item_def_id).parent }; - let mut result = parent.map_or(ty::GenericPredicates { - parent: None, - predicates: vec![] - }, |parent| { - let icx = ItemCtxt::new(tcx, parent); - icx.get_type_parameter_bounds(DUMMY_SP, def_id) - }); + let mut result = parent.map_or( + ty::GenericPredicates { + parent: None, + predicates: vec![], + }, + |parent| { + let icx = ItemCtxt::new(tcx, parent); + icx.get_type_parameter_bounds(DUMMY_SP, def_id) + }, + ); let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); let ast_generics = match tcx.hir.get(item_node_id) { - NodeTraitItem(item) => &item.generics, + Node::TraitItem(item) => &item.generics, - NodeImplItem(item) => &item.generics, + Node::ImplItem(item) => &item.generics, - NodeItem(item) => { + Node::Item(item) => { match item.node { - ItemKind::Fn(.., ref generics, _) | - ItemKind::Impl(_, _, _, ref generics, ..) | - ItemKind::Ty(_, ref generics) | - ItemKind::Existential(ExistTy { ref generics, impl_trait_fn: None, ..}) | - ItemKind::Enum(_, ref generics) | - ItemKind::Struct(_, ref generics) | - ItemKind::Union(_, ref generics) => generics, + ItemKind::Fn(.., ref generics, _) + | ItemKind::Impl(_, _, _, ref generics, ..) + | ItemKind::Ty(_, ref generics) + | ItemKind::Existential(ExistTy { + ref generics, + impl_trait_fn: None, + .. + }) + | ItemKind::Enum(_, ref generics) + | ItemKind::Struct(_, ref generics) + | ItemKind::Union(_, ref generics) => generics, ItemKind::Trait(_, _, ref generics, ..) => { // Implied `Self: Trait` and supertrait bounds. if param_id == item_node_id { - result.predicates.push( - ty::TraitRef::identity(tcx, item_def_id).to_predicate() - ); + result + .predicates + .push(ty::TraitRef::identity(tcx, item_def_id).to_predicate()); } generics } - _ => return result + _ => return result, } } - NodeForeignItem(item) => { - match item.node { - ForeignItemKind::Fn(_, _, ref generics) => generics, - _ => return result - } - } + Node::ForeignItem(item) => match item.node { + ForeignItemKind::Fn(_, _, ref generics) => generics, + _ => return result, + }, - _ => return result + _ => return result, }; let icx = ItemCtxt::new(tcx, item_def_id); - result.predicates.extend( - icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty)); + result + .predicates + .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty)); result } @@ -307,32 +322,33 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { /// AST. We do this to avoid having to convert *all* the bounds, which /// would create artificial cycles. Instead we can only convert the /// bounds for a type parameter `X` if `X::Foo` is used. - fn type_parameter_bounds_in_generics(&self, - ast_generics: &hir::Generics, - param_id: ast::NodeId, - ty: Ty<'tcx>) - -> Vec> - { - let from_ty_params = - ast_generics.params.iter() - .filter_map(|param| match param.kind { - GenericParamKind::Type { .. } if param.id == param_id => Some(¶m.bounds), - _ => None - }) - .flat_map(|bounds| bounds.iter()) - .flat_map(|b| predicates_from_bound(self, ty, b)); - - let from_where_clauses = - ast_generics.where_clause - .predicates - .iter() - .filter_map(|wp| match *wp { - hir::WherePredicate::BoundPredicate(ref bp) => Some(bp), - _ => None - }) - .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id)) - .flat_map(|bp| bp.bounds.iter()) - .flat_map(|b| predicates_from_bound(self, ty, b)); + fn type_parameter_bounds_in_generics( + &self, + ast_generics: &hir::Generics, + param_id: ast::NodeId, + ty: Ty<'tcx>, + ) -> Vec> { + let from_ty_params = ast_generics + .params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Type { .. } if param.id == param_id => Some(¶m.bounds), + _ => None, + }) + .flat_map(|bounds| bounds.iter()) + .flat_map(|b| predicates_from_bound(self, ty, b)); + + let from_where_clauses = ast_generics + .where_clause + .predicates + .iter() + .filter_map(|wp| match *wp { + hir::WherePredicate::BoundPredicate(ref bp) => Some(bp), + _ => None, + }) + .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id)) + .flat_map(|bp| bp.bounds.iter()) + .flat_map(|b| predicates_from_bound(self, ty, b)); from_ty_params.chain(from_where_clauses).collect() } @@ -342,18 +358,17 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { /// parameter with id `param_id`. We use this so as to avoid running /// `ast_ty_to_ty`, because we want to avoid triggering an all-out /// conversion of the type to avoid inducing unnecessary cycles. -fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ast_ty: &hir::Ty, - param_id: ast::NodeId) - -> bool -{ +fn is_param<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + ast_ty: &hir::Ty, + param_id: ast::NodeId, +) -> bool { if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ast_ty.node { match path.def { - Def::SelfTy(Some(def_id), None) | - Def::TyParam(def_id) => { + Def::SelfTy(Some(def_id), None) | Def::TyParam(def_id) => { def_id == tcx.hir.local_def_id(param_id) } - _ => false + _ => false, } } else { false @@ -366,10 +381,10 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { let def_id = tcx.hir.local_def_id(item_id); match it.node { // These don't define types. - hir::ItemKind::ExternCrate(_) | - hir::ItemKind::Use(..) | - hir::ItemKind::Mod(_) | - hir::ItemKind::GlobalAsm(_) => {} + hir::ItemKind::ExternCrate(_) + | hir::ItemKind::Use(..) + | hir::ItemKind::Mod(_) + | hir::ItemKind::GlobalAsm(_) => {} hir::ItemKind::ForeignMod(ref foreign_mod) => { for item in &foreign_mod.items { let def_id = tcx.hir.local_def_id(item.id); @@ -386,25 +401,28 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { tcx.type_of(def_id); tcx.predicates_of(def_id); convert_enum_variant_types(tcx, def_id, &enum_definition.variants); - }, + } hir::ItemKind::Impl(..) => { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.impl_trait_ref(def_id); tcx.predicates_of(def_id); - }, + } hir::ItemKind::Trait(..) => { tcx.generics_of(def_id); tcx.trait_def(def_id); tcx.at(it.span).super_predicates_of(def_id); tcx.predicates_of(def_id); - }, + } hir::ItemKind::TraitAlias(..) => { - span_err!(tcx.sess, it.span, E0645, - "trait aliases are not yet implemented (see issue #41517)"); - }, - hir::ItemKind::Struct(ref struct_def, _) | - hir::ItemKind::Union(ref struct_def, _) => { + span_err!( + tcx.sess, + it.span, + E0645, + "trait aliases are not yet implemented (see issue #41517)" + ); + } + hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); @@ -419,16 +437,19 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { if !struct_def.is_struct() { convert_variant_ctor(tcx, struct_def.id()); } - }, + } // Desugared from `impl Trait` -> visited by the function's return type - hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => {} - - hir::ItemKind::Existential(..) | - hir::ItemKind::Ty(..) | - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) => { + hir::ItemKind::Existential(hir::ExistTy { + impl_trait_fn: Some(_), + .. + }) => {} + + hir::ItemKind::Existential(..) + | hir::ItemKind::Ty(..) + | hir::ItemKind::Static(..) + | hir::ItemKind::Const(..) + | hir::ItemKind::Fn(..) => { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); @@ -445,9 +466,9 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast: tcx.generics_of(def_id); match trait_item.node { - hir::TraitItemKind::Const(..) | - hir::TraitItemKind::Type(_, Some(_)) | - hir::TraitItemKind::Method(..) => { + hir::TraitItemKind::Const(..) + | hir::TraitItemKind::Type(_, Some(_)) + | hir::TraitItemKind::Method(..) => { tcx.type_of(def_id); if let hir::TraitItemKind::Method(..) = trait_item.node { tcx.fn_sig(def_id); @@ -470,17 +491,18 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::N } } -fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ctor_id: ast::NodeId) { +fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ctor_id: ast::NodeId) { let def_id = tcx.hir.local_def_id(ctor_id); tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); } -fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId, - variants: &[hir::Variant]) { +fn convert_enum_variant_types<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + variants: &[hir::Variant], +) { let def = tcx.adt_def(def_id); let repr_type = def.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx); @@ -489,21 +511,30 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // fill the discriminant values and field types for variant in variants { let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); - prev_discr = Some(if let Some(ref e) = variant.node.disr_expr { - let expr_did = tcx.hir.local_def_id(e.id); - def.eval_explicit_discr(tcx, expr_did) - } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { - Some(discr) - } else { - struct_span_err!(tcx.sess, variant.span, E0370, - "enum discriminant overflowed") - .span_label(variant.span, format!("overflowed on value after {}", - prev_discr.unwrap())) - .note(&format!("explicitly set `{} = {}` if that is desired outcome", - variant.node.name, wrapped_discr)) - .emit(); - None - }.unwrap_or(wrapped_discr)); + prev_discr = Some( + if let Some(ref e) = variant.node.disr_expr { + let expr_did = tcx.hir.local_def_id(e.id); + def.eval_explicit_discr(tcx, expr_did) + } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { + Some(discr) + } else { + struct_span_err!( + tcx.sess, + variant.span, + E0370, + "enum discriminant overflowed" + ).span_label( + variant.span, + format!("overflowed on value after {}", prev_discr.unwrap()), + ) + .note(&format!( + "explicitly set `{} = {}` if that is desired outcome", + variant.node.name, wrapped_discr + )) + .emit(); + None + }.unwrap_or(wrapped_discr), + ); for f in variant.node.data.fields() { let def_id = tcx.hir.local_def_id(f.id); @@ -518,71 +549,83 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - did: DefId, - name: ast::Name, - discr: ty::VariantDiscr, - def: &hir::VariantData) - -> ty::VariantDef { +fn convert_variant<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + did: DefId, + name: ast::Name, + discr: ty::VariantDiscr, + def: &hir::VariantData, + adt_kind: ty::AdtKind +) -> ty::VariantDef { let mut seen_fields: FxHashMap = FxHashMap(); let node_id = tcx.hir.as_local_node_id(did).unwrap(); - let fields = def.fields().iter().map(|f| { - let fid = tcx.hir.local_def_id(f.id); - let dup_span = seen_fields.get(&f.ident.modern()).cloned(); - if let Some(prev_span) = dup_span { - struct_span_err!(tcx.sess, f.span, E0124, - "field `{}` is already declared", - f.ident) - .span_label(f.span, "field already declared") - .span_label(prev_span, format!("`{}` first declared here", f.ident)) - .emit(); - } else { - seen_fields.insert(f.ident.modern(), f.span); - } + let fields = def + .fields() + .iter() + .map(|f| { + let fid = tcx.hir.local_def_id(f.id); + let dup_span = seen_fields.get(&f.ident.modern()).cloned(); + if let Some(prev_span) = dup_span { + struct_span_err!( + tcx.sess, + f.span, + E0124, + "field `{}` is already declared", + f.ident + ).span_label(f.span, "field already declared") + .span_label(prev_span, format!("`{}` first declared here", f.ident)) + .emit(); + } else { + seen_fields.insert(f.ident.modern(), f.span); + } - ty::FieldDef { - did: fid, - ident: f.ident, - vis: ty::Visibility::from_hir(&f.vis, node_id, tcx) - } - }).collect(); - ty::VariantDef { + ty::FieldDef { + did: fid, + ident: f.ident, + vis: ty::Visibility::from_hir(&f.vis, node_id, tcx), + } + }) + .collect(); + ty::VariantDef::new(tcx, did, name, discr, fields, - ctor_kind: CtorKind::from_hir(def), - } + adt_kind, + CtorKind::from_hir(def)) } -fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> &'tcx ty::AdtDef { - use rustc::hir::map::*; +fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::AdtDef { use rustc::hir::*; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let item = match tcx.hir.get(node_id) { - NodeItem(item) => item, - _ => bug!() + Node::Item(item) => item, + _ => bug!(), }; let repr = ReprOptions::new(tcx, def_id); let (kind, variants) = match item.node { ItemKind::Enum(ref def, _) => { let mut distance_from_explicit = 0; - (AdtKind::Enum, def.variants.iter().map(|v| { - let did = tcx.hir.local_def_id(v.node.data.id()); - let discr = if let Some(ref e) = v.node.disr_expr { - distance_from_explicit = 0; - ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.id)) - } else { - ty::VariantDiscr::Relative(distance_from_explicit) - }; - distance_from_explicit += 1; + ( + AdtKind::Enum, + def.variants + .iter() + .map(|v| { + let did = tcx.hir.local_def_id(v.node.data.id()); + let discr = if let Some(ref e) = v.node.disr_expr { + distance_from_explicit = 0; + ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.id)) + } else { + ty::VariantDiscr::Relative(distance_from_explicit) + }; + distance_from_explicit += 1; - convert_struct_variant(tcx, did, v.node.name, discr, &v.node.data) - }).collect()) + convert_variant(tcx, did, v.node.name, discr, &v.node.data, AdtKind::Enum) + }) + .collect(), + ) } ItemKind::Struct(ref def, _) => { // Use separate constructor id for unit/tuple structs and reuse did for braced structs. @@ -591,18 +634,30 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { None }; - (AdtKind::Struct, vec![ - convert_struct_variant(tcx, ctor_id.unwrap_or(def_id), item.name, - ty::VariantDiscr::Relative(0), def) - ]) - } - ItemKind::Union(ref def, _) => { - (AdtKind::Union, vec![ - convert_struct_variant(tcx, def_id, item.name, - ty::VariantDiscr::Relative(0), def) - ]) + ( + AdtKind::Struct, + vec![convert_variant( + tcx, + ctor_id.unwrap_or(def_id), + item.name, + ty::VariantDiscr::Relative(0), + def, + AdtKind::Struct + )], + ) } - _ => bug!() + ItemKind::Union(ref def, _) => ( + AdtKind::Union, + vec![convert_variant( + tcx, + def_id, + item.name, + ty::VariantDiscr::Relative(0), + def, + AdtKind::Union + )], + ), + _ => bug!(), }; tcx.alloc_adt_def(def_id, kind, variants, repr) } @@ -610,33 +665,29 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// Ensures that the super-predicates of the trait with def-id /// trait_def_id are converted and stored. This also ensures that /// the transitive super-predicates are converted; -fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - trait_def_id: DefId) - -> ty::GenericPredicates<'tcx> { +fn super_predicates_of<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + trait_def_id: DefId, +) -> ty::GenericPredicates<'tcx> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap(); let item = match tcx.hir.get(trait_node_id) { - hir_map::NodeItem(item) => item, - _ => bug!("trait_node_id {} is not an item", trait_node_id) + Node::Item(item) => item, + _ => bug!("trait_node_id {} is not an item", trait_node_id), }; let (generics, bounds) = match item.node { hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), - _ => span_bug!(item.span, - "super_predicates invoked on non-trait"), + _ => span_bug!(item.span, "super_predicates invoked on non-trait"), }; let icx = ItemCtxt::new(tcx, trait_def_id); // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`. let self_param_ty = tcx.mk_self_type(); - let superbounds1 = compute_bounds(&icx, - self_param_ty, - bounds, - SizedByDefault::No, - item.span); + let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); let superbounds1 = superbounds1.predicates(tcx, self_param_ty); @@ -655,13 +706,11 @@ fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::GenericPredicates { parent: None, - predicates: superbounds + predicates: superbounds, } } -fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> &'tcx ty::TraitDef { +fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::TraitDef { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let item = tcx.hir.expect_item(node_id); @@ -676,25 +725,25 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut err = tcx.sess.struct_span_err( item.span, "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ - which traits can use parenthetical notation"); - help!(&mut err, + which traits can use parenthetical notation", + ); + help!( + &mut err, "add `#![feature(unboxed_closures)]` to \ - the crate attributes to use it"); + the crate attributes to use it" + ); err.emit(); } let def_path_hash = tcx.def_path_hash(def_id); - let def = ty::TraitDef::new(def_id, - unsafety, - paren_sugar, - is_auto, - def_path_hash); + let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, def_path_hash); tcx.alloc_trait_def(def) } -fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - node: hir_map::Node<'tcx>) - -> Option { +fn has_late_bound_regions<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + node: Node<'tcx>, +) -> Option { struct LateBoundRegionsDetector<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, outer_index: ty::DebruijnIndex, @@ -707,49 +756,57 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if self.has_late_bound_regions.is_some() { return } + if self.has_late_bound_regions.is_some() { + return; + } match ty.node { hir::TyKind::BareFn(..) => { self.outer_index.shift_in(1); intravisit::walk_ty(self, ty); self.outer_index.shift_out(1); } - _ => intravisit::walk_ty(self, ty) + _ => intravisit::walk_ty(self, ty), } } - fn visit_poly_trait_ref(&mut self, - tr: &'tcx hir::PolyTraitRef, - m: hir::TraitBoundModifier) { - if self.has_late_bound_regions.is_some() { return } + fn visit_poly_trait_ref( + &mut self, + tr: &'tcx hir::PolyTraitRef, + m: hir::TraitBoundModifier, + ) { + if self.has_late_bound_regions.is_some() { + return; + } self.outer_index.shift_in(1); intravisit::walk_poly_trait_ref(self, tr, m); self.outer_index.shift_out(1); } fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { - if self.has_late_bound_regions.is_some() { return } + if self.has_late_bound_regions.is_some() { + return; + } let hir_id = self.tcx.hir.node_to_hir_id(lt.id); match self.tcx.named_region(hir_id) { Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {} - Some(rl::Region::LateBound(debruijn, _, _)) | - Some(rl::Region::LateBoundAnon(debruijn, _)) - if debruijn < self.outer_index => {} - Some(rl::Region::LateBound(..)) | - Some(rl::Region::LateBoundAnon(..)) | - Some(rl::Region::Free(..)) | - None => { + Some(rl::Region::LateBound(debruijn, _, _)) + | Some(rl::Region::LateBoundAnon(debruijn, _)) if debruijn < self.outer_index => {} + Some(rl::Region::LateBound(..)) + | Some(rl::Region::LateBoundAnon(..)) + | Some(rl::Region::Free(..)) + | None => { self.has_late_bound_regions = Some(lt.span); } } } } - fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - generics: &'tcx hir::Generics, - decl: &'tcx hir::FnDecl) - -> Option { + fn has_late_bound_regions<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + generics: &'tcx hir::Generics, + decl: &'tcx hir::FnDecl, + ) -> Option { let mut visitor = LateBoundRegionsDetector { tcx, outer_index: ty::INNERMOST, @@ -763,7 +820,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return Some(param.span); } } - _ => {}, + _ => {} } } visitor.visit_fn_decl(decl); @@ -771,58 +828,55 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } match node { - hir_map::NodeTraitItem(item) => match item.node { - hir::TraitItemKind::Method(ref sig, _) => - has_late_bound_regions(tcx, &item.generics, &sig.decl), + Node::TraitItem(item) => match item.node { + hir::TraitItemKind::Method(ref sig, _) => { + has_late_bound_regions(tcx, &item.generics, &sig.decl) + } _ => None, }, - hir_map::NodeImplItem(item) => match item.node { - hir::ImplItemKind::Method(ref sig, _) => - has_late_bound_regions(tcx, &item.generics, &sig.decl), + Node::ImplItem(item) => match item.node { + hir::ImplItemKind::Method(ref sig, _) => { + has_late_bound_regions(tcx, &item.generics, &sig.decl) + } _ => None, }, - hir_map::NodeForeignItem(item) => match item.node { - hir::ForeignItemKind::Fn(ref fn_decl, _, ref generics) => - has_late_bound_regions(tcx, generics, fn_decl), + Node::ForeignItem(item) => match item.node { + hir::ForeignItemKind::Fn(ref fn_decl, _, ref generics) => { + has_late_bound_regions(tcx, generics, fn_decl) + } _ => None, }, - hir_map::NodeItem(item) => match item.node { - hir::ItemKind::Fn(ref fn_decl, .., ref generics, _) => - has_late_bound_regions(tcx, generics, fn_decl), + Node::Item(item) => match item.node { + hir::ItemKind::Fn(ref fn_decl, .., ref generics, _) => { + has_late_bound_regions(tcx, generics, fn_decl) + } _ => None, }, - _ => None + _ => None, } } -fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> &'tcx ty::Generics { - use rustc::hir::map::*; +fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Generics { use rustc::hir::*; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let node = tcx.hir.get(node_id); let parent_def_id = match node { - NodeImplItem(_) | - NodeTraitItem(_) | - NodeVariant(_) | - NodeStructCtor(_) | - NodeField(_) => { + Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) + | Node::StructCtor(_) | Node::Field(_) => { let parent_id = tcx.hir.get_parent(node_id); Some(tcx.hir.local_def_id(parent_id)) } - NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(..), .. }) => { - Some(tcx.closure_base_def_id(def_id)) - } - NodeItem(item) => { - match item.node { - ItemKind::Existential(hir::ExistTy { impl_trait_fn, .. }) => impl_trait_fn, - _ => None, - } + Node::Expr(&hir::Expr { + node: hir::ExprKind::Closure(..), + .. + }) => Some(tcx.closure_base_def_id(def_id)), + Node::Item(item) => match item.node { + ItemKind::Existential(hir::ExistTy { impl_trait_fn, .. }) => impl_trait_fn, + _ => None, }, - _ => None + _ => None, }; let mut opt_self = None; @@ -830,26 +884,27 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let no_generics = hir::Generics::empty(); let ast_generics = match node { - NodeTraitItem(item) => &item.generics, + Node::TraitItem(item) => &item.generics, - NodeImplItem(item) => &item.generics, + Node::ImplItem(item) => &item.generics, - NodeItem(item) => { + Node::Item(item) => { match item.node { - ItemKind::Fn(.., ref generics, _) | - ItemKind::Impl(_, _, _, ref generics, ..) => generics, - - ItemKind::Ty(_, ref generics) | - ItemKind::Enum(_, ref generics) | - ItemKind::Struct(_, ref generics) | - ItemKind::Existential(hir::ExistTy { ref generics, .. }) | - ItemKind::Union(_, ref generics) => { + ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(_, _, _, ref generics, ..) => { + generics + } + + ItemKind::Ty(_, ref generics) + | ItemKind::Enum(_, ref generics) + | ItemKind::Struct(_, ref generics) + | ItemKind::Existential(hir::ExistTy { ref generics, .. }) + | ItemKind::Union(_, ref generics) => { allow_defaults = true; generics } - ItemKind::Trait(_, _, ref generics, ..) | - ItemKind::TraitAlias(ref generics, ..) => { + ItemKind::Trait(_, _, ref generics, ..) + | ItemKind::TraitAlias(ref generics, ..) => { // Add in the self type parameter. // // Something of a hack: use the node id for the trait, also as @@ -876,13 +931,11 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - NodeForeignItem(item) => { - match item.node { - ForeignItemKind::Static(..) => &no_generics, - ForeignItemKind::Fn(_, _, ref generics) => generics, - ForeignItemKind::Type => &no_generics, - } - } + Node::ForeignItem(item) => match item.node { + ForeignItemKind::Static(..) => &no_generics, + ForeignItemKind::Fn(_, _, ref generics) => generics, + ForeignItemKind::Type => &no_generics, + }, _ => &no_generics, }; @@ -901,15 +954,17 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut params: Vec<_> = opt_self.into_iter().collect(); let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); - params.extend(early_lifetimes.enumerate().map(|(i, param)| { - ty::GenericParamDef { - name: param.name.ident().as_interned_str(), - index: own_start + i as u32, - def_id: tcx.hir.local_def_id(param.id), - pure_wrt_drop: param.pure_wrt_drop, - kind: ty::GenericParamDefKind::Lifetime, - } - })); + params.extend( + early_lifetimes + .enumerate() + .map(|(i, param)| ty::GenericParamDef { + name: param.name.ident().as_interned_str(), + index: own_start + i as u32, + def_id: tcx.hir.local_def_id(param.id), + pure_wrt_drop: param.pure_wrt_drop, + kind: ty::GenericParamDefKind::Lifetime, + }), + ); let hir_id = tcx.hir.node_to_hir_id(node_id); let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id); @@ -917,45 +972,65 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Now create the real type parameters. let type_start = own_start - has_self as u32 + params.len() as u32; let mut i = 0; - params.extend(ast_generics.params.iter().filter_map(|param| match param.kind { - GenericParamKind::Type { ref default, synthetic, .. } => { - if param.name.ident().name == keywords::SelfType.name() { - span_bug!(param.span, "`Self` should not be the name of a regular parameter"); - } + params.extend( + ast_generics + .params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Type { + ref default, + synthetic, + .. + } => { + if param.name.ident().name == keywords::SelfType.name() { + span_bug!( + param.span, + "`Self` should not be the name of a regular parameter" + ); + } - if !allow_defaults && default.is_some() { - if !tcx.features().default_type_parameter_fallback { - tcx.lint_node( - lint::builtin::INVALID_TYPE_PARAM_DEFAULT, - param.id, - param.span, - &format!("defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions.")); - } - } + if !allow_defaults && default.is_some() { + if !tcx.features().default_type_parameter_fallback { + tcx.lint_node( + lint::builtin::INVALID_TYPE_PARAM_DEFAULT, + param.id, + param.span, + &format!( + "defaults for type parameters are only allowed in \ + `struct`, `enum`, `type`, or `trait` definitions." + ), + ); + } + } - let ty_param = ty::GenericParamDef { - index: type_start + i as u32, - name: param.name.ident().as_interned_str(), - def_id: tcx.hir.local_def_id(param.id), - pure_wrt_drop: param.pure_wrt_drop, - kind: ty::GenericParamDefKind::Type { - has_default: default.is_some(), - object_lifetime_default: - object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]), - synthetic, - }, - }; - i += 1; - Some(ty_param) - } - _ => None, - })); + let ty_param = ty::GenericParamDef { + index: type_start + i as u32, + name: param.name.ident().as_interned_str(), + def_id: tcx.hir.local_def_id(param.id), + pure_wrt_drop: param.pure_wrt_drop, + kind: ty::GenericParamDefKind::Type { + has_default: default.is_some(), + object_lifetime_default: object_lifetime_defaults + .as_ref() + .map_or(rl::Set1::Empty, |o| o[i]), + synthetic, + }, + }; + i += 1; + Some(ty_param) + } + _ => None, + }), + ); // provide junk type parameter defs - the only place that // cares about anything but the length is instantiation, // and we don't do that for closures. - if let NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(.., gen), .. }) = node { + if let Node::Expr(&hir::Expr { + node: hir::ExprKind::Closure(.., gen), + .. + }) = node + { let dummy_args = if gen.is_some() { &["", "", ""][..] } else { @@ -963,8 +1038,10 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; params.extend( - dummy_args.iter().enumerate().map(|(i, &arg)| - ty::GenericParamDef { + dummy_args + .iter() + .enumerate() + .map(|(i, &arg)| ty::GenericParamDef { index: type_start + i as u32, name: Symbol::intern(arg).as_interned_str(), def_id, @@ -974,8 +1051,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, object_lifetime_default: rl::Set1::Empty, synthetic: None, }, - } - ) + }), ); tcx.with_freevars(node_id, |fv| { @@ -995,9 +1071,10 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); } - let param_def_id_to_index = params.iter() - .map(|param| (param.def_id, param.index)) - .collect(); + let param_def_id_to_index = params + .iter() + .map(|param| (param.def_id, param.index)) + .collect(); tcx.alloc_generics(ty::Generics { parent: parent_def_id, @@ -1009,17 +1086,16 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) } -fn report_assoc_ty_on_inherent_impl<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - span: Span, -) { - span_err!(tcx.sess, span, E0202, "associated types are not allowed in inherent impls"); +fn report_assoc_ty_on_inherent_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) { + span_err!( + tcx.sess, + span, + E0202, + "associated types are not allowed in inherent impls" + ); } -fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> Ty<'tcx> { - use rustc::hir::map::*; +fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { use rustc::hir::*; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -1027,109 +1103,132 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let icx = ItemCtxt::new(tcx, def_id); match tcx.hir.get(node_id) { - NodeTraitItem(item) => { - match item.node { - TraitItemKind::Method(..) => { - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) - } - TraitItemKind::Const(ref ty, _) | - TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), - TraitItemKind::Type(_, None) => { - span_bug!(item.span, "associated type missing default"); - } + Node::TraitItem(item) => match item.node { + TraitItemKind::Method(..) => { + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) } - } + TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), + TraitItemKind::Type(_, None) => { + span_bug!(item.span, "associated type missing default"); + } + }, - NodeImplItem(item) => { - match item.node { - ImplItemKind::Method(..) => { - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) + Node::ImplItem(item) => match item.node { + ImplItemKind::Method(..) => { + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) + } + ImplItemKind::Const(ref ty, _) => icx.to_ty(ty), + ImplItemKind::Existential(_) => { + if tcx + .impl_trait_ref(tcx.hir.get_parent_did(node_id)) + .is_none() + { + report_assoc_ty_on_inherent_impl(tcx, item.span); } - ImplItemKind::Const(ref ty, _) => icx.to_ty(ty), - ImplItemKind::Existential(_) => { - if tcx.impl_trait_ref(tcx.hir.get_parent_did(node_id)).is_none() { - report_assoc_ty_on_inherent_impl(tcx, item.span); - } - find_existential_constraints(tcx, def_id) + find_existential_constraints(tcx, def_id) + } + ImplItemKind::Type(ref ty) => { + if tcx + .impl_trait_ref(tcx.hir.get_parent_did(node_id)) + .is_none() + { + report_assoc_ty_on_inherent_impl(tcx, item.span); } - ImplItemKind::Type(ref ty) => { - if tcx.impl_trait_ref(tcx.hir.get_parent_did(node_id)).is_none() { - report_assoc_ty_on_inherent_impl(tcx, item.span); - } - icx.to_ty(ty) - } + icx.to_ty(ty) } - } + }, - NodeItem(item) => { + Node::Item(item) => { match item.node { - ItemKind::Static(ref t, ..) | ItemKind::Const(ref t, _) | - ItemKind::Ty(ref t, _) | ItemKind::Impl(.., ref t, _) => { - icx.to_ty(t) - } + ItemKind::Static(ref t, ..) + | ItemKind::Const(ref t, _) + | ItemKind::Ty(ref t, _) + | ItemKind::Impl(.., ref t, _) => icx.to_ty(t), ItemKind::Fn(..) => { let substs = Substs::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id, substs) } - ItemKind::Enum(..) | - ItemKind::Struct(..) | - ItemKind::Union(..) => { + ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { let def = tcx.adt_def(def_id); let substs = Substs::identity_for_item(tcx, def_id); tcx.mk_adt(def, substs) } - ItemKind::Existential(hir::ExistTy { impl_trait_fn: None, .. }) => { - find_existential_constraints(tcx, def_id) - }, + ItemKind::Existential(hir::ExistTy { + impl_trait_fn: None, + .. + }) => find_existential_constraints(tcx, def_id), // existential types desugared from impl Trait - ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(owner), .. }) => { - tcx.typeck_tables_of(owner).concrete_existential_types[&def_id] - }, - ItemKind::Trait(..) | ItemKind::TraitAlias(..) | - ItemKind::Mod(..) | - ItemKind::ForeignMod(..) | - ItemKind::GlobalAsm(..) | - ItemKind::ExternCrate(..) | - ItemKind::Use(..) => { + ItemKind::Existential(hir::ExistTy { + impl_trait_fn: Some(owner), + .. + }) => { + tcx.typeck_tables_of(owner) + .concrete_existential_types + .get(&def_id) + .cloned() + .unwrap_or_else(|| { + // This can occur if some error in the + // owner fn prevented us from populating + // the `concrete_existential_types` table. + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "owner {:?} has no existential type for {:?} in its tables", + owner, def_id, + ), + ); + tcx.types.err + }) + } + ItemKind::Trait(..) + | ItemKind::TraitAlias(..) + | ItemKind::Mod(..) + | ItemKind::ForeignMod(..) + | ItemKind::GlobalAsm(..) + | ItemKind::ExternCrate(..) + | ItemKind::Use(..) => { span_bug!( item.span, "compute_type_of_item: unexpected item type: {:?}", - item.node); + item.node + ); } } } - NodeForeignItem(foreign_item) => { - match foreign_item.node { - ForeignItemKind::Fn(..) => { - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) - } - ForeignItemKind::Static(ref t, _) => icx.to_ty(t), - ForeignItemKind::Type => tcx.mk_foreign(def_id), + Node::ForeignItem(foreign_item) => match foreign_item.node { + ForeignItemKind::Fn(..) => { + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) } - } + ForeignItemKind::Static(ref t, _) => icx.to_ty(t), + ForeignItemKind::Type => tcx.mk_foreign(def_id), + }, - NodeStructCtor(&ref def) | - NodeVariant(&Spanned { node: hir::VariantKind { data: ref def, .. }, .. }) => { - match *def { - VariantData::Unit(..) | VariantData::Struct(..) => { - tcx.type_of(tcx.hir.get_parent_did(node_id)) - } - VariantData::Tuple(..) => { - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) - } + Node::StructCtor(&ref def) + | Node::Variant(&Spanned { + node: hir::VariantKind { data: ref def, .. }, + .. + }) => match *def { + VariantData::Unit(..) | VariantData::Struct(..) => { + tcx.type_of(tcx.hir.get_parent_did(node_id)) } - } + VariantData::Tuple(..) => { + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) + } + }, - NodeField(field) => icx.to_ty(&field.ty), + Node::Field(field) => icx.to_ty(&field.ty), - NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(.., gen), .. }) => { + Node::Expr(&hir::Expr { + node: hir::ExprKind::Closure(.., gen), + .. + }) => { if gen.is_some() { let hir_id = tcx.hir.node_to_hir_id(node_id); return tcx.typeck_tables_of(def_id).node_id_to_type(hir_id); @@ -1142,31 +1241,50 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.mk_closure(def_id, substs) } - NodeAnonConst(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) { - NodeTy(&hir::Ty { node: hir::TyKind::Array(_, ref constant), .. }) | - NodeTy(&hir::Ty { node: hir::TyKind::Typeof(ref constant), .. }) | - NodeExpr(&hir::Expr { node: ExprKind::Repeat(_, ref constant), .. }) - if constant.id == node_id => tcx.types.usize, + Node::AnonConst(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) { + Node::Ty(&hir::Ty { + node: hir::TyKind::Array(_, ref constant), + .. + }) + | Node::Ty(&hir::Ty { + node: hir::TyKind::Typeof(ref constant), + .. + }) + | Node::Expr(&hir::Expr { + node: ExprKind::Repeat(_, ref constant), + .. + }) if constant.id == node_id => + { + tcx.types.usize + } - NodeVariant(&Spanned { node: VariantKind { disr_expr: Some(ref e), .. }, .. }) - if e.id == node_id => { - tcx.adt_def(tcx.hir.get_parent_did(node_id)) - .repr.discr_type().to_ty(tcx) - } + Node::Variant(&Spanned { + node: + VariantKind { + disr_expr: Some(ref e), + .. + }, + .. + }) if e.id == node_id => + { + tcx.adt_def(tcx.hir.get_parent_did(node_id)) + .repr + .discr_type() + .to_ty(tcx) + } x => { bug!("unexpected const parent in type_of_def_id(): {:?}", x); } }, - NodeGenericParam(param) => { - match param.kind { - hir::GenericParamKind::Type { default: Some(ref ty), .. } => { - icx.to_ty(ty) - } - _ => bug!("unexpected non-type NodeGenericParam"), - } - } + Node::GenericParam(param) => match param.kind { + hir::GenericParamKind::Type { + default: Some(ref ty), + .. + } => icx.to_ty(ty), + _ => bug!("unexpected non-type NodeGenericParam"), + }, x => { bug!("unexpected sort of node in type_of_def_id(): {:?}", x); @@ -1178,7 +1296,6 @@ fn find_existential_constraints<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ) -> ty::Ty<'tcx> { - use rustc::hir::map::*; use rustc::hir::*; struct ConstraintLocator<'a, 'tcx: 'a> { @@ -1245,7 +1362,11 @@ fn find_existential_constraints<'a, 'tcx>( intravisit::walk_trait_item(self, it); } } - let mut locator = ConstraintLocator { def_id, tcx, found: None }; + let mut locator = ConstraintLocator { + def_id, + tcx, + found: None, + }; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let parent = tcx.hir.get_parent(node_id); trace!("parent_id: {:?}", parent); @@ -1254,10 +1375,13 @@ fn find_existential_constraints<'a, 'tcx>( } else { trace!("parent: {:?}", tcx.hir.get(parent)); match tcx.hir.get(parent) { - NodeItem(ref it) => intravisit::walk_item(&mut locator, it), - NodeImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it), - NodeTraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it), - other => bug!("{:?} is not a valid parent of an existential type item", other), + Node::Item(ref it) => intravisit::walk_item(&mut locator, it), + Node::ImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it), + Node::TraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it), + other => bug!( + "{:?} is not a valid parent of an existential type item", + other + ), } } match locator.found { @@ -1270,49 +1394,63 @@ fn find_existential_constraints<'a, 'tcx>( } } -fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> ty::PolyFnSig<'tcx> { - use rustc::hir::map::*; +fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig<'tcx> { use rustc::hir::*; + use rustc::hir::Node::*; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let icx = ItemCtxt::new(tcx, def_id); match tcx.hir.get(node_id) { - NodeTraitItem(hir::TraitItem { node: TraitItemKind::Method(sig, _), .. }) | - NodeImplItem(hir::ImplItem { node: ImplItemKind::Method(sig, _), .. }) => { - AstConv::ty_of_fn(&icx, sig.header.unsafety, sig.header.abi, &sig.decl) - } - - NodeItem(hir::Item { node: ItemKind::Fn(decl, header, _, _), .. }) => { - AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl) - } - - NodeForeignItem(&hir::ForeignItem { node: ForeignItemKind::Fn(ref fn_decl, _, _), .. }) => { + TraitItem(hir::TraitItem { + node: TraitItemKind::Method(sig, _), + .. + }) + | ImplItem(hir::ImplItem { + node: ImplItemKind::Method(sig, _), + .. + }) => AstConv::ty_of_fn(&icx, sig.header.unsafety, sig.header.abi, &sig.decl), + + Item(hir::Item { + node: ItemKind::Fn(decl, header, _, _), + .. + }) => AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl), + + ForeignItem(&hir::ForeignItem { + node: ForeignItemKind::Fn(ref fn_decl, _, _), + .. + }) => { let abi = tcx.hir.get_foreign_abi(node_id); compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) } - NodeStructCtor(&VariantData::Tuple(ref fields, _)) | - NodeVariant(&Spanned { node: hir::VariantKind { - data: VariantData::Tuple(ref fields, _), .. - }, .. }) => { + StructCtor(&VariantData::Tuple(ref fields, _)) + | Variant(&Spanned { + node: + hir::VariantKind { + data: VariantData::Tuple(ref fields, _), + .. + }, + .. + }) => { let ty = tcx.type_of(tcx.hir.get_parent_did(node_id)); - let inputs = fields.iter().map(|f| { - tcx.type_of(tcx.hir.local_def_id(f.id)) - }); + let inputs = fields + .iter() + .map(|f| tcx.type_of(tcx.hir.local_def_id(f.id))); ty::Binder::bind(tcx.mk_fn_sig( inputs, ty, false, hir::Unsafety::Normal, - abi::Abi::Rust + abi::Abi::Rust, )) } - NodeExpr(&hir::Expr { node: hir::ExprKind::Closure(..), .. }) => { + Expr(&hir::Expr { + node: hir::ExprKind::Closure(..), + .. + }) => { // Closure signatures are not like other function // signatures and cannot be accessed through `fn_sig`. For // example, a closure signature excludes the `self` @@ -1337,9 +1475,10 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> Option> { +fn impl_trait_ref<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> Option> { let icx = ItemCtxt::new(tcx, def_id); let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -1350,37 +1489,40 @@ fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) }) } - _ => bug!() + _ => bug!(), } } -fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> hir::ImplPolarity { +fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> hir::ImplPolarity { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); match tcx.hir.expect_item(node_id).node { hir::ItemKind::Impl(_, polarity, ..) => polarity, - ref item => bug!("impl_polarity: {:?} not an impl", item) + ref item => bug!("impl_polarity: {:?} not an impl", item), } } // Is it marked with ?Sized -fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, - ast_bounds: &[hir::GenericBound], - span: Span) -> bool -{ +fn is_unsized<'gcx: 'tcx, 'tcx>( + astconv: &dyn AstConv<'gcx, 'tcx>, + ast_bounds: &[hir::GenericBound], + span: Span, +) -> bool { let tcx = astconv.tcx(); // Try to find an unbound in bounds. let mut unbound = None; for ab in ast_bounds { - if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab { + if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab { if unbound.is_none() { unbound = Some(ptr.trait_ref.clone()); } else { - span_err!(tcx.sess, span, E0203, - "type parameter has more than one relaxed default \ - bound, only one is supported"); + span_err!( + tcx.sess, + span, + E0203, + "type parameter has more than one relaxed default \ + bound, only one is supported" + ); } } } @@ -1391,10 +1533,12 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, // FIXME(#8559) currently requires the unbound to be built-in. if let Ok(kind_id) = kind_id { if tpb.path.def != Def::Trait(kind_id) { - tcx.sess.span_warn(span, - "default bound relaxed for a type parameter, but \ - this does nothing because the given bound is not \ - a default. Only `?Sized` is supported"); + tcx.sess.span_warn( + span, + "default bound relaxed for a type parameter, but \ + this does nothing because the given bound is not \ + a default. Only `?Sized` is supported", + ); } } } @@ -1415,25 +1559,29 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, /// `resolve_lifetime::early_bound_lifetimes`. fn early_bound_lifetimes_from_generics<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - generics: &'a hir::Generics) - -> impl Iterator + Captures<'tcx> -{ - generics.params.iter().filter(move |param| match param.kind { - GenericParamKind::Lifetime { .. } => { - let hir_id = tcx.hir.node_to_hir_id(param.id); - !tcx.is_late_bound(hir_id) - } - _ => false, - }) + generics: &'a hir::Generics, +) -> impl Iterator + Captures<'tcx> { + generics + .params + .iter() + .filter(move |param| match param.kind { + GenericParamKind::Lifetime { .. } => { + let hir_id = tcx.hir.node_to_hir_id(param.id); + !tcx.is_late_bound(hir_id) + } + _ => false, + }) } -fn predicates_defined_on<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> ty::GenericPredicates<'tcx> { +fn predicates_defined_on<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> ty::GenericPredicates<'tcx> { let explicit = tcx.explicit_predicates_of(def_id); - let predicates = if tcx.sess.features_untracked().infer_outlives_requirements { - [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat() - } else { explicit.predicates }; + let predicates = [ + &explicit.predicates[..], + &tcx.inferred_outlives_of(def_id)[..], + ].concat(); ty::GenericPredicates { parent: explicit.parent, @@ -1441,11 +1589,14 @@ fn predicates_defined_on<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> ty::GenericPredicates<'tcx> { - let ty::GenericPredicates { parent, mut predicates } = - tcx.predicates_defined_on(def_id); +fn predicates_of<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> ty::GenericPredicates<'tcx> { + let ty::GenericPredicates { + parent, + mut predicates, + } = tcx.predicates_defined_on(def_id); if tcx.is_trait(def_id) { // For traits, add `Self: Trait` predicate. This is @@ -1470,7 +1621,6 @@ fn explicit_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ) -> ty::GenericPredicates<'tcx> { - use rustc::hir::map::*; use rustc::hir::*; debug!("explicit_predicates_of(def_id={:?})", def_id); @@ -1487,29 +1637,29 @@ fn explicit_predicates_of<'a, 'tcx>( let mut predicates = vec![]; let ast_generics = match node { - NodeTraitItem(item) => { - &item.generics - } + Node::TraitItem(item) => &item.generics, - NodeImplItem(item) => match item.node { + Node::ImplItem(item) => match item.node { ImplItemKind::Existential(ref bounds) => { let substs = Substs::identity_for_item(tcx, def_id); - let anon_ty = tcx.mk_anon(def_id, substs); + let opaque_ty = tcx.mk_opaque(def_id, substs); // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. - let bounds = compute_bounds(&icx, - anon_ty, - bounds, - SizedByDefault::Yes, - tcx.def_span(def_id)); + let bounds = compute_bounds( + &icx, + opaque_ty, + bounds, + SizedByDefault::Yes, + tcx.def_span(def_id), + ); - predicates.extend(bounds.predicates(tcx, anon_ty)); + predicates.extend(bounds.predicates(tcx, opaque_ty)); &item.generics - }, + } _ => &item.generics, - } + }, - NodeItem(item) => { + Node::Item(item) => { match item.node { ItemKind::Impl(_, _, defaultness, ref generics, ..) => { if defaultness.is_default() { @@ -1517,36 +1667,42 @@ fn explicit_predicates_of<'a, 'tcx>( } generics } - ItemKind::Fn(.., ref generics, _) | - ItemKind::Ty(_, ref generics) | - ItemKind::Enum(_, ref generics) | - ItemKind::Struct(_, ref generics) | - ItemKind::Union(_, ref generics) => generics, + ItemKind::Fn(.., ref generics, _) + | ItemKind::Ty(_, ref generics) + | ItemKind::Enum(_, ref generics) + | ItemKind::Struct(_, ref generics) + | ItemKind::Union(_, ref generics) => generics, ItemKind::Trait(_, _, ref generics, .., ref items) => { is_trait = Some((ty::TraitRef::identity(tcx, def_id), items)); generics } - ItemKind::Existential(ExistTy { ref bounds, impl_trait_fn, ref generics }) => { + ItemKind::Existential(ExistTy { + ref bounds, + impl_trait_fn, + ref generics, + }) => { let substs = Substs::identity_for_item(tcx, def_id); - let anon_ty = tcx.mk_anon(def_id, substs); + let opaque_ty = tcx.mk_opaque(def_id, substs); // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. - let bounds = compute_bounds(&icx, - anon_ty, - bounds, - SizedByDefault::Yes, - tcx.def_span(def_id)); + let bounds = compute_bounds( + &icx, + opaque_ty, + bounds, + SizedByDefault::Yes, + tcx.def_span(def_id), + ); if impl_trait_fn.is_some() { // impl Trait return ty::GenericPredicates { parent: None, - predicates: bounds.predicates(tcx, anon_ty), + predicates: bounds.predicates(tcx, opaque_ty), }; } else { // named existential types - predicates.extend(bounds.predicates(tcx, anon_ty)); + predicates.extend(bounds.predicates(tcx, opaque_ty)); generics } } @@ -1555,13 +1711,11 @@ fn explicit_predicates_of<'a, 'tcx>( } } - NodeForeignItem(item) => { - match item.node { - ForeignItemKind::Static(..) => &no_generics, - ForeignItemKind::Fn(_, _, ref generics) => generics, - ForeignItemKind::Type => &no_generics, - } - } + Node::ForeignItem(item) => match item.node { + ForeignItemKind::Static(..) => &no_generics, + ForeignItemKind::Fn(_, _, ref generics) => generics, + ForeignItemKind::Type => &no_generics, + }, _ => &no_generics, }; @@ -1612,7 +1766,7 @@ fn explicit_predicates_of<'a, 'tcx>( } _ => bug!(), }); - }, + } _ => bug!(), } } @@ -1641,25 +1795,39 @@ fn explicit_predicates_of<'a, 'tcx>( &hir::WherePredicate::BoundPredicate(ref bound_pred) => { let ty = icx.to_ty(&bound_pred.bounded_ty); + // Keep the type around in a WF predicate, in case of no bounds. + // That way, `where Ty:` is not a complete noop (see #53696). + if bound_pred.bounds.is_empty() { + if let ty::Param(_) = ty.sty { + // This is a `where T:`, which can be in the HIR from the + // transformation that moves `?Sized` to `T`'s declaration. + // We can skip the predicate because type parameters are + // trivially WF, but also we *should*, to avoid exposing + // users who never wrote `where Type:,` themselves, to + // compiler/tooling bugs from not handling WF predicates. + } else { + predicates.push(ty::Predicate::WellFormed(ty)); + } + } + for bound in bound_pred.bounds.iter() { match bound { &hir::GenericBound::Trait(ref poly_trait_ref, _) => { let mut projections = Vec::new(); - let trait_ref = - AstConv::instantiate_poly_trait_ref(&icx, - poly_trait_ref, - ty, - &mut projections); + let trait_ref = AstConv::instantiate_poly_trait_ref( + &icx, + poly_trait_ref, + ty, + &mut projections, + ); predicates.push(trait_ref.to_predicate()); predicates.extend(projections.iter().map(|p| p.to_predicate())); } &hir::GenericBound::Outlives(ref lifetime) => { - let region = AstConv::ast_region_to_region(&icx, - lifetime, - None); + let region = AstConv::ast_region_to_region(&icx, lifetime, None); let pred = ty::Binder::bind(ty::OutlivesPredicate(ty, region)); predicates.push(ty::Predicate::TypeOutlives(pred)) } @@ -1698,16 +1866,16 @@ fn explicit_predicates_of<'a, 'tcx>( } }; - let assoc_ty = tcx.mk_projection( - tcx.hir.local_def_id(trait_item.id), - self_trait_ref.substs, - ); + let assoc_ty = + tcx.mk_projection(tcx.hir.local_def_id(trait_item.id), self_trait_ref.substs); - let bounds = compute_bounds(&ItemCtxt::new(tcx, def_id), - assoc_ty, - bounds, - SizedByDefault::Yes, - trait_item.span); + let bounds = compute_bounds( + &ItemCtxt::new(tcx, def_id), + assoc_ty, + bounds, + SizedByDefault::Yes, + trait_item.span, + ); bounds.predicates(tcx, assoc_ty).into_iter() })) @@ -1718,13 +1886,19 @@ fn explicit_predicates_of<'a, 'tcx>( // before uses of `U`. This avoids false ambiguity errors // in trait checking. See `setup_constraining_predicates` // for details. - if let NodeItem(&Item { node: ItemKind::Impl(..), .. }) = node { + if let Node::Item(&Item { + node: ItemKind::Impl(..), + .. + }) = node + { let self_ty = tcx.type_of(def_id); let trait_ref = tcx.impl_trait_ref(def_id); - ctp::setup_constraining_predicates(tcx, - &mut predicates, - trait_ref, - &mut ctp::parameters_for_impl(self_ty, trait_ref)); + ctp::setup_constraining_predicates( + tcx, + &mut predicates, + trait_ref, + &mut ctp::parameters_for_impl(self_ty, trait_ref), + ); } ty::GenericPredicates { @@ -1733,18 +1907,21 @@ fn explicit_predicates_of<'a, 'tcx>( } } -pub enum SizedByDefault { Yes, No, } +pub enum SizedByDefault { + Yes, + No, +} /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the /// built-in trait (formerly known as kind): Send. -pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound], - sized_by_default: SizedByDefault, - span: Span) - -> Bounds<'tcx> -{ +pub fn compute_bounds<'gcx: 'tcx, 'tcx>( + astconv: &dyn AstConv<'gcx, 'tcx>, + param_ty: Ty<'tcx>, + ast_bounds: &[hir::GenericBound], + sized_by_default: SizedByDefault, + span: Span, +) -> Bounds<'tcx> { let mut region_bounds = vec![]; let mut trait_bounds = vec![]; for ast_bound in ast_bounds { @@ -1757,13 +1934,15 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, let mut projection_bounds = vec![]; - let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| { - astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds) - }).collect(); + let mut trait_bounds: Vec<_> = trait_bounds + .iter() + .map(|&bound| astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds)) + .collect(); - let region_bounds = region_bounds.into_iter().map(|r| { - astconv.ast_region_to_region(r, None) - }).collect(); + let region_bounds = region_bounds + .into_iter() + .map(|r| astconv.ast_region_to_region(r, None)) + .collect(); trait_bounds.sort_by_key(|t| t.def_id()); @@ -1786,21 +1965,20 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, /// because this can be anywhere from 0 predicates (`T:?Sized` adds no /// predicates) to 1 (`T:Foo`) to many (`T:Bar` adds `T:Bar` /// and `::X == i32`). -fn predicates_from_bound<'tcx>(astconv: &dyn AstConv<'tcx, 'tcx>, - param_ty: Ty<'tcx>, - bound: &hir::GenericBound) - -> Vec> -{ +fn predicates_from_bound<'tcx>( + astconv: &dyn AstConv<'tcx, 'tcx>, + param_ty: Ty<'tcx>, + bound: &hir::GenericBound, +) -> Vec> { match *bound { hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => { let mut projections = Vec::new(); - let pred = astconv.instantiate_poly_trait_ref(tr, - param_ty, - &mut projections); - projections.into_iter() - .map(|p| p.to_predicate()) - .chain(Some(pred.to_predicate())) - .collect() + let pred = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections); + projections + .into_iter() + .map(|p| p.to_predicate()) + .chain(Some(pred.to_predicate())) + .collect() } hir::GenericBound::Outlives(ref lifetime) => { let region = astconv.ast_region_to_region(lifetime, None); @@ -1815,21 +1993,35 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, decl: &hir::FnDecl, - abi: abi::Abi) - -> ty::PolyFnSig<'tcx> -{ - let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl); + abi: abi::Abi, +) -> ty::PolyFnSig<'tcx> { + let unsafety = if abi == abi::Abi::RustIntrinsic { + match &*tcx.item_name(def_id).as_str() { + "size_of" | "min_align_of" => hir::Unsafety::Normal, + _ => hir::Unsafety::Unsafe, + } + } else { + hir::Unsafety::Unsafe + }; + let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl); // feature gate SIMD types in FFI, since I (huonw) am not sure the // ABIs are handled at all correctly. - if abi != abi::Abi::RustIntrinsic && abi != abi::Abi::PlatformIntrinsic - && !tcx.features().simd_ffi { + if abi != abi::Abi::RustIntrinsic + && abi != abi::Abi::PlatformIntrinsic + && !tcx.features().simd_ffi + { let check = |ast_ty: &hir::Ty, ty: Ty| { if ty.is_simd() { - tcx.sess.struct_span_err(ast_ty.span, - &format!("use of SIMD type `{}` in FFI is highly experimental and \ - may result in invalid code", - tcx.hir.node_to_pretty_string(ast_ty.id))) + tcx.sess + .struct_span_err( + ast_ty.span, + &format!( + "use of SIMD type `{}` in FFI is highly experimental and \ + may result in invalid code", + tcx.hir.node_to_pretty_string(ast_ty.id) + ), + ) .help("add #![feature(simd_ffi)] to the crate attributes to enable") .emit(); } @@ -1845,13 +2037,11 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( fty } -fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> bool { +fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { match tcx.hir.get_if_local(def_id) { - Some(hir_map::NodeForeignItem(..)) => true, + Some(Node::ForeignItem(..)) => true, Some(_) => false, - _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id) + _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id), } } @@ -1868,7 +2058,7 @@ fn from_target_feature( let msg = "#[target_feature] attribute must be of the form \ #[target_feature(..)]"; tcx.sess.span_err(attr.span, &msg); - return + return; } }; let rust_features = tcx.features(); @@ -1878,7 +2068,7 @@ fn from_target_feature( let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \ currently"; tcx.sess.span_err(item.span, &msg); - continue + continue; } // Must be of the form `enable = "..."` ( a string) @@ -1888,19 +2078,21 @@ fn from_target_feature( let msg = "#[target_feature] attribute must be of the form \ #[target_feature(enable = \"..\")]"; tcx.sess.span_err(item.span, &msg); - continue + continue; } }; // We allow comma separation to enable multiple features for feature in value.as_str().split(',') { - // Only allow whitelisted features per platform let feature_gate = match whitelist.get(feature) { Some(g) => g, None => { - let msg = format!("the feature named `{}` is not valid for \ - this target", feature); + let msg = format!( + "the feature named `{}` is not valid for \ + this target", + feature + ); let mut err = tcx.sess.struct_span_err(item.span, &msg); if feature.starts_with("+") { @@ -1910,7 +2102,7 @@ fn from_target_feature( } } err.emit(); - continue + continue; } }; @@ -1925,6 +2117,7 @@ fn from_target_feature( Some("mmx_target_feature") => rust_features.mmx_target_feature, Some("sse4a_target_feature") => rust_features.sse4a_target_feature, Some("tbm_target_feature") => rust_features.tbm_target_feature, + Some("wasm_target_feature") => rust_features.wasm_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; @@ -1934,10 +2127,9 @@ fn from_target_feature( feature_gate.as_ref().unwrap(), item.span, feature_gate::GateIssue::Language, - &format!("the target feature `{}` is currently unstable", - feature), + &format!("the target feature `{}` is currently unstable", feature), ); - continue + continue; } target_features.push(Symbol::intern(feature)); } @@ -1972,7 +2164,8 @@ fn linkage_by_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, name: & if let Some(span) = span { tcx.sess.span_fatal(span, "invalid linkage specified") } else { - tcx.sess.fatal(&format!("invalid linkage specified: {}", name)) + tcx.sess + .fatal(&format!("invalid linkage specified: {}", name)) } } } @@ -2025,16 +2218,24 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen mark_used(attr); inline_span = Some(attr.span); if items.len() != 1 { - span_err!(tcx.sess.diagnostic(), attr.span, E0534, - "expected one argument"); + span_err!( + tcx.sess.diagnostic(), + attr.span, + E0534, + "expected one argument" + ); InlineAttr::None } else if list_contains_name(&items[..], "always") { InlineAttr::Always } else if list_contains_name(&items[..], "never") { InlineAttr::Never } else { - span_err!(tcx.sess.diagnostic(), items[0].span, E0535, - "invalid argument"); + span_err!( + tcx.sess.diagnostic(), + items[0].span, + E0535, + "invalid argument" + ); InlineAttr::None } @@ -2047,15 +2248,21 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen if s.as_str().contains("\0") { // `#[export_name = ...]` will be converted to a null-terminated string, // so it may not contain any null characters. - struct_span_err!(tcx.sess, attr.span, E0648, - "`export_name` may not contain null characters") - .emit(); + struct_span_err!( + tcx.sess, + attr.span, + E0648, + "`export_name` may not contain null characters" + ).emit(); } codegen_fn_attrs.export_name = Some(s); } else { - struct_span_err!(tcx.sess, attr.span, E0558, - "`export_name` attribute has invalid format") - .span_label(attr.span, "did you mean #[export_name=\"*\"]?") + struct_span_err!( + tcx.sess, + attr.span, + E0558, + "`export_name` attribute has invalid format" + ).span_label(attr.span, "did you mean #[export_name=\"*\"]?") .emit(); } } else if attr.check_name("target_feature") { @@ -2064,7 +2271,13 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen `unsafe` function"; tcx.sess.span_err(attr.span, msg); } - from_target_feature(tcx, id, attr, &whitelist, &mut codegen_fn_attrs.target_features); + from_target_feature( + tcx, + id, + attr, + &whitelist, + &mut codegen_fn_attrs.target_features, + ); } else if attr.check_name("linkage") { if let Some(val) = attr.value_str() { codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str())); @@ -2072,13 +2285,18 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen } else if attr.check_name("link_section") { if let Some(val) = attr.value_str() { if val.as_str().bytes().any(|b| b == 0) { - let msg = format!("illegal null byte in link_section \ - value: `{}`", &val); + let msg = format!( + "illegal null byte in link_section \ + value: `{}`", + &val + ); tcx.sess.span_err(attr.span, &msg); } else { codegen_fn_attrs.link_section = Some(val); } } + } else if attr.check_name("link_name") { + codegen_fn_attrs.link_name = attr.value_str(); } } @@ -2089,11 +2307,34 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen if codegen_fn_attrs.target_features.len() > 0 { if codegen_fn_attrs.inline == InlineAttr::Always { if let Some(span) = inline_span { - tcx.sess.span_err(span, "cannot use #[inline(always)] with \ - #[target_feature]"); + tcx.sess.span_err( + span, + "cannot use #[inline(always)] with \ + #[target_feature]", + ); } } } + // Weak lang items have the same semantics as "std internal" symbols in the + // sense that they're preserved through all our LTO passes and only + // strippable by the linker. + // + // Additionally weak lang items have predetermined symbol names. + if tcx.is_weak_lang_item(id) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; + } + if let Some(name) = weak_lang_items::link_name(&attrs) { + codegen_fn_attrs.export_name = Some(name); + codegen_fn_attrs.link_name = Some(name); + } + + // Internal symbols to the standard library all have no_mangle semantics in + // that they have defined symbol names present in the function name. This + // also applies to weak symbols where they all have known symbol names. + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; + } + codegen_fn_attrs } diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 5f55b9b06e..1b481fc5a7 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -62,11 +62,11 @@ struct ParameterCollector { impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { match t.sty { - ty::TyProjection(..) | ty::TyAnon(..) if !self.include_nonconstraining => { + ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => { // projections are not injective return false; } - ty::TyParam(data) => { + ty::Param(data) => { self.parameters.push(Parameter::from(data)); } _ => {} diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 4d957c9aa4..80c1ca944b 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1041,32 +1041,38 @@ enum NightsWatch {} "##, E0087: r##" -Too many type parameters were supplied for a function. For example: +#### Note: this error code is no longer emitted by the compiler. + +Too many type arguments were supplied for a function. For example: -```compile_fail,E0087 +```compile_fail,E0107 fn foo() {} fn main() { - foo::(); // error, expected 1 parameter, found 2 parameters + foo::(); // error: wrong number of type arguments: + // expected 1, found 2 } ``` -The number of supplied parameters must exactly match the number of defined type +The number of supplied arguments must exactly match the number of defined type parameters. "##, E0088: r##" -You gave too many lifetime parameters. Erroneous code example: +#### Note: this error code is no longer emitted by the compiler. -```compile_fail,E0088 +You gave too many lifetime arguments. Erroneous code example: + +```compile_fail,E0107 fn f() {} fn main() { - f::<'static>() // error: too many lifetime parameters provided + f::<'static>() // error: wrong number of lifetime arguments: + // expected 0, found 1 } ``` -Please check you give the right number of lifetime parameters. Example: +Please check you give the right number of lifetime arguments. Example: ``` fn f() {} @@ -1101,42 +1107,48 @@ fn main() { "##, E0089: r##" -Not enough type parameters were supplied for a function. For example: +#### Note: this error code is no longer emitted by the compiler. + +Too few type arguments were supplied for a function. For example: -```compile_fail,E0089 +```compile_fail,E0107 fn foo() {} fn main() { - foo::(); // error, expected 2 parameters, found 1 parameter + foo::(); // error: wrong number of type arguments: expected 2, found 1 } ``` -Note that if a function takes multiple type parameters but you want the compiler +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,E0089 +```compile_fail,E0107 fn foo(x: T) {} fn main() { let x: bool = true; - foo::(x); // error, expected 2 parameters, found 1 parameter + foo::(x); // error: wrong number of type arguments: + // expected 2, found 1 foo::<_, f64>(x); // same as `foo::(x)` } ``` "##, E0090: r##" -You gave too few lifetime parameters. Example: +#### Note: this error code is no longer emitted by the compiler. + +You gave too few lifetime arguments. Example: -```compile_fail,E0090 +```compile_fail,E0107 fn foo<'a: 'b, 'b: 'a>() {} fn main() { - foo::<'static>(); // error, expected 2 lifetime parameters + foo::<'static>(); // error: wrong number of lifetime arguments: + // expected 2, found 1 } ``` -Please check you give the right number of lifetime parameters. Example: +Please check you give the right number of lifetime arguments. Example: ``` fn foo<'a: 'b, 'b: 'a>() {} @@ -1254,18 +1266,34 @@ extern "rust-intrinsic" { "##, E0107: r##" -This error means that an incorrect number of lifetime parameters were provided -for a type (like a struct or enum) or trait: +This error means that an incorrect number of generic arguments were provided: ```compile_fail,E0107 -struct Foo<'a, 'b>(&'a str, &'b str); -enum Bar { A, B, C } +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 -struct Baz<'a> { - foo: Foo<'a>, // error: expected 2, found 1 - bar: Bar<'a>, // error: expected 0, found 1 +fn foo(x: T, y: U) {} + +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 +} + +fn f() {} + +fn main() { + f::<'static>(); // error: wrong number of lifetime arguments: + // expected 0, found 1 } ``` + "##, E0109: r##" @@ -2393,13 +2421,15 @@ fn baz(x: &::A) where I: Foo {} "##, E0243: r##" +#### 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,E0243 +```compile_fail,E0107 struct Foo { x: T } struct Bar { x: Foo } @@ -2407,13 +2437,15 @@ struct Bar { x: Foo } "##, E0244: r##" +#### 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,E0244 +```compile_fail,E0107 struct Foo { x: bool } struct Bar { x: Foo } @@ -4626,7 +4658,7 @@ field that requires non-trivial alignment. Erroneous code example: ```compile_fail,E0691 -#![feature(repr_align, attr_literals)] +#![feature(repr_align)] #[repr(align(32))] struct ForceAlign32; @@ -4653,7 +4685,7 @@ 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, attr_literals)] +#![feature(repr_align)] use std::marker::PhantomData; diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index b792130195..11260b8f11 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -152,7 +152,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // } // ``` // - // In a concession to backwards compatbility, we continue to + // In a concession to backwards compatibility, we continue to // permit those, so long as the lifetimes aren't used in // associated types. I believe this is sound, because lifetimes // used elsewhere are not projected back out. diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 0cc1f6333a..c9aa0339dd 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -74,9 +74,8 @@ This API is completely unstable and subject to change. #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] -#![feature(from_ref)] #![feature(exhaustive_patterns)] -#![feature(iterator_find_map)] +#![cfg_attr(not(stage0), feature(nll))] #![feature(quote)] #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] @@ -96,6 +95,7 @@ extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_data_structures; extern crate rustc_errors as errors; extern crate rustc_target; +extern crate smallvec; use rustc::hir; use rustc::lint; @@ -103,12 +103,13 @@ use rustc::middle; use rustc::session; use rustc::util; -use hir::map as hir_map; +use hir::Node; use rustc::infer::InferOk; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::query::Providers; use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; +use rustc::util::profiling::ProfileCategory; use session::{CompileIncomplete, config}; use util::common::time; @@ -184,9 +185,9 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let main_def_id = tcx.hir.local_def_id(main_id); let main_t = tcx.type_of(main_def_id); match main_t.sty { - ty::TyFnDef(..) => { + ty::FnDef(..) => { match tcx.hir.find(main_id) { - Some(hir_map::NodeItem(it)) => { + Some(Node::Item(it)) => { match it.node { hir::ItemKind::Fn(.., ref generics, _) => { let mut error = false; @@ -223,7 +224,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, actual.output().skip_binder() } else { // standard () main return type - tcx.mk_nil() + tcx.mk_unit() }; let se_ty = tcx.mk_fn_ptr(ty::Binder::bind( @@ -256,9 +257,9 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let start_def_id = tcx.hir.local_def_id(start_id); let start_t = tcx.type_of(start_def_id); match start_t.sty { - ty::TyFnDef(..) => { + ty::FnDef(..) => { match tcx.hir.find(start_id) { - Some(hir_map::NodeItem(it)) => { + Some(Node::Item(it)) => { match it.node { hir::ItemKind::Fn(.., ref generics, _) => { let mut error = false; @@ -317,8 +318,8 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() { match entry_type { - config::EntryMain => check_main_fn_ty(tcx, id, sp), - config::EntryStart => check_start_fn_ty(tcx, id, sp), + config::EntryFnType::Main => check_main_fn_ty(tcx, id, sp), + config::EntryFnType::Start => check_start_fn_ty(tcx, id, sp), } } } @@ -334,6 +335,8 @@ pub fn provide(providers: &mut Providers) { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> { + tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking)); + // this ensures that later parts of type checking can assume that items // have valid types and not error tcx.sess.track_errors(|| { @@ -371,6 +374,8 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) check_unused::check_crate(tcx); check_for_entry_fn(tcx); + tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking)); + tcx.sess.compile_status() } diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index e378f1a2dc..254146c0ef 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -9,6 +9,7 @@ // except according to those terms. use rustc::hir; +use hir::Node; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::subst::{Kind, Subst, UnpackedKind}; @@ -71,7 +72,7 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> { .as_local_node_id(item_did) .expect("expected local def-id"); let item = match self.tcx.hir.get(node_id) { - hir::map::NodeItem(item) => item, + Node::Item(item) => item, _ => bug!(), }; @@ -85,7 +86,7 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> { // Calculating the predicate requirements necessary // for item_did. // - // For field of type &'a T (reference) or TyAdt + // For field of type &'a T (reference) or Adt // (struct/enum/union) there will be outlive // requirements for adt_def. let field_ty = self.tcx.type_of(field_def.did); @@ -138,16 +139,16 @@ fn insert_required_predicates_to_be_wf<'tcx>( // a predicate requirement of T: 'a (T outlives 'a). // // We also want to calculate potential predicates for the T - ty::TyRef(region, rty, _) => { - debug!("TyRef"); + ty::Ref(region, rty, _) => { + debug!("Ref"); insert_outlives_predicate(tcx, rty.into(), region, required_predicates); } - // For each TyAdt (struct/enum/union) type `Foo<'a, T>`, we + // For each Adt (struct/enum/union) type `Foo<'a, T>`, we // can load the current set of inferred and explicit // predicates from `global_inferred_outlives` and filter the // ones that are TypeOutlives. - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { // First check the inferred predicates // // Example 1: @@ -166,7 +167,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( // round we will get `U: 'b`. We then apply the substitution // `['b => 'a, U => T]` and thus get the requirement that `T: // 'a` holds for `Foo`. - debug!("TyAdt"); + debug!("Adt"); if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) { for unsubstituted_predicate in unsubstituted_predicates { // `unsubstituted_predicate` is `U: 'b` in the @@ -191,45 +192,52 @@ fn insert_required_predicates_to_be_wf<'tcx>( substs, required_predicates, explicit_map, - false, + IgnoreSelfTy(false), ); } - ty::TyDynamic(obj, ..) => { + ty::Dynamic(obj, ..) => { // This corresponds to `dyn Trait<..>`. In this case, we should // use the explicit predicates as well. - // We are passing type `ty` as a placeholder value with the function - // `with_self_ty`, since there is no concrete type `Self` for a - // `dyn Trait` at this stage. Therefore when checking explicit - // predicates in `check_explicit_predicates` we need to ignore - // checking the explicit_map for Self type. - debug!("TyDynamic"); + debug!("Dynamic"); debug!("field_ty = {}", &field_ty); debug!("ty in field = {}", &ty); if let Some(ex_trait_ref) = obj.principal() { + // Here, we are passing the type `usize` as a + // placeholder value with the function + // `with_self_ty`, since there is no concrete type + // `Self` for a `dyn Trait` at this + // stage. Therefore when checking explicit + // predicates in `check_explicit_predicates` we + // need to ignore checking the explicit_map for + // Self type. + let substs = ex_trait_ref + .with_self_ty(tcx, tcx.types.usize) + .skip_binder() + .substs; check_explicit_predicates( tcx, &ex_trait_ref.skip_binder().def_id, - ex_trait_ref.with_self_ty(tcx, ty).skip_binder().substs, + substs, required_predicates, explicit_map, - true, + IgnoreSelfTy(true), ); } } - ty::TyProjection(obj) => { + ty::Projection(obj) => { // This corresponds to `>::Bar`. In this case, we should use the // explicit predicates as well. - debug!("TyProjection"); + debug!("Projection"); check_explicit_predicates( tcx, &tcx.associated_item(obj.item_def_id).container.id(), obj.substs, required_predicates, explicit_map, - false, + IgnoreSelfTy(false), ); } @@ -238,6 +246,8 @@ fn insert_required_predicates_to_be_wf<'tcx>( } } +pub struct IgnoreSelfTy(bool); + /// We also have to check the explicit predicates /// declared on the type. /// @@ -259,7 +269,7 @@ pub fn check_explicit_predicates<'tcx>( substs: &[Kind<'tcx>], required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, - ignore_self_ty: bool, + ignore_self_ty: IgnoreSelfTy, ) { debug!("def_id = {:?}", &def_id); debug!("substs = {:?}", &substs); @@ -297,7 +307,7 @@ pub fn check_explicit_predicates<'tcx>( // to apply the substs, and not filter this predicate, we might then falsely // conclude that e.g. `X: 'x` was a reasonable inferred requirement. if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() { - if ty.is_self() && ignore_self_ty { + if ty.is_self() && ignore_self_ty.0 { debug!("skipping self ty = {:?}", &ty); continue; } @@ -307,5 +317,4 @@ pub fn check_explicit_predicates<'tcx>( debug!("predicate = {:?}", &predicate); insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, required_predicates); } - // } } diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index 74ef62e0c6..63a424936e 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::map as hir_map; +use hir::Node; use rustc::hir; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::ty::query::Providers; @@ -40,7 +40,7 @@ fn inferred_outlives_of<'a, 'tcx>( .expect("expected local def-id"); match tcx.hir.get(id) { - hir_map::NodeItem(item) => match item.node { + Node::Item(item) => match item.node { hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => { let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE); @@ -59,8 +59,7 @@ fn inferred_outlives_of<'a, 'tcx>( ty::Predicate::TypeOutlives(p) => p.to_string(), err => bug!("unexpected predicate {:?}", err), - }) - .collect(); + }).collect(); pred.sort(); let span = tcx.def_span(item_def_id); @@ -117,11 +116,9 @@ fn inferred_outlives_crate<'tcx>( ty::Binder::bind(ty::OutlivesPredicate(region1, region2)), ), }, - ) - .collect(); + ).collect(); (def_id, Lrc::new(vec)) - }) - .collect(); + }).collect(); let empty_predicate = Lrc::new(Vec::new()); diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs index afcdc7575a..12863cc66a 100644 --- a/src/librustc_typeck/structured_errors.rs +++ b/src/librustc_typeck/structured_errors.rs @@ -10,7 +10,7 @@ use rustc::session::Session; use syntax_pos::Span; -use errors::{DiagnosticId, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticId, DiagnosticBuilder}; use rustc::ty::{Ty, TypeFoldable}; pub trait StructuredDiagnostic<'tcx> { @@ -72,10 +72,13 @@ impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> { self.code(), ) }; - if let Ok(snippet) = self.sess.codemap().span_to_snippet(self.span) { - err.span_suggestion(self.span, - &format!("cast the value to `{}`", self.cast_ty), - format!("{} as {}", snippet, self.cast_ty)); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) { + err.span_suggestion_with_applicability( + self.span, + &format!("cast the value to `{}`", self.cast_ty), + format!("{} as {}", snippet, self.cast_ty), + Applicability::MachineApplicable, + ); } else { err.help(&format!("cast the value to `{}`", self.cast_ty)); } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 9fecf5e73e..95544da0b8 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -152,7 +152,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let inferred_start = self.terms_cx.inferred_starts[&id]; let current_item = &CurrentItem { inferred_start }; match tcx.type_of(def_id).sty { - ty::TyAdt(def, _) => { + ty::Adt(def, _) => { // Not entirely obvious: constraints on structs/enums do not // affect the variance of their type parameters. See discussion // in comment at top of module. @@ -166,7 +166,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } - ty::TyFnDef(..) => { + ty::FnDef(..) => { self.add_constraints_from_sig(current_item, tcx.fn_sig(def_id), self.covariant); @@ -261,52 +261,52 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance); match ty.sty { - ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | - ty::TyStr | ty::TyNever | ty::TyForeign(..) => { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | + ty::Str | ty::Never | ty::Foreign(..) => { // leaf type -- noop } - ty::TyFnDef(..) | - ty::TyGenerator(..) | - ty::TyClosure(..) => { + ty::FnDef(..) | + ty::Generator(..) | + ty::Closure(..) => { bug!("Unexpected closure type in variance computation"); } - ty::TyRef(region, ty, mutbl) => { + ty::Ref(region, ty, mutbl) => { let contra = self.contravariant(variance); self.add_constraints_from_region(current, region, contra); self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance); } - ty::TyArray(typ, _) | - ty::TySlice(typ) => { + ty::Array(typ, _) | + ty::Slice(typ) => { self.add_constraints_from_ty(current, typ, variance); } - ty::TyRawPtr(ref mt) => { + ty::RawPtr(ref mt) => { self.add_constraints_from_mt(current, mt, variance); } - ty::TyTuple(subtys) => { + ty::Tuple(subtys) => { for &subty in subtys { self.add_constraints_from_ty(current, subty, variance); } } - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { self.add_constraints_from_substs(current, def.did, substs, variance); } - ty::TyProjection(ref data) => { + ty::Projection(ref data) => { let tcx = self.tcx(); self.add_constraints_from_trait_ref(current, data.trait_ref(tcx), variance); } - ty::TyAnon(_, substs) => { + ty::Opaque(_, substs) => { self.add_constraints_from_invariant_substs(current, substs, variance); } - ty::TyDynamic(ref data, r) => { + ty::Dynamic(ref data, r) => { // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); self.add_constraints_from_region(current, r, contra); @@ -323,21 +323,21 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } - ty::TyParam(ref data) => { + ty::Param(ref data) => { self.add_constraint(current, data.idx, variance); } - ty::TyFnPtr(sig) => { + ty::FnPtr(sig) => { self.add_constraints_from_sig(current, sig, variance); } - ty::TyError => { + ty::Error => { // we encounter this when walking the trait references for object - // types, where we use TyError as the Self type + // types, where we use Error as the Self type } - ty::TyGeneratorWitness(..) | - ty::TyInfer(..) => { + ty::GeneratorWitness(..) | + ty::Infer(..) => { bug!("unexpected type encountered in \ variance inference: {}", ty); diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index 3d70550c1d..aaa0fd8e09 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -15,6 +15,7 @@ use arena; use rustc::hir; +use hir::Node; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::ty::{self, CrateVariancesMap, TyCtxt}; use rustc::ty::query::Providers; @@ -61,7 +62,7 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item") }; match tcx.hir.get(id) { - hir::map::NodeItem(item) => match item.node { + Node::Item(item) => match item.node { hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | @@ -70,25 +71,25 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) _ => unsupported() }, - hir::map::NodeTraitItem(item) => match item.node { + Node::TraitItem(item) => match item.node { hir::TraitItemKind::Method(..) => {} _ => unsupported() }, - hir::map::NodeImplItem(item) => match item.node { + Node::ImplItem(item) => match item.node { hir::ImplItemKind::Method(..) => {} _ => unsupported() }, - hir::map::NodeForeignItem(item) => match item.node { + Node::ForeignItem(item) => match item.node { hir::ForeignItemKind::Fn(..) => {} _ => unsupported() }, - hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {} + Node::Variant(_) | Node::StructCtor(_) => {} _ => unsupported() } diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 340a7b1d08..7116a42cea 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { debug!("id={} variances={:?}", id, variances); // Functions can have unused type parameters: make those invariant. - if let ty::TyFnDef(..) = tcx.type_of(def_id).sty { + if let ty::FnDef(..) = tcx.type_of(def_id).sty { for variance in &mut variances { if *variance == ty::Bivariant { *variance = ty::Invariant; diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index f0c40d1d49..e163fc68cb 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,5 +9,5 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.1.2", default-features = false } -minifier = "0.0.14" +minifier = "0.0.19" tempfile = "3" diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 47b3b00056..de5a680ccf 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -12,99 +12,34 @@ use rustc::hir; use rustc::traits::auto_trait as auto; use rustc::ty::{self, TypeFoldable}; use std::fmt::Debug; -use syntax_pos::DUMMY_SP; + +use self::def_ctor::{get_def_from_def_id, get_def_from_node_id}; use super::*; -pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a> { - pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>, +pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { + pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>, pub f: auto::AutoTraitFinder<'a, 'tcx>, } -impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { - pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> Self { +impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { + pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { let f = auto::AutoTraitFinder::new(&cx.tcx); AutoTraitFinder { cx, f } } pub fn get_with_def_id(&self, def_id: DefId) -> Vec { - let ty = self.cx.tcx.type_of(def_id); - - let def_ctor: fn(DefId) -> Def = match ty.sty { - ty::TyAdt(adt, _) => match adt.adt_kind() { - AdtKind::Struct => Def::Struct, - AdtKind::Enum => Def::Enum, - AdtKind::Union => Def::Union, - } - ty::TyInt(_) | - ty::TyUint(_) | - ty::TyFloat(_) | - ty::TyStr | - ty::TyBool | - ty::TyChar => return self.get_auto_trait_impls(def_id, &move |_: DefId| { - match ty.sty { - ty::TyInt(x) => Def::PrimTy(hir::TyInt(x)), - ty::TyUint(x) => Def::PrimTy(hir::TyUint(x)), - ty::TyFloat(x) => Def::PrimTy(hir::TyFloat(x)), - ty::TyStr => Def::PrimTy(hir::TyStr), - ty::TyBool => Def::PrimTy(hir::TyBool), - ty::TyChar => Def::PrimTy(hir::TyChar), - _ => unreachable!(), - } - }, None), - _ => { - debug!("Unexpected type {:?}", def_id); - return Vec::new() - } - }; - - self.get_auto_trait_impls(def_id, &def_ctor, None) + get_def_from_def_id(&self.cx, def_id, &|def_ctor| { + self.get_auto_trait_impls(def_id, &def_ctor, None) + }) } pub fn get_with_node_id(&self, id: ast::NodeId, name: String) -> Vec { - let item = &self.cx.tcx.hir.expect_item(id).node; - let did = self.cx.tcx.hir.local_def_id(id); - - let def_ctor = match *item { - hir::ItemKind::Struct(_, _) => Def::Struct, - hir::ItemKind::Union(_, _) => Def::Union, - hir::ItemKind::Enum(_, _) => Def::Enum, - _ => panic!("Unexpected type {:?} {:?}", item, id), - }; - - self.get_auto_trait_impls(did, &def_ctor, Some(name)) - } - - fn get_real_ty(&self, - def_id: DefId, - def_ctor: &F, - real_name: &Option, - generics: &ty::Generics, - ) -> hir::Ty - where F: Fn(DefId) -> Def { - let path = get_path_for_type(self.cx.tcx, def_id, def_ctor); - let mut segments = path.segments.into_vec(); - let last = segments.pop().unwrap(); - - segments.push(hir::PathSegment::new( - real_name.unwrap_or(last.ident), - self.generics_to_path_params(generics.clone()), - false, - )); - - let new_path = hir::Path { - span: path.span, - def: path.def, - segments: HirVec::from_vec(segments), - }; - - hir::Ty { - id: ast::DUMMY_NODE_ID, - node: hir::TyKind::Path(hir::QPath::Resolved(None, P(new_path))), - span: DUMMY_SP, - hir_id: hir::DUMMY_HIR_ID, - } + get_def_from_node_id(&self.cx, id, name, &|def_ctor, name| { + let did = self.cx.tcx.hir.local_def_id(id); + self.get_auto_trait_impls(did, &def_ctor, Some(name)) + }) } pub fn get_auto_trait_impls( @@ -191,6 +126,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { let trait_ = hir::TraitRef { path: get_path_for_type(self.cx.tcx, trait_def_id, hir::def::Def::Trait), ref_id: ast::DUMMY_NODE_ID, + hir_ref_id: hir::DUMMY_HIR_ID, }; let polarity; @@ -229,14 +165,14 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { _ => unreachable!(), }; let real_name = name.map(|name| Ident::from_str(&name)); - let ty = self.get_real_ty(def_id, def_ctor, &real_name, &generics); + let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, &generics); return Some(Item { source: Span::empty(), name: None, attrs: Default::default(), visibility: None, - def_id: self.next_def_id(def_id.krate), + def_id: self.cx.next_def_id(def_id.krate), stability: None, deprecation: None, inner: ImplItem(Impl { @@ -255,56 +191,6 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { None } - fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs { - let mut args = vec![]; - - for param in generics.params.iter() { - match param.kind { - ty::GenericParamDefKind::Lifetime => { - let name = if param.name == "" { - hir::ParamName::Plain(keywords::StaticLifetime.ident()) - } else { - hir::ParamName::Plain(ast::Ident::from_interned_str(param.name)) - }; - - args.push(hir::GenericArg::Lifetime(hir::Lifetime { - id: ast::DUMMY_NODE_ID, - span: DUMMY_SP, - name: hir::LifetimeName::Param(name), - })); - } - ty::GenericParamDefKind::Type {..} => { - args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone()))); - } - } - } - - hir::GenericArgs { - args: HirVec::from_vec(args), - bindings: HirVec::new(), - parenthesized: false, - } - } - - fn ty_param_to_ty(&self, param: ty::GenericParamDef) -> hir::Ty { - debug!("ty_param_to_ty({:?}) {:?}", param, param.def_id); - hir::Ty { - id: ast::DUMMY_NODE_ID, - node: hir::TyKind::Path(hir::QPath::Resolved( - None, - P(hir::Path { - span: DUMMY_SP, - def: Def::TyParam(param.def_id), - segments: HirVec::from_vec(vec![ - hir::PathSegment::from_ident(Ident::from_interned_str(param.name)) - ]), - }), - )), - span: DUMMY_SP, - hir_id: hir::DUMMY_HIR_ID, - } - } - fn find_auto_trait_generics( &self, did: DefId, @@ -381,7 +267,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // all intermediate RegionVids. At the end, all constraints should // be between Regions (aka region variables). This gives us the information // we need to create the Generics. - let mut finished = FxHashMap(); + let mut finished: FxHashMap<_, Vec<_>> = FxHashMap(); let mut vid_map: FxHashMap = FxHashMap(); @@ -395,25 +281,25 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { { let deps1 = vid_map .entry(RegionTarget::RegionVid(r1)) - .or_insert_with(|| Default::default()); + .or_default(); deps1.larger.insert(RegionTarget::RegionVid(r2)); } let deps2 = vid_map .entry(RegionTarget::RegionVid(r2)) - .or_insert_with(|| Default::default()); + .or_default(); deps2.smaller.insert(RegionTarget::RegionVid(r1)); } &Constraint::RegSubVar(region, vid) => { let deps = vid_map .entry(RegionTarget::RegionVid(vid)) - .or_insert_with(|| Default::default()); + .or_default(); deps.smaller.insert(RegionTarget::Region(region)); } &Constraint::VarSubReg(vid, region) => { let deps = vid_map .entry(RegionTarget::RegionVid(vid)) - .or_insert_with(|| Default::default()); + .or_default(); deps.larger.insert(RegionTarget::Region(region)); } &Constraint::RegSubReg(r1, r2) => { @@ -421,8 +307,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // Desired order is 'larger, smaller', so flip then if self.region_name(r1) != self.region_name(r2) { finished - .entry(self.region_name(r2).unwrap()) - .or_insert_with(|| Vec::new()) + .entry(self.region_name(r2).expect("no region_name found")) + .or_default() .push(r1); } } @@ -456,8 +342,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { (&RegionTarget::Region(r1), &RegionTarget::Region(r2)) => { if self.region_name(r1) != self.region_name(r2) { finished - .entry(self.region_name(r2).unwrap()) - .or_insert_with(|| Vec::new()) + .entry(self.region_name(r2).expect("no region name found")) + .or_default() .push(r1) // Larger, smaller } } @@ -533,8 +419,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { name: name.to_string(), kind: GenericParamDefKind::Lifetime, }) - } - &ty::ReVar(_) | &ty::ReEarlyBound(_) => None, + }, + &ty::ReVar(_) | &ty::ReEarlyBound(_) | &ty::ReStatic => None, _ => panic!("Unexpected region type {:?}", r), } }) @@ -553,7 +439,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { .flat_map(|(ty, mut bounds)| { if let Some(data) = ty_to_fn.get(&ty) { let (poly_trait, output) = - (data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned()); + (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned()); let new_ty = match &poly_trait.trait_ { &Type::ResolvedPath { ref path, @@ -562,7 +448,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { ref is_generic, } => { let mut new_path = path.clone(); - let last_segment = new_path.segments.pop().unwrap(); + let last_segment = new_path.segments.pop() + .expect("segments were empty"); let (old_input, old_output) = match last_segment.args { GenericArgs::AngleBracketed { types, .. } => (types, None), @@ -690,8 +577,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { } = full_generics.clean(self.cx); let mut has_sized = FxHashSet(); - let mut ty_to_bounds = FxHashMap(); - let mut lifetime_to_bounds = FxHashMap(); + let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = FxHashMap(); + let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = FxHashMap(); let mut ty_to_traits: FxHashMap> = FxHashMap(); let mut ty_to_fn: FxHashMap, Option)> = FxHashMap(); @@ -720,7 +607,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { let mut for_generics = self.extract_for_generics(tcx, orig_p.clone()); assert!(bounds.len() == 1); - let mut b = bounds.pop().unwrap(); + let mut b = bounds.pop().expect("bounds were empty"); if b.is_sized_bound(self.cx) { has_sized.insert(ty.clone()); @@ -750,7 +637,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { _ => false, }; - let poly_trait = b.get_poly_trait().unwrap(); + let poly_trait = b.get_poly_trait().expect("Cannot get poly trait"); if is_fn { ty_to_fn @@ -760,11 +647,11 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { ty_to_bounds .entry(ty.clone()) - .or_insert_with(|| FxHashSet()); + .or_default(); } else { ty_to_bounds .entry(ty.clone()) - .or_insert_with(|| FxHashSet()) + .or_default() .insert(b.clone()); } } @@ -772,7 +659,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { WherePredicate::RegionPredicate { lifetime, bounds } => { lifetime_to_bounds .entry(lifetime) - .or_insert_with(|| FxHashSet()) + .or_default() .extend(bounds); } WherePredicate::EqPredicate { lhs, rhs } => { @@ -803,7 +690,10 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // FIXME: Remove this scope when NLL lands { let args = - &mut new_trait_path.segments.last_mut().unwrap().args; + &mut new_trait_path.segments + .last_mut() + .expect("segments were empty") + .args; match args { // Convert somethiung like ' = u8' @@ -832,7 +722,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { let bounds = ty_to_bounds .entry(*ty.clone()) - .or_insert_with(|| FxHashSet()); + .or_default(); bounds.insert(GenericBound::TraitBound( PolyTrait { @@ -862,7 +752,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // loop ty_to_traits .entry(*ty.clone()) - .or_insert_with(|| FxHashSet()) + .or_default() .insert(*trait_.clone()); } _ => panic!("Unexpected trait {:?} for {:?}", trait_, did), @@ -934,7 +824,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // In fact, the iteration of an FxHashMap can even vary between platforms, // since FxHasher has different behavior for 32-bit and 64-bit platforms. // - // Obviously, it's extremely undesireable for documentation rendering + // Obviously, it's extremely undesirable for documentation rendering // to be depndent on the platform it's run on. Apart from being confusing // to end users, it makes writing tests much more difficult, as predicates // can appear in any order in the final result. @@ -946,7 +836,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // predicates and bounds, however, we ensure that for a given codebase, all // auto-trait impls always render in exactly the same way. // - // Using the Debug impementation for sorting prevents us from needing to + // Using the Debug implementation for sorting prevents us from needing to // write quite a bit of almost entirely useless code (e.g. how should two // Types be sorted relative to each other). It also allows us to solve the // problem for both WherePredicates and GenericBounds at the same time. This @@ -967,61 +857,6 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { _ => false, } } - - // This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly - // refactoring either librustdoc or librustc. In particular, allowing new DefIds to be - // registered after the AST is constructed would require storing the defid mapping in a - // RefCell, decreasing the performance for normal compilation for very little gain. - // - // Instead, we construct 'fake' def ids, which start immediately after the last DefId in - // DefIndexAddressSpace::Low. In the Debug impl for clean::Item, we explicitly check for fake - // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds - fn next_def_id(&self, crate_num: CrateNum) -> DefId { - let start_def_id = { - let next_id = if crate_num == LOCAL_CRATE { - self.cx - .tcx - .hir - .definitions() - .def_path_table() - .next_id(DefIndexAddressSpace::Low) - } else { - self.cx - .cstore - .def_path_table(crate_num) - .next_id(DefIndexAddressSpace::Low) - }; - - DefId { - krate: crate_num, - index: next_id, - } - }; - - let mut fake_ids = self.cx.fake_def_ids.borrow_mut(); - - let def_id = fake_ids.entry(crate_num).or_insert(start_def_id).clone(); - fake_ids.insert( - crate_num, - DefId { - krate: crate_num, - index: DefIndex::from_array_index( - def_id.index.as_array_index() + 1, - def_id.index.address_space(), - ), - }, - ); - - MAX_DEF_ID.with(|m| { - m.borrow_mut() - .entry(def_id.krate.clone()) - .or_insert(start_def_id); - }); - - self.cx.all_fake_def_ids.borrow_mut().insert(def_id); - - def_id.clone() - } } // Replaces all ReVars in a type with ty::Region's, using the provided map diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs new file mode 100644 index 0000000000..e7e371cd56 --- /dev/null +++ b/src/librustdoc/clean/blanket_impl.rs @@ -0,0 +1,161 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::hir; +use rustc::traits; +use rustc::ty::ToPredicate; +use rustc::ty::subst::Subst; +use rustc::infer::InferOk; +use syntax_pos::DUMMY_SP; + +use core::DocAccessLevels; + +use super::*; + +use self::def_ctor::{get_def_from_def_id, get_def_from_node_id}; + +pub struct BlanketImplFinder<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { + pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>, +} + +impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { + pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { + BlanketImplFinder { cx } + } + + pub fn get_with_def_id(&self, def_id: DefId) -> Vec { + get_def_from_def_id(&self.cx, def_id, &|def_ctor| { + self.get_blanket_impls(def_id, &def_ctor, None) + }) + } + + pub fn get_with_node_id(&self, id: ast::NodeId, name: String) -> Vec { + get_def_from_node_id(&self.cx, id, name, &|def_ctor, name| { + let did = self.cx.tcx.hir.local_def_id(id); + self.get_blanket_impls(did, &def_ctor, Some(name)) + }) + } + + pub fn get_blanket_impls( + &self, + def_id: DefId, + def_ctor: &F, + name: Option, + ) -> Vec + where F: Fn(DefId) -> Def { + let mut impls = Vec::new(); + if self.cx + .tcx + .get_attrs(def_id) + .lists("doc") + .has_word("hidden") + { + debug!( + "get_blanket_impls(def_id={:?}, def_ctor=...): item has doc('hidden'), \ + aborting", + def_id + ); + return impls; + } + let ty = self.cx.tcx.type_of(def_id); + let generics = self.cx.tcx.generics_of(def_id); + let real_name = name.clone().map(|name| Ident::from_str(&name)); + let param_env = self.cx.tcx.param_env(def_id); + for &trait_def_id in self.cx.all_traits.iter() { + if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) || + self.cx.generated_synthetics + .borrow_mut() + .get(&(def_id, trait_def_id)) + .is_some() { + continue + } + self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { + self.cx.tcx.infer_ctxt().enter(|infcx| { + let t_generics = infcx.tcx.generics_of(impl_def_id); + let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id) + .expect("Cannot get impl trait"); + + match trait_ref.self_ty().sty { + ty::Param(_) => {}, + _ => return, + } + + let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id); + let ty = ty.subst(infcx.tcx, substs); + let param_env = param_env.subst(infcx.tcx, substs); + + let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); + let trait_ref = trait_ref.subst(infcx.tcx, impl_substs); + + // Require the type the impl is implemented on to match + // our type, and ignore the impl if there was a mismatch. + let cause = traits::ObligationCause::dummy(); + let eq_result = infcx.at(&cause, param_env) + .eq(trait_ref.self_ty(), ty); + if let Ok(InferOk { value: (), obligations }) = eq_result { + // FIXME(eddyb) ignoring `obligations` might cause false positives. + drop(obligations); + + let may_apply = infcx.predicate_may_hold(&traits::Obligation::new( + cause.clone(), + param_env, + trait_ref.to_predicate(), + )); + if !may_apply { + return + } + self.cx.generated_synthetics.borrow_mut() + .insert((def_id, trait_def_id)); + let trait_ = hir::TraitRef { + path: get_path_for_type(infcx.tcx, + trait_def_id, + hir::def::Def::Trait), + ref_id: ast::DUMMY_NODE_ID, + hir_ref_id: hir::DUMMY_HIR_ID, + }; + let provided_trait_methods = + infcx.tcx.provided_trait_methods(trait_def_id) + .into_iter() + .map(|meth| meth.ident.to_string()) + .collect(); + + let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics); + let predicates = infcx.tcx.predicates_of(impl_def_id); + + impls.push(Item { + source: infcx.tcx.def_span(impl_def_id).clean(self.cx), + name: None, + attrs: Default::default(), + visibility: None, + def_id: self.cx.next_def_id(impl_def_id.krate), + stability: None, + deprecation: None, + inner: ImplItem(Impl { + unsafety: hir::Unsafety::Normal, + generics: (t_generics, &predicates).clean(self.cx), + provided_trait_methods, + trait_: Some(trait_.clean(self.cx)), + for_: ty.clean(self.cx), + items: infcx.tcx.associated_items(impl_def_id) + .collect::>() + .clean(self.cx), + polarity: None, + synthetic: false, + blanket_impl: Some(infcx.tcx.type_of(impl_def_id) + .clean(self.cx)), + }), + }); + } + }); + }); + } + impls + } +} diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index dceb04a7da..f90f1e54da 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -31,7 +31,7 @@ pub enum Cfg { True, /// Denies all configurations. False, - /// A generic configration option, e.g. `test` or `target_os = "linux"`. + /// A generic configuration option, e.g. `test` or `target_os = "linux"`. Cfg(Symbol, Option), /// Negate a configuration requirement, i.e. `not(x)`. Not(Box), @@ -417,7 +417,7 @@ mod test { use syntax::symbol::Symbol; use syntax::ast::*; - use syntax::codemap::dummy_spanned; + use syntax::source_map::dummy_spanned; use syntax_pos::DUMMY_SP; use syntax::with_globals; diff --git a/src/librustdoc/clean/def_ctor.rs b/src/librustdoc/clean/def_ctor.rs new file mode 100644 index 0000000000..cd9f4eb42d --- /dev/null +++ b/src/librustdoc/clean/def_ctor.rs @@ -0,0 +1,65 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::DocContext; + +use super::*; + +pub fn get_def_from_def_id(cx: &DocContext, + def_id: DefId, + callback: &F, +) -> Vec +where F: Fn(& dyn Fn(DefId) -> Def) -> Vec { + let ty = cx.tcx.type_of(def_id); + + match ty.sty { + ty::Adt(adt, _) => callback(&match adt.adt_kind() { + AdtKind::Struct => Def::Struct, + AdtKind::Enum => Def::Enum, + AdtKind::Union => Def::Union, + }), + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Str | + ty::Bool | + ty::Char => callback(&move |_: DefId| { + match ty.sty { + ty::Int(x) => Def::PrimTy(hir::Int(x)), + ty::Uint(x) => Def::PrimTy(hir::Uint(x)), + ty::Float(x) => Def::PrimTy(hir::Float(x)), + ty::Str => Def::PrimTy(hir::Str), + ty::Bool => Def::PrimTy(hir::Bool), + ty::Char => Def::PrimTy(hir::Char), + _ => unreachable!(), + } + }), + _ => { + debug!("Unexpected type {:?}", def_id); + Vec::new() + } + } +} + +pub fn get_def_from_node_id(cx: &DocContext, + id: ast::NodeId, + name: String, + callback: &F, +) -> Vec +where F: Fn(& dyn Fn(DefId) -> Def, String) -> Vec { + let item = &cx.tcx.hir.expect_item(id).node; + + callback(&match *item { + hir::ItemKind::Struct(_, _) => Def::Struct, + hir::ItemKind::Union(_, _) => Def::Union, + hir::ItemKind::Enum(_, _) => Def::Enum, + _ => panic!("Unexpected type {:?} {:?}", item, id), + }, name) +} diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9245ef3cf5..507461f2ea 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -19,13 +19,19 @@ use syntax_pos::Span; use rustc::hir; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; -use rustc::middle::cstore::LoadedMacro; +use rustc_metadata::cstore::LoadedMacro; use rustc::ty; use rustc::util::nodemap::FxHashSet; use core::{DocContext, DocAccessLevels}; use doctree; -use clean::{self, GetDefId, ToSource, get_auto_traits_with_def_id}; +use clean::{ + self, + GetDefId, + ToSource, + get_auto_traits_with_def_id, + get_blanket_impls_with_def_id, +}; use super::Clean; @@ -77,7 +83,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa ret.extend(build_impls(cx, did, true)); clean::EnumItem(build_enum(cx, did)) } - Def::TyForeign(did) => { + Def::ForeignTy(did) => { record_extern_fqn(cx, did, clean::TypeKind::Foreign); ret.extend(build_impls(cx, did, false)); clean::ForeignTypeItem @@ -87,7 +93,8 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa // Assume that enum variants and struct types are re-exported next to // their constructors. Def::VariantCtor(..) | - Def::StructCtor(..) => return Some(Vec::new()), + Def::StructCtor(..) | + Def::SelfCtor(..) => return Some(Vec::new()), Def::Mod(did) => { record_extern_fqn(cx, did, clean::TypeKind::Module); clean::ModuleItem(build_module(cx, did, visited)) @@ -168,7 +175,7 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) { } }); let fqn = if let clean::TypeKind::Macro = kind { - vec![crate_name, relative.last().unwrap()] + vec![crate_name, relative.last().expect("relative was empty")] } else { once(crate_name).chain(relative).collect() }; @@ -274,11 +281,14 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec = auto_impls.into_iter() - .filter(|i| renderinfo.inlined.insert(i.def_id)).collect(); + { + let mut renderinfo = cx.renderinfo.borrow_mut(); + let new_impls: Vec = auto_impls.into_iter() + .filter(|i| renderinfo.inlined.insert(i.def_id)).collect(); - impls.extend(new_impls); + impls.extend(new_impls); + } + impls.extend(get_blanket_impls_with_def_id(cx, did)); } // If this is the first time we've inlined something from another crate, then @@ -336,10 +346,13 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec = auto_impls.into_iter() - .filter(|i| renderinfo.inlined.insert(i.def_id)).collect(); + .chain(blanket_impls.into_iter()) + .filter(|i| renderinfo.inlined.insert(i.def_id)) + .collect(); impls.extend(new_impls); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7454f79ed6..20b17afeab 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -19,14 +19,12 @@ pub use self::FunctionRetTy::*; pub use self::Visibility::{Public, Inherited}; use rustc_target::spec::abi::Abi; -use syntax; -use syntax::ast::{self, AttrStyle, Name, NodeId, Ident}; +use syntax::ast::{self, AttrStyle, Ident}; use syntax::attr; -use syntax::codemap::{dummy_spanned, Spanned}; -use syntax::feature_gate::UnstableFeatures; +use syntax::source_map::{dummy_spanned, Spanned}; use syntax::ptr::P; use syntax::symbol::keywords::{self, Keyword}; -use syntax::symbol::{Symbol, InternedString}; +use syntax::symbol::InternedString; use syntax_pos::{self, DUMMY_SP, Pos, FileName}; use rustc::mir::interpret::ConstValue; @@ -37,16 +35,13 @@ use rustc::middle::lang_items; use rustc::mir::interpret::GlobalId; use rustc::hir::{self, GenericArg, HirVec}; use rustc::hir::def::{self, Def, CtorKind}; -use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::hir::def_id::DefIndexAddressSpace; -use rustc::hir::map::Node; +use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::ty::subst::Substs; use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::middle::stability; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_typeck::hir_ty_to_ty; use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; -use rustc::lint as lint; use std::collections::hash_map::Entry; use std::fmt; @@ -60,24 +55,26 @@ use std::str::FromStr; use std::cell::RefCell; use std::sync::Arc; use std::u32; -use std::ops::Range; use core::{self, DocContext}; use doctree; use visit_ast; use html::render::{cache, ExternalLocation}; use html::item_type::ItemType; -use html::markdown::markdown_links; pub mod inline; pub mod cfg; mod simplify; mod auto_trait; +mod blanket_impl; +pub mod def_ctor; use self::cfg::Cfg; use self::auto_trait::AutoTraitFinder; +use self::blanket_impl::BlanketImplFinder; -thread_local!(static MAX_DEF_ID: RefCell> = RefCell::new(FxHashMap())); +thread_local!(pub static MAX_DEF_ID: RefCell> = + RefCell::new(FxHashMap())); const FN_OUTPUT_NAME: &'static str = "Output"; @@ -145,7 +142,7 @@ pub struct Crate { pub masked_crates: FxHashSet, } -impl<'a, 'tcx, 'rcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx> { +impl<'a, 'tcx, 'rcx, 'cstore> Clean for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { fn clean(&self, cx: &DocContext) -> Crate { use ::visit_lib::LibEmbargoVisitor; @@ -242,7 +239,7 @@ impl Clean for CrateNum { fn clean(&self, cx: &DocContext) -> ExternalCrate { let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; let krate_span = cx.tcx.def_span(root); - let krate_src = cx.sess().codemap().span_to_filename(krate_span); + let krate_src = cx.sess().source_map().span_to_filename(krate_span); // Collect all inner modules which are tagged as implementations of // primitives. @@ -569,40 +566,15 @@ pub struct Module { impl Clean for doctree::Module { fn clean(&self, cx: &DocContext) -> Item { let name = if self.name.is_some() { - self.name.unwrap().clean(cx) + self.name.expect("No name provided").clean(cx) } else { - "".to_string() + String::new() }; // maintain a stack of mod ids, for doc comment path resolution // but we also need to resolve the module's own docs based on whether its docs were written // inside or outside the module, so check for that - let attrs = if self.attrs.iter() - .filter(|a| a.check_name("doc")) - .next() - .map_or(true, |a| a.style == AttrStyle::Inner) { - // inner doc comment, use the module's own scope for resolution - if self.id != NodeId::new(0) { - *cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(self.id)); - } else { - *cx.current_item_name.borrow_mut() = None; - } - cx.mod_ids.borrow_mut().push(self.id); - self.attrs.clean(cx) - } else { - // outer doc comment, use its parent's scope - match cx.mod_ids.borrow().last() { - Some(parent) if *parent != NodeId::new(0) => { - *cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(*parent)); - } - _ => { - *cx.current_item_name.borrow_mut() = None; - } - } - let attrs = self.attrs.clean(cx); - cx.mod_ids.borrow_mut().push(self.id); - attrs - }; + let attrs = self.attrs.clean(cx); let mut items: Vec = vec![]; items.extend(self.extern_crates.iter().map(|x| x.clean(cx))); @@ -621,19 +593,17 @@ impl Clean for doctree::Module { items.extend(self.impls.iter().flat_map(|x| x.clean(cx))); items.extend(self.macros.iter().map(|x| x.clean(cx))); - cx.mod_ids.borrow_mut().pop(); - // determine if we should display the inner contents or // the outer `mod` item for the source code. let whence = { - let cm = cx.sess().codemap(); + let cm = cx.sess().source_map(); let outer = cm.lookup_char_pos(self.where_outer.lo()); let inner = cm.lookup_char_pos(self.where_inner.lo()); if outer.file.start_pos == inner.file.start_pos { // mod foo { ... } self.where_outer } else { - // mod foo; (and a separate FileMap for the contents) + // mod foo; (and a separate SourceFile for the contents) self.where_inner } }; @@ -782,6 +752,7 @@ pub struct Attributes { pub span: Option, /// map from Rust paths to resolved defs and potential URL fragments pub links: Vec<(String, Option, Option)>, + pub inner_docs: bool, } impl Attributes { @@ -926,12 +897,18 @@ impl Attributes { } } + let inner_docs = attrs.iter() + .filter(|a| a.check_name("doc")) + .next() + .map_or(true, |a| a.style == AttrStyle::Inner); + Attributes { doc_strings, other_attrs, cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }, span: sp, links: vec![], + inner_docs, } } @@ -1024,483 +1001,9 @@ impl AttributesExt for Attributes { } } -/// Given a def, returns its name and disambiguator -/// for a value namespace -/// -/// Returns None for things which cannot be ambiguous since -/// they exist in both namespaces (structs and modules) -fn value_ns_kind(def: Def, path_str: &str) -> Option<(&'static str, String)> { - match def { - // structs, variants, and mods exist in both namespaces. skip them - Def::StructCtor(..) | Def::Mod(..) | Def::Variant(..) | Def::VariantCtor(..) => None, - Def::Fn(..) - => Some(("function", format!("{}()", path_str))), - Def::Method(..) - => Some(("method", format!("{}()", path_str))), - Def::Const(..) - => Some(("const", format!("const@{}", path_str))), - Def::Static(..) - => Some(("static", format!("static@{}", path_str))), - _ => Some(("value", format!("value@{}", path_str))), - } -} - -/// Given a def, returns its name, the article to be used, and a disambiguator -/// for the type namespace -fn type_ns_kind(def: Def, path_str: &str) -> (&'static str, &'static str, String) { - let (kind, article) = match def { - // we can still have non-tuple structs - Def::Struct(..) => ("struct", "a"), - Def::Enum(..) => ("enum", "an"), - Def::Trait(..) => ("trait", "a"), - Def::Union(..) => ("union", "a"), - _ => ("type", "a"), - }; - (kind, article, format!("{}@{}", kind, path_str)) -} - -fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span { - if attrs.doc_strings.is_empty() { - return DUMMY_SP; - } - let start = attrs.doc_strings[0].span(); - let end = attrs.doc_strings.last().unwrap().span(); - start.to(end) -} - -fn ambiguity_error(cx: &DocContext, attrs: &Attributes, - path_str: &str, - article1: &str, kind1: &str, disambig1: &str, - article2: &str, kind2: &str, disambig2: &str) { - let sp = span_of_attrs(attrs); - cx.sess() - .struct_span_warn(sp, - &format!("`{}` is both {} {} and {} {}", - path_str, article1, kind1, - article2, kind2)) - .help(&format!("try `{}` if you want to select the {}, \ - or `{}` if you want to \ - select the {}", - disambig1, kind1, disambig2, - kind2)) - .emit(); -} - -/// Given an enum variant's def, return the def of its enum and the associated fragment -fn handle_variant(cx: &DocContext, def: Def) -> Result<(Def, Option), ()> { - use rustc::ty::DefIdTree; - - let parent = if let Some(parent) = cx.tcx.parent(def.def_id()) { - parent - } else { - return Err(()) - }; - let parent_def = Def::Enum(parent); - let variant = cx.tcx.expect_variant_def(def); - Ok((parent_def, Some(format!("{}.v", variant.name)))) -} - -const PRIMITIVES: &[(&str, Def)] = &[ - ("u8", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U8))), - ("u16", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U16))), - ("u32", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U32))), - ("u64", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U64))), - ("u128", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U128))), - ("usize", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::Usize))), - ("i8", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I8))), - ("i16", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I16))), - ("i32", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I32))), - ("i64", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I64))), - ("i128", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I128))), - ("isize", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::Isize))), - ("f32", Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F32))), - ("f64", Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F64))), - ("str", Def::PrimTy(hir::PrimTy::TyStr)), - ("bool", Def::PrimTy(hir::PrimTy::TyBool)), - ("char", Def::PrimTy(hir::PrimTy::TyChar)), -]; - -fn is_primitive(path_str: &str, is_val: bool) -> Option { - if is_val { - None - } else { - PRIMITIVES.iter().find(|x| x.0 == path_str).map(|x| x.1) - } -} - -/// Resolve a given string as a path, along with whether or not it is -/// in the value namespace. Also returns an optional URL fragment in the case -/// of variants and methods -fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option), ()> { - // In case we're in a module, try to resolve the relative - // path - if let Some(id) = cx.mod_ids.borrow().last() { - let result = cx.resolver.borrow_mut() - .with_scope(*id, - |resolver| { - resolver.resolve_str_path_error(DUMMY_SP, - &path_str, is_val) - }); - - if let Ok(result) = result { - // In case this is a trait item, skip the - // early return and try looking for the trait - let value = match result.def { - Def::Method(_) | Def::AssociatedConst(_) => true, - Def::AssociatedTy(_) => false, - Def::Variant(_) => return handle_variant(cx, result.def), - // not a trait item, just return what we found - _ => return Ok((result.def, None)) - }; - - if value != is_val { - return Err(()) - } - } else if let Some(prim) = is_primitive(path_str, is_val) { - return Ok((prim, Some(path_str.to_owned()))) - } else { - // If resolution failed, it may still be a method - // because methods are not handled by the resolver - // If so, bail when we're not looking for a value - if !is_val { - return Err(()) - } - } - - // Try looking for methods and associated items - let mut split = path_str.rsplitn(2, "::"); - let item_name = if let Some(first) = split.next() { - first - } else { - return Err(()) - }; - - let mut path = if let Some(second) = split.next() { - second.to_owned() - } else { - return Err(()) - }; - - if path == "self" || path == "Self" { - if let Some(name) = *cx.current_item_name.borrow() { - path = name.to_string(); - } - } - - let ty = cx.resolver.borrow_mut() - .with_scope(*id, - |resolver| { - resolver.resolve_str_path_error(DUMMY_SP, &path, false) - })?; - match ty.def { - Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => { - let item = cx.tcx.inherent_impls(did).iter() - .flat_map(|imp| cx.tcx.associated_items(*imp)) - .find(|item| item.ident.name == item_name); - if let Some(item) = item { - let out = match item.kind { - ty::AssociatedKind::Method if is_val => "method", - ty::AssociatedKind::Const if is_val => "associatedconstant", - _ => return Err(()) - }; - Ok((ty.def, Some(format!("{}.{}", out, item_name)))) - } else { - let is_enum = match ty.def { - Def::Enum(_) => true, - _ => false, - }; - let elem = if is_enum { - cx.tcx.adt_def(did).all_fields().find(|item| item.ident.name == item_name) - } else { - cx.tcx.adt_def(did) - .non_enum_variant() - .fields - .iter() - .find(|item| item.ident.name == item_name) - }; - if let Some(item) = elem { - Ok((ty.def, - Some(format!("{}.{}", - if is_enum { "variant" } else { "structfield" }, - item.ident)))) - } else { - Err(()) - } - } - } - Def::Trait(did) => { - let item = cx.tcx.associated_item_def_ids(did).iter() - .map(|item| cx.tcx.associated_item(*item)) - .find(|item| item.ident.name == item_name); - if let Some(item) = item { - let kind = match item.kind { - ty::AssociatedKind::Const if is_val => "associatedconstant", - ty::AssociatedKind::Type if !is_val => "associatedtype", - ty::AssociatedKind::Method if is_val => { - if item.defaultness.has_value() { - "method" - } else { - "tymethod" - } - } - _ => return Err(()) - }; - - Ok((ty.def, Some(format!("{}.{}", kind, item_name)))) - } else { - Err(()) - } - } - _ => Err(()) - } - } else { - Err(()) - } -} - -/// Resolve a string as a macro -fn macro_resolve(cx: &DocContext, path_str: &str) -> Option { - use syntax::ext::base::{MacroKind, SyntaxExtension}; - use syntax::ext::hygiene::Mark; - let segment = ast::PathSegment::from_ident(Ident::from_str(path_str)); - let path = ast::Path { segments: vec![segment], span: DUMMY_SP }; - let mut resolver = cx.resolver.borrow_mut(); - let mark = Mark::root(); - let res = resolver - .resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false); - if let Ok(def) = res { - if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) { - return Some(def); - } - } - if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) { - return Some(*def); - } - None -} - -#[derive(Debug)] -enum PathKind { - /// can be either value or type, not a macro - Unknown, - /// macro - Macro, - /// values, functions, consts, statics, everything in the value namespace - Value, - /// types, traits, everything in the type namespace - Type, -} - -fn resolution_failure( - cx: &DocContext, - attrs: &Attributes, - path_str: &str, - dox: &str, - link_range: Option>, -) { - let sp = span_of_attrs(attrs); - let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str); - - let code_dox = sp.to_src(cx); - - let doc_comment_padding = 3; - let mut diag = if let Some(link_range) = link_range { - // blah blah blah\nblah\nblah [blah] blah blah\nblah blah - // ^ ~~~~~~ - // | link_range - // last_new_line_offset - - let mut diag; - if dox.lines().count() == code_dox.lines().count() { - let line_offset = dox[..link_range.start].lines().count(); - // The span starts in the `///`, so we don't have to account for the leading whitespace - let code_dox_len = if line_offset <= 1 { - doc_comment_padding - } else { - // The first `///` - doc_comment_padding + - // Each subsequent leading whitespace and `///` - code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| { - sum + doc_comment_padding + line.len() - line.trim().len() - }) - }; - - // Extract the specific span - let sp = sp.from_inner_byte_pos( - link_range.start + code_dox_len, - link_range.end + code_dox_len, - ); - - diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - NodeId::new(0), - sp, - &msg); - diag.span_label(sp, "cannot be resolved, ignoring"); - } else { - diag = cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - NodeId::new(0), - sp, - &msg); - - let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1); - let line = dox[last_new_line_offset..].lines().next().unwrap_or(""); - - // Print the line containing the `link_range` and manually mark it with '^'s - diag.note(&format!( - "the link appears in this line:\n\n{line}\n\ - {indicator: for [ast::Attribute] { fn clean(&self, cx: &DocContext) -> Attributes { - let mut attrs = Attributes::from_ast(cx.sess().diagnostic(), self); - - if UnstableFeatures::from_environment().is_nightly_build() { - let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new); - for (ori_link, link_range) in markdown_links(&dox) { - // bail early for real links - if ori_link.contains('/') { - continue; - } - let link = ori_link.replace("`", ""); - let (def, fragment) = { - let mut kind = PathKind::Unknown; - let path_str = if let Some(prefix) = - ["struct@", "enum@", "type@", - "trait@", "union@"].iter() - .find(|p| link.starts_with(**p)) { - kind = PathKind::Type; - link.trim_left_matches(prefix) - } else if let Some(prefix) = - ["const@", "static@", - "value@", "function@", "mod@", - "fn@", "module@", "method@"] - .iter().find(|p| link.starts_with(**p)) { - kind = PathKind::Value; - link.trim_left_matches(prefix) - } else if link.ends_with("()") { - kind = PathKind::Value; - link.trim_right_matches("()") - } else if link.starts_with("macro@") { - kind = PathKind::Macro; - link.trim_left_matches("macro@") - } else if link.ends_with('!') { - kind = PathKind::Macro; - link.trim_right_matches('!') - } else { - &link[..] - }.trim(); - - if path_str.contains(|ch: char| !(ch.is_alphanumeric() || - ch == ':' || ch == '_')) { - continue; - } - - match kind { - PathKind::Value => { - if let Ok(def) = resolve(cx, path_str, true) { - def - } else { - resolution_failure(cx, &attrs, path_str, &dox, link_range); - // this could just be a normal link or a broken link - // we could potentially check if something is - // "intra-doc-link-like" and warn in that case - continue; - } - } - PathKind::Type => { - if let Ok(def) = resolve(cx, path_str, false) { - def - } else { - resolution_failure(cx, &attrs, path_str, &dox, link_range); - // this could just be a normal link - continue; - } - } - PathKind::Unknown => { - // try everything! - if let Some(macro_def) = macro_resolve(cx, path_str) { - if let Ok(type_def) = resolve(cx, path_str, false) { - let (type_kind, article, type_disambig) - = type_ns_kind(type_def.0, path_str); - ambiguity_error(cx, &attrs, path_str, - article, type_kind, &type_disambig, - "a", "macro", &format!("macro@{}", path_str)); - continue; - } else if let Ok(value_def) = resolve(cx, path_str, true) { - let (value_kind, value_disambig) - = value_ns_kind(value_def.0, path_str) - .expect("struct and mod cases should have been \ - caught in previous branch"); - ambiguity_error(cx, &attrs, path_str, - "a", value_kind, &value_disambig, - "a", "macro", &format!("macro@{}", path_str)); - } - (macro_def, None) - } else if let Ok(type_def) = resolve(cx, path_str, false) { - // It is imperative we search for not-a-value first - // Otherwise we will find struct ctors for when we are looking - // for structs, and the link won't work. - // if there is something in both namespaces - if let Ok(value_def) = resolve(cx, path_str, true) { - let kind = value_ns_kind(value_def.0, path_str); - if let Some((value_kind, value_disambig)) = kind { - let (type_kind, article, type_disambig) - = type_ns_kind(type_def.0, path_str); - ambiguity_error(cx, &attrs, path_str, - article, type_kind, &type_disambig, - "a", value_kind, &value_disambig); - continue; - } - } - type_def - } else if let Ok(value_def) = resolve(cx, path_str, true) { - value_def - } else { - resolution_failure(cx, &attrs, path_str, &dox, link_range); - // this could just be a normal link - continue; - } - } - PathKind::Macro => { - if let Some(def) = macro_resolve(cx, path_str) { - (def, None) - } else { - resolution_failure(cx, &attrs, path_str, &dox, link_range); - continue - } - } - } - }; - - if let Def::PrimTy(_) = def { - attrs.links.push((ori_link, None, fragment)); - } else { - let id = register_def(cx, def); - attrs.links.push((ori_link, Some(id), fragment)); - } - } - - cx.sess().abort_if_errors(); - } - - attrs + Attributes::from_ast(cx.sess().diagnostic(), self) } } @@ -1574,7 +1077,7 @@ fn external_generic_args(cx: &DocContext, trait_did: Option, has_self: bo Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => { assert_eq!(types.len(), 1); let inputs = match types[0].sty { - ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), + ty::Tuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), _ => { return GenericArgs::AngleBracketed { lifetimes, @@ -1586,7 +1089,7 @@ fn external_generic_args(cx: &DocContext, trait_did: Option, has_self: bo let output = None; // FIXME(#20299) return type comes from a projection now // match types[1].sty { - // ty::TyTuple(ref v) if v.is_empty() => None, // -> () + // ty::Tuple(ref v) if v.is_empty() => None, // -> () // _ => Some(types[1].clean(cx)) // }; GenericArgs::Parenthesized { @@ -1630,9 +1133,9 @@ impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec // collect any late bound regions let mut late_bounds = vec![]; for ty_s in trait_ref.input_types().skip(1) { - if let ty::TyTuple(ts) = ty_s.sty { + if let ty::Tuple(ts) = ty_s.sty { for &ty_s in ts { - if let ty::TyRef(ref reg, _, _) = ty_s.sty { + if let ty::Ref(ref reg, _, _) = ty_s.sty { if let &ty::RegionKind::ReLateBound(..) = *reg { debug!(" hit an ReLateBound {:?}", reg); if let Some(Lifetime(name)) = reg.clean(cx) { @@ -1724,7 +1227,7 @@ impl Clean for hir::GenericParam { hir::GenericBound::Outlives(lt) => lt, _ => panic!(), }); - let name = bounds.next().unwrap().name.ident(); + let name = bounds.next().expect("no more bounds").name.ident(); let mut s = format!("{}: {}", self.name.ident(), name); for bound in bounds { s.push_str(&format!(" + {}", bound.name.ident())); @@ -1809,7 +1312,13 @@ impl<'a> Clean for ty::Predicate<'a> { Predicate::RegionOutlives(ref pred) => pred.clean(cx), Predicate::TypeOutlives(ref pred) => pred.clean(cx), Predicate::Projection(ref pred) => pred.clean(cx), - Predicate::WellFormed(_) => panic!("not user writable"), + Predicate::WellFormed(ty) => { + // This comes from `where Ty:` (i.e. no bounds) (see #53696). + WherePredicate::BoundPredicate { + ty: ty.clean(cx), + bounds: vec![], + } + } Predicate::ObjectSafe(_) => panic!("not user writable"), Predicate::ClosureKind(..) => panic!("not user writable"), Predicate::ConstEvaluatable(..) => panic!("not user writable"), @@ -1837,8 +1346,8 @@ impl<'tcx> Clean for ty::OutlivesPredicate, ty: fn clean(&self, cx: &DocContext) -> WherePredicate { let ty::OutlivesPredicate(ref a, ref b) = *self; WherePredicate::RegionPredicate { - lifetime: a.clean(cx).unwrap(), - bounds: vec![GenericBound::Outlives(b.clean(cx).unwrap())] + lifetime: a.clean(cx).expect("failed to clean lifetime"), + bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))] } } } @@ -1849,7 +1358,7 @@ impl<'tcx> Clean for ty::OutlivesPredicate, ty::Region< WherePredicate::BoundPredicate { ty: ty.clean(cx), - bounds: vec![GenericBound::Outlives(lt.clean(cx).unwrap())] + bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))] } } } @@ -1943,7 +1452,7 @@ impl Clean for hir::GenericParam { hir::GenericBound::Outlives(lt) => lt, _ => panic!(), }); - let name = bounds.next().unwrap().name.ident(); + let name = bounds.next().expect("no more bounds").name.ident(); let mut s = format!("{}: {}", self.name.ident(), name); for bound in bounds { s.push_str(&format!(" + {}", bound.name.ident())); @@ -2158,7 +1667,6 @@ impl Clean for doctree::Function { (self.generics.clean(cx), (&self.decl, self.body).clean(cx)) }); - *cx.current_item_name.borrow_mut() = Some(self.name); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -2258,7 +1766,7 @@ impl<'a, 'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { values: sig.skip_binder().inputs().iter().map(|t| { Argument { type_: t.clean(cx), - name: names.next().map_or("".to_string(), |name| name.to_string()), + name: names.next().map_or(String::new(), |name| name.to_string()), } }).collect(), }, @@ -2333,7 +1841,6 @@ pub struct Trait { impl Clean for doctree::Trait { fn clean(&self, cx: &DocContext) -> Item { - *cx.current_item_name.borrow_mut() = Some(self.name); let attrs = self.attrs.clean(cx); let is_spotlight = attrs.has_doc_flag("spotlight"); Item { @@ -2405,7 +1912,6 @@ impl Clean for hir::TraitItem { AssociatedTypeItem(bounds.clean(cx), default.clean(cx)) } }; - *cx.current_item_name.borrow_mut() = Some(self.ident.name); Item { name: Some(self.ident.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -2438,7 +1944,6 @@ impl Clean for hir::ImplItem { generics: Generics::default(), }, true), }; - *cx.current_item_name.borrow_mut() = Some(self.ident.name); Item { name: Some(self.ident.name.clean(cx)), source: self.span.clean(cx), @@ -2480,7 +1985,7 @@ impl<'tcx> Clean for ty::AssociatedItem { let self_arg_ty = *sig.input(0).skip_binder(); if self_arg_ty == self_ty { decl.inputs.values[0].type_ = Generic(String::from("Self")); - } else if let ty::TyRef(_, ty, _) = self_arg_ty.sty { + } else if let ty::Ref(_, ty, _) = self_arg_ty.sty { if ty == self_ty { match decl.inputs.values[0].type_ { BorrowedRef{ref mut type_, ..} => { @@ -2879,6 +2384,7 @@ impl From for PrimitiveType { impl Clean for hir::Ty { fn clean(&self, cx: &DocContext) -> Type { use rustc::hir::*; + match self.node { TyKind::Never => Never, TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)), @@ -2916,6 +2422,14 @@ impl Clean for hir::Ty { if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) { return ImplTrait(bounds); } + } else if let Def::Existential(did) = path.def { + // This block is for returned impl trait only. + if let Some(node_id) = cx.tcx.hir.as_local_node_id(did) { + let item = cx.tcx.hir.expect_item(node_id); + if let hir::ItemKind::Existential(ref ty) = item.node { + return ImplTrait(ty.bounds.clean(cx)); + } + } } let mut alias = None; @@ -2929,14 +2443,11 @@ impl Clean for hir::Ty { }; if let Some(&hir::ItemKind::Ty(ref ty, ref generics)) = alias { - let provided_params = &path.segments.last().unwrap(); + let provided_params = &path.segments.last().expect("segments were empty"); let mut ty_substs = FxHashMap(); let mut lt_substs = FxHashMap(); provided_params.with_generic_args(|generic_args| { - let mut indices = ty::GenericParamCount { - lifetimes: 0, - types: 0 - }; + let mut indices: GenericParamCount = Default::default(); for param in generics.params.iter() { match param.kind { hir::GenericParamKind::Lifetime { .. } => { @@ -3002,7 +2513,7 @@ impl Clean for hir::Ty { segments: segments.into(), }; Type::QPath { - name: p.segments.last().unwrap().ident.name.clean(cx), + name: p.segments.last().expect("segments were empty").ident.name.clean(cx), self_type: box qself.clean(cx), trait_: box resolve_type(cx, trait_path.clean(cx), self.id) } @@ -3010,7 +2521,7 @@ impl Clean for hir::Ty { TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { let mut def = Def::Err; let ty = hir_ty_to_ty(cx.tcx, self); - if let ty::TyProjection(proj) = ty.sty { + if let ty::Projection(proj) = ty.sty { def = Def::Trait(proj.trait_ref(cx.tcx).def_id); } let trait_path = hir::Path { @@ -3049,16 +2560,16 @@ impl Clean for hir::Ty { impl<'tcx> Clean for Ty<'tcx> { fn clean(&self, cx: &DocContext) -> Type { match self.sty { - ty::TyNever => Never, - ty::TyBool => Primitive(PrimitiveType::Bool), - ty::TyChar => Primitive(PrimitiveType::Char), - ty::TyInt(int_ty) => Primitive(int_ty.into()), - ty::TyUint(uint_ty) => Primitive(uint_ty.into()), - ty::TyFloat(float_ty) => Primitive(float_ty.into()), - ty::TyStr => Primitive(PrimitiveType::Str), - ty::TySlice(ty) => Slice(box ty.clean(cx)), - ty::TyArray(ty, n) => { - let mut n = cx.tcx.lift(&n).unwrap(); + ty::Never => Never, + ty::Bool => Primitive(PrimitiveType::Bool), + ty::Char => Primitive(PrimitiveType::Char), + ty::Int(int_ty) => Primitive(int_ty.into()), + ty::Uint(uint_ty) => Primitive(uint_ty.into()), + ty::Float(float_ty) => Primitive(float_ty.into()), + ty::Str => Primitive(PrimitiveType::Str), + ty::Slice(ty) => Slice(box ty.clean(cx)), + ty::Array(ty, n) => { + let mut n = cx.tcx.lift(&n).expect("array lift failed"); if let ConstValue::Unevaluated(def_id, substs) = n.val { let param_env = cx.tcx.param_env(def_id); let cid = GlobalId { @@ -3072,15 +2583,15 @@ impl<'tcx> Clean for Ty<'tcx> { let n = print_const(cx, n); Array(box ty.clean(cx), n) } - ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)), - ty::TyRef(r, ty, mutbl) => BorrowedRef { + ty::RawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)), + ty::Ref(r, ty, mutbl) => BorrowedRef { lifetime: r.clean(cx), mutability: mutbl.clean(cx), type_: box ty.clean(cx), }, - ty::TyFnDef(..) | - ty::TyFnPtr(_) => { - let ty = cx.tcx.lift(self).unwrap(); + ty::FnDef(..) | + ty::FnPtr(_) => { + let ty = cx.tcx.lift(self).expect("FnPtr lift failed"); let sig = ty.fn_sig(cx.tcx); BareFunction(box BareFunctionDecl { unsafety: sig.unsafety(), @@ -3089,7 +2600,7 @@ impl<'tcx> Clean for Ty<'tcx> { abi: sig.abi(), }) } - ty::TyAdt(def, substs) => { + ty::Adt(def, substs) => { let did = def.did; let kind = match def.adt_kind() { AdtKind::Struct => TypeKind::Struct, @@ -3106,7 +2617,7 @@ impl<'tcx> Clean for Ty<'tcx> { is_generic: false, } } - ty::TyForeign(did) => { + ty::Foreign(did) => { inline::record_extern_fqn(cx, did, TypeKind::Foreign); let path = external_path(cx, &cx.tcx.item_name(did).as_str(), None, false, vec![], Substs::empty()); @@ -3117,7 +2628,7 @@ impl<'tcx> Clean for Ty<'tcx> { is_generic: false, } } - ty::TyDynamic(ref obj, ref reg) => { + ty::Dynamic(ref obj, ref reg) => { if let Some(principal) = obj.principal() { let did = principal.def_id(); inline::record_extern_fqn(cx, did, TypeKind::Trait); @@ -3161,17 +2672,17 @@ impl<'tcx> Clean for Ty<'tcx> { Never } } - ty::TyTuple(ref t) => Tuple(t.clean(cx)), + ty::Tuple(ref t) => Tuple(t.clean(cx)), - ty::TyProjection(ref data) => data.clean(cx), + ty::Projection(ref data) => data.clean(cx), - ty::TyParam(ref p) => Generic(p.name.to_string()), + ty::Param(ref p) => Generic(p.name.to_string()), - ty::TyAnon(def_id, substs) => { + ty::Opaque(def_id, substs) => { // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. let predicates_of = cx.tcx.predicates_of(def_id); - let substs = cx.tcx.lift(&substs).unwrap(); + let substs = cx.tcx.lift(&substs).expect("Opaque lift failed"); let bounds = predicates_of.instantiate(cx.tcx, substs); let mut regions = vec![]; let mut has_sized = false; @@ -3221,18 +2732,17 @@ impl<'tcx> Clean for Ty<'tcx> { ImplTrait(bounds) } - ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton) + ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton) - ty::TyGeneratorWitness(..) => panic!("TyGeneratorWitness"), - ty::TyInfer(..) => panic!("TyInfer"), - ty::TyError => panic!("TyError"), + ty::GeneratorWitness(..) => panic!("GeneratorWitness"), + ty::Infer(..) => panic!("Infer"), + ty::Error => panic!("Error"), } } } impl Clean for hir::StructField { fn clean(&self, cx: &DocContext) -> Item { - *cx.current_item_name.borrow_mut() = Some(self.ident.name); Item { name: Some(self.ident.name).clean(cx), attrs: self.attrs.clean(cx), @@ -3310,8 +2820,8 @@ impl Clean> for doctree::Struct { fn clean(&self, cx: &DocContext) -> Vec { let name = self.name.clean(cx); let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); + ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - *cx.current_item_name.borrow_mut() = Some(self.name); ret.push(Item { name: Some(name), attrs: self.attrs.clean(cx), @@ -3336,8 +2846,8 @@ impl Clean> for doctree::Union { fn clean(&self, cx: &DocContext) -> Vec { let name = self.name.clean(cx); let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); + ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - *cx.current_item_name.borrow_mut() = Some(self.name); ret.push(Item { name: Some(name), attrs: self.attrs.clean(cx), @@ -3389,8 +2899,8 @@ impl Clean> for doctree::Enum { fn clean(&self, cx: &DocContext) -> Vec { let name = self.name.clean(cx); let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone()); + ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone())); - *cx.current_item_name.borrow_mut() = Some(self.name); ret.push(Item { name: Some(name), attrs: self.attrs.clean(cx), @@ -3417,7 +2927,6 @@ pub struct Variant { impl Clean for doctree::Variant { fn clean(&self, cx: &DocContext) -> Item { - *cx.current_item_name.borrow_mut() = Some(self.name); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -3518,7 +3027,7 @@ impl Clean for syntax_pos::Span { return Span::empty(); } - let cm = cx.sess().codemap(); + let cm = cx.sess().source_map(); let filename = cm.span_to_filename(*self); let lo = cm.lookup_char_pos(self.lo()); let hi = cm.lookup_char_pos(self.hi()); @@ -3541,7 +3050,7 @@ pub struct Path { impl Path { pub fn last_name(&self) -> &str { - self.segments.last().unwrap().name.as_str() + self.segments.last().expect("segments were empty").name.as_str() } } @@ -3698,7 +3207,6 @@ pub struct Typedef { impl Clean for doctree::Typedef { fn clean(&self, cx: &DocContext) -> Item { - *cx.current_item_name.borrow_mut() = Some(self.name); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -3774,7 +3282,6 @@ pub struct Static { impl Clean for doctree::Static { fn clean(&self, cx: &DocContext) -> Item { debug!("cleaning static {}: {:?}", self.name.clean(cx), self); - *cx.current_item_name.borrow_mut() = Some(self.name); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -3800,7 +3307,6 @@ pub struct Constant { impl Clean for doctree::Constant { fn clean(&self, cx: &DocContext) -> Item { - *cx.current_item_name.borrow_mut() = Some(self.name); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -3871,21 +3377,15 @@ pub fn get_auto_traits_with_def_id(cx: &DocContext, id: DefId) -> Vec { finder.get_with_def_id(id) } -fn get_name_if_possible(cx: &DocContext, node: NodeId) -> Option { - match cx.tcx.hir.get(node) { - Node::NodeItem(_) | - Node::NodeForeignItem(_) | - Node::NodeImplItem(_) | - Node::NodeTraitItem(_) | - Node::NodeVariant(_) | - Node::NodeField(_) | - Node::NodeLifetime(_) | - Node::NodeGenericParam(_) | - Node::NodeBinding(&hir::Pat { node: hir::PatKind::Binding(_,_,_,_), .. }) | - Node::NodeStructCtor(_) => {} - _ => return None, - } - Some(cx.tcx.hir.name(node)) +pub fn get_blanket_impls_with_node_id(cx: &DocContext, id: ast::NodeId, name: String) -> Vec { + let finder = BlanketImplFinder::new(cx); + finder.get_with_node_id(id, name) +} + +pub fn get_blanket_impls_with_def_id(cx: &DocContext, id: DefId) -> Vec { + let finder = BlanketImplFinder::new(cx); + + finder.get_with_def_id(id) } impl Clean> for doctree::Impl { @@ -3907,7 +3407,6 @@ impl Clean> for doctree::Impl { .collect() }).unwrap_or(FxHashSet()); - *cx.current_item_name.borrow_mut() = get_name_if_possible(cx, self.for_.id); ret.push(Item { name: None, attrs: self.attrs.clean(cx), @@ -3995,7 +3494,6 @@ fn build_deref_target_impls(cx: &DocContext, impl Clean for doctree::ExternCrate { fn clean(&self, cx: &DocContext) -> Item { - *cx.current_item_name.borrow_mut() = Some(self.name); Item { name: None, attrs: self.attrs.clean(cx), @@ -4043,7 +3541,6 @@ impl Clean> for doctree::Import { Import::Simple(name.clean(cx), resolve_use_source(cx, path)) }; - *cx.current_item_name.borrow_mut() = Some(self.name); vec![Item { name: None, attrs: self.attrs.clean(cx), @@ -4105,7 +3602,7 @@ impl Clean for hir::ForeignItem { ForeignStaticItem(Static { type_: ty.clean(cx), mutability: if mutbl {Mutable} else {Immutable}, - expr: "".to_string(), + expr: String::new(), }) } hir::ForeignItemKind::Type => { @@ -4113,7 +3610,6 @@ impl Clean for hir::ForeignItem { } }; - *cx.current_item_name.borrow_mut() = Some(self.name); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -4129,16 +3625,16 @@ impl Clean for hir::ForeignItem { // Utilities -trait ToSource { +pub trait ToSource { fn to_src(&self, cx: &DocContext) -> String; } impl ToSource for syntax_pos::Span { fn to_src(&self, cx: &DocContext) -> String { debug!("converting span {:?} to snippet", self.clean(cx)); - let sn = match cx.sess().codemap().span_to_snippet(*self) { + let sn = match cx.sess().source_map().span_to_snippet(*self) { Ok(x) => x.to_string(), - Err(_) => "".to_string() + Err(_) => String::new() }; debug!("got snippet {}", sn); sn @@ -4192,7 +3688,7 @@ fn print_const(cx: &DocContext, n: &ty::Const) -> String { }, _ => { let mut s = String::new(); - ::rustc::mir::fmt_const_val(&mut s, n).unwrap(); + ::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed"); // array lengths are obviously usize if s.ends_with("usize") { let n = s.len() - "usize".len(); @@ -4219,12 +3715,12 @@ fn resolve_type(cx: &DocContext, let is_generic = match path.def { Def::PrimTy(p) => match p { - hir::TyStr => return Primitive(PrimitiveType::Str), - hir::TyBool => return Primitive(PrimitiveType::Bool), - hir::TyChar => return Primitive(PrimitiveType::Char), - hir::TyInt(int_ty) => return Primitive(int_ty.into()), - hir::TyUint(uint_ty) => return Primitive(uint_ty.into()), - hir::TyFloat(float_ty) => return Primitive(float_ty.into()), + hir::Str => return Primitive(PrimitiveType::Str), + hir::Bool => return Primitive(PrimitiveType::Bool), + hir::Char => return Primitive(PrimitiveType::Char), + hir::Int(int_ty) => return Primitive(int_ty.into()), + hir::Uint(uint_ty) => return Primitive(uint_ty.into()), + hir::Float(float_ty) => return Primitive(float_ty.into()), }, Def::SelfTy(..) if path.segments.len() == 1 => { return Generic(keywords::SelfType.name().to_string()); @@ -4239,7 +3735,7 @@ fn resolve_type(cx: &DocContext, ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic } } -fn register_def(cx: &DocContext, def: Def) -> DefId { +pub fn register_def(cx: &DocContext, def: Def) -> DefId { debug!("register_def({:?})", def); let (did, kind) = match def { @@ -4250,10 +3746,11 @@ fn register_def(cx: &DocContext, def: Def) -> DefId { Def::Struct(i) => (i, TypeKind::Struct), Def::Union(i) => (i, TypeKind::Union), Def::Mod(i) => (i, TypeKind::Module), - Def::TyForeign(i) => (i, TypeKind::Foreign), + Def::ForeignTy(i) => (i, TypeKind::Foreign), Def::Const(i) => (i, TypeKind::Const), Def::Static(i, _) => (i, TypeKind::Static), - Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum), + Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"), + TypeKind::Enum), Def::Macro(i, _) => (i, TypeKind::Macro), Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait), Def::SelfTy(_, Some(impl_def_id)) => { @@ -4289,7 +3786,6 @@ pub struct Macro { impl Clean for doctree::Macro { fn clean(&self, cx: &DocContext) -> Item { let name = self.name.clean(cx); - *cx.current_item_name.borrow_mut() = None; Item { name: Some(name.clone()), attrs: self.attrs.clean(cx), @@ -4334,19 +3830,19 @@ impl Clean for attr::Stability { feature: self.feature.to_string(), since: match self.level { attr::Stable {ref since} => since.to_string(), - _ => "".to_string(), + _ => String::new(), }, deprecated_since: match self.rustc_depr { Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(), - _=> "".to_string(), + _=> String::new(), }, deprecated_reason: match self.rustc_depr { Some(ref depr) => depr.reason.to_string(), - _ => "".to_string(), + _ => String::new(), }, unstable_reason: match self.level { attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(), - _ => "".to_string(), + _ => String::new(), }, issue: match self.level { attr::Unstable {issue, ..} => Some(issue), @@ -4365,8 +3861,8 @@ impl<'a> Clean for &'a attr::Stability { impl Clean for attr::Deprecation { fn clean(&self, _: &DocContext) -> Deprecation { Deprecation { - since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()), - note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()), + since: self.since.as_ref().map_or(String::new(), |s| s.to_string()), + note: self.note.as_ref().map_or(String::new(), |s| s.to_string()), } } } @@ -4482,7 +3978,7 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option { } } -fn get_path_for_type(tcx: TyCtxt, def_id: DefId, def_ctor: F) -> hir::Path +pub fn get_path_for_type(tcx: TyCtxt, def_id: DefId, def_ctor: F) -> hir::Path where F: Fn(DefId) -> Def { struct AbsolutePathBuffer { names: Vec, diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 30a55bf0d1..e938d2d0a1 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -34,7 +34,7 @@ use core::DocContext; pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { // First, partition the where clause into its separate components - let mut params = BTreeMap::new(); + let mut params: BTreeMap<_, Vec<_>> = BTreeMap::new(); let mut lifetimes = Vec::new(); let mut equalities = Vec::new(); let mut tybounds = Vec::new(); @@ -43,7 +43,7 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { match clause { WP::BoundPredicate { ty, bounds } => { match ty { - clean::Generic(s) => params.entry(s).or_insert(Vec::new()) + clean::Generic(s) => params.entry(s).or_default() .extend(bounds), t => tybounds.push((t, ty_bounds(bounds))), } @@ -96,7 +96,7 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { if !trait_is_same_or_supertrait(cx, did, trait_did) { return false } - let last = path.segments.last_mut().unwrap(); + let last = path.segments.last_mut().expect("segments were empty"); match last.args { PP::AngleBracketed { ref mut bindings, .. } => { bindings.push(clean::TypeBinding { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 769c9804a3..ee0c6ee005 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -11,8 +11,9 @@ use rustc_lint; use rustc_driver::{self, driver, target_features, abort_on_err}; use rustc::session::{self, config}; -use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; +use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CrateNum, LOCAL_CRATE}; use rustc::hir::def::Def; +use rustc::hir::{self, HirVec}; use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt, AllArenas}; @@ -25,11 +26,14 @@ use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::CStore; use rustc_target::spec::TargetTriple; -use syntax::ast::{Name, NodeId}; -use syntax::codemap; +use syntax::ast::{self, Ident}; +use syntax::source_map; use syntax::edition::Edition; use syntax::feature_gate::UnstableFeatures; use syntax::json::JsonEmitter; +use syntax::ptr::P; +use syntax::symbol::keywords; +use syntax_pos::DUMMY_SP; use errors; use errors::emitter::{Emitter, EmitterWriter}; @@ -41,21 +45,21 @@ use std::path::PathBuf; use visit_ast::RustdocVisitor; use clean; -use clean::Clean; +use clean::{get_path_for_type, Clean, MAX_DEF_ID, AttributesExt}; use html::render::RenderInfo; +use passes; -pub use rustc::session::config::{Input, CodegenOptions}; +pub use rustc::session::config::{Input, Options, CodegenOptions}; pub use rustc::session::search_paths::SearchPaths; pub type ExternalPaths = FxHashMap, clean::TypeKind)>; -pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { +pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub resolver: &'a RefCell>, + pub resolver: &'a RefCell>, /// The stack of module NodeIds up till this point - pub mod_ids: RefCell>, pub crate_name: Option, - pub cstore: Rc, + pub cstore: Rc, pub populated_all_crate_impls: Cell, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing @@ -83,11 +87,10 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { pub all_fake_def_ids: RefCell>, /// Maps (type_id, trait_id) -> auto trait impl pub generated_synthetics: RefCell>, - pub current_item_name: RefCell>, pub all_traits: Vec, } -impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> { +impl<'a, 'tcx, 'rcx, 'cstore> DocContext<'a, 'tcx, 'rcx, 'cstore> { pub fn sess(&self) -> &session::Session { &self.tcx.sess } @@ -107,6 +110,140 @@ impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> { *self.lt_substs.borrow_mut() = old_lts; r } + + // This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly + // refactoring either librustdoc or librustc. In particular, allowing new DefIds to be + // registered after the AST is constructed would require storing the defid mapping in a + // RefCell, decreasing the performance for normal compilation for very little gain. + // + // Instead, we construct 'fake' def ids, which start immediately after the last DefId in + // DefIndexAddressSpace::Low. In the Debug impl for clean::Item, we explicitly check for fake + // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds + pub fn next_def_id(&self, crate_num: CrateNum) -> DefId { + let start_def_id = { + let next_id = if crate_num == LOCAL_CRATE { + self.tcx + .hir + .definitions() + .def_path_table() + .next_id(DefIndexAddressSpace::Low) + } else { + self.cstore + .def_path_table(crate_num) + .next_id(DefIndexAddressSpace::Low) + }; + + DefId { + krate: crate_num, + index: next_id, + } + }; + + let mut fake_ids = self.fake_def_ids.borrow_mut(); + + let def_id = fake_ids.entry(crate_num).or_insert(start_def_id).clone(); + fake_ids.insert( + crate_num, + DefId { + krate: crate_num, + index: DefIndex::from_array_index( + def_id.index.as_array_index() + 1, + def_id.index.address_space(), + ), + }, + ); + + MAX_DEF_ID.with(|m| { + m.borrow_mut() + .entry(def_id.krate.clone()) + .or_insert(start_def_id); + }); + + self.all_fake_def_ids.borrow_mut().insert(def_id); + + def_id.clone() + } + + pub fn get_real_ty(&self, + def_id: DefId, + def_ctor: &F, + real_name: &Option, + generics: &ty::Generics, + ) -> hir::Ty + where F: Fn(DefId) -> Def { + let path = get_path_for_type(self.tcx, def_id, def_ctor); + let mut segments = path.segments.into_vec(); + let last = segments.pop().expect("segments were empty"); + + segments.push(hir::PathSegment::new( + real_name.unwrap_or(last.ident), + self.generics_to_path_params(generics.clone()), + false, + )); + + let new_path = hir::Path { + span: path.span, + def: path.def, + segments: HirVec::from_vec(segments), + }; + + hir::Ty { + id: ast::DUMMY_NODE_ID, + node: hir::TyKind::Path(hir::QPath::Resolved(None, P(new_path))), + span: DUMMY_SP, + hir_id: hir::DUMMY_HIR_ID, + } + } + + pub fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs { + let mut args = vec![]; + + for param in generics.params.iter() { + match param.kind { + ty::GenericParamDefKind::Lifetime => { + let name = if param.name == "" { + hir::ParamName::Plain(keywords::StaticLifetime.ident()) + } else { + hir::ParamName::Plain(ast::Ident::from_interned_str(param.name)) + }; + + args.push(hir::GenericArg::Lifetime(hir::Lifetime { + id: ast::DUMMY_NODE_ID, + span: DUMMY_SP, + name: hir::LifetimeName::Param(name), + })); + } + ty::GenericParamDefKind::Type {..} => { + args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone()))); + } + } + } + + hir::GenericArgs { + args: HirVec::from_vec(args), + bindings: HirVec::new(), + parenthesized: false, + } + } + + pub fn ty_param_to_ty(&self, param: ty::GenericParamDef) -> hir::Ty { + debug!("ty_param_to_ty({:?}) {:?}", param, param.def_id); + hir::Ty { + id: ast::DUMMY_NODE_ID, + node: hir::TyKind::Path(hir::QPath::Resolved( + None, + P(hir::Path { + span: DUMMY_SP, + def: Def::TyParam(param.def_id), + segments: HirVec::from_vec(vec![ + hir::PathSegment::from_ident(Ident::from_interned_str(param.name)) + ]), + }), + )), + span: DUMMY_SP, + hir_id: hir::DUMMY_HIR_ID, + } + } } pub trait DocAccessLevels { @@ -121,30 +258,30 @@ impl DocAccessLevels for AccessLevels { /// Creates a new diagnostic `Handler` that can be used to emit warnings and errors. /// -/// If the given `error_format` is `ErrorOutputType::Json` and no `CodeMap` is given, a new one +/// If the given `error_format` is `ErrorOutputType::Json` and no `SourceMap` is given, a new one /// will be created for the handler. -pub fn new_handler(error_format: ErrorOutputType, codemap: Option>) +pub fn new_handler(error_format: ErrorOutputType, source_map: Option>) -> errors::Handler { // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so // stick to the defaults - let sessopts = config::basic_options(); + let sessopts = Options::default(); let emitter: Box = match error_format { ErrorOutputType::HumanReadable(color_config) => Box::new( EmitterWriter::stderr( color_config, - codemap.map(|cm| cm as _), + source_map.map(|cm| cm as _), false, sessopts.debugging_opts.teach, ).ui_testing(sessopts.debugging_opts.ui_testing) ), ErrorOutputType::Json(pretty) => { - let codemap = codemap.unwrap_or_else( - || Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()))); + let source_map = source_map.unwrap_or_else( + || Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping()))); Box::new( JsonEmitter::stderr( None, - codemap, + source_map, pretty, ).ui_testing(sessopts.debugging_opts.ui_testing) ) @@ -152,7 +289,7 @@ pub fn new_handler(error_format: ErrorOutputType, codemap: Option Box::new( EmitterWriter::stderr( color_config, - codemap.map(|cm| cm as _), + source_map.map(|cm| cm as _), true, false) ), @@ -184,7 +321,10 @@ pub fn run_core(search_paths: SearchPaths, error_format: ErrorOutputType, cmd_lints: Vec<(String, lint::Level)>, lint_cap: Option, - describe_lints: bool) -> (clean::Crate, RenderInfo) + describe_lints: bool, + mut manual_passes: Vec, + mut default_passes: passes::DefaultPassOption) + -> (clean::Crate, RenderInfo, Vec) { // Parse, resolve, and typecheck the given crate. @@ -224,7 +364,7 @@ pub fn run_core(search_paths: SearchPaths, let sessopts = config::Options { maybe_sysroot, search_paths, - crate_types: vec![config::CrateTypeRlib], + crate_types: vec![config::CrateType::Rlib], lint_opts: if !allow_warnings { lints } else { @@ -244,14 +384,14 @@ pub fn run_core(search_paths: SearchPaths, error_format, edition, describe_lints, - ..config::basic_options() + ..Options::default() }; driver::spawn_thread_pool(sessopts, move |sessopts| { - let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())); - let diagnostic_handler = new_handler(error_format, Some(codemap.clone())); + let source_map = Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping())); + let diagnostic_handler = new_handler(error_format, Some(source_map.clone())); let mut sess = session::build_session_( - sessopts, cpath, diagnostic_handler, codemap, + sessopts, cpath, diagnostic_handler, source_map, ); lint::builtin::HardwiredLints.get_lints() @@ -303,12 +443,10 @@ pub fn run_core(search_paths: SearchPaths, |_| Ok(())); let driver::InnerExpansionResult { mut hir_forest, - mut resolver, + resolver, .. } = abort_on_err(result, &sess); - resolver.ignore_extern_prelude_feature = true; - // We need to hold on to the complete resolver, so we clone everything // for the analysis passes to use. Suboptimal, but necessary in the // current architecture. @@ -346,7 +484,7 @@ pub fn run_core(search_paths: SearchPaths, &name, &output_filenames, |tcx, analysis, _, result| { - if let Err(_) = result { + if result.is_err() { sess.fatal("Compilation failed, aborting rustdoc"); } @@ -379,23 +517,86 @@ pub fn run_core(search_paths: SearchPaths, ty_substs: Default::default(), lt_substs: Default::default(), impl_trait_bounds: Default::default(), - mod_ids: Default::default(), send_trait: send_trait, fake_def_ids: RefCell::new(FxHashMap()), all_fake_def_ids: RefCell::new(FxHashSet()), generated_synthetics: RefCell::new(FxHashSet()), - current_item_name: RefCell::new(None), all_traits: tcx.all_traits(LOCAL_CRATE).to_vec(), }; debug!("crate: {:?}", tcx.hir.krate()); - let krate = { + let mut krate = { let mut v = RustdocVisitor::new(&ctxt); v.visit(tcx.hir.krate()); v.clean(&ctxt) }; - (krate, ctxt.renderinfo.into_inner()) + fn report_deprecated_attr(name: &str, diag: &errors::Handler) { + let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \ + considered deprecated", name)); + msg.warn("please see https://github.com/rust-lang/rust/issues/44136"); + + if name == "no_default_passes" { + msg.help("you may want to use `#![doc(document_private_items)]`"); + } + + msg.emit(); + } + + // Process all of the crate attributes, extracting plugin metadata along + // with the passes which we are supposed to run. + for attr in krate.module.as_ref().unwrap().attrs.lists("doc") { + let diag = ctxt.sess().diagnostic(); + + let name = attr.name().map(|s| s.as_str()); + let name = name.as_ref().map(|s| &s[..]); + if attr.is_word() { + if name == Some("no_default_passes") { + report_deprecated_attr("no_default_passes", diag); + if default_passes == passes::DefaultPassOption::Default { + default_passes = passes::DefaultPassOption::None; + } + } + } else if let Some(value) = attr.value_str() { + let sink = match name { + Some("passes") => { + report_deprecated_attr("passes = \"...\"", diag); + &mut manual_passes + }, + Some("plugins") => { + report_deprecated_attr("plugins = \"...\"", diag); + eprintln!("WARNING: #![doc(plugins = \"...\")] no longer functions; \ + see CVE-2018-1000622"); + continue + }, + _ => continue, + }; + for p in value.as_str().split_whitespace() { + sink.push(p.to_string()); + } + } + + if attr.is_word() && name == Some("document_private_items") { + if default_passes == passes::DefaultPassOption::Default { + default_passes = passes::DefaultPassOption::Private; + } + } + } + + let mut passes: Vec = + passes::defaults(default_passes).iter().map(|p| p.to_string()).collect(); + passes.extend(manual_passes); + + for pass in &passes { + // the "unknown pass" error will be reported when late passes are run + if let Some(pass) = passes::find_pass(pass).and_then(|p| p.early_fn()) { + krate = pass(krate, &ctxt); + } + } + + ctxt.sess().abort_if_errors(); + + (krate, ctxt.renderinfo.into_inner(), passes) }), &sess) }) } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index d6e8f3d938..dd1e1e9995 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -16,7 +16,7 @@ use syntax::ast; use syntax::ast::{Name, NodeId}; use syntax::attr; use syntax::ptr::P; -use syntax::codemap::Spanned; +use syntax::source_map::Spanned; use syntax_pos::{self, Span}; use rustc::hir; diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 10b6c9850a..9631ea059c 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -12,7 +12,9 @@ use std::fs; use std::path::Path; use std::str; use errors; -use html::markdown::Markdown; +use syntax::feature_gate::UnstableFeatures; +use html::markdown::{IdMap, ErrorCodes, Markdown}; +use std::cell::RefCell; #[derive(Clone)] pub struct ExternalHtml { @@ -29,8 +31,10 @@ pub struct ExternalHtml { impl ExternalHtml { pub fn load(in_header: &[String], before_content: &[String], after_content: &[String], - md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler) + md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler, + id_map: &mut IdMap) -> Option { + let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); load_external_files(in_header, diag) .and_then(|ih| load_external_files(before_content, diag) @@ -38,7 +42,8 @@ impl ExternalHtml { ) .and_then(|(ih, bc)| load_external_files(md_before_content, diag) - .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[])))) + .map(|m_bc| (ih, + format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), codes)))) ) .and_then(|(ih, bc)| load_external_files(after_content, diag) @@ -46,7 +51,8 @@ impl ExternalHtml { ) .and_then(|(ih, bc, ac)| load_external_files(md_after_content, diag) - .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[])))) + .map(|m_ac| (ih, bc, + format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map), codes)))) ) .map(|(ih, bc, ac)| ExternalHtml { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 58034d1df5..7643aade83 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -620,7 +620,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: clean::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty} => { let lt = match *l { Some(ref l) => format!("{} ", *l), - _ => "".to_string(), + _ => String::new(), }; let m = MutableSpace(mutability); let amp = if f.alternate() { diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 065778d8d0..5df4862290 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -13,12 +13,7 @@ //! This module uses libsyntax's lexer to provide token-based highlighting for //! the HTML documentation generated by rustdoc. //! -//! If you just want to syntax highlighting for a Rust program, then you can use -//! the `render_inner_with_highlighting` or `render_with_highlighting` -//! functions. For more advanced use cases (if you want to supply your own css -//! classes or control how the HTML is generated, or even generate something -//! other then HTML), then you should implement the `Writer` trait and use a -//! `Classifier`. +//! Use the `render_with_highlighting` to highlight some rust code. use html::escape::Escape; @@ -26,19 +21,20 @@ use std::fmt::Display; use std::io; use std::io::prelude::*; -use syntax::codemap::{CodeMap, FilePathMapping}; +use syntax::source_map::{SourceMap, FilePathMapping}; use syntax::parse::lexer::{self, TokenAndSpan}; use syntax::parse::token; use syntax::parse; use syntax_pos::{Span, FileName}; /// Highlights `src`, returning the HTML output. -pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>, +pub fn render_with_highlighting(src: &str, class: Option<&str>, extension: Option<&str>, tooltip: Option<(&str, &str)>) -> String { debug!("highlighting: ================\n{}\n==============", src); let sess = parse::ParseSess::new(FilePathMapping::empty()); - let fm = sess.codemap().new_filemap(FileName::Custom("stdin".to_string()), src.to_string()); + let fm = sess.source_map().new_source_file(FileName::Custom("stdin".to_string()), + src.to_string()); let mut out = Vec::new(); if let Some((tooltip, class)) = tooltip { @@ -46,10 +42,11 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str> class='tooltiptext'>{}", class, tooltip).unwrap(); } - write_header(class, id, &mut out).unwrap(); + write_header(class, &mut out).unwrap(); - let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None), sess.codemap()); - if let Err(_) = classifier.write_source(&mut out) { + let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None), + sess.source_map()); + if classifier.write_source(&mut out).is_err() { return format!("

{}
", src); } @@ -63,9 +60,9 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str> /// Processes a program (nested in the internal `lexer`), classifying strings of /// text by highlighting category (`Class`). Calls out to a `Writer` to write /// each span of text in sequence. -pub struct Classifier<'a> { +struct Classifier<'a> { lexer: lexer::StringReader<'a>, - codemap: &'a CodeMap, + source_map: &'a SourceMap, // State of the classifier. in_attribute: bool, @@ -75,7 +72,7 @@ pub struct Classifier<'a> { /// How a span of text is classified. Mostly corresponds to token kinds. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Class { +enum Class { None, Comment, DocComment, @@ -103,7 +100,7 @@ pub enum Class { /// The classifier will call into the `Writer` implementation as it finds spans /// of text to highlight. Exactly how that text should be highlighted is up to /// the implementation. -pub trait Writer { +trait Writer { /// Called when we start processing a span of text that should be highlighted. /// The `Class` argument specifies how it should be highlighted. fn enter_span(&mut self, _: Class) -> io::Result<()>; @@ -111,11 +108,9 @@ pub trait Writer { /// Called at the end of a span of highlighted text. fn exit_span(&mut self) -> io::Result<()>; - /// Called for a span of text, usually, but not always, a single token. If - /// the string of text (`T`) does correspond to a token, then the token will - /// also be passed. If the text should be highlighted differently from the - /// surrounding text, then the `Class` argument will be a value other than - /// `None`. + /// Called for a span of text. If the text should be highlighted differently from the + /// surrounding text, then the `Class` argument will be a value other than `None`. + /// /// The following sequences of callbacks are equivalent: /// ```plain /// enter_span(Foo), string("text", None), exit_span() @@ -125,8 +120,7 @@ pub trait Writer { /// more flexible. fn string(&mut self, text: T, - klass: Class, - tok: Option<&TokenAndSpan>) + klass: Class) -> io::Result<()>; } @@ -135,8 +129,7 @@ pub trait Writer { impl Writer for U { fn string(&mut self, text: T, - klass: Class, - _tas: Option<&TokenAndSpan>) + klass: Class) -> io::Result<()> { match klass { Class::None => write!(self, "{}", text), @@ -154,10 +147,10 @@ impl Writer for U { } impl<'a> Classifier<'a> { - pub fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> { + fn new(lexer: lexer::StringReader<'a>, source_map: &'a SourceMap) -> Classifier<'a> { Classifier { lexer, - codemap, + source_map, in_attribute: false, in_macro: false, in_macro_nonterminal: false, @@ -186,7 +179,7 @@ impl<'a> Classifier<'a> { /// is used. All source code emission is done as slices from the source map, /// not from the tokens themselves, in order to stay true to the original /// source. - pub fn write_source(&mut self, + fn write_source(&mut self, out: &mut W) -> io::Result<()> { loop { @@ -208,7 +201,7 @@ impl<'a> Classifier<'a> { -> io::Result<()> { let klass = match tas.tok { token::Shebang(s) => { - out.string(Escape(&s.as_str()), Class::None, Some(&tas))?; + out.string(Escape(&s.as_str()), Class::None)?; return Ok(()); }, @@ -272,8 +265,8 @@ impl<'a> Classifier<'a> { self.in_attribute = true; out.enter_span(Class::Attribute)?; } - out.string("#", Class::None, None)?; - out.string("!", Class::None, None)?; + out.string("#", Class::None)?; + out.string("!", Class::None)?; return Ok(()); } @@ -282,13 +275,13 @@ impl<'a> Classifier<'a> { self.in_attribute = true; out.enter_span(Class::Attribute)?; } - out.string("#", Class::None, None)?; + out.string("#", Class::None)?; return Ok(()); } token::CloseDelim(token::Bracket) => { if self.in_attribute { self.in_attribute = false; - out.string("]", Class::None, None)?; + out.string("]", Class::None)?; out.exit_span()?; return Ok(()); } else { @@ -344,18 +337,18 @@ impl<'a> Classifier<'a> { // Anything that didn't return above is the simple case where we the // class just spans a single token, so we can use the `string` method. - out.string(Escape(&self.snip(tas.sp)), klass, Some(&tas)) + out.string(Escape(&self.snip(tas.sp)), klass) } - // Helper function to get a snippet from the codemap. + // Helper function to get a snippet from the source_map. fn snip(&self, sp: Span) -> String { - self.codemap.span_to_snippet(sp).unwrap() + self.source_map.span_to_snippet(sp).unwrap() } } impl Class { /// Returns the css class expected by rustdoc for each `Class`. - pub fn rustdoc_class(self) -> &'static str { + fn rustdoc_class(self) -> &'static str { match self { Class::None => "", Class::Comment => "comment", @@ -379,15 +372,8 @@ impl Class { } } -fn write_header(class: Option<&str>, - id: Option<&str>, - out: &mut dyn Write) - -> io::Result<()> { - write!(out, "
\n", class.unwrap_or(""))
+fn write_header(class: Option<&str>, out: &mut dyn Write) -> io::Result<()> {
+    write!(out, "
\n", class.unwrap_or(""))
 }
 
 fn write_footer(out: &mut dyn Write) -> io::Result<()> {
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index af7c0a0421..582f31ce7c 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -156,13 +156,13 @@ pub fn render(
                 root_path = page.root_path,
                 suffix=page.resource_suffix)
     } else {
-        "".to_owned()
+        String::new()
     },
     content   = *t,
     root_path = page.root_path,
     css_class = page.css_class,
     logo      = if layout.logo.is_empty() {
-        "".to_string()
+        String::new()
     } else {
         format!("\
                  logo",
@@ -173,7 +173,7 @@ pub fn render(
     description = page.description,
     keywords = page.keywords,
     favicon   = if layout.favicon.is_empty() {
-        "".to_string()
+        String::new()
     } else {
         format!(r#""#, layout.favicon)
     },
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 8d85adfb3d..18ad862c11 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -18,27 +18,26 @@
 //! ```
 //! #![feature(rustc_private)]
 //!
-//! use rustdoc::html::markdown::Markdown;
+//! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes};
+//! use std::cell::RefCell;
 //!
 //! let s = "My *markdown* _text_";
-//! let html = format!("{}", Markdown(s, &[]));
+//! let mut id_map = IdMap::new();
+//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map), ErrorCodes::Yes));
 //! // ... something using html
 //! ```
 
 #![allow(non_camel_case_types)]
 
-use rustc::session;
+use rustc_data_structures::fx::FxHashMap;
 use std::cell::RefCell;
-use std::collections::{HashMap, VecDeque};
+use std::collections::VecDeque;
 use std::default::Default;
 use std::fmt::{self, Write};
 use std::borrow::Cow;
 use std::ops::Range;
 use std::str;
-use syntax::feature_gate::UnstableFeatures;
-use syntax::codemap::Span;
 
-use html::render::derive_id;
 use html::toc::TocBuilder;
 use html::highlight;
 use test;
@@ -50,15 +49,38 @@ use pulldown_cmark::{Options, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES};
 /// formatted, this struct will emit the HTML corresponding to the rendered
 /// version of the contained markdown string.
 /// The second parameter is a list of link replacements
-pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)]);
+pub struct Markdown<'a>(
+    pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders the markdown with a
 /// table of contents.
-pub struct MarkdownWithToc<'a>(pub &'a str);
+pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
-pub struct MarkdownHtml<'a>(pub &'a str);
+pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders only the first paragraph.
 pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
 
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum ErrorCodes {
+    Yes,
+    No,
+}
+
+impl ErrorCodes {
+    pub fn from(b: bool) -> Self {
+        match b {
+            true => ErrorCodes::Yes,
+            false => ErrorCodes::No,
+        }
+    }
+
+    pub fn as_bool(self) -> bool {
+        match self {
+            ErrorCodes::Yes => true,
+            ErrorCodes::No => false,
+        }
+    }
+}
+
 /// Controls whether a line will be hidden or shown in HTML output.
 ///
 /// All lines are used in documentation tests.
@@ -129,12 +151,14 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> =
 /// Adds syntax highlighting and playground Run buttons to rust code blocks.
 struct CodeBlocks<'a, I: Iterator>> {
     inner: I,
+    check_error_codes: ErrorCodes,
 }
 
 impl<'a, I: Iterator>> CodeBlocks<'a, I> {
-    fn new(iter: I) -> Self {
+    fn new(iter: I, error_codes: ErrorCodes) -> Self {
         CodeBlocks {
             inner: iter,
+            check_error_codes: error_codes,
         }
     }
 }
@@ -147,7 +171,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> {
         let compile_fail;
         let ignore;
         if let Some(Event::Start(Tag::CodeBlock(lang))) = event {
-            let parse_result = LangString::parse(&lang);
+            let parse_result = LangString::parse(&lang, self.check_error_codes);
             if !parse_result.rust {
                 return Some(Event::Start(Tag::CodeBlock(lang)));
             }
@@ -224,7 +248,6 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> {
                                       if ignore { " ignore" }
                                       else if compile_fail { " compile_fail" }
                                       else { "" })),
-                        None,
                         playground_button.as_ref().map(String::as_str),
                         tooltip));
             Some(Event::Html(s.into()))
@@ -266,23 +289,25 @@ impl<'a, 'b, I: Iterator>> Iterator for LinkReplacer<'a, 'b, I>
 }
 
 /// Make headings links with anchor ids and build up TOC.
-struct HeadingLinks<'a, 'b, I: Iterator>> {
+struct HeadingLinks<'a, 'b, 'ids, I: Iterator>> {
     inner: I,
     toc: Option<&'b mut TocBuilder>,
     buf: VecDeque>,
+    id_map: &'ids mut IdMap,
 }
 
-impl<'a, 'b, I: Iterator>> HeadingLinks<'a, 'b, I> {
-    fn new(iter: I, toc: Option<&'b mut TocBuilder>) -> Self {
+impl<'a, 'b, 'ids, I: Iterator>> HeadingLinks<'a, 'b, 'ids, I> {
+    fn new(iter: I, toc: Option<&'b mut TocBuilder>, ids: &'ids mut IdMap) -> Self {
         HeadingLinks {
             inner: iter,
             toc,
             buf: VecDeque::new(),
+            id_map: ids,
         }
     }
 }
 
-impl<'a, 'b, I: Iterator>> Iterator for HeadingLinks<'a, 'b, I> {
+impl<'a, 'b, 'ids, I: Iterator>> Iterator for HeadingLinks<'a, 'b, 'ids, I> {
     type Item = Event<'a>;
 
     fn next(&mut self) -> Option {
@@ -301,7 +326,7 @@ impl<'a, 'b, I: Iterator>> Iterator for HeadingLinks<'a, 'b, I>
                 }
                 self.buf.push_back(event);
             }
-            let id = derive_id(id);
+            let id = self.id_map.derive(id);
 
             if let Some(ref mut builder) = self.toc {
                 let mut html_header = String::new();
@@ -393,14 +418,14 @@ impl<'a, I: Iterator>> Iterator for SummaryLine<'a, I> {
 /// references.
 struct Footnotes<'a, I: Iterator>> {
     inner: I,
-    footnotes: HashMap>, u16)>,
+    footnotes: FxHashMap>, u16)>,
 }
 
 impl<'a, I: Iterator>> Footnotes<'a, I> {
     fn new(iter: I) -> Self {
         Footnotes {
             inner: iter,
-            footnotes: HashMap::new(),
+            footnotes: FxHashMap::default(),
         }
     }
     fn get_entry(&mut self, key: &str) -> &mut (Vec>, u16) {
@@ -467,10 +492,17 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> {
     }
 }
 
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span,
-                          sess: Option<&session::Session>) {
-    tests.set_position(position);
+pub struct TestableCodeError(());
 
+impl fmt::Display for TestableCodeError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "invalid start of a new code block")
+    }
+}
+
+pub fn find_testable_code(
+    doc: &str, tests: &mut test::Collector, error_codes: ErrorCodes,
+) -> Result<(), TestableCodeError> {
     let mut parser = Parser::new(doc);
     let mut prev_offset = 0;
     let mut nb_lines = 0;
@@ -481,7 +513,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                 let block_info = if s.is_empty() {
                     LangString::all_false()
                 } else {
-                    LangString::parse(&*s)
+                    LangString::parse(&*s, error_codes)
                 };
                 if !block_info.rust {
                     continue
@@ -510,18 +542,10 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                     let text = lines.collect::>>().join("\n");
                     nb_lines += doc[prev_offset..offset].lines().count();
                     let line = tests.get_line() + (nb_lines - 1);
-                    let filename = tests.get_filename();
-                    tests.add_test(text.to_owned(),
-                                   block_info.should_panic, block_info.no_run,
-                                   block_info.ignore, block_info.test_harness,
-                                   block_info.compile_fail, block_info.error_codes,
-                                   line, filename, block_info.allow_fail);
+                    tests.add_test(text, block_info, line);
                     prev_offset = offset;
                 } else {
-                    if let Some(ref sess) = sess {
-                        sess.span_warn(position, "invalid start of a new code block");
-                    }
-                    break;
+                    return Err(TestableCodeError(()));
                 }
             }
             Event::Start(Tag::Header(level)) => {
@@ -539,19 +563,20 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
             _ => {}
         }
     }
+    Ok(())
 }
 
 #[derive(Eq, PartialEq, Clone, Debug)]
-struct LangString {
+pub struct LangString {
     original: String,
-    should_panic: bool,
-    no_run: bool,
-    ignore: bool,
-    rust: bool,
-    test_harness: bool,
-    compile_fail: bool,
-    error_codes: Vec,
-    allow_fail: bool,
+    pub should_panic: bool,
+    pub no_run: bool,
+    pub ignore: bool,
+    pub rust: bool,
+    pub test_harness: bool,
+    pub compile_fail: bool,
+    pub error_codes: Vec,
+    pub allow_fail: bool,
 }
 
 impl LangString {
@@ -569,14 +594,11 @@ impl LangString {
         }
     }
 
-    fn parse(string: &str) -> LangString {
+    fn parse(string: &str, allow_error_code_check: ErrorCodes) -> LangString {
+        let allow_error_code_check = allow_error_code_check.as_bool();
         let mut seen_rust_tags = false;
         let mut seen_other_tags = false;
         let mut data = LangString::all_false();
-        let mut allow_error_code_check = false;
-        if UnstableFeatures::from_environment().is_nightly_build() {
-            allow_error_code_check = true;
-        }
 
         data.original = string.to_owned();
         let tokens = string.split(|c: char|
@@ -604,7 +626,7 @@ impl LangString {
                     data.no_run = true;
                 }
                 x if allow_error_code_check && x.starts_with("E") && x.len() == 5 => {
-                    if let Ok(_) = x[1..].parse::() {
+                    if x[1..].parse::().is_ok() {
                         data.error_codes.push(x.to_owned());
                         seen_rust_tags = !seen_other_tags || seen_rust_tags;
                     } else {
@@ -623,7 +645,8 @@ impl LangString {
 
 impl<'a> fmt::Display for Markdown<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let Markdown(md, links) = *self;
+        let Markdown(md, links, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
@@ -643,12 +666,11 @@ impl<'a> fmt::Display for Markdown<'a> {
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
-        html::push_html(&mut s,
-                        Footnotes::new(
-                            CodeBlocks::new(
-                                LinkReplacer::new(
-                                    HeadingLinks::new(p, None),
-                                    links))));
+        let p = HeadingLinks::new(p, None, &mut ids);
+        let p = LinkReplacer::new(p, links);
+        let p = CodeBlocks::new(p, codes);
+        let p = Footnotes::new(p);
+        html::push_html(&mut s, p);
 
         fmt.write_str(&s)
     }
@@ -656,7 +678,8 @@ impl<'a> fmt::Display for Markdown<'a> {
 
 impl<'a> fmt::Display for MarkdownWithToc<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let MarkdownWithToc(md) = *self;
+        let MarkdownWithToc(md, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         let mut opts = Options::empty();
         opts.insert(OPTION_ENABLE_TABLES);
@@ -668,8 +691,12 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> {
 
         let mut toc = TocBuilder::new();
 
-        html::push_html(&mut s,
-                        Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, Some(&mut toc)))));
+        {
+            let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
+            let p = CodeBlocks::new(p, codes);
+            let p = Footnotes::new(p);
+            html::push_html(&mut s, p);
+        }
 
         write!(fmt, "", toc.into_toc())?;
 
@@ -679,7 +706,8 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> {
 
 impl<'a> fmt::Display for MarkdownHtml<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let MarkdownHtml(md) = *self;
+        let MarkdownHtml(md, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
@@ -697,8 +725,10 @@ impl<'a> fmt::Display for MarkdownHtml<'a> {
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
-        html::push_html(&mut s,
-                        Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, None))));
+        let p = HeadingLinks::new(p, None, &mut ids);
+        let p = CodeBlocks::new(p, codes);
+        let p = Footnotes::new(p);
+        html::push_html(&mut s, p);
 
         fmt.write_str(&s)
     }
@@ -812,7 +842,10 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option>)> {
         let p = Parser::new_with_broken_link_callback(md, opts,
             Some(&push));
 
-        let iter = Footnotes::new(HeadingLinks::new(p, None));
+        // There's no need to thread an IdMap through to here because
+        // the IDs generated aren't going to be emitted anywhere.
+        let mut ids = IdMap::new();
+        let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
 
         for ev in iter {
             if let Event::Start(Tag::Link(dest, _)) = ev {
@@ -831,18 +864,74 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option>)> {
     links
 }
 
+#[derive(Default)]
+pub struct IdMap {
+    map: FxHashMap,
+}
+
+impl IdMap {
+    pub fn new() -> Self {
+        IdMap::default()
+    }
+
+    pub fn populate>(&mut self, ids: I) {
+        for id in ids {
+            let _ = self.derive(id);
+        }
+    }
+
+    pub fn reset(&mut self) {
+        self.map = FxHashMap::default();
+    }
+
+    pub fn derive(&mut self, candidate: String) -> String {
+        let id = match self.map.get_mut(&candidate) {
+            None => candidate,
+            Some(a) => {
+                let id = format!("{}-{}", candidate, *a);
+                *a += 1;
+                id
+            }
+        };
+
+        self.map.insert(id.clone(), 1);
+        id
+    }
+}
+
+#[cfg(test)]
+#[test]
+fn test_unique_id() {
+    let input = ["foo", "examples", "examples", "method.into_iter","examples",
+                 "method.into_iter", "foo", "main", "search", "methods",
+                 "examples", "method.into_iter", "assoc_type.Item", "assoc_type.Item"];
+    let expected = ["foo", "examples", "examples-1", "method.into_iter", "examples-2",
+                    "method.into_iter-1", "foo-1", "main", "search", "methods",
+                    "examples-3", "method.into_iter-2", "assoc_type.Item", "assoc_type.Item-1"];
+
+    let map = RefCell::new(IdMap::new());
+    let test = || {
+        let mut map = map.borrow_mut();
+        let actual: Vec = input.iter().map(|s| map.derive(s.to_string())).collect();
+        assert_eq!(&actual[..], expected);
+    };
+    test();
+    map.borrow_mut().reset();
+    test();
+}
+
 #[cfg(test)]
 mod tests {
-    use super::{LangString, Markdown, MarkdownHtml};
+    use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap};
     use super::plain_summary_line;
-    use html::render::reset_ids;
+    use std::cell::RefCell;
 
     #[test]
     fn test_lang_string_parse() {
         fn t(s: &str,
             should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
             compile_fail: bool, allow_fail: bool, error_codes: Vec) {
-            assert_eq!(LangString::parse(s), LangString {
+            assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString {
                 should_panic,
                 no_run,
                 ignore,
@@ -878,19 +967,12 @@ mod tests {
         t("text,no_run",           false,        true,   false,  false, false, false, false, v());
     }
 
-    #[test]
-    fn issue_17736() {
-        let markdown = "# title";
-        Markdown(markdown, &[]).to_string();
-        reset_ids(true);
-    }
-
     #[test]
     fn test_header() {
         fn t(input: &str, expect: &str) {
-            let output = Markdown(input, &[]).to_string();
+            let mut map = IdMap::new();
+            let output = Markdown(input, &[], RefCell::new(&mut map), ErrorCodes::Yes).to_string();
             assert_eq!(output, expect, "original: {}", input);
-            reset_ids(true);
         }
 
         t("# Foo bar", "

\ @@ -909,28 +991,24 @@ mod tests { #[test] fn test_header_ids_multiple_blocks() { - fn t(input: &str, expect: &str) { - let output = Markdown(input, &[]).to_string(); + let mut map = IdMap::new(); + fn t(map: &mut IdMap, input: &str, expect: &str) { + let output = Markdown(input, &[], RefCell::new(map), ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); } - let test = || { - t("# Example", "

\ - Example

"); - t("# Panics", "

\ - Panics

"); - t("# Example", "

\ - Example

"); - t("# Main", "

\ - Main

"); - t("# Example", "

\ - Example

"); - t("# Panics", "

\ - Panics

"); - }; - test(); - reset_ids(true); - test(); + t(&mut map, "# Example", "

\ + Example

"); + t(&mut map, "# Panics", "

\ + Panics

"); + t(&mut map, "# Example", "

\ + Example

"); + t(&mut map, "# Main", "

\ + Main

"); + t(&mut map, "# Example", "

\ + Example

"); + t(&mut map, "# Panics", "

\ + Panics

"); } #[test] @@ -951,7 +1029,8 @@ mod tests { #[test] fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { - let output = MarkdownHtml(input).to_string(); + let mut idmap = IdMap::new(); + let output = MarkdownHtml(input, RefCell::new(&mut idmap), ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 24a9bf416e..75311d9385 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -38,7 +38,7 @@ pub use self::ExternalLocation::*; use std::borrow::Cow; use std::cell::RefCell; use std::cmp::Ordering; -use std::collections::{BTreeMap, HashSet, VecDeque}; +use std::collections::{BTreeMap, VecDeque}; use std::default::Default; use std::error; use std::fmt::{self, Display, Formatter, Write as FmtWrite}; @@ -50,12 +50,14 @@ use std::mem; use std::path::{PathBuf, Path, Component}; use std::str; use std::sync::Arc; +use std::rc::Rc; use externalfiles::ExternalHtml; use serialize::json::{ToJson, Json, as_json}; use syntax::ast; -use syntax::codemap::FileName; +use syntax::source_map::FileName; +use syntax::feature_gate::UnstableFeatures; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; @@ -72,7 +74,7 @@ use html::format::{GenericBounds, WhereClause, href, AbiSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; use html::item_type::ItemType; -use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine}; +use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap}; use html::{highlight, layout}; use minifier; @@ -88,7 +90,7 @@ pub type NameDoc = (String, Option); /// easily cloned because it is cloned per work-job (about once per item in the /// rustdoc tree). #[derive(Clone)] -pub struct Context { +struct Context { /// Current hierarchy of components leading down to what's currently being /// rendered pub current: Vec, @@ -99,10 +101,13 @@ pub struct Context { /// real location of an item. This is used to allow external links to /// publicly reused items to redirect to the right location. pub render_redirect_pages: bool, + pub codes: ErrorCodes, + /// The map used to ensure all generated 'id=' attributes are unique. + id_map: Rc>, pub shared: Arc, } -pub struct SharedContext { +struct SharedContext { /// The path to the crate root source minus the file name. /// Used for simplifying paths to the highlighted source code files. pub src_root: PathBuf, @@ -310,7 +315,7 @@ pub struct Cache { // the access levels from crateanalysis. pub access_levels: Arc>, - /// The version of the crate being documented, if given fron the `--crate-version` flag. + /// The version of the crate being documented, if given from the `--crate-version` flag. pub crate_version: Option, // Private fields only used when initially crawling a crate to build a cache @@ -450,9 +455,8 @@ impl ToJson for IndexItemFunctionType { thread_local!(static CACHE_KEY: RefCell> = Default::default()); thread_local!(pub static CURRENT_LOCATION_KEY: RefCell> = RefCell::new(Vec::new())); -thread_local!(pub static USED_ID_MAP: RefCell> = RefCell::new(init_ids())); -fn init_ids() -> FxHashMap { +pub fn initial_ids() -> Vec { [ "main", "search", @@ -470,40 +474,12 @@ fn init_ids() -> FxHashMap { "methods", "deref-methods", "implementations", - ].into_iter().map(|id| (String::from(*id), 1)).collect() -} - -/// This method resets the local table of used ID attributes. This is typically -/// used at the beginning of rendering an entire HTML page to reset from the -/// previous state (if any). -pub fn reset_ids(embedded: bool) { - USED_ID_MAP.with(|s| { - *s.borrow_mut() = if embedded { - init_ids() - } else { - FxHashMap() - }; - }); -} - -pub fn derive_id(candidate: String) -> String { - USED_ID_MAP.with(|map| { - let id = match map.borrow_mut().get_mut(&candidate) { - None => candidate, - Some(a) => { - let id = format!("{}-{}", candidate, *a); - *a += 1; - id - } - }; - - map.borrow_mut().insert(id.clone(), 1); - id - }) + ].into_iter().map(|id| (String::from(*id))).collect() } /// Generates the documentation for `crate` into the directory `dst` pub fn run(mut krate: clean::Crate, + extern_urls: BTreeMap, external_html: &ExternalHtml, playground_url: Option, dst: PathBuf, @@ -513,7 +489,8 @@ pub fn run(mut krate: clean::Crate, renderinfo: RenderInfo, sort_modules_alphabetically: bool, themes: Vec, - enable_minification: bool) -> Result<(), Error> { + enable_minification: bool, + id_map: IdMap) -> Result<(), Error> { let src_root = match krate.src { FileName::Real(ref p) => match p.parent() { Some(p) => p.to_path_buf(), @@ -528,8 +505,8 @@ pub fn run(mut krate: clean::Crate, local_sources: FxHashMap(), issue_tracker_base_url: None, layout: layout::Layout { - logo: "".to_string(), - favicon: "".to_string(), + logo: String::new(), + favicon: String::new(), external_html: external_html.clone(), krate: krate.name.clone(), }, @@ -581,6 +558,8 @@ pub fn run(mut krate: clean::Crate, current: Vec::new(), dst, render_redirect_pages: false, + codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), + id_map: Rc::new(RefCell::new(id_map)), shared: Arc::new(scx), }; @@ -633,8 +612,9 @@ pub fn run(mut krate: clean::Crate, }, _ => PathBuf::new(), }; + let extern_url = extern_urls.get(&e.name).map(|u| &**u); cache.extern_locations.insert(n, (e.name.clone(), src_root, - extern_location(e, &cx.dst))); + extern_location(e, extern_url, &cx.dst))); let did = DefId { krate: n, index: CRATE_DEF_INDEX }; cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module)); @@ -763,7 +743,7 @@ fn write_shared(cx: &Context, // To avoid "light.css" to be overwritten, we'll first run over the received themes and only // then we'll run over the "official" styles. - let mut themes: HashSet = HashSet::new(); + let mut themes: FxHashSet = FxHashSet::default(); for entry in &cx.shared.themes { let mut content = Vec::with_capacity(100000); @@ -1118,13 +1098,23 @@ fn clean_srcpath(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) wh /// Attempts to find where an external crate is located, given that we're /// rendering in to the specified source destination. -fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation { +fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Path) + -> ExternalLocation +{ // See if there's documentation generated into the local directory let local_location = dst.join(&e.name); if local_location.is_dir() { return Local; } + if let Some(url) = extern_url { + let mut url = url.to_string(); + if !url.ends_with("/") { + url.push('/'); + } + return Remote(url); + } + // Failing that, see if there's an attribute specifying where to find this // external crate e.attrs.lists("doc") @@ -1267,9 +1257,11 @@ impl DocFolder for Cache { // Collect all the implementors of traits. if let clean::ImplItem(ref i) = item.inner { if let Some(did) = i.trait_.def_id() { - self.implementors.entry(did).or_insert(vec![]).push(Impl { - impl_item: item.clone(), - }); + if i.blanket_impl.is_none() { + self.implementors.entry(did).or_default().push(Impl { + impl_item: item.clone(), + }); + } } } @@ -1462,7 +1454,7 @@ impl DocFolder for Cache { unreachable!() }; for did in dids { - self.impls.entry(did).or_insert(vec![]).push(Impl { + self.impls.entry(did).or_default().push(Impl { impl_item: item.clone(), }); } @@ -1561,35 +1553,36 @@ impl Ord for ItemEntry { #[derive(Debug)] struct AllTypes { - structs: HashSet, - enums: HashSet, - unions: HashSet, - primitives: HashSet, - traits: HashSet, - macros: HashSet, - functions: HashSet, - typedefs: HashSet, - existentials: HashSet, - statics: HashSet, - constants: HashSet, - keywords: HashSet, + structs: FxHashSet, + enums: FxHashSet, + unions: FxHashSet, + primitives: FxHashSet, + traits: FxHashSet, + macros: FxHashSet, + functions: FxHashSet, + typedefs: FxHashSet, + existentials: FxHashSet, + statics: FxHashSet, + constants: FxHashSet, + keywords: FxHashSet, } impl AllTypes { fn new() -> AllTypes { + let new_set = |cap| FxHashSet::with_capacity_and_hasher(cap, Default::default()); AllTypes { - structs: HashSet::with_capacity(100), - enums: HashSet::with_capacity(100), - unions: HashSet::with_capacity(100), - primitives: HashSet::with_capacity(26), - traits: HashSet::with_capacity(100), - macros: HashSet::with_capacity(100), - functions: HashSet::with_capacity(100), - typedefs: HashSet::with_capacity(100), - existentials: HashSet::with_capacity(100), - statics: HashSet::with_capacity(100), - constants: HashSet::with_capacity(100), - keywords: HashSet::with_capacity(100), + structs: new_set(100), + enums: new_set(100), + unions: new_set(100), + primitives: new_set(26), + traits: new_set(100), + macros: new_set(100), + functions: new_set(100), + typedefs: new_set(100), + existentials: new_set(100), + statics: new_set(100), + constants: new_set(100), + keywords: new_set(100), } } @@ -1617,7 +1610,7 @@ impl AllTypes { } } -fn print_entries(f: &mut fmt::Formatter, e: &HashSet, title: &str, +fn print_entries(f: &mut fmt::Formatter, e: &FxHashSet, title: &str, class: &str) -> fmt::Result { if !e.is_empty() { let mut e: Vec<&ItemEntry> = e.iter().collect(); @@ -1635,7 +1628,6 @@ impl fmt::Display for AllTypes { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "

\ - List of all items\ \ \ \ @@ -1643,6 +1635,7 @@ impl fmt::Display for AllTypes { \ + List of all items\

")?; print_entries(f, &self.structs, "Structs", "structs")?; print_entries(f, &self.enums, "Enums", "enums")?; @@ -1674,6 +1667,7 @@ impl<'a> Settings<'a> { ("item-attributes", "Auto-hide item attributes.", true), ("trait-implementations", "Auto-hide trait implementations documentation", true), + ("method-docs", "Auto-hide item methods' documentation", false), ("go-to-only-result", "Directly go to item in search if there is only one result", false), ], @@ -1708,6 +1702,11 @@ impl<'a> fmt::Display for Settings<'a> { } impl Context { + fn derive_id(&self, id: String) -> String { + let mut map = self.id_map.borrow_mut(); + map.derive(id) + } + /// String representation of how to get back to the root path of the 'doc/' /// folder in terms of a relative URL. fn root_path(&self) -> String { @@ -1862,7 +1861,10 @@ impl Context { resource_suffix: &self.shared.resource_suffix, }; - reset_ids(true); + { + self.id_map.borrow_mut().reset(); + self.id_map.borrow_mut().populate(initial_ids()); + } if !self.render_redirect_pages { layout::render(writer, &self.shared.layout, &page, @@ -1985,7 +1987,7 @@ impl Context { fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap> { // BTreeMap instead of HashMap to get a sorted output - let mut map = BTreeMap::new(); + let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new(); for item in &m.items { if item.is_stripped() { continue } @@ -1995,7 +1997,7 @@ impl Context { Some(ref s) => s.to_string(), }; let short = short.to_string(); - map.entry(short).or_insert(vec![]) + map.entry(short).or_default() .push((myname, Some(plain_summary_line(item.doc_value())))); } @@ -2073,7 +2075,7 @@ impl<'a> Item<'a> { fn wrap_into_docblock(w: &mut fmt::Formatter, f: F) -> fmt::Result where F: Fn(&mut fmt::Formatter) -> fmt::Result { - write!(w, "
")?; + write!(w, "
")?; f(w)?; write!(w, "
") } @@ -2082,7 +2084,34 @@ impl<'a> fmt::Display for Item<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { debug_assert!(!self.item.is_stripped()); // Write the breadcrumb trail header for the top - write!(fmt, "

")?; + write!(fmt, "

")?; + if let Some(version) = self.item.stable_since() { + write!(fmt, "{0}", + version)?; + } + write!(fmt, + "\ + \ + []\ + \ + ")?; + + // Write `src` tag + // + // When this item is part of a `pub use` in a downstream crate, the + // [src] link in the downstream documentation will actually come back to + // this page, and this link will be auto-clicked. The `id` attribute is + // used to find the link to auto-click. + if self.cx.shared.include_sources && !self.item.is_primitive() { + if let Some(l) = self.src_href() { + write!(fmt, "[src]", + l, "goto source code")?; + } + } + + write!(fmt, "")?; // out-of-band + write!(fmt, "")?; match self.item.inner { clean::ModuleItem(ref m) => if m.is_crate { write!(fmt, "Crate ")?; @@ -2119,34 +2148,7 @@ impl<'a> fmt::Display for Item<'a> { write!(fmt, "{}", self.item.type_(), self.item.name.as_ref().unwrap())?; - write!(fmt, "")?; // in-band - write!(fmt, "")?; - if let Some(version) = self.item.stable_since() { - write!(fmt, "{0}", - version)?; - } - write!(fmt, - "\ - \ - []\ - \ - ")?; - - // Write `src` tag - // - // When this item is part of a `pub use` in a downstream crate, the - // [src] link in the downstream documentation will actually come back to - // this page, and this link will be auto-clicked. The `id` attribute is - // used to find the link to auto-click. - if self.cx.shared.include_sources && !self.item.is_primitive() { - if let Some(l) = self.src_href() { - write!(fmt, "[src]", - l, "goto source code")?; - } - } - - write!(fmt, "

")?; // out-of-band + write!(fmt, "

")?; // in-band match self.item.inner { clean::ModuleItem(ref m) => @@ -2197,7 +2199,7 @@ fn shorter<'a>(s: Option<&'a str>) -> String { !chr.is_whitespace() }) }).collect::>().join("\n"), - None => "".to_string() + None => String::new() } } @@ -2212,21 +2214,23 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re info!("Documenting {}", name); } document_stability(w, cx, item)?; - let prefix = render_assoc_const_value(item); - document_full(w, item, cx, &prefix)?; + document_full(w, item, cx, "")?; Ok(()) } /// Render md_text as markdown. fn render_markdown(w: &mut fmt::Formatter, + cx: &Context, md_text: &str, links: Vec<(String, String)>, - prefix: &str,) + prefix: &str) -> fmt::Result { - write!(w, "
{}{}
", prefix, Markdown(md_text, &links)) + let mut ids = cx.id_map.borrow_mut(); + write!(w, "
{}{}
", + prefix, Markdown(md_text, &links, RefCell::new(&mut ids), cx.codes)) } -fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink, +fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink, prefix: &str) -> fmt::Result { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { @@ -2235,33 +2239,18 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin } else { plain_summary_line(Some(s)).to_string() }; - render_markdown(w, &markdown, item.links(), prefix)?; + render_markdown(w, cx, &markdown, item.links(), prefix)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } Ok(()) } -fn render_assoc_const_value(item: &clean::Item) -> String { - match item.inner { - clean::AssociatedConstItem(ref ty, Some(ref default)) => { - highlight::render_with_highlighting( - &format!("{}: {:#} = {}", item.name.as_ref().unwrap(), ty, default), - None, - None, - None, - None, - ) - } - _ => String::new(), - } -} - fn document_full(w: &mut fmt::Formatter, item: &clean::Item, cx: &Context, prefix: &str) -> fmt::Result { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); - render_markdown(w, &*s, item.links(), prefix)?; + render_markdown(w, cx, &*s, item.links(), prefix)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2312,17 +2301,21 @@ fn document_non_exhaustive(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::R } fn name_key(name: &str) -> (&str, u64, usize) { + let end = name.bytes() + .rposition(|b| b.is_ascii_digit()).map_or(name.len(), |i| i + 1); + // find number at end - let split = name.bytes().rposition(|b| b < b'0' || b'9' < b).map_or(0, |s| s + 1); + let split = name[0..end].bytes() + .rposition(|b| !b.is_ascii_digit()).map_or(0, |i| i + 1); // count leading zeroes let after_zeroes = - name[split..].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra); + name[split..end].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra); // sort leading zeroes last let num_zeroes = after_zeroes - split; - match name[split..].parse() { + match name[split..end].parse() { Ok(n) => (&name[..split], n, num_zeroes), Err(_) => (name, 0, num_zeroes), } @@ -2427,7 +2420,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, let (short, name) = item_ty_to_strs(&myty.unwrap()); write!(w, "

\ {name}

\n", - id = derive_id(short.to_owned()), name = name)?; + id = cx.derive_id(short.to_owned()), name = name)?; } match myitem.inner { @@ -2491,7 +2484,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, stab_docs = stab_docs, docs = MarkdownSummaryLine(doc_value, &myitem.links()), class = myitem.type_(), - stab = myitem.stability_class().unwrap_or("".to_string()), + stab = myitem.stability_class().unwrap_or(String::new()), unsafety_flag = unsafety_flag, href = item_path(myitem.type_(), myitem.name.as_ref().unwrap()), title_type = myitem.type_(), @@ -2508,6 +2501,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec { let mut stability = vec![]; + let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); if let Some(stab) = item.stability.as_ref() { let deprecated_reason = if show_reason && !stab.deprecated_reason.is_empty() { @@ -2521,14 +2515,12 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) }; @@ -2555,11 +2547,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec", unstable_extra)); } else { + let mut ids = cx.id_map.borrow_mut(); let text = format!("🔬 \ This is a nightly-only experimental API. {}\ {}", unstable_extra, - MarkdownHtml(&stab.unstable_reason)); + MarkdownHtml( + &stab.unstable_reason, + RefCell::new(&mut ids), + error_codes)); stability.push(format!("
{}
", text)); } @@ -2579,14 +2575,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) } @@ -2602,27 +2599,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec(&'a str); - -impl<'a> fmt::Display for Initializer<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Initializer(s) = *self; - if s.is_empty() { return Ok(()); } - write!(f, " = ")?; - write!(f, "{}", Escape(s)) - } -} - fn item_constant(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, c: &clean::Constant) -> fmt::Result { write!(w, "
")?;
     render_attributes(w, it)?;
     write!(w, "{vis}const \
-               {name}: {typ}{init}
", + {name}: {typ}", vis = VisSpace(&it.visibility), name = it.name.as_ref().unwrap(), - typ = c.type_, - init = Initializer(&c.expr))?; + typ = c.type_)?; document(w, cx, it) } @@ -2631,12 +2616,11 @@ fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, write!(w, "
")?;
     render_attributes(w, it)?;
     write!(w, "{vis}static {mutability}\
-               {name}: {typ}{init}
", + {name}: {typ}", vis = VisSpace(&it.visibility), mutability = MutableSpace(s.mutability), name = it.name.as_ref().unwrap(), - typ = s.type_, - init = Initializer(&s.expr))?; + typ = s.type_)?; document(w, cx, it) } @@ -2673,7 +2657,6 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter, implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> fmt::Result { - write!(w, "
  • ")?; // If there's already another implementor that has the same abbridged name, use the // full path, for example in `std::iter::ExactSizeIterator` let use_absolute = match implementor.inner_impl().for_ { @@ -2684,22 +2667,8 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter, } => implementor_dups[path.last_name()].1, _ => false, }; - fmt_impl_for_trait_page(&implementor.inner_impl(), w, use_absolute)?; - for it in &implementor.inner_impl().items { - if let clean::TypedefItem(ref tydef, _) = it.inner { - write!(w, " ")?; - assoc_type(w, it, &[], Some(&tydef.type_), AssocItemLink::Anchor(None))?; - write!(w, ";")?; - } - } - write!(w, "")?; - if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() { - write!(w, "
    ")?; - write!(w, "[src]", - l, "goto source code")?; - write!(w, "
    ")?; - } - writeln!(w, "
    ")?; + render_impl(w, cx, implementor, AssocItemLink::Anchor(None), RenderMode::Normal, + implementor.impl_item.stable_since(), false, Some(use_absolute))?; Ok(()) } @@ -2710,7 +2679,7 @@ fn render_impls(cx: &Context, w: &mut fmt::Formatter, let did = i.trait_did().unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); render_impl(w, cx, i, assoc_link, - RenderMode::Normal, containing_item.stable_since(), true)?; + RenderMode::Normal, containing_item.stable_since(), true, None)?; } Ok(()) } @@ -2737,6 +2706,14 @@ fn bounds(t_bounds: &[clean::GenericBound]) -> String { bounds } +fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering { + let lhs = format!("{}", lhs.inner_impl()); + let rhs = format!("{}", rhs.inner_impl()); + + // lhs and rhs are formatted as HTML, which may be unnecessary + name_key(&lhs).cmp(&name_key(&rhs)) +} + fn item_trait( w: &mut fmt::Formatter, cx: &Context, @@ -2827,8 +2804,8 @@ fn item_trait( -> fmt::Result { let name = m.name.as_ref().unwrap(); let item_type = m.type_(); - let id = derive_id(format!("{}.{}", item_type, name)); - let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); + let id = cx.derive_id(format!("{}.{}", item_type, name)); + let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "{extra}

    \

    ")?; } } else { // even without any implementations to write in, we still want the heading and list, so the // implementors javascript file pulled in below has somewhere to write the impls into write!(w, "{}", impl_header)?; - write!(w, "")?; + write!(w, "")?; if t.auto { write!(w, "{}", synthetic_impl_header)?; - write!(w, "")?; + write!(w, "")?; } } write!(w, r#""#, @@ -3183,10 +3164,10 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, document_non_exhaustive_header(it))?; document_non_exhaustive(w, it)?; for (field, ty) in fields { - let id = derive_id(format!("{}.{}", + let id = cx.derive_id(format!("{}.{}", ItemType::StructField, field.name.as_ref().unwrap())); - let ns_id = derive_id(format!("{}.{}", + let ns_id = cx.derive_id(format!("{}.{}", field.name.as_ref().unwrap(), ItemType::StructField.name_space())); write!(w, " @@ -3317,10 +3298,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, document_non_exhaustive_header(it))?; document_non_exhaustive(w, it)?; for variant in &e.variants { - let id = derive_id(format!("{}.{}", + let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.as_ref().unwrap())); - let ns_id = derive_id(format!("{}.{}", + let ns_id = cx.derive_id(format!("{}.{}", variant.name.as_ref().unwrap(), ItemType::Variant.name_space())); write!(w, "\ @@ -3348,7 +3329,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if let clean::VariantItem(Variant { kind: VariantKind::Struct(ref s) }) = variant.inner { - let variant_id = derive_id(format!("{}.{}.fields", + let variant_id = cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.as_ref().unwrap())); write!(w, "", @@ -3358,10 +3339,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, for field in &s.fields { use clean::StructFieldItem; if let StructFieldItem(ref ty) = field.inner { - let id = derive_id(format!("variant.{}.field.{}", + let id = cx.derive_id(format!("variant.{}.field.{}", variant.name.as_ref().unwrap(), field.name.as_ref().unwrap())); - let ns_id = derive_id(format!("{}.{}.{}.{}", + let ns_id = cx.derive_id(format!("{}.{}.{}.{}", variant.name.as_ref().unwrap(), ItemType::Variant.name_space(), field.name.as_ref().unwrap(), @@ -3607,7 +3588,7 @@ fn render_assoc_items(w: &mut fmt::Formatter, }; for i in &non_trait { render_impl(w, cx, i, AssocItemLink::Anchor(None), render_mode, - containing_item.stable_since(), true)?; + containing_item.stable_since(), true, None)?; } } if let AssocItemRender::DerefFor { .. } = what { @@ -3788,15 +3769,32 @@ fn spotlight_decl(decl: &clean::FnDecl) -> Result { fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink, render_mode: RenderMode, outer_version: Option<&str>, - show_def_docs: bool) -> fmt::Result { + show_def_docs: bool, use_absolute: Option) -> fmt::Result { if render_mode == RenderMode::Normal { - let id = derive_id(match i.inner_impl().trait_ { + let id = cx.derive_id(match i.inner_impl().trait_ { Some(ref t) => format!("impl-{}", small_url_encode(&format!("{:#}", t))), None => "impl".to_string(), }); - write!(w, "

    \ -
    {}", - id, i.inner_impl())?; + if let Some(use_absolute) = use_absolute { + write!(w, "

    \ +
    ", id)?; + fmt_impl_for_trait_page(&i.inner_impl(), w, use_absolute)?; + if show_def_docs { + for it in &i.inner_impl().items { + if let clean::TypedefItem(ref tydef, _) = it.inner { + write!(w, " ")?; + assoc_type(w, it, &vec![], Some(&tydef.type_), + AssocItemLink::Anchor(None))?; + write!(w, ";")?; + } + } + } + write!(w, "")?; + } else { + write!(w, "

    \ +
    {}", + id, i.inner_impl())?; + } write!(w, "", id)?; write!(w, "")?; let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); @@ -3810,8 +3808,9 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } write!(w, "

    ")?; if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { + let mut ids = cx.id_map.borrow_mut(); write!(w, "
    {}
    ", - Markdown(&*dox, &i.impl_item.links()))?; + Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), cx.codes))?; } } @@ -3832,8 +3831,8 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi clean::TyMethodItem(clean::TyMethod{ ref decl, .. }) => { // Only render when the method is not static or we allow static methods if render_method_item { - let id = derive_id(format!("{}.{}", item_type, name)); - let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); + let id = cx.derive_id(format!("{}.{}", item_type, name)); + let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

    ", id, item_type)?; write!(w, "{}", spotlight_decl(decl)?)?; write!(w, "

    \n", src)?; } clean::AssociatedTypeItem(ref bounds, ref default) => { - let id = derive_id(format!("{}.{}", item_type, name)); - let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); + let id = cx.derive_id(format!("{}.{}", item_type, name)); + let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

    ", id, item_type)?; write!(w, "