From 32a655c1fba63375bf899446ce63c00556238dcb Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 17 Mar 2017 10:21:12 +0100 Subject: [PATCH] New upstream version 1.16.0+dfsg1 --- Makefile.in | 4 + README.md | 5 +- RELEASES.md | 196 +- configure | 32 +- mk/cfg/sparc64-unknown-linux-gnu.mk | 1 + mk/cfg/sparc64-unknown-netbsd.mk | 3 + mk/cfg/x86_64-unknown-redox.mk | 1 + mk/crates.mk | 30 +- mk/main.mk | 8 +- src/Cargo.lock | 49 +- src/Cargo.toml | 1 + src/bootstrap/Cargo.toml | 4 + src/bootstrap/README.md | 36 + src/bootstrap/bin/rustc.rs | 36 +- src/bootstrap/bin/rustdoc.rs | 5 + src/bootstrap/bootstrap.py | 10 +- src/bootstrap/cc.rs | 8 +- src/bootstrap/channel.rs | 3 + src/bootstrap/check.rs | 81 +- src/bootstrap/clean.rs | 1 + src/bootstrap/compile.rs | 191 +- src/bootstrap/config.rs | 86 +- src/bootstrap/config.toml.example | 71 + src/bootstrap/dist.rs | 450 +++- src/bootstrap/doc.rs | 59 +- src/bootstrap/flags.rs | 41 +- src/bootstrap/install.rs | 52 +- src/bootstrap/lib.rs | 82 +- src/bootstrap/mk/Makefile.in | 16 +- src/bootstrap/native.rs | 9 +- src/bootstrap/sanity.rs | 14 +- src/bootstrap/step.rs | 805 +++++-- src/bootstrap/util.rs | 4 +- src/ci/docker/README.md | 200 ++ src/ci/docker/arm-android/Dockerfile | 28 +- src/ci/docker/arm-android/install-ndk.sh | 12 - src/ci/docker/arm-android/start-emulator.sh | 3 +- src/ci/docker/cross/Dockerfile | 96 +- src/ci/docker/cross/build-arm-musl.sh | 120 + src/ci/docker/cross/build-rumprun.sh | 38 + src/ci/docker/dist-android/Dockerfile | 48 + src/ci/docker/dist-android/install-ndk.sh | 38 + src/ci/docker/dist-arm-linux/Dockerfile | 80 + .../dist-arm-linux/arm-linux-gnueabi.config | 560 +++++ .../dist-arm-linux/arm-linux-gnueabihf.config | 561 +++++ .../docker/dist-arm-linux/build-toolchains.sh | 45 + .../dist-armv7-aarch64-linux/Dockerfile | 81 + .../aarch64-linux-gnu.config | 551 +++++ .../armv7-linux-gnueabihf.config | 569 +++++ .../build-toolchains.sh | 45 + src/ci/docker/dist-freebsd/Dockerfile | 42 + .../build-toolchain.sh | 32 +- .../Dockerfile | 26 +- src/ci/docker/dist-mips64-linux/Dockerfile | 31 + src/ci/docker/dist-powerpc-linux/Dockerfile | 81 + .../build-powerpc-toolchain.sh | 36 + ...PC-Remove-unnecessary-mnew-mnemonics.patch | 24 + .../powerpc-linux-gnu.config | 528 +++++ src/ci/docker/dist-powerpc64-linux/Dockerfile | 85 + .../build-powerpc64-toolchain.sh | 36 + .../build-powerpc64le-toolchain.sh | 79 + ...PC-Remove-unnecessary-mnew-mnemonics.patch | 24 + ...Prevent-inlining-in-PPC64-initfini.s.patch | 26 + .../powerpc64-linux-gnu.config | 528 +++++ .../docker/dist-s390x-linux-netbsd/Dockerfile | 84 + .../build-netbsd-toolchain.sh | 120 + .../build-s390x-toolchain.sh | 36 + ...prevent-AS-from-complaining-about-z9.patch | 63 + .../s390x-linux-gnu.config | 508 +++++ src/ci/docker/dist-x86-linux/Dockerfile | 80 + .../docker/dist-x86-linux/build-binutils.sh | 26 + src/ci/docker/dist-x86-linux/build-cmake.sh | 25 + src/ci/docker/dist-x86-linux/build-curl.sh | 43 + src/ci/docker/dist-x86-linux/build-gcc.sh | 31 + src/ci/docker/dist-x86-linux/build-git.sh | 24 + src/ci/docker/dist-x86-linux/build-openssl.sh | 27 + src/ci/docker/dist-x86-linux/build-python.sh | 30 + src/ci/docker/dist-x86-linux/shared.sh | 25 + src/ci/docker/emscripten/Dockerfile | 41 + src/ci/docker/emscripten/build-emscripten.sh | 36 + src/ci/docker/i686-gnu-nopt/Dockerfile | 3 - src/ci/docker/i686-gnu/Dockerfile | 5 +- src/ci/docker/linux-tested-targets/Dockerfile | 44 + .../docker/linux-tested-targets/build-musl.sh | 64 + .../musl-libunwind-patch.patch | 15 + src/ci/docker/run.sh | 24 +- .../Dockerfile | 8 +- src/ci/docker/x86_64-gnu-debug/Dockerfile | 5 +- src/ci/docker/x86_64-gnu-distcheck/Dockerfile | 26 + .../Dockerfile | 26 +- .../docker/x86_64-gnu-incremental/Dockerfile | 27 + src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile | 3 - src/ci/docker/x86_64-gnu-make/Dockerfile | 3 - src/ci/docker/x86_64-gnu-nopt/Dockerfile | 3 - src/ci/docker/x86_64-gnu/Dockerfile | 5 +- src/ci/docker/x86_64-musl/build-musl.sh | 33 - src/ci/run.sh | 53 +- src/doc/book/casting-between-types.md | 18 +- src/doc/book/closures.md | 4 +- src/doc/book/documentation.md | 5 +- src/doc/book/ffi.md | 35 +- src/doc/book/lang-items.md | 11 +- src/doc/book/lifetimes.md | 2 +- src/doc/book/match.md | 2 +- src/doc/book/no-stdlib.md | 10 +- src/doc/book/patterns.md | 27 + src/doc/book/strings.md | 4 +- src/doc/book/syntax-index.md | 2 +- src/doc/book/testing.md | 11 +- src/doc/book/trait-objects.md | 5 +- src/doc/book/variable-bindings.md | 2 +- src/doc/grammar.md | 5 +- src/doc/nomicon/atomics.md | 8 +- src/doc/nomicon/coercions.md | 4 +- src/doc/nomicon/destructors.md | 6 +- src/doc/nomicon/dropck.md | 2 +- src/doc/nomicon/meet-safe-and-unsafe.md | 2 +- src/doc/nomicon/races.md | 10 +- src/doc/nomicon/unbounded-lifetimes.md | 2 +- src/doc/reference.md | 22 +- src/etc/debugger_pretty_printers_common.py | 16 +- src/etc/installer/README.md | 28 + src/etc/installer/exe/modpath.iss | 219 ++ src/etc/installer/exe/rust.iss | 80 + src/etc/installer/exe/upgrade.iss | 61 + src/etc/installer/gfx/banner.bmp | Bin 0 -> 114514 bytes src/etc/installer/gfx/banner.xcf | Bin 0 -> 148261 bytes src/etc/installer/gfx/dialogbg.bmp | Bin 0 -> 615402 bytes src/etc/installer/gfx/dialogbg.xcf | Bin 0 -> 216045 bytes src/etc/installer/gfx/rust-logo.ico | Bin 0 -> 370070 bytes src/etc/installer/gfx/rust-logo.png | Bin 0 -> 5844 bytes src/etc/installer/msi/remove-duplicates.xsl | 24 + src/etc/installer/msi/rust.wxs | 279 +++ src/etc/installer/msi/rustwelcomedlg.wxs | 57 + src/etc/installer/msi/squash-components.xsl | 34 + src/etc/installer/msi/ui.wxs | 83 + src/etc/installer/pkg/Distribution.xml | 71 + src/etc/installer/pkg/postinstall | 26 + src/etc/lldb_rust_formatters.py | 4 +- src/etc/platform-intrinsics/nvptx/cuda.json | 13 + src/etc/platform-intrinsics/nvptx/info.json | 7 + src/etc/platform-intrinsics/nvptx/sreg.json | 90 + src/etc/unicode.py | 71 +- src/jemalloc/configure.ac | 31 - .../jemalloc/internal/jemalloc_internal.h.in | 1 - .../internal/jemalloc_internal_defs.h.in | 1 - .../jemalloc/internal/private_symbols.txt | 2 +- src/jemalloc/src/zone.c | 382 +++- src/liballoc/arc.rs | 35 +- src/liballoc/boxed.rs | 17 +- src/liballoc/heap.rs | 2 + src/liballoc/lib.rs | 7 +- src/liballoc/raw_vec.rs | 3 +- src/liballoc/rc.rs | 3 +- src/liballoc_jemalloc/build.rs | 20 +- src/liballoc_jemalloc/lib.rs | 7 +- src/liballoc_jemalloc/pthread_atfork_dummy.c | 16 + src/liballoc_system/lib.rs | 13 +- src/libarena/lib.rs | 140 +- src/libbacktrace/pecoff.c | 4 +- src/libcollections/Cargo.toml | 7 +- src/libcollections/binary_heap.rs | 85 +- src/libcollections/borrow.rs | 36 +- src/libcollections/btree/map.rs | 59 +- src/libcollections/btree/set.rs | 96 +- src/libcollections/enum_set.rs | 5 +- src/libcollections/lib.rs | 7 +- src/libcollections/linked_list.rs | 73 +- src/libcollections/range.rs | 90 +- src/libcollections/slice.rs | 118 +- src/libcollections/str.rs | 16 +- src/libcollections/string.rs | 32 +- src/libcollections/vec.rs | 107 +- src/libcollections/vec_deque.rs | 131 +- src/libcollectionstest/binary_heap.rs | 36 +- src/libcollectionstest/btree/map.rs | 39 +- src/libcollectionstest/enum_set.rs | 268 --- src/libcollectionstest/lib.rs | 9 +- src/libcollectionstest/str.rs | 16 +- src/libcollectionstest/vec.rs | 19 + src/libcompiler_builtins/build.rs | 11 - src/libcompiler_builtins/lib.rs | 788 ++++++- src/libcore/Cargo.toml | 7 +- src/libcore/any.rs | 16 +- src/libcore/char.rs | 29 +- src/libcore/clone.rs | 4 + src/libcore/cmp.rs | 8 +- src/libcore/convert.rs | 28 +- src/libcore/default.rs | 4 + src/libcore/fmt/num.rs | 21 +- src/libcore/hash/mod.rs | 20 + src/libcore/intrinsics.rs | 52 +- src/libcore/iter/iterator.rs | 26 +- src/libcore/iter/range.rs | 2 + src/libcore/iter/sources.rs | 8 +- src/libcore/iter/traits.rs | 86 +- src/libcore/lib.rs | 12 +- src/libcore/macros.rs | 19 +- src/libcore/marker.rs | 77 +- src/libcore/nonzero.rs | 4 + src/libcore/num/i128.rs | 17 + src/libcore/num/i16.rs | 2 +- src/libcore/num/i32.rs | 2 +- src/libcore/num/i64.rs | 2 +- src/libcore/num/i8.rs | 2 +- src/libcore/num/int_macros.rs | 23 +- src/libcore/num/isize.rs | 7 +- src/libcore/num/mod.rs | 131 +- src/libcore/num/u128.rs | 16 + src/libcore/num/u16.rs | 2 +- src/libcore/num/u32.rs | 2 +- src/libcore/num/u64.rs | 2 +- src/libcore/num/u8.rs | 2 +- src/libcore/num/uint_macros.rs | 23 +- src/libcore/num/usize.rs | 7 +- src/libcore/num/wrapping.rs | 2 + src/libcore/ops.rs | 106 +- src/libcore/option.rs | 6 +- src/libcore/ptr.rs | 11 +- src/libcore/result.rs | 58 +- src/libcore/slice.rs | 266 ++- src/libcore/str/mod.rs | 79 +- src/libcore/sync/atomic.rs | 181 +- src/libcoretest/char.rs | 224 +- src/libcoretest/hash/mod.rs | 5 +- src/libcoretest/iter.rs | 16 + src/libcoretest/lib.rs | 2 +- src/libcoretest/result.rs | 13 + src/libflate/lib.rs | 2 +- src/libfmt_macros/lib.rs | 2 +- src/libgetopts/lib.rs | 2 +- src/libgraphviz/lib.rs | 2 +- src/liblibc/.travis.yml | 6 +- .../mipsel-unknown-linux-musl/Dockerfile | 5 +- src/liblibc/ci/dox.sh | 2 +- src/liblibc/libc-test/build.rs | 4 +- src/liblibc/src/dox.rs | 38 + src/liblibc/src/redox.rs | 4 + src/liblibc/src/unix/bsd/apple/mod.rs | 2 + .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 69 +- .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 50 + src/liblibc/src/unix/bsd/freebsdlike/mod.rs | 47 - src/liblibc/src/unix/bsd/mod.rs | 6 + src/liblibc/src/unix/bsd/netbsdlike/mod.rs | 2 + .../unix/bsd/netbsdlike/netbsd/other/mod.rs | 3 +- src/liblibc/src/unix/haiku/mod.rs | 7 + src/liblibc/src/unix/mod.rs | 6 + src/liblibc/src/unix/notbsd/android/mod.rs | 35 +- .../src/unix/notbsd/linux/mips/mips32.rs | 6 + .../src/unix/notbsd/linux/mips/mips64.rs | 6 + src/liblibc/src/unix/notbsd/linux/mips/mod.rs | 34 + src/liblibc/src/unix/notbsd/linux/mod.rs | 166 +- .../src/unix/notbsd/linux/musl/b32/mod.rs | 6 + .../src/unix/notbsd/linux/musl/b64/mod.rs | 7 + src/liblibc/src/unix/notbsd/linux/musl/mod.rs | 34 + .../src/unix/notbsd/linux/other/b32/mod.rs | 195 ++ .../unix/notbsd/linux/other/b64/aarch64.rs | 197 ++ .../src/unix/notbsd/linux/other/b64/mod.rs | 4 +- .../unix/notbsd/linux/other/b64/powerpc64.rs | 197 ++ .../unix/notbsd/linux/other/b64/sparc64.rs | 369 +++ .../src/unix/notbsd/linux/other/b64/x86_64.rs | 197 ++ .../src/unix/notbsd/linux/other/mod.rs | 184 +- src/liblibc/src/unix/notbsd/linux/s390x.rs | 40 + src/liblibc/src/unix/notbsd/mod.rs | 32 +- src/liblibc/src/unix/solaris/mod.rs | 7 + src/liblog/lib.rs | 2 +- src/libpanic_abort/lib.rs | 2 +- src/libpanic_unwind/gcc.rs | 3 + src/libpanic_unwind/lib.rs | 2 +- src/libproc_macro/lib.rs | 76 +- src/libproc_macro_plugin/Cargo.toml | 2 - src/libproc_macro_plugin/lib.rs | 17 +- src/libproc_macro_plugin/qquote.rs | 551 ++--- src/libproc_macro_tokens/Cargo.toml | 13 - src/libproc_macro_tokens/build.rs | 90 - src/libproc_macro_tokens/lib.rs | 66 - src/libproc_macro_tokens/parse.rs | 26 - src/librand/chacha.rs | 11 + src/librand/distributions/exponential.rs | 19 + src/librand/distributions/gamma.rs | 52 + src/librand/distributions/mod.rs | 26 + src/librand/distributions/normal.rs | 31 + src/librand/distributions/range.rs | 12 + src/librand/isaac.rs | 27 + src/librand/lib.rs | 39 +- src/librand/reseeding.rs | 15 +- src/librustc/Cargo.toml | 2 +- src/librustc/cfg/construct.rs | 31 +- src/librustc/cfg/graphviz.rs | 14 +- src/librustc/dep_graph/README.md | 43 +- src/librustc/dep_graph/dep_node.rs | 10 +- src/librustc/dep_graph/dep_tracking_map.rs | 2 +- src/librustc/dep_graph/graph.rs | 12 + src/librustc/dep_graph/thread.rs | 2 +- src/librustc/dep_graph/visit.rs | 18 +- src/librustc/diagnostics.rs | 142 +- src/librustc/hir/def_id.rs | 4 +- src/librustc/hir/intravisit.rs | 201 +- src/librustc/hir/itemlikevisit.rs | 9 +- src/librustc/hir/lowering.rs | 512 +++-- src/librustc/hir/map/blocks.rs | 40 +- src/librustc/hir/map/collector.rs | 108 +- src/librustc/hir/map/def_collector.rs | 236 +- src/librustc/hir/map/definitions.rs | 208 +- src/librustc/hir/map/mod.rs | 593 +++-- src/librustc/hir/mod.rs | 277 ++- src/librustc/hir/print.rs | 620 ++---- src/librustc/infer/error_reporting.rs | 996 +-------- src/librustc/infer/freshen.rs | 1 - src/librustc/infer/mod.rs | 215 +- src/librustc/infer/region_inference/mod.rs | 36 +- src/librustc/lib.rs | 19 +- src/librustc/lint/builtin.rs | 9 +- src/librustc/lint/context.rs | 122 +- src/librustc/lint/mod.rs | 4 +- src/librustc/middle/const_qualif.rs | 44 - src/librustc/middle/const_val.rs | 15 +- src/librustc/middle/cstore.rs | 175 +- src/librustc/middle/dataflow.rs | 52 +- src/librustc/middle/dead.rs | 125 +- src/librustc/middle/dependency_format.rs | 6 +- src/librustc/middle/effect.rs | 28 +- src/librustc/middle/entry.rs | 19 +- src/librustc/middle/expr_use_visitor.rs | 29 +- src/librustc/middle/intrinsicck.rs | 62 +- src/librustc/middle/lang_items.rs | 21 +- src/librustc/middle/liveness.rs | 142 +- src/librustc/middle/mem_categorization.rs | 126 +- src/librustc/middle/reachable.rs | 134 +- src/librustc/middle/region.rs | 126 +- src/librustc/middle/resolve_lifetime.rs | 1347 ++++++++--- src/librustc/middle/stability.rs | 36 +- src/librustc/middle/weak_lang_items.rs | 3 +- src/librustc/mir/mod.rs | 21 +- src/librustc/mir/transform.rs | 8 +- src/librustc/session/config.rs | 72 +- src/librustc/session/mod.rs | 5 + src/librustc/traits/coherence.rs | 13 +- src/librustc/traits/error_reporting.rs | 72 +- src/librustc/traits/mod.rs | 4 +- src/librustc/traits/object_safety.rs | 20 +- src/librustc/traits/select.rs | 68 +- src/librustc/traits/specialize/mod.rs | 4 +- .../traits/specialize/specialization_graph.rs | 2 +- src/librustc/ty/contents.rs | 30 +- src/librustc/ty/context.rs | 293 ++- src/librustc/ty/error.rs | 5 +- src/librustc/ty/fast_reject.rs | 5 - src/librustc/ty/flags.rs | 2 +- .../ty/inhabitedness/def_id_forest.rs | 133 ++ src/librustc/ty/inhabitedness/mod.rs | 201 ++ src/librustc/ty/item_path.rs | 14 +- src/librustc/ty/layout.rs | 158 +- src/librustc/ty/maps.rs | 3 + src/librustc/ty/mod.rs | 396 ++-- src/librustc/ty/outlives.rs | 1 - src/librustc/ty/relate.rs | 6 - src/librustc/ty/structural_impls.rs | 46 +- src/librustc/ty/sty.rs | 105 +- src/librustc/ty/trait_def.rs | 2 +- src/librustc/ty/util.rs | 71 +- src/librustc/ty/walk.rs | 2 +- src/librustc/ty/wf.rs | 1 - src/librustc/util/common.rs | 20 +- src/librustc/util/ppaux.rs | 28 +- src/librustc_back/lib.rs | 2 +- src/librustc_back/target/apple_base.rs | 1 + .../target/asmjs_unknown_emscripten.rs | 6 +- src/librustc_back/target/bitrig_base.rs | 1 + src/librustc_back/target/dragonfly_base.rs | 1 + src/librustc_back/target/emscripten_base.rs | 17 + src/librustc_back/target/freebsd_base.rs | 1 + src/librustc_back/target/fuchsia_base.rs | 1 + src/librustc_back/target/haiku_base.rs | 1 + .../target/i686_pc_windows_gnu.rs | 1 + .../target/i686_unknown_linux_musl.rs | 14 + src/librustc_back/target/linux_base.rs | 1 + src/librustc_back/target/mod.rs | 25 + src/librustc_back/target/netbsd_base.rs | 1 + src/librustc_back/target/openbsd_base.rs | 1 + src/librustc_back/target/redox_base.rs | 42 + .../target/s390x_unknown_linux_gnu.rs | 2 + src/librustc_back/target/solaris_base.rs | 1 + .../target/sparc64_unknown_linux_gnu.rs | 30 + .../target/sparc64_unknown_netbsd.rs | 30 + .../target/wasm32_unknown_emscripten.rs | 6 +- src/librustc_back/target/windows_base.rs | 1 + src/librustc_back/target/windows_msvc_base.rs | 1 + .../target/x86_64_unknown_redox.rs | 30 + src/librustc_bitflags/lib.rs | 2 +- src/librustc_borrowck/borrowck/check_loans.rs | 15 +- src/librustc_borrowck/borrowck/fragments.rs | 6 +- .../borrowck/gather_loans/gather_moves.rs | 12 +- .../borrowck/gather_loans/lifetime.rs | 2 +- .../borrowck/gather_loans/mod.rs | 47 +- .../borrowck/mir/dataflow/graphviz.rs | 35 +- .../borrowck/mir/dataflow/impls.rs | 128 +- .../borrowck/mir/dataflow/mod.rs | 40 +- .../borrowck/mir/dataflow/sanity_check.rs | 14 +- .../borrowck/mir/elaborate_drops.rs | 24 +- .../borrowck/mir/gather_moves.rs | 6 +- src/librustc_borrowck/borrowck/mir/mod.rs | 74 +- src/librustc_borrowck/borrowck/mod.rs | 251 ++- src/librustc_borrowck/borrowck/move_data.rs | 9 +- src/librustc_borrowck/lib.rs | 2 +- src/librustc_const_eval/Cargo.toml | 4 +- src/librustc_const_eval/_match.rs | 543 +++-- src/librustc_const_eval/check_match.rs | 218 +- src/librustc_const_eval/diagnostics.rs | 14 +- src/librustc_const_eval/eval.rs | 720 +++--- src/librustc_const_eval/lib.rs | 4 +- src/librustc_const_eval/pattern.rs | 463 +++- src/librustc_const_math/Cargo.toml | 2 +- src/librustc_const_math/err.rs | 2 + src/librustc_const_math/int.rs | 339 +-- src/librustc_const_math/is.rs | 5 +- src/librustc_const_math/lib.rs | 8 +- src/librustc_const_math/us.rs | 5 +- src/librustc_data_structures/Cargo.toml | 1 + .../accumulate_vec.rs | 41 +- src/librustc_data_structures/array_vec.rs | 103 +- src/librustc_data_structures/bitvec.rs | 9 + src/librustc_data_structures/lib.rs | 7 +- src/librustc_data_structures/stable_hasher.rs | 5 +- src/librustc_driver/Cargo.toml | 1 - src/librustc_driver/derive_registrar.rs | 3 + src/librustc_driver/driver.rs | 83 +- src/librustc_driver/lib.rs | 56 +- src/librustc_driver/pretty.rs | 221 +- src/librustc_driver/test.rs | 42 +- src/librustc_errors/Cargo.toml | 2 - src/librustc_errors/diagnostic.rs | 56 +- src/librustc_errors/emitter.rs | 190 +- src/librustc_errors/lib.rs | 9 +- src/librustc_errors/snippet.rs | 36 + src/librustc_i128/Cargo.toml | 8 + src/librustc_i128/lib.rs | 29 + src/librustc_incremental/assert_dep_graph.rs | 10 +- src/librustc_incremental/calculate_svh/mod.rs | 16 +- .../calculate_svh/svh_visitor.rs | 124 +- src/librustc_incremental/lib.rs | 5 +- .../persist/dirty_clean.rs | 20 +- src/librustc_incremental/persist/hash.rs | 5 - src/librustc_incremental/persist/load.rs | 14 +- src/librustc_incremental/persist/mod.rs | 1 + src/librustc_incremental/persist/preds.rs | 316 ++- src/librustc_incremental/persist/save.rs | 63 +- .../persist/work_product.rs | 15 + src/librustc_lint/Cargo.toml | 1 + src/librustc_lint/bad_style.rs | 29 +- src/librustc_lint/builtin.rs | 103 +- src/librustc_lint/lib.rs | 6 +- src/librustc_lint/types.rs | 148 +- src/librustc_lint/unused.rs | 12 +- src/librustc_llvm/build.rs | 3 +- src/librustc_llvm/ffi.rs | 13 +- src/librustc_llvm/lib.rs | 27 +- src/librustc_metadata/Cargo.toml | 1 + src/librustc_metadata/astencode.rs | 141 +- src/librustc_metadata/creader.rs | 23 +- src/librustc_metadata/cstore.rs | 17 +- src/librustc_metadata/cstore_impl.rs | 167 +- src/librustc_metadata/decoder.rs | 233 +- src/librustc_metadata/diagnostics.rs | 6 +- src/librustc_metadata/encoder.rs | 261 ++- src/librustc_metadata/index_builder.rs | 6 +- src/librustc_metadata/lib.rs | 5 +- src/librustc_metadata/schema.rs | 25 +- src/librustc_mir/Cargo.toml | 2 +- src/librustc_mir/build/block.rs | 2 +- src/librustc_mir/build/expr/as_constant.rs | 3 +- src/librustc_mir/build/expr/as_lvalue.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 13 +- src/librustc_mir/build/expr/as_temp.rs | 7 + src/librustc_mir/build/expr/category.rs | 2 +- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 6 +- src/librustc_mir/build/matches/simplify.rs | 26 +- src/librustc_mir/build/matches/test.rs | 15 +- src/librustc_mir/build/misc.rs | 2 + src/librustc_mir/build/mod.rs | 27 +- src/librustc_mir/build/scope.rs | 8 +- src/librustc_mir/graphviz.rs | 2 +- src/librustc_mir/hair/cx/block.rs | 7 +- src/librustc_mir/hair/cx/expr.rs | 219 +- src/librustc_mir/hair/cx/mod.rs | 27 +- src/librustc_mir/hair/mod.rs | 5 +- src/librustc_mir/lib.rs | 6 +- src/librustc_mir/mir_map.rs | 205 +- src/librustc_mir/pretty.rs | 6 +- src/librustc_mir/transform/copy_prop.rs | 2 +- src/librustc_mir/transform/deaggregator.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 25 +- src/librustc_mir/transform/qualify_consts.rs | 18 +- src/librustc_mir/transform/type_check.rs | 7 +- src/librustc_passes/ast_validation.rs | 48 +- src/librustc_passes/consts.rs | 587 ++--- src/librustc_passes/diagnostics.rs | 19 + src/librustc_passes/hir_stats.rs | 7 +- src/librustc_passes/lib.rs | 3 +- src/librustc_passes/loops.rs | 20 +- src/librustc_passes/rvalues.rs | 27 +- src/librustc_passes/static_recursion.rs | 100 +- src/librustc_platform_intrinsics/lib.rs | 5 +- src/librustc_platform_intrinsics/nvptx.rs | 92 + src/librustc_plugin/Cargo.toml | 3 +- src/librustc_plugin/build.rs | 3 + src/librustc_plugin/lib.rs | 4 +- src/librustc_plugin/registry.rs | 18 + src/librustc_privacy/lib.rs | 177 +- src/librustc_resolve/build_reduced_graph.rs | 334 ++- src/librustc_resolve/check_unused.rs | 32 +- src/librustc_resolve/diagnostics.rs | 27 +- src/librustc_resolve/lib.rs | 1980 ++++++++--------- src/librustc_resolve/macros.rs | 221 +- src/librustc_resolve/resolve_imports.rs | 221 +- src/librustc_save_analysis/data.rs | 35 + src/librustc_save_analysis/dump_visitor.rs | 191 +- src/librustc_save_analysis/external_data.rs | 129 +- src/librustc_save_analysis/json_api_dumper.rs | 55 +- src/librustc_save_analysis/json_dumper.rs | 55 +- src/librustc_save_analysis/lib.rs | 123 +- src/librustc_save_analysis/span_utils.rs | 49 +- src/librustc_trans/Cargo.toml | 6 +- src/librustc_trans/README.md | 1 + src/librustc_trans/README.txt | 1 - src/librustc_trans/abi.rs | 82 +- src/librustc_trans/adt.rs | 478 +--- src/librustc_trans/asm.rs | 49 +- src/librustc_trans/assert_module_sources.rs | 2 +- src/librustc_trans/back/link.rs | 110 +- src/librustc_trans/back/lto.rs | 1 - src/librustc_trans/back/rpath.rs | 23 +- src/librustc_trans/back/symbol_export.rs | 40 +- src/librustc_trans/back/symbol_names.rs | 13 +- src/librustc_trans/back/write.rs | 29 +- src/librustc_trans/base.rs | 929 ++------ src/librustc_trans/basic_block.rs | 58 - src/librustc_trans/build.rs | 1167 ---------- src/librustc_trans/builder.rs | 154 +- src/librustc_trans/cabi_arm.rs | 2 - src/librustc_trans/cabi_nvptx.rs | 53 + src/librustc_trans/cabi_nvptx64.rs | 53 + src/librustc_trans/cabi_sparc.rs | 108 + src/librustc_trans/cabi_sparc64.rs | 185 ++ src/librustc_trans/cabi_x86.rs | 50 +- src/librustc_trans/cabi_x86_win64.rs | 24 +- src/librustc_trans/callee.rs | 271 +-- src/librustc_trans/cleanup.rs | 730 +----- src/librustc_trans/collector.rs | 400 ++-- src/librustc_trans/common.rs | 678 +----- src/librustc_trans/consts.rs | 11 +- src/librustc_trans/context.rs | 204 +- .../debuginfo/create_scope_map.rs | 12 +- src/librustc_trans/debuginfo/doc.rs | 2 +- src/librustc_trans/debuginfo/gdb.rs | 29 +- src/librustc_trans/debuginfo/metadata.rs | 79 +- src/librustc_trans/debuginfo/mod.rs | 104 +- src/librustc_trans/debuginfo/source_loc.rs | 66 +- src/librustc_trans/debuginfo/type_names.rs | 5 - src/librustc_trans/declare.rs | 2 +- src/librustc_trans/disr.rs | 3 +- src/librustc_trans/glue.rs | 597 +++-- src/librustc_trans/intrinsic.rs | 766 +++---- src/librustc_trans/lib.rs | 14 +- src/librustc_trans/meth.rs | 65 +- src/librustc_trans/mir/analyze.rs | 64 +- src/librustc_trans/mir/block.rs | 522 ++--- src/librustc_trans/mir/constant.rs | 300 ++- src/librustc_trans/mir/lvalue.rs | 370 ++- src/librustc_trans/mir/mod.rs | 337 +-- src/librustc_trans/mir/operand.rs | 111 +- src/librustc_trans/mir/rvalue.rs | 293 ++- src/librustc_trans/mir/statement.rs | 38 +- src/librustc_trans/monomorphize.rs | 28 +- src/librustc_trans/partitioning.rs | 81 +- src/librustc_trans/symbol_map.rs | 4 +- src/librustc_trans/symbol_names_test.rs | 4 +- src/librustc_trans/trans_item.rs | 83 +- src/librustc_trans/tvec.rs | 59 +- src/librustc_trans/type_.rs | 11 +- src/librustc_trans/type_of.rs | 67 +- src/librustc_trans/value.rs | 156 +- src/librustc_typeck/astconv.rs | 996 ++------- src/librustc_typeck/check/_match.rs | 51 +- src/librustc_typeck/check/autoderef.rs | 8 + src/librustc_typeck/check/callee.rs | 11 +- src/librustc_typeck/check/cast.rs | 13 +- src/librustc_typeck/check/closure.rs | 22 +- src/librustc_typeck/check/compare_method.rs | 108 +- src/librustc_typeck/check/demand.rs | 86 +- src/librustc_typeck/check/dropck.rs | 14 +- src/librustc_typeck/check/intrinsic.rs | 10 +- src/librustc_typeck/check/method/mod.rs | 15 +- src/librustc_typeck/check/method/probe.rs | 310 ++- src/librustc_typeck/check/method/suggest.rs | 36 +- src/librustc_typeck/check/mod.rs | 483 ++-- src/librustc_typeck/check/op.rs | 18 +- src/librustc_typeck/check/regionck.rs | 65 +- src/librustc_typeck/check/upvar.rs | 48 +- src/librustc_typeck/check/wfcheck.rs | 44 +- src/librustc_typeck/check/writeback.rs | 154 +- src/librustc_typeck/check_unused.rs | 5 +- src/librustc_typeck/coherence/builtin.rs | 347 +++ src/librustc_typeck/coherence/mod.rs | 409 +--- src/librustc_typeck/coherence/orphan.rs | 41 +- src/librustc_typeck/coherence/overlap.rs | 16 +- src/librustc_typeck/coherence/unsafety.rs | 7 +- src/librustc_typeck/collect.rs | 475 ++-- src/librustc_typeck/diagnostics.rs | 225 +- src/librustc_typeck/impl_wf_check.rs | 8 +- src/librustc_typeck/lib.rs | 16 +- src/librustc_typeck/rscope.rs | 389 ---- src/librustc_typeck/variance/constraints.rs | 32 +- src/librustc_typeck/variance/solve.rs | 4 +- src/librustc_typeck/variance/terms.rs | 11 +- src/librustdoc/Cargo.toml | 1 - src/librustdoc/clean/inline.rs | 44 +- src/librustdoc/clean/mod.rs | 486 ++-- src/librustdoc/core.rs | 25 +- src/librustdoc/doctree.rs | 9 +- src/librustdoc/html/format.rs | 349 +-- src/librustdoc/html/highlight.rs | 24 +- src/librustdoc/html/layout.rs | 1 + src/librustdoc/html/markdown.rs | 40 +- src/librustdoc/html/render.rs | 79 +- src/librustdoc/html/static/main.js | 21 +- src/librustdoc/html/static/rustdoc.css | 18 +- src/librustdoc/html/static/styles/main.css | 8 +- src/librustdoc/lib.rs | 13 +- src/librustdoc/markdown.rs | 4 +- src/librustdoc/test.rs | 63 +- src/librustdoc/visit_ast.rs | 48 +- src/libserialize/Cargo.toml | 2 +- src/libserialize/collection_impls.rs | 29 - src/libserialize/json.rs | 8 + src/libserialize/leb128.rs | 34 +- src/libserialize/lib.rs | 12 +- src/libserialize/opaque.rs | 24 +- src/libserialize/serialize.rs | 33 + src/libstd/Cargo.toml | 1 + src/libstd/ascii.rs | 40 +- src/libstd/build.rs | 7 +- src/libstd/collections/hash/map.rs | 87 +- src/libstd/collections/hash/set.rs | 77 + src/libstd/collections/hash/table.rs | 32 +- src/libstd/env.rs | 64 +- src/libstd/ffi/os_str.rs | 133 +- src/libstd/fs.rs | 228 +- src/libstd/io/buffered.rs | 131 +- src/libstd/io/cursor.rs | 8 +- src/libstd/io/error.rs | 6 +- src/libstd/io/mod.rs | 141 +- src/libstd/io/stdio.rs | 60 +- src/libstd/io/util.rs | 24 +- src/libstd/lib.rs | 23 +- src/libstd/macros.rs | 27 +- src/libstd/net/addr.rs | 42 +- src/libstd/net/ip.rs | 154 +- src/libstd/net/mod.rs | 10 +- src/libstd/net/tcp.rs | 42 +- src/libstd/net/test.rs | 2 +- src/libstd/net/udp.rs | 26 +- src/libstd/num.rs | 1 + src/libstd/os/linux/raw.rs | 10 +- src/libstd/os/mod.rs | 2 +- src/libstd/os/raw.rs | 9 + src/libstd/panic.rs | 12 +- src/libstd/panicking.rs | 2 + src/libstd/path.rs | 133 +- src/libstd/primitive_docs.rs | 99 +- src/libstd/process.rs | 203 +- src/libstd/rand/mod.rs | 7 + src/libstd/sync/barrier.rs | 17 + src/libstd/sync/condvar.rs | 8 + src/libstd/sync/mpsc/mod.rs | 3 + src/libstd/sync/mutex.rs | 92 +- src/libstd/sync/once.rs | 9 + src/libstd/sync/rwlock.rs | 21 +- src/libstd/sys/mod.rs | 2 + src/libstd/sys/redox/args.rs | 14 +- src/libstd/sys/redox/ext/fs.rs | 10 +- src/libstd/sys/redox/ext/io.rs | 35 +- src/libstd/sys/redox/fs.rs | 5 +- src/libstd/sys/redox/mod.rs | 4 +- src/libstd/sys/redox/net/mod.rs | 7 +- src/libstd/sys/redox/net/netc.rs | 57 + src/libstd/sys/redox/net/tcp.rs | 98 +- src/libstd/sys/redox/net/udp.rs | 71 +- src/libstd/sys/redox/os.rs | 9 +- src/libstd/sys/redox/process.rs | 14 + src/libstd/sys/redox/rand.rs | 25 +- src/libstd/sys/redox/syscall/arch/arm.rs | 83 + src/libstd/sys/redox/syscall/arch/x86.rs | 83 + src/libstd/sys/redox/syscall/arch/x86_64.rs | 84 + src/libstd/sys/redox/syscall/call.rs | 300 +++ src/libstd/sys/redox/syscall/data.rs | 105 + src/libstd/sys/redox/syscall/error.rs | 325 +++ src/libstd/sys/redox/syscall/flag.rs | 94 + src/libstd/sys/redox/syscall/mod.rs | 43 + src/libstd/sys/redox/syscall/number.rs | 73 + src/libstd/sys/unix/backtrace/mod.rs | 11 + src/libstd/sys/unix/ext/ffi.rs | 60 +- src/libstd/sys/unix/ext/fs.rs | 10 +- src/libstd/sys/unix/ext/net.rs | 591 ++++- src/libstd/sys/unix/fast_thread_local.rs | 7 + src/libstd/sys/unix/fd.rs | 28 +- src/libstd/sys/unix/fs.rs | 3 +- src/libstd/sys/unix/process/magenta.rs | 141 +- .../sys/unix/process/process_fuchsia.rs | 50 +- src/libstd/sys/unix/process/process_unix.rs | 17 + src/libstd/sys/windows/backtrace.rs | 4 + src/libstd/sys/windows/backtrace_gnu.rs | 62 + src/libstd/sys/windows/c.rs | 54 +- src/libstd/sys/windows/ext/fs.rs | 4 +- src/libstd/sys/windows/ext/process.rs | 6 +- src/libstd/sys/windows/fs.rs | 3 +- src/libstd/sys/windows/handle.rs | 9 +- src/libstd/sys/windows/mod.rs | 47 + src/libstd/sys/windows/process.rs | 15 + src/libstd/sys/windows/stdio.rs | 24 +- src/libstd/sys/windows/thread_local.rs | 2 +- src/libstd/sys_common/gnu/libbacktrace.rs | 17 +- src/libstd/sys_common/mod.rs | 1 + src/libstd/thread/local.rs | 18 +- src/libstd/thread/mod.rs | 247 +- src/libstd/time/duration.rs | 110 +- src/libstd/time/mod.rs | 129 +- src/libstd_unicode/char.rs | 199 +- src/libstd_unicode/lib.rs | 2 +- src/libstd_unicode/tables.rs | 253 +-- src/libsyntax/Cargo.toml | 1 + src/libsyntax/abi.rs | 54 +- src/libsyntax/ast.rs | 237 +- src/libsyntax/attr.rs | 67 +- src/libsyntax/codemap.rs | 17 - src/libsyntax/config.rs | 69 +- src/libsyntax/diagnostic_list.rs | 22 + src/libsyntax/ext/base.rs | 14 +- src/libsyntax/ext/build.rs | 89 +- src/libsyntax/ext/expand.rs | 127 +- src/libsyntax/ext/hygiene.rs | 18 +- src/libsyntax/ext/placeholders.rs | 52 +- src/libsyntax/ext/proc_macro_shim.rs | 72 - src/libsyntax/ext/quote.rs | 18 +- src/libsyntax/ext/tt/macro_parser.rs | 26 +- src/libsyntax/ext/tt/macro_rules.rs | 65 +- src/libsyntax/ext/tt/transcribe.rs | 98 +- src/libsyntax/feature_gate.rs | 146 +- src/libsyntax/fold.rs | 77 +- src/libsyntax/json.rs | 20 +- src/libsyntax/lib.rs | 13 +- src/libsyntax/parse/lexer/comments.rs | 13 +- src/libsyntax/parse/lexer/mod.rs | 216 +- src/libsyntax/parse/lexer/tokentrees.rs | 134 ++ src/libsyntax/parse/lexer/unicode_chars.rs | 6 +- src/libsyntax/parse/mod.rs | 91 +- src/libsyntax/parse/parser.rs | 1228 +++++----- src/libsyntax/parse/token.rs | 53 +- src/libsyntax/print/pprust.rs | 1804 +++++++-------- src/libsyntax/std_inject.rs | 6 +- src/libsyntax/symbol.rs | 3 + src/libsyntax/test.rs | 8 +- src/libsyntax/test_snippet.rs | 388 ++++ src/libsyntax/tokenstream.rs | 854 ++----- src/libsyntax/util/rc_slice.rs | 50 + src/libsyntax/visit.rs | 28 +- src/libsyntax_ext/concat_idents.rs | 7 +- src/libsyntax_ext/deriving/custom.rs | 17 +- src/libsyntax_ext/deriving/generic/mod.rs | 27 +- src/libsyntax_ext/deriving/generic/ty.rs | 2 +- src/libsyntax_ext/deriving/mod.rs | 55 +- src/libsyntax_ext/lib.rs | 9 +- src/libsyntax_ext/proc_macro_impl.rs | 58 + src/libsyntax_ext/proc_macro_registrar.rs | 204 +- src/libsyntax_pos/lib.rs | 2 +- src/libterm/lib.rs | 2 +- src/libterm/terminfo/mod.rs | 2 +- src/libtest/lib.rs | 253 ++- src/libtest/stats.rs | 5 +- src/libunwind/lib.rs | 2 +- src/libunwind/libunwind.rs | 3 + src/rt/rust_test_helpers.c | 16 + src/rustc/std_shim/Cargo.toml | 1 + src/rustllvm/ArchiveWrapper.cpp | 306 +-- src/rustllvm/PassWrapper.cpp | 671 +++--- src/rustllvm/RustWrapper.cpp | 1861 +++++++--------- src/rustllvm/llvm-auto-clean-trigger | 2 +- src/rustllvm/rustllvm.h | 139 +- src/stage0.txt | 4 +- .../partitioning/extern-generic.rs | 6 +- .../partitioning/local-generic.rs | 8 +- .../partitioning/vtable-through-const.rs | 10 +- src/test/codegen/fastcall-inreg.rs | 86 + src/test/codegen/packed.rs | 29 + src/test/codegen/stores.rs | 4 +- .../gated-macro-reexports.rs | 1 + src/test/compile-fail-fulldeps/gated-quote.rs | 2 + .../macro-crate-doesnt-resolve.rs | 2 +- .../proc-macro/auxiliary/attr_proc_macro.rs | 23 + .../proc-macro/derive-bad.rs | 3 +- .../proc-macro/feature-gate-proc_macro.rs | 24 + .../proc-macro/macro-use-attr.rs | 22 + .../proc-macro-custom-attr-mutex.rs | 24 + .../proc-macro/signature.rs | 1 - src/test/compile-fail-fulldeps/qquote.rs | 2 +- src/test/compile-fail/E0001.rs | 6 +- src/test/compile-fail/E0033.rs | 4 +- src/test/compile-fail/E0106.rs | 12 + src/test/compile-fail/E0107.rs | 3 - src/test/compile-fail/E0117.rs | 1 + src/test/compile-fail/E0178.rs | 3 + src/test/compile-fail/E0205.rs | 30 - src/test/compile-fail/E0206.rs | 1 + src/test/compile-fail/E0259.rs | 2 +- src/test/compile-fail/E0277-2.rs | 34 + src/test/compile-fail/E0277.rs | 9 + src/test/compile-fail/E0423.rs | 1 - src/test/compile-fail/E0424.rs | 5 +- src/test/compile-fail/E0425.rs | 2 +- .../compile-fail/{E0308-3.rs => E0580.rs} | 2 +- .../allocator-rust-dylib-is-jemalloc.rs | 6 +- src/test/compile-fail/asm-bad-clobber.rs | 1 + src/test/compile-fail/asm-gated.rs | 2 + src/test/compile-fail/asm-gated2.rs | 2 + src/test/compile-fail/asm-in-bad-modifier.rs | 1 + src/test/compile-fail/asm-misplaced-option.rs | 1 + src/test/compile-fail/asm-out-assign-imm.rs | 1 + src/test/compile-fail/asm-out-no-modifier.rs | 1 + src/test/compile-fail/asm-out-read-uninit.rs | 1 + .../compile-fail/asm-src-loc-codegen-units.rs | 1 + src/test/compile-fail/asm-src-loc.rs | 2 + ...ssociated-const-type-parameter-arrays-2.rs | 6 +- .../associated-const-type-parameter-arrays.rs | 4 +- src/test/compile-fail/associated-path-shl.rs | 10 +- .../compile-fail/associated-types-eq-1.rs | 2 +- ...iated-types-project-from-hrtb-in-struct.rs | 9 +- src/test/compile-fail/attr-literals.rs | 2 + .../attr-on-generic-formals-are-visited.rs | 2 + ...attr-on-generic-formals-wo-feature-gate.rs | 2 + .../attrs-with-no-formal-in-generics-2.rs | 9 +- src/test/compile-fail/autoderef-full-lval.rs | 5 +- .../compile-fail/auxiliary/lint_stability.rs | 4 + src/test/compile-fail/auxiliary/rmeta_meta.rs | 18 + .../compile-fail/auxiliary/rmeta_rlib.rs} | 7 +- src/test/compile-fail/bad-expr-path.rs | 9 +- src/test/compile-fail/bad-expr-path2.rs | 7 +- src/test/compile-fail/bad-main.rs | 2 +- .../compile-fail/binary-op-on-double-ref.rs | 20 + .../compile-fail/blind-item-item-shadow.rs | 2 +- .../borrowck/borrowck-box-insensitivity.rs | 12 +- src/test/compile-fail/can-begin-expr-check.rs | 30 + src/test/compile-fail/cast-rfc0401.rs | 123 - .../cdylib-deps-must-be-static.rs | 1 + .../check-static-values-constraints.rs | 2 + src/test/compile-fail/class-missing-self.rs | 4 +- .../coherence-error-suppression.rs | 2 +- src/test/compile-fail/coherence-impls-copy.rs | 5 +- ...herence-overlapping-inherent-impl-trait.rs | 18 + src/test/compile-fail/concat_idents-gate.rs | 2 + src/test/compile-fail/concat_idents-gate2.rs | 2 + src/test/compile-fail/const-eval-overflow.rs | 14 +- src/test/compile-fail/const-eval-overflow0.rs | 100 - src/test/compile-fail/const-fn-stability.rs | 5 + src/test/compile-fail/const-tup-index-span.rs | 2 +- src/test/compile-fail/cross-borrow-trait.rs | 3 +- .../dep-graph-assoc-type-trans.rs | 2 +- .../compile-fail/dep-graph-caller-callee.rs | 4 +- .../dep-graph-struct-signature.rs | 6 +- ...graph-trait-impl-two-traits-same-method.rs | 4 +- .../dep-graph-trait-impl-two-traits.rs | 4 +- src/test/compile-fail/dep-graph-trait-impl.rs | 10 +- src/test/compile-fail/dep-graph-type-alias.rs | 3 +- .../dep_graph_crosscontaminate_tables.rs | 40 + .../derived-errors/issue-31997.rs | 2 +- .../deriving-meta-unknown-trait.rs | 2 +- src/test/compile-fail/deriving-primitive.rs | 2 +- .../compile-fail/destructure-trait-ref.rs | 3 +- src/test/compile-fail/does-nothing.rs | 2 +- .../compile-fail/empty-struct-braces-expr.rs | 12 +- .../compile-fail/empty-struct-braces-pat-2.rs | 8 +- src/test/compile-fail/enum-variant-type-2.rs | 2 +- .../compile-fail/enums-pats-not-idents.rs | 2 +- ...xclusive_range_pattern_syntax_collision.rs | 18 + ...clusive_range_pattern_syntax_collision2.rs | 18 + ...clusive_range_pattern_syntax_collision3.rs | 18 + .../explicit-self-lifetime-mismatch.rs | 6 +- .../compile-fail/export-fully-qualified.rs | 4 +- src/test/compile-fail/export.rs | 7 +- src/test/compile-fail/export2.rs | 4 +- src/test/compile-fail/extern-main-fn.rs | 2 +- .../compile-fail/extern-with-type-bounds.rs | 2 +- .../feature-gate-abi-msp430-interrupt.rs | 19 + src/test/compile-fail/feature-gate-abi.rs | 11 + .../feature-gate-advanced-slice-features.rs | 2 + ...te-allow-internal-unstable-nested-macro.rs | 2 + .../feature-gate-assoc-type-defaults.rs | 2 + .../compile-fail/feature-gate-box-expr.rs | 2 + src/test/compile-fail/feature-gate-box-pat.rs | 2 + .../feature-gate-dropck-ugeh-2.rs | 22 + .../compile-fail/feature-gate-dropck-ugeh.rs | 5 +- .../feature-gate-exclusive-range-pattern.rs} | 4 +- .../compile-fail/feature-gate-may-dangle.rs | 2 + .../feature-gate-negate-unsigned.rs | 15 +- .../feature-gate-negate-unsigned0.rs | 34 - .../compile-fail/feature-gate-no-debug.rs | 2 + .../feature-gate-placement-expr.rs | 2 + src/test/compile-fail/fn-trait-formatting.rs | 9 +- src/test/compile-fail/for-expn.rs | 2 +- src/test/compile-fail/for-loop-hygiene.rs | 2 +- .../compile-fail/gated-associated_consts.rs | 2 + src/test/compile-fail/gated-attr-literals.rs | 3 + src/test/compile-fail/gated-box-syntax.rs | 2 + src/test/compile-fail/gated-concat_idents.rs | 2 + src/test/compile-fail/gated-link-args.rs | 2 + .../gated-link-llvm-intrinsics.rs | 2 + .../compile-fail/gated-naked_functions.rs | 2 + src/test/compile-fail/gated-no-core.rs | 2 + .../compile-fail/gated-non-ascii-idents.rs | 2 + .../compile-fail/gated-plugin_registrar.rs | 2 + src/test/compile-fail/gated-target_feature.rs | 2 + src/test/compile-fail/gated-thread-local.rs | 2 + src/test/compile-fail/gated-trace_macros.rs | 1 + .../generic-non-trailing-defaults.rs | 20 + src/test/compile-fail/glob-resolve1.rs | 18 +- src/test/compile-fail/i128-feature-2.rs | 32 + src/test/compile-fail/i128-feature-libs.rs | 17 + src/test/compile-fail/i128-feature.rs | 20 + .../compile-fail/impl-trait/disallowed.rs | 2 +- .../compile-fail/impl-trait/feature-gate.rs | 2 + src/test/compile-fail/impl-trait/no-trait.rs | 15 + src/test/compile-fail/import-glob-0.rs | 4 +- src/test/compile-fail/import-glob-circular.rs | 4 +- src/test/compile-fail/imports/duplicate.rs | 8 +- src/test/compile-fail/imports/macro-paths.rs | 8 +- src/test/compile-fail/imports/macros.rs | 12 +- .../imports/rfc-1560-warning-cycle.rs | 4 +- .../compile-fail/imports/unused-macro-use.rs | 21 + src/test/compile-fail/issue-12116.rs | 6 +- src/test/compile-fail/issue-12369.rs | 2 + src/test/compile-fail/issue-13058.rs | 1 - src/test/compile-fail/issue-13727.rs | 3 + src/test/compile-fail/issue-14221.rs | 4 + src/test/compile-fail/issue-14254.rs | 137 -- src/test/compile-fail/issue-1476.rs | 2 +- src/test/compile-fail/issue-14915.rs | 3 +- src/test/compile-fail/issue-15167.rs | 8 +- src/test/compile-fail/issue-17441.rs | 4 +- src/test/compile-fail/issue-17546.rs | 8 +- src/test/compile-fail/issue-17728.rs | 5 +- src/test/compile-fail/issue-17994.rs | 3 +- src/test/compile-fail/issue-18058.rs | 2 +- src/test/compile-fail/issue-18119.rs | 6 +- src/test/compile-fail/issue-18937.rs | 2 - src/test/compile-fail/issue-19498.rs | 6 +- src/test/compile-fail/issue-19883.rs | 2 +- src/test/compile-fail/issue-20616-1.rs | 2 +- src/test/compile-fail/issue-20616-2.rs | 2 +- src/test/compile-fail/issue-20616-3.rs | 2 +- src/test/compile-fail/issue-20616-4.rs | 3 +- src/test/compile-fail/issue-20616-5.rs | 3 +- src/test/compile-fail/issue-20616-6.rs | 3 +- src/test/compile-fail/issue-20616-7.rs | 2 +- src/test/compile-fail/issue-20616-8.rs | 2 +- src/test/compile-fail/issue-20616-9.rs | 2 +- src/test/compile-fail/issue-22037.rs | 2 +- src/test/compile-fail/issue-22384.rs | 2 +- src/test/compile-fail/issue-2281-part1.rs | 4 +- src/test/compile-fail/issue-2330.rs | 2 +- src/test/compile-fail/issue-2356.rs | 109 - src/test/compile-fail/issue-24081.rs | 10 +- src/test/compile-fail/issue-27008.rs | 2 - src/test/compile-fail/issue-27942.rs | 2 - src/test/compile-fail/issue-28075.rs | 2 - src/test/compile-fail/issue-28388-1.rs | 4 +- src/test/compile-fail/issue-28388-3.rs | 5 +- src/test/compile-fail/issue-30240-b.rs | 26 + src/test/compile-fail/issue-30240.rs | 1 - src/test/compile-fail/issue-30302.rs | 5 + src/test/compile-fail/issue-30535.rs | 2 +- src/test/compile-fail/issue-30589.rs | 2 +- src/test/compile-fail/issue-31212.rs | 2 +- src/test/compile-fail/issue-31221.rs | 18 +- src/test/compile-fail/issue-31845.rs | 2 +- src/test/compile-fail/issue-34334.rs | 2 +- src/test/compile-fail/issue-35075.rs | 4 +- src/test/compile-fail/issue-3601.rs | 1 - src/test/compile-fail/issue-36082.rs | 27 + src/test/compile-fail/issue-37534.rs | 4 +- src/test/compile-fail/issue-37884.rs | 1 - src/test/compile-fail/issue-38293.rs | 33 + src/test/compile-fail/issue-38404.rs | 16 + src/test/compile-fail/issue-38458.rs | 15 + src/test/compile-fail/issue-38604.rs | 26 + src/test/compile-fail/issue-39122.rs | 13 + src/test/compile-fail/issue-39388.rs | 17 + src/test/compile-fail/issue-39616.rs | 15 + src/test/compile-fail/issue-4366-2.rs | 4 +- src/test/compile-fail/issue-4366.rs | 2 +- src/test/compile-fail/issue-5099.rs | 2 +- src/test/compile-fail/issue-5100.rs | 3 +- src/test/compile-fail/issue-5927.rs | 4 +- src/test/compile-fail/issue-7061.rs | 3 +- src/test/compile-fail/issue-7607-1.rs | 2 +- src/test/compile-fail/issue-8767.rs | 2 +- .../keyword-self-as-identifier.rs | 2 +- .../keyword-super-as-identifier.rs | 2 +- src/test/compile-fail/keyword-super.rs | 2 +- .../compile-fail/kindck-impl-type-params-2.rs | 2 +- ...-return-type-requires-explicit-lifetime.rs | 24 + ...me-inference-give-expl-lifetime-param-2.rs | 36 - ...me-inference-give-expl-lifetime-param-3.rs | 32 - ...time-inference-give-expl-lifetime-param.rs | 57 - src/test/compile-fail/link-cfg-gated.rs | 2 + src/test/compile-fail/linkage1.rs | 2 + .../compile-fail/lint-attr-non-item-node.rs | 19 + src/test/compile-fail/lint-ctypes.rs | 4 +- .../compile-fail/lint-unused-extern-crate.rs | 7 +- src/test/compile-fail/log-syntax-gate.rs | 2 + src/test/compile-fail/log-syntax-gate2.rs | 2 + .../macro-expanded-include/test.rs | 2 + .../compile-fail/macro-outer-attributes.rs | 2 +- src/test/compile-fail/macro-parameter-span.rs | 2 +- .../compile-fail/macro-with-seps-err-msg.rs | 2 + src/test/compile-fail/main-wrong-type-2.rs | 2 +- src/test/compile-fail/main-wrong-type.rs | 2 +- src/test/compile-fail/map-types.rs | 2 +- src/test/compile-fail/match-argm-statics-2.rs | 71 + src/test/compile-fail/match-arm-statics.rs | 42 +- .../match-byte-array-patterns-2.rs | 26 + .../compile-fail/match-byte-array-patterns.rs | 9 +- src/test/compile-fail/match-join.rs | 2 +- .../compile-fail/match-privately-empty.rs | 30 + src/test/compile-fail/match-range-fail-2.rs | 8 + .../compile-fail/match-range-fail-dominate.rs | 2 + src/test/compile-fail/match-ref-ice.rs | 3 +- src/test/compile-fail/match-slice-patterns.rs | 2 +- src/test/compile-fail/match-vec-fixed.rs | 1 + src/test/compile-fail/match-vec-mismatch.rs | 2 +- .../compile-fail/match-vec-unreachable.rs | 4 +- .../compile-fail/mod_file_correct_spans.rs | 3 +- src/test/compile-fail/name-clash-nullary.rs | 4 +- src/test/compile-fail/namespace-mix.rs | 8 +- ...spaced-enum-glob-import-no-impls-xcrate.rs | 8 +- .../namespaced-enum-glob-import-no-impls.rs | 8 +- src/test/compile-fail/nested-cfg-attrs.rs | 2 +- src/test/compile-fail/never-disabled.rs | 2 + src/test/compile-fail/no-core-gated.rs | 2 + .../no-implicit-prelude-nested.rs | 36 +- src/test/compile-fail/no-implicit-prelude.rs | 12 +- src/test/compile-fail/no-link.rs | 2 +- .../non-constant-expr-for-fixed-len-vec.rs | 4 +- .../non-constant-expr-for-vec-repeat.rs | 7 +- .../numeric-fields-feature-gate.rs | 2 + .../object-does-not-impl-trait.rs | 2 +- src/test/compile-fail/occurs-check-2.rs | 2 +- src/test/compile-fail/occurs-check.rs | 2 +- .../abort-link-to-unwind-dylib.rs | 1 + .../compile-fail/panic-runtime/needs-gate.rs | 3 + src/test/compile-fail/parser-recovery-1.rs | 4 +- src/test/compile-fail/parser-recovery-2.rs | 4 +- .../compile-fail/pattern-macro-hygiene.rs | 2 +- src/test/compile-fail/privacy-ns1.rs | 8 +- src/test/compile-fail/privacy-ns2.rs | 8 +- .../privacy/restricted/feature-gate.rs | 2 + .../compile-fail/privacy/restricted/test.rs | 2 +- .../privacy/restricted/ty-params.rs | 4 +- .../compile-fail/private-in-public-warn.rs | 1 + src/test/compile-fail/recursive-reexports.rs | 2 +- ...=> recursive-types-are-not-uninhabited.rs} | 17 +- src/test/compile-fail/reflect-assoc.rs | 37 - src/test/compile-fail/reflect-object-param.rs | 49 - src/test/compile-fail/reflect.rs | 41 - ...n-bounds-on-objects-and-type-parameters.rs | 6 +- .../regions-infer-paramd-indirect.rs | 4 +- src/test/compile-fail/repeat_count.rs | 21 +- ...e-gate.rs => resolve-bad-import-prefix.rs} | 27 +- .../compile-fail/resolve-bad-visibility.rs | 27 + .../resolve-conflict-item-vs-import.rs | 2 +- .../resolve-primitive-fallback.rs | 4 +- .../compile-fail/resolve-self-in-impl-2.rs | 17 + src/test/compile-fail/resolve-self-in-impl.rs | 26 + .../compile-fail/resolve-unknown-trait.rs | 6 +- .../resolve-variant-assoc-item.rs | 17 + src/test/compile-fail/rfc1445/feature-gate.rs | 2 + src/test/compile-fail/rfc1623.rs | 4 +- src/test/compile-fail/rmeta-lib-pass.rs | 24 + src/test/compile-fail/rmeta-pass.rs | 25 + src/test/compile-fail/rmeta-priv-warn.rs | 21 + src/test/compile-fail/rmeta.rs | 18 + src/test/compile-fail/rmeta_lib.rs | 23 + src/test/compile-fail/rmeta_meta_main.rs | 24 + src/test/compile-fail/self_type_keyword-2.rs | 6 +- src/test/compile-fail/single-derive-attr.rs | 2 + .../specialization-feature-gate-default.rs | 2 + .../specialization-feature-gate-overlap.rs | 2 + .../compile-fail/static-mut-not-constant.rs | 2 + .../compile-fail/str-concat-on-double-ref.rs | 18 + .../struct-field-attr-feature-gate.rs | 22 + src/test/compile-fail/struct-field-cfg.rs | 30 + .../struct-fields-shorthand-unresolved.rs | 2 +- .../struct-path-associated-type.rs | 2 - .../struct-path-self-type-mismatch.rs | 2 - src/test/compile-fail/struct-path-self.rs | 2 - .../struct-pattern-match-useless.rs | 4 +- .../compile-fail/syntax-extension-minor.rs | 2 +- src/test/compile-fail/terr-sorts.rs | 3 +- src/test/compile-fail/test-cfg.rs | 2 +- .../trait-bounds-not-on-struct.rs | 2 +- ...ect-reference-without-parens-suggestion.rs | 2 + src/test/compile-fail/trivial_casts.rs | 5 +- src/test/compile-fail/two-allocators-3.rs | 1 + .../type-ascription-feature-gate.rs | 2 + .../type-mismatch-same-crate-name.rs | 4 +- .../type-parameter-invalid-lint.rs | 2 + .../compile-fail/ufcs-partially-resolved.rs | 66 + src/test/compile-fail/unadjusted-unstable.rs | 19 + .../unboxed-closure-sugar-region.rs | 4 +- .../compile-fail/uninhabited-irrefutable.rs | 38 + .../uninhabited-matches-feature-gated.rs | 46 + src/test/compile-fail/uninhabited-patterns.rs | 57 + .../compile-fail/union/union-feature-gate.rs | 2 + src/test/compile-fail/unreachable-arm.rs | 15 +- .../compile-fail/unreachable-loop-patterns.rs | 20 + .../compile-fail/unreachable-try-pattern.rs | 50 + src/test/compile-fail/variant-used-as-type.rs | 4 +- .../where-equality-constraints.rs | 16 + .../compile-fail/where-lifetime-resolution.rs | 23 + .../compile-fail/windows-subsystem-gated.rs | 2 + src/test/compile-fail/xcrate-unit-struct.rs | 2 +- src/test/debuginfo/borrowed-enum.rs | 1 + .../debuginfo/generic-struct-style-enum.rs | 1 + .../debuginfo/generic-tuple-style-enum.rs | 1 + .../{issue12886.rs => issue-12886.rs} | 0 .../{issue13213.rs => issue-13213.rs} | 0 .../{issue14411.rs => issue-14411.rs} | 0 .../{issue22656.rs => issue-22656.rs} | 0 .../debuginfo/{issue7712.rs => issue-7712.rs} | 0 src/test/debuginfo/packed-struct.rs | 1 + src/test/debuginfo/recursive-struct.rs | 1 + src/test/debuginfo/struct-in-enum.rs | 1 + src/test/debuginfo/struct-style-enum.rs | 1 + src/test/debuginfo/tuple-style-enum.rs | 1 + src/test/debuginfo/type-names.rs | 12 +- src/test/debuginfo/union-smoke.rs | 5 +- src/test/debuginfo/unique-enum.rs | 1 + src/test/debuginfo/unsized.rs | 45 + .../auxiliary/point.rs | 2 + .../struct_point.rs | 10 +- .../callee_caller_cross_crate/auxiliary/a.rs | 2 + .../callee_caller_cross_crate/b.rs | 4 +- .../change_add_field/struct_point.rs | 14 +- .../incremental/change_crate_order/main.rs | 2 +- .../change_private_fn/struct_point.rs | 10 +- .../change_private_fn_cc/auxiliary/point.rs | 2 + .../change_private_fn_cc/struct_point.rs | 10 +- .../struct_point.rs | 10 +- .../auxiliary/point.rs | 2 + .../struct_point.rs | 10 +- .../struct_point.rs | 10 +- .../struct_point.rs | 10 +- src/test/incremental/dirty_clean.rs | 8 +- src/test/incremental/hashes/consts.rs | 16 +- src/test/incremental/hashes/enum_defs.rs | 6 +- src/test/incremental/hashes/extern_mods.rs | 272 +++ src/test/incremental/hashes/inherent_impls.rs | 410 +++- src/test/incremental/hashes/inline_asm.rs | 265 +++ src/test/incremental/hashes/statics.rs | 24 +- src/test/incremental/hashes/trait_defs.rs | 180 +- src/test/incremental/hashes/trait_impls.rs | 152 ++ src/test/incremental/hello_world.rs | 4 +- .../auxiliary/a.rs | 2 + .../rlib_cross_crate/auxiliary/a.rs | 1 + src/test/incremental/rlib_cross_crate/b.rs | 8 +- src/test/incremental/string_constant.rs | 10 +- src/test/incremental/struct_add_field.rs | 6 +- .../incremental/struct_change_field_name.rs | 6 +- .../incremental/struct_change_field_type.rs | 6 +- .../auxiliary/a.rs | 2 + .../struct_change_field_type_cross_crate/b.rs | 6 +- src/test/incremental/struct_change_nothing.rs | 6 +- src/test/incremental/struct_remove_field.rs | 6 +- .../type_alias_cross_crate/auxiliary/a.rs | 2 + .../incremental/type_alias_cross_crate/b.rs | 8 +- src/test/parse-fail/bounds-lifetime-1.rs | 15 + src/test/parse-fail/bounds-lifetime-2.rs | 15 + .../parse-fail/bounds-lifetime-where-1.rs | 15 + src/test/parse-fail/bounds-lifetime-where.rs | 22 + src/test/parse-fail/bounds-lifetime.rs | 24 + src/test/parse-fail/bounds-obj-parens.rs | 15 + src/test/parse-fail/bounds-type-where.rs | 23 + src/test/parse-fail/bounds-type.rs | 23 + .../parse-fail/int-literal-too-large-span.rs | 4 +- src/test/parse-fail/issue-14303-path.rs | 1 - ...-trailing-defaults.rs => issue-17904-2.rs} | 6 +- src/test/parse-fail/issue-17904.rs | 3 +- src/test/parse-fail/issue-32214.rs | 5 +- src/test/parse-fail/issue-33569.rs | 2 +- src/test/parse-fail/issue-5544-a.rs | 2 +- src/test/parse-fail/issue-5544-b.rs | 2 +- .../parse-fail/lex-bad-numeric-literals.rs | 4 +- src/test/parse-fail/lifetime-semicolon.rs | 3 +- src/test/parse-fail/pat-ranges-4.rs | 2 +- src/test/parse-fail/pat-tuple-5.rs | 2 +- .../where-clauses-no-bounds-or-predicates.rs | 4 +- src/test/pretty/attr-variant-data.rs | 51 - src/test/pretty/issue-4264.pp | 2 +- src/test/pretty/path-type-bounds.rs | 6 +- .../graphviz-flowgraph/f18.dot-expected.dot | 6 +- .../graphviz-flowgraph/f19.dot-expected.dot | 8 +- .../pretty-print-path-suffix/foo_method.pp | 5 +- .../run-make/stable-symbol-names/Makefile | 28 +- .../stable-symbol-names1.rs | 21 +- .../stable-symbol-names2.rs | 12 +- src/test/run-make/test-harness/Makefile | 2 +- .../auxiliary/cond_noprelude_plugin.rs | 65 - .../auxiliary/cond_plugin.rs | 69 +- .../auxiliary/cond_prelude_plugin.rs | 60 - .../auxiliary/custom_derive_plugin.rs | 2 +- .../auxiliary/hello_macro.rs | 34 + .../auxiliary/proc_macro_def.rs | 17 +- .../issue-37290/auxiliary/lint.rs | 8 +- src/test/run-pass-fulldeps/macro-quote-1.rs | 12 +- .../macro-quote-empty-delims.rs | 22 + .../macro-quote-noprelude.rs | 54 - .../run-pass-fulldeps/macro-quote-prelude.rs | 54 - .../run-pass-fulldeps/proc-macro/attr-args.rs | 24 + .../proc-macro/auxiliary/attr-args.rs | 32 + .../proc-macro/auxiliary/derive-atob.rs | 2 +- .../proc-macro/auxiliary/derive-ctod.rs | 2 +- .../auxiliary/derive-same-struct.rs | 4 +- .../proc-macro/derive-test.rs | 3 + .../down-with-thread-dtors.rs | 1 + src/test/run-pass-valgrind/exit-flushes.rs | 1 + src/test/run-pass/allocator-default.rs | 3 +- .../run-pass/auxiliary/debuginfo-lto-aux.rs | 39 + src/test/run-pass/auxiliary/issue13507.rs | 2 +- src/test/run-pass/auxiliary/issue_39823.rs | 17 + src/test/run-pass/auxiliary/rmeta_rlib.rs | 18 + src/test/run-pass/auxiliary/rmeta_rmeta.rs | 19 + src/test/run-pass/auxiliary/sepcomp_lib.rs | 2 +- src/test/run-pass/backtrace-debuginfo.rs | 2 - src/test/run-pass/backtrace.rs | 4 - src/test/run-pass/conditional-compile-arch.rs | 6 + src/test/run-pass/const-enum-vec-index.rs | 2 + src/test/run-pass/debuginfo-lto.rs | 33 + src/test/run-pass/empty-types-in-patterns.rs | 65 + src/test/run-pass/extern_fat_drop.rs | 2 - src/test/run-pass/i128-ffi.rs | 47 + src/test/run-pass/i128.rs | 110 + .../{issue18173.rs => issue-18173.rs} | 0 src/test/run-pass/issue-21634.rs | 6 +- .../{issue22008.rs => issue-22008.rs} | 0 .../{issue22346.rs => issue-22346.rs} | 0 .../{issue24353.rs => issue-24353.rs} | 0 .../{issue26127.rs => issue-26127.rs} | 0 .../{issue29927.rs => issue-29927.rs} | 0 src/test/run-pass/issue-31260.rs | 20 + src/test/run-pass/issue-32947.rs | 31 + src/test/run-pass/issue-33187.rs | 27 + .../{issue34569.rs => issue-34569.rs} | 0 .../{issue34796.rs => issue-34796.rs} | 0 .../{issue36260.rs => issue-36260.rs} | 0 src/test/run-pass/issue-38074.rs | 27 + .../E0248.rs => run-pass/issue-38556.rs} | 12 +- src/test/run-pass/issue-38942.rs | 26 + src/test/run-pass/issue-38972.rs | 25 + src/test/run-pass/issue-38987.rs | 18 + .../issue-39089.rs} | 6 +- src/test/run-pass/issue-39709.rs | 18 + src/test/run-pass/issue-39823.rs | 34 + .../issue-40136.rs} | 16 +- src/test/run-pass/match-range.rs | 19 +- ...object-lifetime-default-from-ref-struct.rs | 18 + .../object-lifetime-default-from-rptr.rs | 6 + src/test/run-pass/panic-safe.rs | 5 +- src/test/run-pass/process-envs.rs | 62 + src/test/run-pass/process-remove-from-env.rs | 3 +- src/test/run-pass/rmeta.rs | 22 + src/test/run-pass/sepcomp-lib-lto.rs | 2 +- src/test/run-pass/sse2.rs | 15 +- src/test/run-pass/stdio-is-blocking.rs | 2 + .../run-pass/struct-path-associated-type.rs | 2 - src/test/run-pass/struct-path-self.rs | 2 - .../sync-send-iterators-in-libcollections.rs | 6 +- ...est-allow-dead-extern-static-no-warning.rs | 20 + src/test/run-pass/trans-object-shim.rs | 14 + src/test/run-pass/try-wait.rs | 67 + src/test/run-pass/u128.rs | 83 + src/test/run-pass/union/union-nodrop.rs | 63 + src/test/rustdoc/issue-32374.rs | 12 +- src/test/rustdoc/search-index-summaries.rs | 20 + src/test/ui/check_match/issue-35609.stderr | 4 +- src/test/ui/codemap_tests/tab.stderr | 4 +- src/test/ui/codemap_tests/two_files.stderr | 6 +- src/test/ui/codemap_tests/unicode.stderr | 2 +- .../proj-outlives-region.stderr | 7 +- .../ui/compare-method/region-unrelated.stderr | 7 +- .../reordered-type-param.stderr | 2 +- src/test/ui/custom-derive/auxiliary/plugin.rs | 28 + src/test/ui/custom-derive/issue-36935.rs | 23 + src/test/ui/custom-derive/issue-36935.stderr | 8 + ...issue-21659-show-relevant-trait-impls-1.rs | 0 ...e-21659-show-relevant-trait-impls-1.stderr | 12 + ...issue-21659-show-relevant-trait-impls-2.rs | 0 ...e-21659-show-relevant-trait-impls-2.stderr | 15 + src/test/ui/did_you_mean/issue-38147-1.rs | 31 + src/test/ui/did_you_mean/issue-38147-1.stderr | 10 + src/test/ui/did_you_mean/issue-38147-2.rs | 21 + src/test/ui/did_you_mean/issue-38147-2.stderr | 11 + src/test/ui/did_you_mean/issue-38147-3.rs | 21 + src/test/ui/did_you_mean/issue-38147-3.stderr | 13 + src/test/ui/did_you_mean/issue-38147-4.rs | 19 + src/test/ui/did_you_mean/issue-38147-4.stderr | 10 + .../did_you_mean/issue-39544.rs} | 13 +- src/test/ui/did_you_mean/issue-39544.stderr | 8 + .../ex1-return-one-existing-name-if-else.rs} | 9 +- ...x1-return-one-existing-name-if-else.stderr | 25 + .../ex1b-return-no-names-if-else.rs | 15 + .../ex1b-return-no-names-if-else.stderr | 10 + .../ex2a-push-one-existing-name.rs | 19 + .../ex2a-push-one-existing-name.stderr | 27 + .../ex2b-push-no-existing-names.rs | 19 + .../ex2b-push-no-existing-names.stderr | 27 + .../ex2c-push-inference-variable.rs | 20 + .../ex2c-push-inference-variable.stderr | 37 + .../ex2d-push-inference-variable-2.rs | 21 + .../ex2d-push-inference-variable-2.stderr | 39 + .../ex2e-push-inference-variable-3.rs | 21 + .../ex2e-push-inference-variable-3.stderr | 39 + .../consider-using-explicit-lifetime.stderr | 25 - .../ui/macros/macro-backtrace-nested.stderr | 8 +- .../mismatched_types}/E0053.rs | 0 src/test/ui/mismatched_types/E0053.stderr | 23 + .../mismatched_types}/E0409.rs | 0 src/test/ui/mismatched_types/E0409.stderr | 19 + src/test/ui/mismatched_types/cast-rfc0401.rs | 82 + .../ui/mismatched_types/cast-rfc0401.stderr | 240 ++ .../mismatched_types}/issue-19109.rs | 0 .../ui/mismatched_types/issue-19109.stderr | 11 + .../ui/mismatched_types/issue-35030.stderr | 2 +- src/test/ui/mismatched_types/issue-38371.rs | 37 + .../ui/mismatched_types/issue-38371.stderr | 36 + src/test/ui/mismatched_types/main.stderr | 2 +- .../mismatched_types}/overloaded-calls-bad.rs | 0 .../overloaded-calls-bad.stderr | 23 + .../trait-bounds-cant-coerce.rs | 0 .../trait-bounds-cant-coerce.stderr | 11 + .../trait-impl-fn-incompatibility.stderr | 2 +- src/test/ui/missing-items/issue-40221.rs | 26 + src/test/ui/missing-items/issue-40221.stderr | 8 + .../resolve}/auxiliary/issue-21221-3.rs | 0 .../resolve}/auxiliary/issue-21221-4.rs | 0 .../resolve}/auxiliary/issue_19452_aux.rs | 0 .../resolve}/auxiliary/issue_3907.rs | 0 .../ui/resolve/auxiliary/namespaced_enums.rs | 20 + .../resolve}/enums-are-namespaced-xc.rs | 9 +- .../ui/resolve/enums-are-namespaced-xc.stderr | 29 + src/test/ui/resolve/issue-14254.rs | 137 ++ src/test/ui/resolve/issue-14254.stderr | 148 ++ .../resolve}/issue-16058.rs | 7 +- src/test/ui/resolve/issue-16058.stderr | 13 + .../resolve}/issue-17518.rs | 1 + src/test/ui/resolve/issue-17518.stderr | 11 + .../resolve}/issue-18252.rs | 3 +- src/test/ui/resolve/issue-18252.stderr | 8 + .../resolve}/issue-19452.rs | 6 +- src/test/ui/resolve/issue-19452.stderr | 14 + .../resolve}/issue-21221-1.rs | 13 +- src/test/ui/resolve/issue-21221-1.stderr | 41 + .../resolve}/issue-21221-2.rs | 4 +- src/test/ui/resolve/issue-21221-2.stderr | 13 + .../resolve}/issue-21221-3.rs | 4 +- src/test/ui/resolve/issue-21221-3.stderr | 11 + .../resolve}/issue-21221-4.rs | 4 +- src/test/ui/resolve/issue-21221-4.stderr | 11 + .../resolve}/issue-23305.rs | 8 +- src/test/ui/resolve/issue-23305.stderr | 8 + src/test/ui/resolve/issue-2356.rs | 125 ++ src/test/ui/resolve/issue-2356.stderr | 110 + .../resolve}/issue-24968.rs | 3 +- src/test/ui/resolve/issue-24968.stderr | 8 + .../resolve}/issue-33876.rs | 3 +- src/test/ui/resolve/issue-33876.stderr | 8 + .../resolve}/issue-3907-2.rs | 0 src/test/ui/resolve/issue-3907-2.stderr | 10 + .../resolve}/issue-3907.rs | 4 +- src/test/ui/resolve/issue-3907.stderr | 11 + .../resolve}/issue-5035-2.rs | 0 src/test/ui/resolve/issue-5035-2.stderr | 11 + .../resolve}/issue-5035.rs | 5 +- src/test/ui/resolve/issue-5035.stderr | 14 + .../resolve}/issue-6702.rs | 4 +- src/test/ui/resolve/issue-6702.stderr | 8 + src/test/ui/resolve/levenshtein.rs | 33 + src/test/ui/resolve/levenshtein.stderr | 56 + .../ui/resolve/resolve-assoc-suggestions.rs | 58 + .../resolve/resolve-assoc-suggestions.stderr | 56 + .../resolve}/resolve-hint-macro.rs | 4 +- src/test/ui/resolve/resolve-hint-macro.stderr | 8 + .../resolve/resolve-speculative-adjustment.rs | 44 + .../resolve-speculative-adjustment.stderr | 26 + .../suggest-path-instead-of-mod-dot-item.rs | 36 +- ...uggest-path-instead-of-mod-dot-item.stderr | 58 + .../resolve}/token-error-correct-2.rs | 7 +- .../ui/resolve/token-error-correct-2.stderr | 20 + .../resolve}/token-error-correct-3.rs | 4 +- .../ui/resolve/token-error-correct-3.stderr | 45 + .../resolve}/token-error-correct.rs | 20 +- .../ui/resolve/token-error-correct.stderr | 56 + .../resolve/tuple-struct-alias.rs} | 19 +- src/test/ui/resolve/tuple-struct-alias.stderr | 26 + ...unboxed-closure-sugar-nonexistent-trait.rs | 21 + ...xed-closure-sugar-nonexistent-trait.stderr | 14 + .../unresolved_static_type_field.rs} | 23 +- .../unresolved_static_type_field.stderr | 11 + src/test/{compile-fail => ui/span}/E0204.rs | 18 +- src/test/ui/span/E0204.stderr | 38 + ...ck-borrow-overloaded-auto-deref-mut.stderr | 8 +- ...orrowck-borrow-overloaded-deref-mut.stderr | 4 +- ...borrowck-call-is-borrow-issue-12224.stderr | 6 +- ...owck-call-method-from-mut-aliasable.stderr | 2 +- .../ui/span/borrowck-fn-in-const-b.stderr | 2 +- .../ui/span/borrowck-object-mutability.stderr | 4 +- src/test/ui/span/coerce-suggestions.rs | 47 + src/test/ui/span/coerce-suggestions.stderr | 55 + .../ui/span/impl-wrong-item-for-trait.stderr | 6 + src/test/ui/span/issue-24690.stderr | 24 +- src/test/ui/span/issue-27522.rs | 19 + src/test/ui/span/issue-27522.stderr | 11 + src/test/ui/span/issue-35987.stderr | 9 +- src/test/ui/span/issue-37767.rs | 51 + src/test/ui/span/issue-37767.stderr | 59 + .../{compile-fail => ui/span}/issue-7575.rs | 12 +- src/test/ui/span/issue-7575.stderr | 67 + src/test/ui/span/move-closure.stderr | 2 +- src/test/ui/span/multiline-span-simple.stderr | 8 +- src/test/ui/span/mut-arg-hint.stderr | 20 +- src/test/ui/span/typo-suggestion.stderr | 6 +- src/tools/build-manifest/Cargo.toml | 8 + src/tools/build-manifest/src/main.rs | 416 ++++ src/tools/cargotest/main.rs | 51 +- src/tools/compiletest/Cargo.toml | 2 +- src/tools/compiletest/src/header.rs | 50 +- src/tools/compiletest/src/main.rs | 29 +- src/tools/compiletest/src/procsrv.rs | 48 +- src/tools/compiletest/src/runtest.rs | 99 +- src/tools/compiletest/src/util.rs | 69 +- src/tools/linkchecker/main.rs | 21 +- src/tools/rustbook/Cargo.toml | 1 + src/tools/tidy/src/features.rs | 133 +- src/tools/tidy/src/main.rs | 5 + src/tools/tidy/src/pal.rs | 2 + version | 2 +- x.py | 22 + 1455 files changed, 50034 insertions(+), 29810 deletions(-) create mode 100644 mk/cfg/sparc64-unknown-linux-gnu.mk create mode 100644 mk/cfg/sparc64-unknown-netbsd.mk create mode 100644 mk/cfg/x86_64-unknown-redox.mk create mode 100644 src/ci/docker/README.md create mode 100755 src/ci/docker/cross/build-arm-musl.sh create mode 100755 src/ci/docker/cross/build-rumprun.sh create mode 100644 src/ci/docker/dist-android/Dockerfile create mode 100644 src/ci/docker/dist-android/install-ndk.sh create mode 100644 src/ci/docker/dist-arm-linux/Dockerfile create mode 100644 src/ci/docker/dist-arm-linux/arm-linux-gnueabi.config create mode 100644 src/ci/docker/dist-arm-linux/arm-linux-gnueabihf.config create mode 100755 src/ci/docker/dist-arm-linux/build-toolchains.sh create mode 100644 src/ci/docker/dist-armv7-aarch64-linux/Dockerfile create mode 100644 src/ci/docker/dist-armv7-aarch64-linux/aarch64-linux-gnu.config create mode 100644 src/ci/docker/dist-armv7-aarch64-linux/armv7-linux-gnueabihf.config create mode 100755 src/ci/docker/dist-armv7-aarch64-linux/build-toolchains.sh create mode 100644 src/ci/docker/dist-freebsd/Dockerfile rename src/ci/docker/{x86_64-freebsd => dist-freebsd}/build-toolchain.sh (83%) mode change 100644 => 100755 rename src/ci/docker/{x86_64-freebsd => dist-mips-linux}/Dockerfile (66%) create mode 100644 src/ci/docker/dist-mips64-linux/Dockerfile create mode 100644 src/ci/docker/dist-powerpc-linux/Dockerfile create mode 100755 src/ci/docker/dist-powerpc-linux/build-powerpc-toolchain.sh create mode 100644 src/ci/docker/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch create mode 100644 src/ci/docker/dist-powerpc-linux/powerpc-linux-gnu.config create mode 100644 src/ci/docker/dist-powerpc64-linux/Dockerfile create mode 100755 src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh create mode 100755 src/ci/docker/dist-powerpc64-linux/build-powerpc64le-toolchain.sh create mode 100644 src/ci/docker/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch create mode 100644 src/ci/docker/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch create mode 100644 src/ci/docker/dist-powerpc64-linux/powerpc64-linux-gnu.config create mode 100644 src/ci/docker/dist-s390x-linux-netbsd/Dockerfile create mode 100755 src/ci/docker/dist-s390x-linux-netbsd/build-netbsd-toolchain.sh create mode 100755 src/ci/docker/dist-s390x-linux-netbsd/build-s390x-toolchain.sh create mode 100644 src/ci/docker/dist-s390x-linux-netbsd/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch create mode 100644 src/ci/docker/dist-s390x-linux-netbsd/s390x-linux-gnu.config create mode 100644 src/ci/docker/dist-x86-linux/Dockerfile create mode 100755 src/ci/docker/dist-x86-linux/build-binutils.sh create mode 100755 src/ci/docker/dist-x86-linux/build-cmake.sh create mode 100755 src/ci/docker/dist-x86-linux/build-curl.sh create mode 100755 src/ci/docker/dist-x86-linux/build-gcc.sh create mode 100755 src/ci/docker/dist-x86-linux/build-git.sh create mode 100755 src/ci/docker/dist-x86-linux/build-openssl.sh create mode 100755 src/ci/docker/dist-x86-linux/build-python.sh create mode 100644 src/ci/docker/dist-x86-linux/shared.sh create mode 100644 src/ci/docker/emscripten/Dockerfile create mode 100755 src/ci/docker/emscripten/build-emscripten.sh create mode 100644 src/ci/docker/linux-tested-targets/Dockerfile create mode 100644 src/ci/docker/linux-tested-targets/build-musl.sh create mode 100644 src/ci/docker/linux-tested-targets/musl-libunwind-patch.patch rename src/ci/docker/{x86_64-gnu-cargotest => x86_64-gnu-aux}/Dockerfile (88%) create mode 100644 src/ci/docker/x86_64-gnu-distcheck/Dockerfile rename src/ci/docker/{x86_64-musl => x86_64-gnu-full-bootstrap}/Dockerfile (62%) create mode 100644 src/ci/docker/x86_64-gnu-incremental/Dockerfile delete mode 100644 src/ci/docker/x86_64-musl/build-musl.sh create mode 100644 src/etc/installer/README.md create mode 100644 src/etc/installer/exe/modpath.iss create mode 100644 src/etc/installer/exe/rust.iss create mode 100644 src/etc/installer/exe/upgrade.iss create mode 100644 src/etc/installer/gfx/banner.bmp create mode 100644 src/etc/installer/gfx/banner.xcf create mode 100644 src/etc/installer/gfx/dialogbg.bmp create mode 100644 src/etc/installer/gfx/dialogbg.xcf create mode 100644 src/etc/installer/gfx/rust-logo.ico create mode 100644 src/etc/installer/gfx/rust-logo.png create mode 100644 src/etc/installer/msi/remove-duplicates.xsl create mode 100644 src/etc/installer/msi/rust.wxs create mode 100644 src/etc/installer/msi/rustwelcomedlg.wxs create mode 100644 src/etc/installer/msi/squash-components.xsl create mode 100644 src/etc/installer/msi/ui.wxs create mode 100644 src/etc/installer/pkg/Distribution.xml create mode 100755 src/etc/installer/pkg/postinstall create mode 100644 src/etc/platform-intrinsics/nvptx/cuda.json create mode 100644 src/etc/platform-intrinsics/nvptx/info.json create mode 100644 src/etc/platform-intrinsics/nvptx/sreg.json create mode 100644 src/liballoc_jemalloc/pthread_atfork_dummy.c delete mode 100644 src/libcollectionstest/enum_set.rs create mode 100644 src/libcore/num/i128.rs create mode 100644 src/libcore/num/u128.rs create mode 100644 src/liblibc/src/unix/notbsd/linux/other/b64/sparc64.rs delete mode 100644 src/libproc_macro_tokens/Cargo.toml delete mode 100644 src/libproc_macro_tokens/build.rs delete mode 100644 src/libproc_macro_tokens/lib.rs delete mode 100644 src/libproc_macro_tokens/parse.rs delete mode 100644 src/librustc/middle/const_qualif.rs create mode 100644 src/librustc/ty/inhabitedness/def_id_forest.rs create mode 100644 src/librustc/ty/inhabitedness/mod.rs create mode 100644 src/librustc_back/target/emscripten_base.rs create mode 100644 src/librustc_back/target/redox_base.rs create mode 100644 src/librustc_back/target/sparc64_unknown_linux_gnu.rs create mode 100644 src/librustc_back/target/sparc64_unknown_netbsd.rs create mode 100644 src/librustc_back/target/x86_64_unknown_redox.rs create mode 100644 src/librustc_i128/Cargo.toml create mode 100644 src/librustc_i128/lib.rs create mode 100644 src/librustc_platform_intrinsics/nvptx.rs create mode 100644 src/librustc_trans/README.md delete mode 100644 src/librustc_trans/README.txt delete mode 100644 src/librustc_trans/basic_block.rs delete mode 100644 src/librustc_trans/build.rs create mode 100644 src/librustc_trans/cabi_nvptx.rs create mode 100644 src/librustc_trans/cabi_nvptx64.rs create mode 100644 src/librustc_trans/cabi_sparc.rs create mode 100644 src/librustc_trans/cabi_sparc64.rs create mode 100644 src/librustc_typeck/coherence/builtin.rs delete mode 100644 src/librustc_typeck/rscope.rs create mode 100644 src/libstd/sys/redox/net/netc.rs create mode 100644 src/libstd/sys/redox/syscall/arch/arm.rs create mode 100644 src/libstd/sys/redox/syscall/arch/x86.rs create mode 100644 src/libstd/sys/redox/syscall/arch/x86_64.rs create mode 100644 src/libstd/sys/redox/syscall/call.rs create mode 100644 src/libstd/sys/redox/syscall/data.rs create mode 100644 src/libstd/sys/redox/syscall/error.rs create mode 100644 src/libstd/sys/redox/syscall/flag.rs create mode 100644 src/libstd/sys/redox/syscall/mod.rs create mode 100644 src/libstd/sys/redox/syscall/number.rs create mode 100644 src/libstd/sys/windows/backtrace_gnu.rs delete mode 100644 src/libsyntax/ext/proc_macro_shim.rs create mode 100644 src/libsyntax/parse/lexer/tokentrees.rs create mode 100644 src/libsyntax/util/rc_slice.rs create mode 100644 src/libsyntax_ext/proc_macro_impl.rs create mode 100644 src/test/codegen/fastcall-inreg.rs create mode 100644 src/test/codegen/packed.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr_proc_macro.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/macro-use-attr.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/proc-macro-custom-attr-mutex.rs delete mode 100644 src/test/compile-fail/E0205.rs create mode 100644 src/test/compile-fail/E0277-2.rs rename src/test/compile-fail/{E0308-3.rs => E0580.rs} (92%) create mode 100644 src/test/compile-fail/auxiliary/rmeta_meta.rs rename src/{libproc_macro_tokens/prelude.rs => test/compile-fail/auxiliary/rmeta_rlib.rs} (88%) create mode 100644 src/test/compile-fail/binary-op-on-double-ref.rs create mode 100644 src/test/compile-fail/can-begin-expr-check.rs delete mode 100644 src/test/compile-fail/cast-rfc0401.rs create mode 100644 src/test/compile-fail/coherence-overlapping-inherent-impl-trait.rs delete mode 100644 src/test/compile-fail/const-eval-overflow0.rs create mode 100644 src/test/compile-fail/dep_graph_crosscontaminate_tables.rs create mode 100644 src/test/compile-fail/exclusive_range_pattern_syntax_collision.rs create mode 100644 src/test/compile-fail/exclusive_range_pattern_syntax_collision2.rs create mode 100644 src/test/compile-fail/exclusive_range_pattern_syntax_collision3.rs create mode 100644 src/test/compile-fail/feature-gate-abi-msp430-interrupt.rs create mode 100644 src/test/compile-fail/feature-gate-dropck-ugeh-2.rs rename src/test/{parse-fail/pat-range-bad-dots.rs => compile-fail/feature-gate-exclusive-range-pattern.rs} (81%) delete mode 100644 src/test/compile-fail/feature-gate-negate-unsigned0.rs create mode 100644 src/test/compile-fail/generic-non-trailing-defaults.rs create mode 100644 src/test/compile-fail/i128-feature-2.rs create mode 100644 src/test/compile-fail/i128-feature-libs.rs create mode 100644 src/test/compile-fail/i128-feature.rs create mode 100644 src/test/compile-fail/impl-trait/no-trait.rs create mode 100644 src/test/compile-fail/imports/unused-macro-use.rs delete mode 100644 src/test/compile-fail/issue-14254.rs delete mode 100644 src/test/compile-fail/issue-2356.rs create mode 100644 src/test/compile-fail/issue-30240-b.rs create mode 100644 src/test/compile-fail/issue-36082.rs create mode 100644 src/test/compile-fail/issue-38293.rs create mode 100644 src/test/compile-fail/issue-38404.rs create mode 100644 src/test/compile-fail/issue-38458.rs create mode 100644 src/test/compile-fail/issue-38604.rs create mode 100644 src/test/compile-fail/issue-39122.rs create mode 100644 src/test/compile-fail/issue-39388.rs create mode 100644 src/test/compile-fail/issue-39616.rs delete mode 100644 src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs delete mode 100644 src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs delete mode 100644 src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs create mode 100644 src/test/compile-fail/lint-attr-non-item-node.rs create mode 100644 src/test/compile-fail/match-argm-statics-2.rs create mode 100644 src/test/compile-fail/match-byte-array-patterns-2.rs create mode 100644 src/test/compile-fail/match-privately-empty.rs rename src/test/compile-fail/{unboxed-closure-sugar-nonexistent-trait.rs => recursive-types-are-not-uninhabited.rs} (70%) delete mode 100644 src/test/compile-fail/reflect-assoc.rs delete mode 100644 src/test/compile-fail/reflect-object-param.rs delete mode 100644 src/test/compile-fail/reflect.rs rename src/test/compile-fail/{struct-path-self-feature-gate.rs => resolve-bad-import-prefix.rs} (59%) create mode 100644 src/test/compile-fail/resolve-bad-visibility.rs create mode 100644 src/test/compile-fail/resolve-self-in-impl-2.rs create mode 100644 src/test/compile-fail/resolve-self-in-impl.rs create mode 100644 src/test/compile-fail/resolve-variant-assoc-item.rs create mode 100644 src/test/compile-fail/rmeta-lib-pass.rs create mode 100644 src/test/compile-fail/rmeta-pass.rs create mode 100644 src/test/compile-fail/rmeta-priv-warn.rs create mode 100644 src/test/compile-fail/rmeta.rs create mode 100644 src/test/compile-fail/rmeta_lib.rs create mode 100644 src/test/compile-fail/rmeta_meta_main.rs create mode 100644 src/test/compile-fail/str-concat-on-double-ref.rs create mode 100644 src/test/compile-fail/struct-field-attr-feature-gate.rs create mode 100644 src/test/compile-fail/struct-field-cfg.rs create mode 100644 src/test/compile-fail/ufcs-partially-resolved.rs create mode 100644 src/test/compile-fail/unadjusted-unstable.rs create mode 100644 src/test/compile-fail/uninhabited-irrefutable.rs create mode 100644 src/test/compile-fail/uninhabited-matches-feature-gated.rs create mode 100644 src/test/compile-fail/uninhabited-patterns.rs create mode 100644 src/test/compile-fail/unreachable-loop-patterns.rs create mode 100644 src/test/compile-fail/unreachable-try-pattern.rs create mode 100644 src/test/compile-fail/where-equality-constraints.rs create mode 100644 src/test/compile-fail/where-lifetime-resolution.rs rename src/test/debuginfo/{issue12886.rs => issue-12886.rs} (100%) rename src/test/debuginfo/{issue13213.rs => issue-13213.rs} (100%) rename src/test/debuginfo/{issue14411.rs => issue-14411.rs} (100%) rename src/test/debuginfo/{issue22656.rs => issue-22656.rs} (100%) rename src/test/debuginfo/{issue7712.rs => issue-7712.rs} (100%) create mode 100644 src/test/debuginfo/unsized.rs create mode 100644 src/test/incremental/hashes/extern_mods.rs create mode 100644 src/test/incremental/hashes/inline_asm.rs create mode 100644 src/test/parse-fail/bounds-lifetime-1.rs create mode 100644 src/test/parse-fail/bounds-lifetime-2.rs create mode 100644 src/test/parse-fail/bounds-lifetime-where-1.rs create mode 100644 src/test/parse-fail/bounds-lifetime-where.rs create mode 100644 src/test/parse-fail/bounds-lifetime.rs create mode 100644 src/test/parse-fail/bounds-obj-parens.rs create mode 100644 src/test/parse-fail/bounds-type-where.rs create mode 100644 src/test/parse-fail/bounds-type.rs rename src/test/parse-fail/{generic-non-trailing-defaults.rs => issue-17904-2.rs} (74%) delete mode 100644 src/test/pretty/attr-variant-data.rs delete mode 100644 src/test/run-pass-fulldeps/auxiliary/cond_noprelude_plugin.rs delete mode 100644 src/test/run-pass-fulldeps/auxiliary/cond_prelude_plugin.rs create mode 100644 src/test/run-pass-fulldeps/auxiliary/hello_macro.rs create mode 100644 src/test/run-pass-fulldeps/macro-quote-empty-delims.rs delete mode 100644 src/test/run-pass-fulldeps/macro-quote-noprelude.rs delete mode 100644 src/test/run-pass-fulldeps/macro-quote-prelude.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/attr-args.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs create mode 100644 src/test/run-pass/auxiliary/debuginfo-lto-aux.rs create mode 100644 src/test/run-pass/auxiliary/issue_39823.rs create mode 100644 src/test/run-pass/auxiliary/rmeta_rlib.rs create mode 100644 src/test/run-pass/auxiliary/rmeta_rmeta.rs create mode 100644 src/test/run-pass/debuginfo-lto.rs create mode 100644 src/test/run-pass/empty-types-in-patterns.rs create mode 100644 src/test/run-pass/i128-ffi.rs create mode 100644 src/test/run-pass/i128.rs rename src/test/run-pass/{issue18173.rs => issue-18173.rs} (100%) rename src/test/run-pass/{issue22008.rs => issue-22008.rs} (100%) rename src/test/run-pass/{issue22346.rs => issue-22346.rs} (100%) rename src/test/run-pass/{issue24353.rs => issue-24353.rs} (100%) rename src/test/run-pass/{issue26127.rs => issue-26127.rs} (100%) rename src/test/run-pass/{issue29927.rs => issue-29927.rs} (100%) create mode 100644 src/test/run-pass/issue-31260.rs create mode 100644 src/test/run-pass/issue-32947.rs create mode 100644 src/test/run-pass/issue-33187.rs rename src/test/run-pass/{issue34569.rs => issue-34569.rs} (100%) rename src/test/run-pass/{issue34796.rs => issue-34796.rs} (100%) rename src/test/run-pass/{issue36260.rs => issue-36260.rs} (100%) create mode 100644 src/test/run-pass/issue-38074.rs rename src/test/{compile-fail/E0248.rs => run-pass/issue-38556.rs} (80%) create mode 100644 src/test/run-pass/issue-38942.rs create mode 100644 src/test/run-pass/issue-38972.rs create mode 100644 src/test/run-pass/issue-38987.rs rename src/test/{compile-fail/oversized-literal.rs => run-pass/issue-39089.rs} (82%) create mode 100644 src/test/run-pass/issue-39709.rs create mode 100644 src/test/run-pass/issue-39823.rs rename src/test/{compile-fail/unresolved_static_type_field.rs => run-pass/issue-40136.rs} (74%) create mode 100644 src/test/run-pass/process-envs.rs create mode 100644 src/test/run-pass/rmeta.rs create mode 100644 src/test/run-pass/test-allow-dead-extern-static-no-warning.rs create mode 100644 src/test/run-pass/trans-object-shim.rs create mode 100644 src/test/run-pass/try-wait.rs create mode 100644 src/test/run-pass/u128.rs create mode 100644 src/test/run-pass/union/union-nodrop.rs create mode 100644 src/test/rustdoc/search-index-summaries.rs create mode 100644 src/test/ui/custom-derive/auxiliary/plugin.rs create mode 100644 src/test/ui/custom-derive/issue-36935.rs create mode 100644 src/test/ui/custom-derive/issue-36935.stderr rename src/test/{compile-fail => ui/did_you_mean}/issue-21659-show-relevant-trait-impls-1.rs (100%) create mode 100644 src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr rename src/test/{compile-fail => ui/did_you_mean}/issue-21659-show-relevant-trait-impls-2.rs (100%) create mode 100644 src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr create mode 100644 src/test/ui/did_you_mean/issue-38147-1.rs create mode 100644 src/test/ui/did_you_mean/issue-38147-1.stderr create mode 100644 src/test/ui/did_you_mean/issue-38147-2.rs create mode 100644 src/test/ui/did_you_mean/issue-38147-2.stderr create mode 100644 src/test/ui/did_you_mean/issue-38147-3.rs create mode 100644 src/test/ui/did_you_mean/issue-38147-3.stderr create mode 100644 src/test/ui/did_you_mean/issue-38147-4.rs create mode 100644 src/test/ui/did_you_mean/issue-38147-4.stderr rename src/test/{run-pass/issue-28189.rs => ui/did_you_mean/issue-39544.rs} (73%) create mode 100644 src/test/ui/did_you_mean/issue-39544.stderr rename src/test/{compile-fail/E0172.rs => ui/lifetime-errors/ex1-return-one-existing-name-if-else.rs} (82%) create mode 100644 src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr create mode 100644 src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.rs create mode 100644 src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr create mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name.rs create mode 100644 src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr create mode 100644 src/test/ui/lifetime-errors/ex2b-push-no-existing-names.rs create mode 100644 src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr create mode 100644 src/test/ui/lifetime-errors/ex2c-push-inference-variable.rs create mode 100644 src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr create mode 100644 src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.rs create mode 100644 src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr create mode 100644 src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.rs create mode 100644 src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr delete mode 100644 src/test/ui/lifetimes/consider-using-explicit-lifetime.stderr rename src/test/{compile-fail => ui/mismatched_types}/E0053.rs (100%) create mode 100644 src/test/ui/mismatched_types/E0053.stderr rename src/test/{compile-fail => ui/mismatched_types}/E0409.rs (100%) create mode 100644 src/test/ui/mismatched_types/E0409.stderr create mode 100644 src/test/ui/mismatched_types/cast-rfc0401.rs create mode 100644 src/test/ui/mismatched_types/cast-rfc0401.stderr rename src/test/{compile-fail => ui/mismatched_types}/issue-19109.rs (100%) create mode 100644 src/test/ui/mismatched_types/issue-19109.stderr create mode 100644 src/test/ui/mismatched_types/issue-38371.rs create mode 100644 src/test/ui/mismatched_types/issue-38371.stderr rename src/test/{compile-fail => ui/mismatched_types}/overloaded-calls-bad.rs (100%) create mode 100644 src/test/ui/mismatched_types/overloaded-calls-bad.stderr rename src/test/{compile-fail => ui/mismatched_types}/trait-bounds-cant-coerce.rs (100%) create mode 100644 src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr create mode 100644 src/test/ui/missing-items/issue-40221.rs create mode 100644 src/test/ui/missing-items/issue-40221.stderr rename src/test/{compile-fail => ui/resolve}/auxiliary/issue-21221-3.rs (100%) rename src/test/{compile-fail => ui/resolve}/auxiliary/issue-21221-4.rs (100%) rename src/test/{compile-fail => ui/resolve}/auxiliary/issue_19452_aux.rs (100%) rename src/test/{compile-fail => ui/resolve}/auxiliary/issue_3907.rs (100%) create mode 100644 src/test/ui/resolve/auxiliary/namespaced_enums.rs rename src/test/{compile-fail => ui/resolve}/enums-are-namespaced-xc.rs (61%) create mode 100644 src/test/ui/resolve/enums-are-namespaced-xc.stderr create mode 100644 src/test/ui/resolve/issue-14254.rs create mode 100644 src/test/ui/resolve/issue-14254.stderr rename src/test/{compile-fail => ui/resolve}/issue-16058.rs (71%) create mode 100644 src/test/ui/resolve/issue-16058.stderr rename src/test/{compile-fail => ui/resolve}/issue-17518.rs (87%) create mode 100644 src/test/ui/resolve/issue-17518.stderr rename src/test/{compile-fail => ui/resolve}/issue-18252.rs (87%) create mode 100644 src/test/ui/resolve/issue-18252.stderr rename src/test/{compile-fail => ui/resolve}/issue-19452.rs (81%) create mode 100644 src/test/ui/resolve/issue-19452.stderr rename src/test/{compile-fail => ui/resolve}/issue-21221-1.rs (82%) create mode 100644 src/test/ui/resolve/issue-21221-1.stderr rename src/test/{compile-fail => ui/resolve}/issue-21221-2.rs (90%) create mode 100644 src/test/ui/resolve/issue-21221-2.stderr rename src/test/{compile-fail => ui/resolve}/issue-21221-3.rs (94%) create mode 100644 src/test/ui/resolve/issue-21221-3.stderr rename src/test/{compile-fail => ui/resolve}/issue-21221-4.rs (87%) create mode 100644 src/test/ui/resolve/issue-21221-4.stderr rename src/test/{compile-fail => ui/resolve}/issue-23305.rs (66%) create mode 100644 src/test/ui/resolve/issue-23305.stderr create mode 100644 src/test/ui/resolve/issue-2356.rs create mode 100644 src/test/ui/resolve/issue-2356.stderr rename src/test/{compile-fail => ui/resolve}/issue-24968.rs (84%) create mode 100644 src/test/ui/resolve/issue-24968.stderr rename src/test/{compile-fail => ui/resolve}/issue-33876.rs (86%) create mode 100644 src/test/ui/resolve/issue-33876.stderr rename src/test/{compile-fail => ui/resolve}/issue-3907-2.rs (100%) create mode 100644 src/test/ui/resolve/issue-3907-2.stderr rename src/test/{compile-fail => ui/resolve}/issue-3907.rs (79%) create mode 100644 src/test/ui/resolve/issue-3907.stderr rename src/test/{compile-fail => ui/resolve}/issue-5035-2.rs (100%) create mode 100644 src/test/ui/resolve/issue-5035-2.stderr rename src/test/{compile-fail => ui/resolve}/issue-5035.rs (79%) create mode 100644 src/test/ui/resolve/issue-5035.stderr rename src/test/{compile-fail => ui/resolve}/issue-6702.rs (77%) create mode 100644 src/test/ui/resolve/issue-6702.stderr create mode 100644 src/test/ui/resolve/levenshtein.rs create mode 100644 src/test/ui/resolve/levenshtein.stderr create mode 100644 src/test/ui/resolve/resolve-assoc-suggestions.rs create mode 100644 src/test/ui/resolve/resolve-assoc-suggestions.stderr rename src/test/{compile-fail => ui/resolve}/resolve-hint-macro.rs (83%) create mode 100644 src/test/ui/resolve/resolve-hint-macro.stderr create mode 100644 src/test/ui/resolve/resolve-speculative-adjustment.rs create mode 100644 src/test/ui/resolve/resolve-speculative-adjustment.stderr rename src/test/{compile-fail => ui/resolve}/suggest-path-instead-of-mod-dot-item.rs (54%) create mode 100644 src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr rename src/test/{compile-fail => ui/resolve}/token-error-correct-2.rs (83%) create mode 100644 src/test/ui/resolve/token-error-correct-2.stderr rename src/test/{compile-fail => ui/resolve}/token-error-correct-3.rs (93%) create mode 100644 src/test/ui/resolve/token-error-correct-3.stderr rename src/test/{compile-fail => ui/resolve}/token-error-correct.rs (61%) create mode 100644 src/test/ui/resolve/token-error-correct.stderr rename src/test/{compile-fail/E0513.rs => ui/resolve/tuple-struct-alias.rs} (68%) create mode 100644 src/test/ui/resolve/tuple-struct-alias.stderr create mode 100644 src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs create mode 100644 src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr rename src/test/ui/{lifetimes/consider-using-explicit-lifetime.rs => resolve/unresolved_static_type_field.rs} (61%) create mode 100644 src/test/ui/resolve/unresolved_static_type_field.stderr rename src/test/{compile-fail => ui/span}/E0204.rs (77%) create mode 100644 src/test/ui/span/E0204.stderr create mode 100644 src/test/ui/span/coerce-suggestions.rs create mode 100644 src/test/ui/span/coerce-suggestions.stderr create mode 100644 src/test/ui/span/issue-27522.rs create mode 100644 src/test/ui/span/issue-27522.stderr create mode 100644 src/test/ui/span/issue-37767.rs create mode 100644 src/test/ui/span/issue-37767.stderr rename src/test/{compile-fail => ui/span}/issue-7575.rs (73%) create mode 100644 src/test/ui/span/issue-7575.stderr create mode 100644 src/tools/build-manifest/Cargo.toml create mode 100644 src/tools/build-manifest/src/main.rs create mode 100755 x.py diff --git a/Makefile.in b/Makefile.in index 9e87ce1d9e..8dbe242139 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,6 +17,10 @@ # most intimate workings of the compiler itself, you've come to the # right place. Let's see what's on the menu. # +# Please note that most of these options only work if configure was +# run with --disable-rustbuild. For documentation on the new build +# system, see CONTRIBUTING.md. +# # First, start with one of these build targets: # # * all - The default. Build a complete, bootstrapped compiler. diff --git a/README.md b/README.md index 2133b17de0..c1218e9c60 100644 --- a/README.md +++ b/README.md @@ -82,8 +82,9 @@ build. # Install build tools needed for Rust. If you're building a 32-bit compiler, # then replace "x86_64" below with "i686". If you've already got git, python, # or CMake installed and in PATH you can remove them from this list. Note - # that it is important that the `python2` and `cmake` packages **not** used. - # The build has historically been known to fail with these packages. + # that it is important that you do **not** use the 'python2' and 'cmake' + # packages from the 'msys2' subsystem. The build has historically been known + # to fail with these packages. $ pacman -S git \ make \ diffutils \ diff --git a/RELEASES.md b/RELEASES.md index bf67ddfbbe..606936778c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,194 @@ +Version 1.16.0 (2017-03-16) +=========================== + +Language +-------- + +* Lifetimes in statics and consts default to `'static`. [RFC 1623] +* [The compiler's `dead_code` lint now accounts for type aliases][38051]. +* [Uninhabitable enums (those without any variants) no longer permit wildcard + match patterns][38069] +* [Clean up semantics of `self` in an import list][38313] +* [`Self` may appear in `impl` headers][38920] +* [`Self` may appear in struct expressions][39282] + +Compiler +-------- + +* [`rustc` now supports `--emit=metadata`, which causes rustc to emit + a `.rmeta` file containing only crate metadata][38571]. This can be + used by tools like the Rust Language Service to perform + metadata-only builds. +* [Levenshtein based typo suggestions now work in most places, while + previously they worked only for fields and sometimes for local + variables][38927]. Together with the overhaul of "no + resolution"/"unexpected resolution" errors (#[38154]) they result in + large and systematic improvement in resolution diagnostics. +* [Fix `transmute::` where `T` requires a bigger alignment than + `U`][38670] +* [rustc: use -Xlinker when specifying an rpath with ',' in it][38798] +* [`rustc` no longer attempts to provide "consider using an explicit + lifetime" suggestions][37057]. They were inaccurate. + +Stabilized APIs +--------------- + +* [`VecDeque::truncate`] +* [`VecDeque::resize`] +* [`String::insert_str`] +* [`Duration::checked_add`] +* [`Duration::checked_sub`] +* [`Duration::checked_div`] +* [`Duration::checked_mul`] +* [`str::replacen`] +* [`str::repeat`] +* [`SocketAddr::is_ipv4`] +* [`SocketAddr::is_ipv6`] +* [`IpAddr::is_ipv4`] +* [`IpAddr::is_ipv6`] +* [`Vec::dedup_by`] +* [`Vec::dedup_by_key`] +* [`Result::unwrap_or_default`] +* [`<*const T>::wrapping_offset`] +* [`<*mut T>::wrapping_offset`] +* `CommandExt::creation_flags` +* [`File::set_permissions`] +* [`String::split_off`] + +Libraries +--------- + +* [`[T]::binary_search` and `[T]::binary_search_by_key` now take + their argument by `Borrow` parameter][37761] +* [All public types in std implement `Debug`][38006] +* [`IpAddr` implements `From` and `From`][38327] +* [`Ipv6Addr` implements `From<[u16; 8]>`][38131] +* [Ctrl-Z returns from `Stdin.read()` when reading from the console on + Windows][38274] +* [std: Fix partial writes in `LineWriter`][38062] +* [std: Clamp max read/write sizes on Unix][38062] +* [Use more specific panic message for `&str` slicing errors][38066] +* [`TcpListener::set_only_v6` is deprecated][38304]. This + functionality cannot be achieved in std currently. +* [`writeln!`, like `println!`, now accepts a form with no string + or formatting arguments, to just print a newline][38469] +* [Implement `iter::Sum` and `iter::Product` for `Result`][38580] +* [Reduce the size of static data in `std_unicode::tables`][38781] +* [`char::EscapeDebug`, `EscapeDefault`, `EscapeUnicode`, + `CaseMappingIter`, `ToLowercase`, `ToUppercase`, implement + `Display`][38909] +* [`Duration` implements `Sum`][38712] +* [`String` implements `ToSocketAddrs`][39048] + +Cargo +----- + +* [The `cargo check` command does a type check of a project without + building it][cargo/3296] +* [crates.io will display CI badges from Travis and AppVeyor, if + specified in Cargo.toml][cargo/3546] +* [crates.io will display categories listed in Cargo.toml][cargo/3301] +* [Compilation profiles accept integer values for `debug`, in addition + to `true` and `false`. These are passed to `rustc` as the value to + `-C debuginfo`][cargo/3534] +* [Implement `cargo --version --verbose`][cargo/3604] +* [All builds now output 'dep-info' build dependencies compatible with + make and ninja][cargo/3557] +* [Build all workspace members with `build --all`][cargo/3511] +* [Document all workspace members with `doc --all`][cargo/3515] +* [Path deps outside workspace are not members][cargo/3443] + +Misc +---- + +* [`rustdoc` has a `--sysroot` argument that, like `rustc`, specifies + the path to the Rust implementation][38589] +* [The `armv7-linux-androideabi` target no longer enables NEON + extensions, per Google's ABI guide][38413] +* [The stock standard library can be compiled for Redox OS][38401] +* [Rust has initial SPARC support][38726]. Tier 3. No builds + available. +* [Rust has experimental support for Nvidia PTX][38559]. Tier 3. No + builds available. +* [Fix backtraces on i686-pc-windows-gnu by disabling FPO][39379] + +Compatibility Notes +------------------- + +* [Uninhabitable enums (those without any variants) no longer permit wildcard + match patterns][38069] +* In this release, references to uninhabited types can not be + pattern-matched. This was accidentally allowed in 1.15. +* [The compiler's `dead_code` lint now accounts for type aliases][38051]. +* [Ctrl-Z returns from `Stdin.read()` when reading from the console on + Windows][38274] +* [Clean up semantics of `self` in an import list][38313] + +[37057]: https://github.com/rust-lang/rust/pull/37057 +[37761]: https://github.com/rust-lang/rust/pull/37761 +[38006]: https://github.com/rust-lang/rust/pull/38006 +[38051]: https://github.com/rust-lang/rust/pull/38051 +[38062]: https://github.com/rust-lang/rust/pull/38062 +[38062]: https://github.com/rust-lang/rust/pull/38622 +[38066]: https://github.com/rust-lang/rust/pull/38066 +[38069]: https://github.com/rust-lang/rust/pull/38069 +[38131]: https://github.com/rust-lang/rust/pull/38131 +[38154]: https://github.com/rust-lang/rust/pull/38154 +[38274]: https://github.com/rust-lang/rust/pull/38274 +[38304]: https://github.com/rust-lang/rust/pull/38304 +[38313]: https://github.com/rust-lang/rust/pull/38313 +[38314]: https://github.com/rust-lang/rust/pull/38314 +[38327]: https://github.com/rust-lang/rust/pull/38327 +[38401]: https://github.com/rust-lang/rust/pull/38401 +[38413]: https://github.com/rust-lang/rust/pull/38413 +[38469]: https://github.com/rust-lang/rust/pull/38469 +[38559]: https://github.com/rust-lang/rust/pull/38559 +[38571]: https://github.com/rust-lang/rust/pull/38571 +[38580]: https://github.com/rust-lang/rust/pull/38580 +[38589]: https://github.com/rust-lang/rust/pull/38589 +[38670]: https://github.com/rust-lang/rust/pull/38670 +[38712]: https://github.com/rust-lang/rust/pull/38712 +[38726]: https://github.com/rust-lang/rust/pull/38726 +[38781]: https://github.com/rust-lang/rust/pull/38781 +[38798]: https://github.com/rust-lang/rust/pull/38798 +[38909]: https://github.com/rust-lang/rust/pull/38909 +[38920]: https://github.com/rust-lang/rust/pull/38920 +[38927]: https://github.com/rust-lang/rust/pull/38927 +[39048]: https://github.com/rust-lang/rust/pull/39048 +[39282]: https://github.com/rust-lang/rust/pull/39282 +[39379]: https://github.com/rust-lang/rust/pull/39379 +[`<*const T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset +[`<*mut T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset +[`Duration::checked_add`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_add +[`Duration::checked_div`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_div +[`Duration::checked_mul`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_mul +[`Duration::checked_sub`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_sub +[`File::set_permissions`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.set_permissions +[`IpAddr::is_ipv4`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_ipv4 +[`IpAddr::is_ipv6`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_ipv6 +[`Result::unwrap_or_default`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_default +[`SocketAddr::is_ipv4`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html#method.is_ipv4 +[`SocketAddr::is_ipv6`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html#method.is_ipv6 +[`String::insert_str`]: https://doc.rust-lang.org/std/string/struct.String.html#method.insert_str +[`String::split_off`]: https://doc.rust-lang.org/std/string/struct.String.html#method.split_off +[`Vec::dedup_by_key`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup_by_key +[`Vec::dedup_by`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup_by +[`VecDeque::resize`]: https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.resize +[`VecDeque::truncate`]: https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.truncate +[`str::repeat`]: https://doc.rust-lang.org/std/primitive.str.html#method.repeat +[`str::replacen`]: https://doc.rust-lang.org/std/primitive.str.html#method.replacen +[cargo/3296]: https://github.com/rust-lang/cargo/pull/3296 +[cargo/3301]: https://github.com/rust-lang/cargo/pull/3301 +[cargo/3443]: https://github.com/rust-lang/cargo/pull/3443 +[cargo/3511]: https://github.com/rust-lang/cargo/pull/3511 +[cargo/3515]: https://github.com/rust-lang/cargo/pull/3515 +[cargo/3534]: https://github.com/rust-lang/cargo/pull/3534 +[cargo/3546]: https://github.com/rust-lang/cargo/pull/3546 +[cargo/3557]: https://github.com/rust-lang/cargo/pull/3557 +[cargo/3604]: https://github.com/rust-lang/cargo/pull/3604 +[RFC 1623]: https://github.com/rust-lang/rfcs/blob/master/text/1623-static.md + + Version 1.15.1 (2017-02-09) =========================== @@ -178,6 +369,7 @@ Compatibility Notes [37613]: https://github.com/rust-lang/rust/pull/37613 [37615]: https://github.com/rust-lang/rust/pull/37615 [37636]: https://github.com/rust-lang/rust/pull/37636 +[37627]: https://github.com/rust-lang/rust/pull/37627 [37642]: https://github.com/rust-lang/rust/pull/37642 [37677]: https://github.com/rust-lang/rust/pull/37677 [37699]: https://github.com/rust-lang/rust/pull/37699 @@ -973,7 +1165,7 @@ Tooling * [Test binaries now support a `--test-threads` argument to specify the number of threads used to run tests, and which acts the same as the `RUST_TEST_THREADS` environment variable] - (https://github.com/rust-lang/rust/pull/35414) + (https://github.com/rust-lang/rust/pull/35414) * [The test runner now emits a warning when tests run over 60 seconds] (https://github.com/rust-lang/rust/pull/35405) * [rustdoc: Fix methods in search results] @@ -3622,7 +3814,7 @@ Version 1.0.0-alpha (2015-01-09) platforms. * Rust comes with rust-gdb and rust-lldb scripts that launch their respective debuggers with Rust-appropriate pretty-printing. - * The Windows installation of Rust is distributed with the the + * The Windows installation of Rust is distributed with the MinGW components currently required to link binaries on that platform. diff --git a/configure b/configure index ab5d2f34fe..505767cede 100755 --- a/configure +++ b/configure @@ -541,6 +541,18 @@ case $CFG_CPUTYPE in CFG_CPUTYPE=x86_64 ;; + mips | mips64) + if [ "$CFG_CPUTYPE" = "mips64" ]; then + CFG_OSTYPE="${CFG_OSTYPE}abi64" + fi + ENDIAN=$(printf '\1' | od -dAn) + if [ "$ENDIAN" -eq 1 ]; then + CFG_CPUTYPE="${CFG_CPUTYPE}el" + elif [ "$ENDIAN" -ne 256 ]; then + err "unknown endianness: $ENDIAN (expecting 1 for little or 256 for big)" + fi + ;; + BePC) CFG_CPUTYPE=i686 ;; @@ -694,6 +706,8 @@ opt_nosave manage-submodules 1 "let the build manage the git submodules" opt_nosave clang 0 "prefer clang to gcc for building the runtime" opt_nosave jemalloc 1 "build liballoc with jemalloc" opt elf-tls 1 "elf thread local storage on platforms where supported" +opt full-bootstrap 0 "build three compilers instead of two" +opt extended 0 "build an extended rust tool set" valopt_nosave prefix "/usr/local" "set installation prefix" valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary" @@ -732,7 +746,7 @@ fi case "$CFG_RELEASE_CHANNEL" in nightly ) msg "overriding settings for $CFG_RELEASE_CHANNEL" - CFG_ENABLE_LLVM_ASSERTIONS=1 + enable_if_not_disabled llvm-assertions # FIXME(stage0) re-enable this on the next stage0 now that #35566 is # fixed case "$CFG_BUILD" in @@ -922,6 +936,18 @@ case $CFG_BUILD in esac putvar CFG_LLDB_PYTHON +# Do some sanity checks if running on buildbot +# (these env vars are set by rust-buildbot) +if [ -n "$RUST_DIST_SERVER" -a -n "$ALLOW_NONZERO_RLIMIT_CORE" ]; then + # Frequently the llvm submodule directory is broken by the build + # being killed + llvm_lock="${CFG_SRC_DIR}/.git/modules/src/llvm/index.lock" + if [ -e "$llvm_lock" ]; then + step_msg "removing $llvm_lock" + rm -f "$llvm_lock" + fi +fi + step_msg "looking for target specific programs" probe CFG_ADB adb @@ -1560,7 +1586,7 @@ do then LLVM_BUILD_DIR=${CFG_BUILD_DIR}$t/llvm LLVM_INST_DIR=$LLVM_BUILD_DIR - # For some crazy reason the MSVC output dir is different than Unix + # For some weird reason the MSVC output dir is different than Unix if [ ${is_msvc} -ne 0 ]; then if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ] then @@ -1814,7 +1840,7 @@ do CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON" fi - CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430'" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc'" CMAKE_ARGS="$CMAKE_ARGS -G '$CFG_CMAKE_GENERATOR'" CMAKE_ARGS="$CMAKE_ARGS $CFG_LLVM_SRC_DIR" diff --git a/mk/cfg/sparc64-unknown-linux-gnu.mk b/mk/cfg/sparc64-unknown-linux-gnu.mk new file mode 100644 index 0000000000..34aee77ae2 --- /dev/null +++ b/mk/cfg/sparc64-unknown-linux-gnu.mk @@ -0,0 +1 @@ +# rustbuild-only target diff --git a/mk/cfg/sparc64-unknown-netbsd.mk b/mk/cfg/sparc64-unknown-netbsd.mk new file mode 100644 index 0000000000..a2b01ba053 --- /dev/null +++ b/mk/cfg/sparc64-unknown-netbsd.mk @@ -0,0 +1,3 @@ +# This file is intentially left empty to indicate that, while this target is +# supported, it's not supported using plain GNU Make builds. Use a --rustbuild +# instead. diff --git a/mk/cfg/x86_64-unknown-redox.mk b/mk/cfg/x86_64-unknown-redox.mk new file mode 100644 index 0000000000..34aee77ae2 --- /dev/null +++ b/mk/cfg/x86_64-unknown-redox.mk @@ -0,0 +1 @@ +# rustbuild-only target diff --git a/mk/crates.mk b/mk/crates.mk index 79df941aeb..f801605d9f 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -54,13 +54,13 @@ TARGET_CRATES := libc std term \ compiler_builtins core alloc \ std_unicode rustc_bitflags \ alloc_system alloc_jemalloc \ - panic_abort panic_unwind unwind + panic_abort panic_unwind unwind rustc_i128 RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \ rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \ rustc_data_structures rustc_platform_intrinsics rustc_errors \ rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \ rustc_const_eval rustc_const_math rustc_incremental proc_macro -HOST_CRATES := syntax syntax_ext proc_macro_tokens proc_macro_plugin syntax_pos $(RUSTC_CRATES) \ +HOST_CRATES := syntax syntax_ext proc_macro_plugin syntax_pos $(RUSTC_CRATES) \ rustdoc fmt_macros flate arena graphviz log serialize TOOLS := compiletest rustdoc rustc rustbook error_index_generator @@ -92,23 +92,25 @@ DEPS_getopts := std DEPS_graphviz := std DEPS_log := std DEPS_num := std -DEPS_serialize := std log +DEPS_serialize := std log rustc_i128 DEPS_term := std DEPS_test := std getopts term native:rust_test_helpers +DEPS_rustc_i128 = std -DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors syntax_pos rustc_data_structures +DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors \ + syntax_pos rustc_data_structures rustc_i128 DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro +DEPS_proc_macro := syntax syntax_pos rustc_plugin log DEPS_syntax_pos := serialize -DEPS_proc_macro_tokens := syntax syntax_pos log -DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin log proc_macro_tokens +DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin -DEPS_rustc_const_math := std syntax log serialize +DEPS_rustc_const_math := std syntax log serialize rustc_i128 DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \ - rustc_back graphviz syntax_pos + rustc_back graphviz syntax_pos rustc_i128 DEPS_rustc := syntax fmt_macros flate arena serialize getopts \ log graphviz rustc_llvm rustc_back rustc_data_structures\ - rustc_const_math syntax_pos rustc_errors + rustc_const_math syntax_pos rustc_errors rustc_i128 DEPS_rustc_back := std syntax flate log libc DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_mir DEPS_rustc_data_structures := std log serialize libc @@ -119,19 +121,20 @@ DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_bo rustc_passes rustc_save_analysis rustc_const_eval \ rustc_incremental syntax_pos rustc_errors proc_macro rustc_data_structures DEPS_rustc_errors := log libc serialize syntax_pos -DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval +DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval rustc_i128 DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags DEPS_proc_macro := std syntax DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \ - proc_macro syntax_ext + proc_macro syntax_ext rustc_i128 DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors -DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags +DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags \ + rustc_i128 DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors DEPS_rustc_platform_intrinsics := std DEPS_rustc_plugin := rustc rustc_metadata syntax syntax_pos rustc_errors DEPS_rustc_privacy := rustc log syntax syntax_pos DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \ - log syntax serialize rustc_llvm rustc_platform_intrinsics \ + log syntax serialize rustc_llvm rustc_platform_intrinsics rustc_i128 \ rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize @@ -159,6 +162,7 @@ ONLY_RLIB_alloc := 1 ONLY_RLIB_rand := 1 ONLY_RLIB_collections := 1 ONLY_RLIB_std_unicode := 1 +ONLY_RLIB_rustc_i128 := 1 ONLY_RLIB_rustc_bitflags := 1 ONLY_RLIB_alloc_system := 1 ONLY_RLIB_alloc_jemalloc := 1 diff --git a/mk/main.mk b/mk/main.mk index 05500f507a..d2b9a13642 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,12 +13,12 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=1.15.1 +CFG_RELEASE_NUM=1.16.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release # versions (section 9) -CFG_PRERELEASE_VERSION=.5 +CFG_PRERELEASE_VERSION=.4 ifeq ($(CFG_RELEASE_CHANNEL),stable) # This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly" @@ -175,7 +175,7 @@ endif # that the snapshot will be generated with a statically linked rustc so we only # have to worry about the distribution of one file (with its native dynamic # dependencies) -RUSTFLAGS_STAGE0 += -C prefer-dynamic -C no-stack-check +RUSTFLAGS_STAGE0 += -C prefer-dynamic RUSTFLAGS_STAGE1 += -C prefer-dynamic RUST_LIB_FLAGS_ST2 += -C prefer-dynamic RUST_LIB_FLAGS_ST3 += -C prefer-dynamic @@ -285,7 +285,7 @@ endif # LLVM macros ###################################################################### -LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend msp430 +LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend msp430 sparc LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \ interpreter instrumentation diff --git a/src/Cargo.lock b/src/Cargo.lock index 9cd77e71b8..93bbf0f227 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -50,6 +50,14 @@ dependencies = [ "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "build-manifest" +version = "0.1.0" +dependencies = [ + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "build_helper" version = "0.1.0" @@ -89,7 +97,7 @@ version = "0.0.0" dependencies = [ "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serialize 0.0.0", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -208,22 +216,11 @@ dependencies = [ name = "proc_macro_plugin" version = "0.0.0" dependencies = [ - "log 0.0.0", - "proc_macro_tokens 0.0.0", "rustc_plugin 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] -[[package]] -name = "proc_macro_tokens" -version = "0.0.0" -dependencies = [ - "log 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", -] - [[package]] name = "rand" version = "0.0.0" @@ -240,7 +237,6 @@ name = "rustc" version = "0.0.0" dependencies = [ "arena 0.0.0", - "flate 0.0.0", "fmt_macros 0.0.0", "graphviz 0.0.0", "log 0.0.0", @@ -249,6 +245,7 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_i128 0.0.0", "rustc_llvm 0.0.0", "serialize 0.0.0", "syntax 0.0.0", @@ -308,7 +305,7 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", - "serialize 0.0.0", + "rustc_i128 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -317,7 +314,7 @@ dependencies = [ name = "rustc_const_math" version = "0.0.0" dependencies = [ - "log 0.0.0", + "rustc_i128 0.0.0", "serialize 0.0.0", "syntax 0.0.0", ] @@ -327,6 +324,7 @@ name = "rustc_data_structures" version = "0.0.0" dependencies = [ "log 0.0.0", + "rustc_i128 0.0.0", "serialize 0.0.0", ] @@ -335,7 +333,6 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ "arena 0.0.0", - "flate 0.0.0", "graphviz 0.0.0", "log 0.0.0", "proc_macro_plugin 0.0.0", @@ -367,11 +364,13 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ - "log 0.0.0", - "serialize 0.0.0", "syntax_pos 0.0.0", ] +[[package]] +name = "rustc_i128" +version = "0.0.0" + [[package]] name = "rustc_incremental" version = "0.0.0" @@ -393,6 +392,7 @@ dependencies = [ "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", + "rustc_i128 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -418,6 +418,7 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_i128 0.0.0", "rustc_llvm 0.0.0", "serialize 0.0.0", "syntax 0.0.0", @@ -432,11 +433,11 @@ dependencies = [ "graphviz 0.0.0", "log 0.0.0", "rustc 0.0.0", - "rustc_back 0.0.0", "rustc_bitflags 0.0.0", "rustc_const_eval 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", + "rustc_i128 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -462,10 +463,8 @@ version = "0.0.0" name = "rustc_plugin" version = "0.0.0" dependencies = [ - "log 0.0.0", "rustc 0.0.0", "rustc_back 0.0.0", - "rustc_bitflags 0.0.0", "rustc_errors 0.0.0", "rustc_metadata 0.0.0", "syntax 0.0.0", @@ -508,9 +507,7 @@ dependencies = [ name = "rustc_trans" version = "0.0.0" dependencies = [ - "arena 0.0.0", "flate 0.0.0", - "graphviz 0.0.0", "log 0.0.0", "rustc 0.0.0", "rustc_back 0.0.0", @@ -519,10 +516,10 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_i128 0.0.0", "rustc_incremental 0.0.0", "rustc_llvm 0.0.0", "rustc_platform_intrinsics 0.0.0", - "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -556,7 +553,6 @@ dependencies = [ "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_driver 0.0.0", "rustc_errors 0.0.0", @@ -573,7 +569,7 @@ dependencies = [ name = "serialize" version = "0.0.0" dependencies = [ - "log 0.0.0", + "rustc_i128 0.0.0", ] [[package]] @@ -619,6 +615,7 @@ dependencies = [ "rustc_bitflags 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_i128 0.0.0", "serialize 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/Cargo.toml b/src/Cargo.toml index 8fb5c70c41..0db26ea5ae 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -10,6 +10,7 @@ members = [ "tools/linkchecker", "tools/rustbook", "tools/tidy", + "tools/build-manifest", ] # Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 35f8fb43f7..1eda1608c4 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -6,18 +6,22 @@ version = "0.0.0" [lib] name = "bootstrap" path = "lib.rs" +doctest = false [[bin]] name = "bootstrap" path = "bin/main.rs" +test = false [[bin]] name = "rustc" path = "bin/rustc.rs" +test = false [[bin]] name = "rustdoc" path = "bin/rustdoc.rs" +test = false [dependencies] build_helper = { path = "../build_helper" } diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 02c64548eb..ac84edb403 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -116,6 +116,42 @@ compiler. What actually happens when you invoke rustbuild is: The goal of each stage is to (a) leverage Cargo as much as possible and failing that (b) leverage Rust as much as possible! +## Incremental builds + +You can configure rustbuild to use incremental compilation. Because +incremental is new and evolving rapidly, if you want to use it, it is +recommended that you replace the snapshot with a locally installed +nightly build of rustc. You will want to keep this up to date. + +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: + +``` +# configure to use local rust instead of downloding a beta. +# `--local-rust-root` is optional here. If elided, we will +# use whatever rustc we find on your PATH. +> configure --enable-rustbuild --local-rust-root=~/.cargo/ --enable-local-rebuild +``` + +After that, you can use the `--incremental` flag to actually do +incremental builds: + +``` +> ../x.py build --incremental +``` + +The `--incremental` flag will store incremental compilation artifacts +in `build//stage0-incremental`. Note that we only use incremental +compilation for the stage0 -> stage1 compilation -- this is because +the stage1 compiler is changing, and we don't try to cache and reuse +incremental artifacts across different versions of the compiler. For +this reason, `--incremental` defaults to `--stage 1` (though you can +manually select a higher stage, if you prefer). + +You can always drop the `--incremental` to build as normal (but you +will still be using the local nightly as your bootstrap). + ## Directory Layout This build system houses all output under the `build` directory, which looks diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index c5684e6999..90fd31ecbd 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -25,10 +25,15 @@ //! switching compilers for the bootstrap and for build scripts will probably //! never get replaced. +#![deny(warnings)] + extern crate bootstrap; use std::env; use std::ffi::OsString; +use std::io; +use std::io::prelude::*; +use std::str::FromStr; use std::path::PathBuf; use std::process::{Command, ExitStatus}; @@ -41,6 +46,11 @@ fn main() { .and_then(|w| w[1].to_str()); let version = args.iter().find(|w| &**w == "-vV"); + let verbose = match env::var("RUSTC_VERBOSE") { + Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"), + Err(_) => 0, + }; + // Build scripts always use the snapshot compiler which is guaranteed to be // able to produce an executable, whereas intermediate compilers may not // have the standard library built yet and may not be able to produce an @@ -57,6 +67,7 @@ fn main() { ("RUSTC_REAL", "RUSTC_LIBDIR") }; let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set"); + let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"); let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc)); let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir)); @@ -73,12 +84,14 @@ fn main() { if let Some(target) = target { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option. - cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set")); + cmd.arg("--sysroot").arg(sysroot); // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of // linking all deps statically into the dylib. - cmd.arg("-Cprefer-dynamic"); + if env::var_os("RUSTC_NO_PREFER_DYNAMIC").is_none() { + cmd.arg("-Cprefer-dynamic"); + } // Help the libc crate compile by assisting it in finding the MUSL // native libraries. @@ -95,6 +108,15 @@ fn main() { cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::>()); } + // Pass down incremental directory, if any. + if let Ok(dir) = env::var("RUSTC_INCREMENTAL") { + cmd.arg(format!("-Zincremental={}", dir)); + + if verbose > 0 { + cmd.arg("-Zincremental-info"); + } + } + // If we're compiling specifically the `panic_abort` crate then we pass // the `-C panic=abort` option. Note that we do not do this for any // other crate intentionally as this is the only crate for now that we @@ -176,9 +198,19 @@ fn main() { if let Some(rpath) = rpath { cmd.arg("-C").arg(format!("link-args={}", rpath)); } + + if let Ok(s) = env::var("RUSTFLAGS") { + for flag in s.split_whitespace() { + cmd.arg(flag); + } + } } } + if verbose > 1 { + writeln!(&mut io::stderr(), "rustc command: {:?}", cmd).unwrap(); + } + // Actually run the compiler! std::process::exit(match exec_cmd(&mut cmd) { Ok(s) => s.code().unwrap_or(0xfe), diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 67358e540d..e9ca430f15 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -12,6 +12,8 @@ //! //! See comments in `src/bootstrap/rustc.rs` for more information. +#![deny(warnings)] + extern crate bootstrap; use std::env; @@ -23,6 +25,7 @@ fn main() { let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set"); let libdir = env::var_os("RUSTC_LIBDIR").expect("RUSTC_LIBDIR was not set"); let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set"); + let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"); let mut dylib_path = bootstrap::util::dylib_path(); dylib_path.insert(0, PathBuf::from(libdir)); @@ -33,6 +36,8 @@ fn main() { .arg(format!("stage{}", stage)) .arg("--cfg") .arg("dox") + .arg("--sysroot") + .arg(sysroot) .env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); std::process::exit(match cmd.status() { diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 82a546f195..bc83411024 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -72,7 +72,7 @@ def download(path, url, probably_big, verbose): option = "-#" else: option = "-s" - run(["curl", option, "-Sf", "-o", path, url], verbose=verbose) + run(["curl", option, "--retry", "3", "-Sf", "-o", path, url], verbose=verbose) def verify(path, sha_path, verbose): @@ -290,6 +290,8 @@ class RustBuild(object): env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] + if not os.path.isfile(self.cargo()): + raise Exception("no cargo executable found at `%s`" % self.cargo()) args = [self.cargo(), "build", "--manifest-path", os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] if self.use_vendored_sources: @@ -436,14 +438,14 @@ def main(): rb.use_vendored_sources = '\nvendor = true' in rb.config_toml or \ 'CFG_ENABLE_VENDOR' in rb.config_mk - if 'SUDO_USER' in os.environ: - if os.environ['USER'] != os.environ['SUDO_USER']: + if 'SUDO_USER' in os.environ and not rb.use_vendored_sources: + if os.environ.get('USER') != os.environ['SUDO_USER']: rb.use_vendored_sources = True print('info: looks like you are running this command under `sudo`') print(' and so in order to preserve your $HOME this will now') print(' use vendored sources by default. Note that if this') print(' does not work you should run a normal build first') - print(' before running a command like `sudo make intall`') + print(' before running a command like `sudo make install`') if rb.use_vendored_sources: if not os.path.exists('.cargo'): diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs index aa70e24d95..54c8194678 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc.rs @@ -121,10 +121,14 @@ fn set_compiler(cfg: &mut gcc::Config, } "mips-unknown-linux-musl" => { - cfg.compiler("mips-linux-musl-gcc"); + if cfg.get_compiler().path().to_str() == Some("gcc") { + cfg.compiler("mips-linux-musl-gcc"); + } } "mipsel-unknown-linux-musl" => { - cfg.compiler("mipsel-linux-musl-gcc"); + if cfg.get_compiler().path().to_str() == Some("gcc") { + cfg.compiler("mipsel-linux-musl-gcc"); + } } t if t.contains("musl") => { diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index c38bb33aa0..585d9f51b9 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -40,6 +40,9 @@ pub fn collect(build: &mut Build) { } } + build.release_num = release_num.to_string(); + build.prerelease_version = release_num.to_string(); + // Depending on the channel, passed in `./configure --release-channel`, // determine various properties of the build. match &build.config.channel[..] { diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index aa15825d82..4aca843558 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -62,9 +62,9 @@ impl fmt::Display for TestKind { /// /// This tool in `src/tools` will verify the validity of all our links in the /// documentation to ensure we don't have a bunch of dead ones. -pub fn linkcheck(build: &Build, stage: u32, host: &str) { - println!("Linkcheck stage{} ({})", stage, host); - let compiler = Compiler::new(stage, host); +pub fn linkcheck(build: &Build, host: &str) { + println!("Linkcheck ({})", host); + let compiler = Compiler::new(0, host); let _time = util::timeit(); build.run(build.tool_cmd(&compiler, "linkchecker") @@ -93,10 +93,11 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { t!(fs::create_dir_all(&out_dir)); let _time = util::timeit(); - build.run(build.tool_cmd(compiler, "cargotest") - .env("PATH", newpath) - .arg(&build.cargo) - .arg(&out_dir)); + let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest")); + build.prepare_tool_cmd(compiler, &mut cmd); + build.run(cmd.env("PATH", newpath) + .arg(&build.cargo) + .arg(&out_dir)); } /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler. @@ -104,9 +105,9 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { /// This tool in `src/tools` checks up on various bits and pieces of style and /// otherwise just implements a few lint-like checks that are specific to the /// compiler itself. -pub fn tidy(build: &Build, stage: u32, host: &str) { - println!("tidy check stage{} ({})", stage, host); - let compiler = Compiler::new(stage, host); +pub fn tidy(build: &Build, host: &str) { + println!("tidy check ({})", host); + let compiler = Compiler::new(0, host); build.run(build.tool_cmd(&compiler, "tidy") .arg(build.src.join("src"))); } @@ -127,7 +128,9 @@ pub fn compiletest(build: &Build, suite: &str) { println!("Check compiletest suite={} mode={} ({} -> {})", suite, mode, compiler.host, target); - let mut cmd = build.tool_cmd(compiler, "compiletest"); + let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host), + "compiletest")); + build.prepare_tool_cmd(compiler, &mut cmd); // compiletest currently has... a lot of arguments, so let's just pass all // of them! @@ -192,7 +195,7 @@ pub fn compiletest(build: &Build, cmd.args(&build.flags.cmd.test_args()); - if build.config.verbose || build.flags.verbose { + if build.config.verbose() || build.flags.verbose() { cmd.arg("--verbose"); } @@ -287,7 +290,8 @@ pub fn error_index(build: &Build, compiler: &Compiler) { let output = dir.join("error-index.md"); let _time = util::timeit(); - build.run(build.tool_cmd(compiler, "error_index_generator") + build.run(build.tool_cmd(&Compiler::new(0, compiler.host), + "error_index_generator") .arg("markdown") .arg(&output) .env("CFG_BUILD", &build.config.build)); @@ -341,12 +345,22 @@ pub fn krate(build: &Build, println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage, compiler.host, target); + // If we're not doing a full bootstrap but we're testing a stage2 version of + // libstd, then what we're actually testing is the libstd produced in + // stage1. Reflect that here by updating the compiler that we're working + // with automatically. + let compiler = if build.force_use_stage1(compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler.clone() + }; + // Build up the base `cargo test` command. // // Pass in some standard flags then iterate over the graph we've discovered // in `cargo metadata` with the maps above and figure out what `-p` // arguments need to get passed. - let mut cargo = build.cargo(compiler, mode, target, test_kind.subcommand()); + let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand()); cargo.arg("--manifest-path") .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); @@ -359,10 +373,16 @@ pub fn krate(build: &Build, let mut visited = HashSet::new(); let mut next = vec![root]; while let Some(name) = next.pop() { - // Right now jemalloc is our only target-specific crate in the sense - // that it's not present on all platforms. Custom skip it here for now, - // but if we add more this probably wants to get more generalized. - if !name.contains("jemalloc") { + // Right now jemalloc is our only target-specific crate in the + // sense that it's not present on all platforms. Custom skip it + // here for now, but if we add more this probably wants to get + // more generalized. + // + // Also skip `build_helper` as it's not compiled normally for + // target during the bootstrap and it's just meant to be a + // helper crate, not tested. If it leaks through then it ends up + // messing with various mtime calculations and such. + if !name.contains("jemalloc") && name != "build_helper" { cargo.arg("-p").arg(name); } for dep in build.crates[name].deps.iter() { @@ -380,7 +400,7 @@ pub fn krate(build: &Build, // Note that to run the compiler we need to run with the *host* libraries, // but our wrapper scripts arrange for that to be the case anyway. let mut dylib_path = dylib_path(); - dylib_path.insert(0, build.sysroot_libdir(compiler, target)); + dylib_path.insert(0, build.sysroot_libdir(&compiler, target)); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); if target.contains("android") { @@ -399,10 +419,10 @@ pub fn krate(build: &Build, if target.contains("android") { build.run(&mut cargo); - krate_android(build, compiler, target, mode); + krate_android(build, &compiler, target, mode); } else if target.contains("emscripten") { build.run(&mut cargo); - krate_emscripten(build, compiler, target, mode); + krate_emscripten(build, &compiler, target, mode); } else { cargo.args(&build.flags.cmd.test_args()); build.run(&mut cargo); @@ -443,6 +463,8 @@ fn krate_android(build: &Build, let output = output(Command::new("adb").arg("shell").arg(&program)); println!("{}", output); + + t!(fs::create_dir_all(build.out.join("tmp"))); build.run(Command::new("adb") .arg("pull") .arg(&log) @@ -497,7 +519,12 @@ fn find_tests(dir: &Path, pub fn android_copy_libs(build: &Build, compiler: &Compiler, target: &str) { + if !target.contains("android") { + return + } + println!("Android copy libs to emulator ({})", target); + build.run(Command::new("adb").arg("wait-for-device")); build.run(Command::new("adb").arg("remount")); build.run(Command::new("adb").args(&["shell", "rm", "-r", ADB_TEST_DIR])); build.run(Command::new("adb").args(&["shell", "mkdir", ADB_TEST_DIR])); @@ -544,8 +571,20 @@ pub fn distcheck(build: &Build) { .current_dir(&dir); build.run(&mut cmd); build.run(Command::new("./configure") + .args(&build.config.configure_args) .current_dir(&dir)); build.run(Command::new(build_helper::make(&build.config.build)) .arg("check") .current_dir(&dir)); } + +/// Test the build system itself +pub fn bootstrap(build: &Build) { + let mut cmd = Command::new(&build.cargo); + cmd.arg("test") + .current_dir(build.src.join("src/bootstrap")) + .env("CARGO_TARGET_DIR", build.out.join("bootstrap")) + .env("RUSTC", &build.rustc); + cmd.arg("--").args(&build.flags.cmd.test_args()); + build.run(&mut cmd); +} diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index e7655458ae..a66ed46fe4 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -24,6 +24,7 @@ use Build; pub fn clean(build: &Build) { rm_rf(build, "tmp".as_ref()); rm_rf(build, &build.out.join("tmp")); + rm_rf(build, &build.out.join("dist")); for host in build.config.host.iter() { let entries = match build.out.join(host).read_dir() { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 04d01759ab..7c35151a6d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -16,7 +16,6 @@ //! compiler. This module is also responsible for assembling the sysroot as it //! goes along from the output of the previous stage. -use std::cmp; use std::collections::HashMap; use std::fs::{self, File}; use std::path::{Path, PathBuf}; @@ -33,22 +32,26 @@ use {Build, Compiler, Mode}; /// This will build the standard library for a particular stage of the build /// using the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. -pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { - println!("Building stage{} std artifacts ({} -> {})", compiler.stage, - compiler.host, target); - +pub fn std(build: &Build, target: &str, compiler: &Compiler) { let libdir = build.sysroot_libdir(compiler, target); - let _ = fs::remove_dir_all(&libdir); t!(fs::create_dir_all(&libdir)); - // Some platforms have startup objects that may be required to produce the - // libstd dynamic library, for example. - build_startup_objects(build, target, &libdir); + println!("Building stage{} std artifacts ({} -> {})", compiler.stage, + compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Libstd, target); build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); - cargo.arg("--features").arg(build.std_features()) + let mut features = build.std_features(); + // When doing a local rebuild we tell cargo that we're stage1 rather than + // stage0. This works fine if the local rust and being-built rust have the + // same view of what the default allocator is, but fails otherwise. Since + // we don't have a way to express an allocator preference yet, work + // around the issue in the case of a local rebuild with jemalloc disabled. + if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { + features.push_str(" force_alloc_system"); + } + cargo.arg("--features").arg(features) .arg("--manifest-path") .arg(build.src.join("src/rustc/std_shim/Cargo.toml")); @@ -64,30 +67,31 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { } build.run(&mut cargo); - update_mtime(&libstd_stamp(build, &compiler, target)); - std_link(build, target, compiler.stage, compiler.host); + update_mtime(build, &libstd_stamp(build, &compiler, target)); } /// Link all libstd rlibs/dylibs into the sysroot location. /// -/// Links those artifacts generated in the given `stage` for `target` produced -/// by `compiler` into `host`'s sysroot. +/// Links those artifacts generated by `compiler` to a the `stage` compiler's +/// sysroot for the specified `host` and `target`. +/// +/// Note that this assumes that `compiler` has already generated the libstd +/// libraries for `target`, and this method will find them in the relevant +/// output directory. pub fn std_link(build: &Build, - target: &str, - stage: u32, - host: &str) { - let compiler = Compiler::new(stage, &build.config.build); - let target_compiler = Compiler::new(compiler.stage, host); + compiler: &Compiler, + target_compiler: &Compiler, + target: &str) { + println!("Copying stage{} std from stage{} ({} -> {} / {})", + target_compiler.stage, + compiler.stage, + compiler.host, + target_compiler.host, + target); let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(&compiler, Mode::Libstd, target); - // If we're linking one compiler host's output into another, then we weren't - // called from the `std` method above. In that case we clean out what's - // already there. - if host != compiler.host { - let _ = fs::remove_dir_all(&libdir); - t!(fs::create_dir_all(&libdir)); - } + t!(fs::create_dir_all(&libdir)); add_to_sysroot(&out_dir, &libdir); if target.contains("musl") && !target.contains("mips") { @@ -110,12 +114,15 @@ fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) { /// They don't require any library support as they're just plain old object /// files, so we just use the nightly snapshot compiler to always build them (as /// no other compilers are guaranteed to be available). -fn build_startup_objects(build: &Build, target: &str, into: &Path) { +pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &str) { if !target.contains("pc-windows-gnu") { return } + let compiler = Compiler::new(0, &build.config.build); let compiler_path = build.compiler_path(&compiler); + let into = build.sysroot_libdir(for_compiler, target); + t!(fs::create_dir_all(&into)); for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) { let file = t!(file); @@ -123,7 +130,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) { build.run(cmd.env("RUSTC_BOOTSTRAP", "1") .arg("--target").arg(target) .arg("--emit=obj") - .arg("--out-dir").arg(into) + .arg("--out-dir").arg(&into) .arg(file.path())); } @@ -137,7 +144,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) { /// This will build libtest and supporting libraries for a particular stage of /// the build using the `compiler` targeting the `target` architecture. The /// artifacts created will also be linked into the sysroot directory. -pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { +pub fn test(build: &Build, target: &str, compiler: &Compiler) { println!("Building stage{} test artifacts ({} -> {})", compiler.stage, compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Libtest, target); @@ -146,20 +153,20 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { cargo.arg("--manifest-path") .arg(build.src.join("src/rustc/test_shim/Cargo.toml")); build.run(&mut cargo); - update_mtime(&libtest_stamp(build, compiler, target)); - test_link(build, target, compiler.stage, compiler.host); + update_mtime(build, &libtest_stamp(build, compiler, target)); } -/// Link all libtest rlibs/dylibs into the sysroot location. -/// -/// Links those artifacts generated in the given `stage` for `target` produced -/// by `compiler` into `host`'s sysroot. +/// Same as `std_link`, only for libtest pub fn test_link(build: &Build, - target: &str, - stage: u32, - host: &str) { - let compiler = Compiler::new(stage, &build.config.build); - let target_compiler = Compiler::new(compiler.stage, host); + compiler: &Compiler, + target_compiler: &Compiler, + target: &str) { + println!("Copying stage{} test from stage{} ({} -> {} / {})", + target_compiler.stage, + compiler.stage, + compiler.host, + target_compiler.host, + target); let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(&compiler, Mode::Libtest, target); add_to_sysroot(&out_dir, &libdir); @@ -170,7 +177,7 @@ pub fn test_link(build: &Build, /// This will build the compiler for a particular stage of the build using /// the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. -pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { +pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { println!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, compiler.host, target); @@ -187,8 +194,14 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { cargo.env("CFG_RELEASE", &build.release) .env("CFG_RELEASE_CHANNEL", &build.config.channel) .env("CFG_VERSION", &build.version) - .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(String::new())) - .env("CFG_LIBDIR_RELATIVE", "lib"); + .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(PathBuf::new())); + + if compiler.stage == 0 { + cargo.env("CFG_LIBDIR_RELATIVE", "lib"); + } else { + let libdir_relative = build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib")); + cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); + } // If we're not building a compiler with debugging information then remove // these two env vars which would be set otherwise. @@ -215,7 +228,11 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { cargo.env("CFG_LLVM_ROOT", s); } - if build.config.llvm_static_stdcpp { + // Building with a static libstdc++ is only supported on linux right now, + // not for MSVC or OSX + if build.config.llvm_static_stdcpp && + !target.contains("windows") && + !target.contains("apple") { cargo.env("LLVM_STATIC_STDCPP", compiler_file(build.cxx(target), "libstdc++.a")); } @@ -229,20 +246,19 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { cargo.env("CFG_DEFAULT_AR", s); } build.run(&mut cargo); - - rustc_link(build, target, compiler.stage, compiler.host); } -/// Link all librustc rlibs/dylibs into the sysroot location. -/// -/// Links those artifacts generated in the given `stage` for `target` produced -/// by `compiler` into `host`'s sysroot. +/// Same as `std_link`, only for librustc pub fn rustc_link(build: &Build, - target: &str, - stage: u32, - host: &str) { - let compiler = Compiler::new(stage, &build.config.build); - let target_compiler = Compiler::new(compiler.stage, host); + compiler: &Compiler, + target_compiler: &Compiler, + target: &str) { + println!("Copying stage{} rustc from stage{} ({} -> {} / {})", + target_compiler.stage, + compiler.stage, + compiler.host, + target_compiler.host, + target); let libdir = build.sysroot_libdir(&target_compiler, target); let out_dir = build.cargo_out(&compiler, Mode::Librustc, target); add_to_sysroot(&out_dir, &libdir); @@ -266,6 +282,12 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { PathBuf::from(out.trim()) } +pub fn create_sysroot(build: &Build, compiler: &Compiler) { + let sysroot = build.sysroot(compiler); + let _ = fs::remove_dir_all(&sysroot); + t!(fs::create_dir_all(&sysroot)); +} + /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler @@ -276,18 +298,17 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { if stage == 0 { return } + + println!("Copying stage{} compiler ({})", stage, host); + // The compiler that we're assembling let target_compiler = Compiler::new(stage, host); // The compiler that compiled the compiler we're assembling let build_compiler = Compiler::new(stage - 1, &build.config.build); - // Clear out old files - let sysroot = build.sysroot(&target_compiler); - let _ = fs::remove_dir_all(&sysroot); - t!(fs::create_dir_all(&sysroot)); - // Link in all dylibs to the libdir + let sysroot = build.sysroot(&target_compiler); let sysroot_libdir = sysroot.join(libdir(host)); t!(fs::create_dir_all(&sysroot_libdir)); let src_libdir = build.sysroot_libdir(&build_compiler, host); @@ -378,30 +399,48 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) { let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build"); cargo.arg("--manifest-path") .arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool))); + + // We don't want to build tools dynamically as they'll be running across + // stages and such and it's just easier if they're not dynamically linked. + cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + build.run(&mut cargo); } /// Updates the mtime of a stamp file if necessary, only changing it if it's -/// older than some other file in the same directory. +/// older than some other library file in the same directory. /// /// We don't know what file Cargo is going to output (because there's a hash in /// the file name) but we know where it's going to put it. We use this helper to /// detect changes to that output file by looking at the modification time for /// all files in a directory and updating the stamp if any are newer. -fn update_mtime(path: &Path) { - let mut max = None; - if let Ok(entries) = path.parent().unwrap().read_dir() { - for entry in entries.map(|e| t!(e)) { - if t!(entry.file_type()).is_file() { - let meta = t!(entry.metadata()); - let time = FileTime::from_last_modification_time(&meta); - max = cmp::max(max, Some(time)); - } - } - } - - if !max.is_none() && max <= Some(mtime(path)) { - return +/// +/// Note that we only consider Rust libraries as that's what we're interested in +/// propagating changes from. Files like executables are tracked elsewhere. +fn update_mtime(build: &Build, path: &Path) { + let entries = match path.parent().unwrap().join("deps").read_dir() { + Ok(entries) => entries, + Err(_) => return, + }; + let files = entries.map(|e| t!(e)).filter(|e| t!(e.file_type()).is_file()); + let files = files.filter(|e| { + let filename = e.file_name(); + let filename = filename.to_str().unwrap(); + filename.ends_with(".rlib") || + filename.ends_with(".lib") || + is_dylib(&filename) + }); + let max = files.max_by_key(|entry| { + let meta = t!(entry.metadata()); + FileTime::from_last_modification_time(&meta) + }); + let max = match max { + Some(max) => max, + None => return, + }; + + if mtime(&max.path()) > mtime(path) { + build.verbose(&format!("updating {:?} as {:?} changed", path, max.path())); + t!(File::create(path)); } - t!(File::create(path)); } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 1f67b52db8..6e077691b3 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -40,12 +40,14 @@ use util::push_exe_path; pub struct Config { pub ccache: Option, pub ninja: bool, - pub verbose: bool, + pub verbose: usize, pub submodules: bool, pub compiler_docs: bool, pub docs: bool, pub vendor: bool, pub target_config: HashMap, + pub full_bootstrap: bool, + pub extended: bool, // llvm codegen options pub llvm_assertions: bool, @@ -54,6 +56,7 @@ pub struct Config { pub llvm_version_check: bool, pub llvm_static_stdcpp: bool, pub llvm_link_shared: bool, + pub llvm_targets: Option, // rust codegen options pub rust_optimize: bool, @@ -75,6 +78,11 @@ pub struct Config { pub cargo: Option, pub local_rebuild: bool, + // dist misc + pub dist_sign_folder: Option, + pub dist_upload_addr: Option, + pub dist_gpg_password_file: Option, + // libstd features pub debug_jemalloc: bool, pub use_jemalloc: bool, @@ -85,14 +93,16 @@ pub struct Config { pub quiet_tests: bool, // Fallback musl-root for all targets pub musl_root: Option, - pub prefix: Option, - pub docdir: Option, - pub libdir: Option, - pub mandir: Option, + pub prefix: Option, + pub docdir: Option, + pub libdir: Option, + pub libdir_relative: Option, + pub mandir: Option, pub codegen_tests: bool, pub nodejs: Option, pub gdb: Option, pub python: Option, + pub configure_args: Vec, } /// Per-target configuration stored in the global configuration structure. @@ -114,9 +124,11 @@ pub struct Target { #[derive(RustcDecodable, Default)] struct TomlConfig { build: Option, + install: Option, llvm: Option, rust: Option, target: Option>, + dist: Option, } /// TOML representation of various global build decisions. @@ -134,6 +146,17 @@ struct Build { vendor: Option, nodejs: Option, python: Option, + full_bootstrap: Option, + extended: Option, +} + +/// TOML representation of various global install decisions. +#[derive(RustcDecodable, Default, Clone)] +struct Install { + prefix: Option, + mandir: Option, + docdir: Option, + libdir: Option, } /// TOML representation of how the LLVM build is configured. @@ -146,6 +169,14 @@ struct Llvm { release_debuginfo: Option, version_check: Option, static_libstdcpp: Option, + targets: Option, +} + +#[derive(RustcDecodable, Default, Clone)] +struct Dist { + sign_folder: Option, + gpg_password_file: Option, + upload_addr: Option, } #[derive(RustcDecodable)] @@ -259,6 +290,15 @@ impl Config { set(&mut config.docs, build.docs); set(&mut config.submodules, build.submodules); set(&mut config.vendor, build.vendor); + set(&mut config.full_bootstrap, build.full_bootstrap); + set(&mut config.extended, build.extended); + + if let Some(ref install) = toml.install { + config.prefix = install.prefix.clone().map(PathBuf::from); + config.mandir = install.mandir.clone().map(PathBuf::from); + config.docdir = install.docdir.clone().map(PathBuf::from); + config.libdir = install.libdir.clone().map(PathBuf::from); + } if let Some(ref llvm) = toml.llvm { match llvm.ccache { @@ -276,7 +316,9 @@ impl Config { 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); + config.llvm_targets = llvm.targets.clone(); } + if let Some(ref rust) = toml.rust { set(&mut config.rust_debug_assertions, rust.debug_assertions); set(&mut config.rust_debuginfo, rust.debuginfo); @@ -323,6 +365,12 @@ impl Config { } } + if let Some(ref t) = toml.dist { + config.dist_sign_folder = t.sign_folder.clone().map(PathBuf::from); + config.dist_gpg_password_file = t.gpg_password_file.clone().map(PathBuf::from); + config.dist_upload_addr = t.upload_addr.clone(); + } + return config } @@ -385,6 +433,8 @@ impl Config { ("NINJA", self.ninja), ("CODEGEN_TESTS", self.codegen_tests), ("VENDOR", self.vendor), + ("FULL_BOOTSTRAP", self.full_bootstrap), + ("EXTENDED", self.extended), } match key { @@ -443,16 +493,19 @@ impl Config { self.channel = value.to_string(); } "CFG_PREFIX" => { - self.prefix = Some(value.to_string()); + self.prefix = Some(PathBuf::from(value)); } "CFG_DOCDIR" => { - self.docdir = Some(value.to_string()); + self.docdir = Some(PathBuf::from(value)); } "CFG_LIBDIR" => { - self.libdir = Some(value.to_string()); + self.libdir = Some(PathBuf::from(value)); + } + "CFG_LIBDIR_RELATIVE" => { + self.libdir_relative = Some(PathBuf::from(value)); } "CFG_MANDIR" => { - self.mandir = Some(value.to_string()); + self.mandir = Some(PathBuf::from(value)); } "CFG_LLVM_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) @@ -463,7 +516,7 @@ impl Config { "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - target.jemalloc = Some(parse_configure_path(value)); + target.jemalloc = Some(parse_configure_path(value).join("libjemalloc_pic.a")); } "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "arm-linux-androideabi".to_string(); @@ -504,10 +557,23 @@ impl Config { "CFG_ENABLE_SCCACHE" if value == "1" => { self.ccache = Some("sccache".to_string()); } + "CFG_CONFIGURE_ARGS" if value.len() > 0 => { + self.configure_args = value.split_whitespace() + .map(|s| s.to_string()) + .collect(); + } _ => {} } } } + + pub fn verbose(&self) -> bool { + self.verbose > 0 + } + + pub fn very_verbose(&self) -> bool { + self.verbose > 1 + } } #[cfg(not(windows))] diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 22542f8737..a53419ad7f 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -42,6 +42,17 @@ # example. #ninja = false +# LLVM targets to build support for. +# Note: this is NOT related to Rust compilation targets. However, as Rust is +# dependent on LLVM for code generation, turning targets off here WILL lead to +# the resulting rustc being unable to compile for the disabled architectures. +# Also worth pointing out is that, in case support for new targets are added to +# LLVM, enabling them here doesn't mean Rust is automatically gaining said +# support. You'll need to write a target specification at least, and most +# likely, teach rustc about the C ABI of the target. Get in touch with the +# Rust team and file an issue if you need assistance in porting! +#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX" + # ============================================================================= # General build configuration options # ============================================================================= @@ -100,6 +111,36 @@ # Indicate whether the vendored sources are used for Rust dependencies or not #vendor = false +# Typically the build system will build the rust compiler twice. The second +# compiler, however, will simply use its own libraries to link against. If you +# would rather to perform a full bootstrap, compiling the compiler three times, +# then you can set this option to true. You shouldn't ever need to set this +# option to true. +#full-bootstrap = false + +# Enable a build of the and extended rust tool set which is not only the +# compiler but also tools such as Cargo. This will also produce "combined +# installers" which are used to install Rust and Cargo together. This is +# disabled by default. +#extended = false + +# ============================================================================= +# General install configuration options +# ============================================================================= +[install] + +# Instead of installing to /usr/local, install to this path instead. +#prefix = "/usr/local" + +# Where to install libraries in `prefix` above +#libdir = "lib" + +# Where to install man pages in `prefix` above +#mandir = "share/man" + +# Where to install documentation in `prefix` above +#docdir = "share/doc/rust" + # ============================================================================= # Options for compiling Rust code itself # ============================================================================= @@ -201,3 +242,33 @@ # that this option only makes sense for MUSL targets that produce statically # linked binaries #musl-root = "..." + +# ============================================================================= +# Distribution options +# +# These options are related to distribution, mostly for the Rust project itself. +# You probably won't need to concern yourself with any of these options +# ============================================================================= +[dist] + +# This is the folder of artifacts that the build system will sign. All files in +# this directory will be signed with the default gpg key using the system `gpg` +# binary. The `asc` and `sha256` files will all be output into the standard dist +# output folder (currently `build/dist`) +# +# This folder should be populated ahead of time before the build system is +# invoked. +#sign-folder = "path/to/folder/to/sign" + +# This is a file which contains the password of the default gpg key. This will +# be passed to `gpg` down the road when signing all files in `sign-folder` +# above. This should be stored in plaintext. +#gpg-password-file = "path/to/gpg/password" + +# The remote address that all artifacts will eventually be uploaded to. The +# build system generates manifests which will point to these urls, and for the +# manifests to be correct they'll have to have the right URLs encoded. +# +# Note that this address should not contain a trailing slash as file names will +# be appended to it. +#upload-addr = "https://example.com/folder" diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index d9663a507d..9878d1c08b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -18,10 +18,13 @@ //! out to `rust-installer` still. This may one day be replaced with bits and //! pieces of `rustup.rs`! +use std::env; use std::fs::{self, File}; -use std::io::Write; +use std::io::{Read, Write}; use std::path::{PathBuf, Path}; -use std::process::Command; +use std::process::{Command, Stdio}; + +use build_helper::output; use {Build, Compiler, Mode}; use util::{cp_r, libdir, is_dylib, cp_filtered, copy}; @@ -35,6 +38,10 @@ pub fn package_vers(build: &Build) -> &str { } } +fn pkgname(build: &Build, component: &str) -> String { + format!("{}-{}", component, package_vers(build)) +} + fn distdir(build: &Build) -> PathBuf { build.out.join("dist") } @@ -53,8 +60,8 @@ pub fn docs(build: &Build, stage: u32, host: &str) { return } - let name = format!("rust-docs-{}", package_vers(build)); - let image = tmpdir(build).join(format!("{}-{}-image", name, name)); + let name = pkgname(build, "rust-docs"); + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); let dst = image.join("share/doc/rust/html"); @@ -94,7 +101,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) { /// in Rust. pub fn mingw(build: &Build, host: &str) { println!("Dist mingw ({})", host); - let name = format!("rust-mingw-{}", package_vers(build)); + let name = pkgname(build, "rust-mingw"); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); t!(fs::create_dir_all(&image)); @@ -130,7 +137,7 @@ pub fn mingw(build: &Build, host: &str) { /// Creates the `rustc` installer component. pub fn rustc(build: &Build, stage: u32, host: &str) { println!("Dist rustc stage{} ({})", stage, host); - let name = format!("rustc-{}", package_vers(build)); + let name = pkgname(build, "rustc"); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, host)); @@ -274,7 +281,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) { return } - let name = format!("rust-std-{}", package_vers(build)); + let name = pkgname(build, "rust-std"); let image = tmpdir(build).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); @@ -320,10 +327,18 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { return } - let name = format!("rust-analysis-{}", package_vers(build)); + // Package save-analysis from stage1 if not doing a full bootstrap, as the + // stage2 artifacts is simply copied from stage1 in that case. + let compiler = if build.force_use_stage1(compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler.clone() + }; + + let name = pkgname(build, "rust-analysis"); let image = tmpdir(build).join(format!("{}-{}-image", name, target)); - let src = build.stage_out(compiler, Mode::Libstd).join(target).join("release").join("deps"); + let src = build.stage_out(&compiler, Mode::Libstd).join(target).join("release").join("deps"); let image_src = src.join("save-analysis"); let dst = image.join("lib/rustlib").join(target).join("analysis"); @@ -348,14 +363,13 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { /// Creates the `rust-src` installer component and the plain source tarball pub fn rust_src(build: &Build) { println!("Dist src"); - let plain_name = format!("rustc-{}-src", package_vers(build)); - let name = format!("rust-src-{}", package_vers(build)); + + let name = pkgname(build, "rust-src"); let image = tmpdir(build).join(format!("{}-image", name)); let _ = fs::remove_dir_all(&image); let dst = image.join("lib/rustlib/src"); let dst_src = dst.join("rust"); - let plain_dst_src = dst.join(&plain_name); t!(fs::create_dir_all(&dst_src)); // This is the set of root paths which will become part of the source package @@ -367,7 +381,8 @@ pub fn rust_src(build: &Build) { "README.md", "RELEASES.md", "configure", - "Makefile.in" + "Makefile.in", + "x.py", ]; let src_dirs = [ "man", @@ -435,7 +450,11 @@ pub fn rust_src(build: &Build) { build.run(&mut cmd); // Rename directory, so that root folder of tarball has the correct name - t!(fs::rename(&dst_src, &plain_dst_src)); + let plain_name = format!("rustc-{}-src", package_vers(build)); + let plain_dst_src = tmpdir(build).join(&plain_name); + let _ = fs::remove_dir_all(&plain_dst_src); + t!(fs::create_dir_all(&plain_dst_src)); + cp_r(&dst_src, &plain_dst_src); // Create the version file write_file(&plain_dst_src.join("version"), build.version.as_bytes()); @@ -444,10 +463,11 @@ pub fn rust_src(build: &Build) { let mut cmd = Command::new("tar"); cmd.arg("-czf").arg(sanitize_sh(&rust_src_location(build))) .arg(&plain_name) - .current_dir(&dst); + .current_dir(tmpdir(build)); build.run(&mut cmd); t!(fs::remove_dir_all(&image)); + t!(fs::remove_dir_all(&plain_dst_src)); } fn install(src: &Path, dstdir: &Path, perms: u32) { @@ -488,3 +508,403 @@ fn write_file(path: &Path, data: &[u8]) { let mut vf = t!(fs::File::create(path)); t!(vf.write_all(data)); } + +// FIXME(#38531) eventually this should package up a Cargo that we just compiled +// and tested locally, but for now we're downloading cargo +// artifacts from their compiled location. +pub fn cargo(build: &Build, stage: u32, target: &str) { + println!("Dist cargo stage{} ({})", stage, target); + + let branch = match &build.config.channel[..] { + "stable" | + "beta" => format!("rust-{}", build.release_num), + _ => "master".to_string(), + }; + + let dst = tmpdir(build).join("cargo"); + let _ = fs::remove_dir_all(&dst); + build.run(Command::new("git") + .arg("clone") + .arg("--depth").arg("1") + .arg("--branch").arg(&branch) + .arg("https://github.com/rust-lang/cargo") + .current_dir(dst.parent().unwrap())); + let sha = output(Command::new("git") + .arg("rev-parse") + .arg("HEAD") + .current_dir(&dst)); + let sha = sha.trim(); + println!("\tgot cargo sha: {}", sha); + + let input = format!("https://s3.amazonaws.com/rust-lang-ci/cargo-builds\ + /{}/cargo-nightly-{}.tar.gz", sha, target); + let output = distdir(build).join(format!("cargo-nightly-{}.tar.gz", target)); + println!("\tdownloading {}", input); + let mut curl = Command::new("curl"); + curl.arg("-f") + .arg("-o").arg(&output) + .arg(&input) + .arg("--retry").arg("3"); + build.run(&mut curl); +} + +/// Creates a combined installer for the specified target in the provided stage. +pub fn extended(build: &Build, stage: u32, target: &str) { + println!("Dist extended stage{} ({})", stage, target); + + let dist = distdir(build); + let rustc_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rustc"), + target)); + let cargo_installer = dist.join(format!("cargo-nightly-{}.tar.gz", target)); + let docs_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-docs"), + target)); + let mingw_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-mingw"), + target)); + let std_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-std"), + target)); + + let tmp = tmpdir(build); + let overlay = tmp.join("extended-overlay"); + let etc = build.src.join("src/etc/installer"); + let work = tmp.join("work"); + + let _ = fs::remove_dir_all(&overlay); + install(&build.src.join("COPYRIGHT"), &overlay, 0o644); + install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644); + install(&build.src.join("LICENSE-MIT"), &overlay, 0o644); + let version = &build.version; + t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + install(&etc.join("README.md"), &overlay, 0o644); + + // When rust-std package split from rustc, we needed to ensure that during + // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering + // the std files during uninstall. To do this ensure that rustc comes + // before rust-std in the list below. + let mut input_tarballs = format!("{},{},{},{}", + sanitize_sh(&rustc_installer), + sanitize_sh(&cargo_installer), + sanitize_sh(&docs_installer), + sanitize_sh(&std_installer)); + if target.contains("pc-windows-gnu") { + input_tarballs.push_str(","); + input_tarballs.push_str(&sanitize_sh(&mingw_installer)); + } + + let mut cmd = Command::new("sh"); + cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/combine-installers.sh"))) + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-is-ready-to-roll.") + .arg(format!("--work-dir={}", sanitize_sh(&work))) + .arg(format!("--output-dir={}", sanitize_sh(&distdir(build)))) + .arg(format!("--package-name={}-{}", pkgname(build, "rust"), target)) + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg(format!("--input-tarballs={}", input_tarballs)) + .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay))); + build.run(&mut cmd); + + let mut license = String::new(); + t!(t!(File::open(build.src.join("COPYRIGHT"))).read_to_string(&mut license)); + license.push_str("\n"); + t!(t!(File::open(build.src.join("LICENSE-APACHE"))).read_to_string(&mut license)); + license.push_str("\n"); + t!(t!(File::open(build.src.join("LICENSE-MIT"))).read_to_string(&mut license)); + + let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18"; + let mut rtf = rtf.to_string(); + rtf.push_str("\n"); + for line in license.lines() { + rtf.push_str(line); + rtf.push_str("\\line "); + } + rtf.push_str("}"); + + if target.contains("apple-darwin") { + let pkg = tmp.join("pkg"); + let _ = fs::remove_dir_all(&pkg); + t!(fs::create_dir_all(pkg.join("rustc"))); + t!(fs::create_dir_all(pkg.join("cargo"))); + t!(fs::create_dir_all(pkg.join("rust-docs"))); + t!(fs::create_dir_all(pkg.join("rust-std"))); + + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)), + &pkg.join("rustc")); + cp_r(&work.join(&format!("cargo-nightly-{}", target)), + &pkg.join("cargo")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)), + &pkg.join("rust-docs")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)), + &pkg.join("rust-std")); + + install(&etc.join("pkg/postinstall"), &pkg.join("rustc"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("cargo"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("rust-docs"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("rust-std"), 0o755); + + let pkgbuild = |component: &str| { + let mut cmd = Command::new("pkgbuild"); + cmd.arg("--identifier").arg(format!("org.rust-lang.{}", component)) + .arg("--scripts").arg(pkg.join(component)) + .arg("--nopayload") + .arg(pkg.join(component).with_extension("pkg")); + build.run(&mut cmd); + }; + pkgbuild("rustc"); + pkgbuild("cargo"); + pkgbuild("rust-docs"); + pkgbuild("rust-std"); + + // create an 'uninstall' package + install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); + pkgbuild("uninstall"); + + t!(fs::create_dir_all(pkg.join("res"))); + t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes())); + install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); + let mut cmd = Command::new("productbuild"); + cmd.arg("--distribution").arg(etc.join("pkg/Distribution.xml")) + .arg("--resources").arg(pkg.join("res")) + .arg(distdir(build).join(format!("{}-{}.pkg", + pkgname(build, "rust"), + target))) + .arg("--package-path").arg(&pkg); + build.run(&mut cmd); + } + + if target.contains("windows") { + let exe = tmp.join("exe"); + let _ = fs::remove_dir_all(&exe); + t!(fs::create_dir_all(exe.join("rustc"))); + t!(fs::create_dir_all(exe.join("cargo"))); + t!(fs::create_dir_all(exe.join("rust-docs"))); + t!(fs::create_dir_all(exe.join("rust-std"))); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)) + .join("rustc"), + &exe.join("rustc")); + cp_r(&work.join(&format!("cargo-nightly-{}", target)) + .join("cargo"), + &exe.join("cargo")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)) + .join("rust-docs"), + &exe.join("rust-docs")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)) + .join(format!("rust-std-{}", target)), + &exe.join("rust-std")); + + t!(fs::remove_file(exe.join("rustc/manifest.in"))); + t!(fs::remove_file(exe.join("cargo/manifest.in"))); + t!(fs::remove_file(exe.join("rust-docs/manifest.in"))); + t!(fs::remove_file(exe.join("rust-std/manifest.in"))); + + if target.contains("windows-gnu") { + t!(fs::create_dir_all(exe.join("rust-mingw"))); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-mingw"), target)) + .join("rust-mingw"), + &exe.join("rust-mingw")); + t!(fs::remove_file(exe.join("rust-mingw/manifest.in"))); + } + + install(&etc.join("exe/rust.iss"), &exe, 0o644); + install(&etc.join("exe/modpath.iss"), &exe, 0o644); + install(&etc.join("exe/upgrade.iss"), &exe, 0o644); + install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); + t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes())); + + // Generate exe installer + let mut cmd = Command::new("iscc"); + cmd.arg("rust.iss") + .current_dir(&exe); + if target.contains("windows-gnu") { + cmd.arg("/dMINGW"); + } + add_env(build, &mut cmd, target); + build.run(&mut cmd); + install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)), + &distdir(build), + 0o755); + + // Generate msi installer + let wix = PathBuf::from(env::var_os("WIX").unwrap()); + let heat = wix.join("bin/heat.exe"); + let candle = wix.join("bin/candle.exe"); + let light = wix.join("bin/light.exe"); + + let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"]; + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rustc") + .args(&heat_flags) + .arg("-cg").arg("RustcGroup") + .arg("-dr").arg("Rustc") + .arg("-var").arg("var.RustcDir") + .arg("-out").arg(exe.join("RustcGroup.wxs"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-docs") + .args(&heat_flags) + .arg("-cg").arg("DocsGroup") + .arg("-dr").arg("Docs") + .arg("-var").arg("var.DocsDir") + .arg("-out").arg(exe.join("DocsGroup.wxs")) + .arg("-t").arg(etc.join("msi/squash-components.xsl"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("cargo") + .args(&heat_flags) + .arg("-cg").arg("CargoGroup") + .arg("-dr").arg("Cargo") + .arg("-var").arg("var.CargoDir") + .arg("-out").arg(exe.join("CargoGroup.wxs")) + .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-std") + .args(&heat_flags) + .arg("-cg").arg("StdGroup") + .arg("-dr").arg("Std") + .arg("-var").arg("var.StdDir") + .arg("-out").arg(exe.join("StdGroup.wxs"))); + if target.contains("windows-gnu") { + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-mingw") + .args(&heat_flags) + .arg("-cg").arg("GccGroup") + .arg("-dr").arg("Gcc") + .arg("-var").arg("var.GccDir") + .arg("-out").arg(exe.join("GccGroup.wxs"))); + } + + let candle = |input: &Path| { + let output = exe.join(input.file_stem().unwrap()) + .with_extension("wixobj"); + let arch = if target.contains("x86_64") {"x64"} else {"x86"}; + let mut cmd = Command::new(&candle); + cmd.current_dir(&exe) + .arg("-nologo") + .arg("-dRustcDir=rustc") + .arg("-dDocsDir=rust-docs") + .arg("-dCargoDir=cargo") + .arg("-dStdDir=rust-std") + .arg("-arch").arg(&arch) + .arg("-out").arg(&output) + .arg(&input); + add_env(build, &mut cmd, target); + + if target.contains("windows-gnu") { + cmd.arg("-dGccDir=rust-mingw"); + } + build.run(&mut cmd); + }; + candle(&etc.join("msi/rust.wxs")); + candle(&etc.join("msi/ui.wxs")); + candle(&etc.join("msi/rustwelcomedlg.wxs")); + candle("RustcGroup.wxs".as_ref()); + candle("DocsGroup.wxs".as_ref()); + candle("CargoGroup.wxs".as_ref()); + candle("StdGroup.wxs".as_ref()); + + if target.contains("windows-gnu") { + candle("GccGroup.wxs".as_ref()); + } + + t!(t!(File::create(exe.join("LICENSE.rtf"))).write_all(rtf.as_bytes())); + install(&etc.join("gfx/banner.bmp"), &exe, 0o644); + install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); + + let filename = format!("{}-{}.msi", pkgname(build, "rust"), target); + let mut cmd = Command::new(&light); + cmd.arg("-nologo") + .arg("-ext").arg("WixUIExtension") + .arg("-ext").arg("WixUtilExtension") + .arg("-out").arg(exe.join(&filename)) + .arg("rust.wixobj") + .arg("ui.wixobj") + .arg("rustwelcomedlg.wixobj") + .arg("RustcGroup.wixobj") + .arg("DocsGroup.wixobj") + .arg("CargoGroup.wixobj") + .arg("StdGroup.wixobj") + .current_dir(&exe); + + if target.contains("windows-gnu") { + cmd.arg("GccGroup.wixobj"); + } + // ICE57 wrongly complains about the shortcuts + cmd.arg("-sice:ICE57"); + + build.run(&mut cmd); + + t!(fs::rename(exe.join(&filename), distdir(build).join(&filename))); + } +} + +fn add_env(build: &Build, cmd: &mut Command, target: &str) { + let mut parts = build.release_num.split('.'); + cmd.env("CFG_RELEASE_INFO", &build.version) + .env("CFG_RELEASE_NUM", &build.release_num) + .env("CFG_RELEASE", &build.release) + .env("CFG_PRERELEASE_VERSION", &build.prerelease_version) + .env("CFG_VER_MAJOR", parts.next().unwrap()) + .env("CFG_VER_MINOR", parts.next().unwrap()) + .env("CFG_VER_PATCH", parts.next().unwrap()) + .env("CFG_VER_BUILD", "0") // just needed to build + .env("CFG_PACKAGE_VERS", package_vers(build)) + .env("CFG_PACKAGE_NAME", pkgname(build, "rust")) + .env("CFG_BUILD", target) + .env("CFG_CHANNEL", &build.config.channel); + + if target.contains("windows-gnu") { + cmd.env("CFG_MINGW", "1") + .env("CFG_ABI", "GNU"); + } else { + cmd.env("CFG_MINGW", "0") + .env("CFG_ABI", "MSVC"); + } + + if target.contains("x86_64") { + cmd.env("CFG_PLATFORM", "x64"); + } else { + cmd.env("CFG_PLATFORM", "x86"); + } +} + +pub fn hash_and_sign(build: &Build) { + let compiler = Compiler::new(0, &build.config.build); + let mut cmd = build.tool_cmd(&compiler, "build-manifest"); + let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") + }); + let addr = build.config.dist_upload_addr.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n") + }); + let file = build.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") + }); + let mut pass = String::new(); + t!(t!(File::open(&file)).read_to_string(&mut pass)); + + let today = output(Command::new("date").arg("+%Y-%m-%d")); + + cmd.arg(sign); + cmd.arg(distdir(build)); + cmd.arg(today.trim()); + cmd.arg(package_vers(build)); + cmd.arg(addr); + + t!(fs::create_dir_all(distdir(build))); + + let mut child = t!(cmd.stdin(Stdio::piped()).spawn()); + t!(child.stdin.take().unwrap().write_all(pass.as_bytes())); + let status = t!(child.wait()); + assert!(status.success()); +} diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 15cb16fad3..d1c9918a73 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -29,19 +29,19 @@ use util::{up_to_date, cp_r}; /// /// This will not actually generate any documentation if the documentation has /// already been generated. -pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str) { +pub fn rustbook(build: &Build, target: &str, name: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let out = out.join(name); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(0, &build.config.build); let src = build.src.join("src/doc").join(name); let index = out.join("index.html"); let rustbook = build.tool(&compiler, "rustbook"); if up_to_date(&src, &index) && up_to_date(&rustbook, &index) { return } - println!("Rustbook stage{} ({}) - {}", stage, target, name); + println!("Rustbook ({}) - {}", target, name); let _ = fs::remove_dir_all(&out); build.run(build.tool_cmd(&compiler, "rustbook") .arg("build") @@ -57,12 +57,12 @@ pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str) { /// `STAMP` alongw ith providing the various header/footer HTML we've cutomized. /// /// In the end, this is just a glorified wrapper around rustdoc! -pub fn standalone(build: &Build, stage: u32, target: &str) { - println!("Documenting stage{} standalone ({})", stage, target); +pub fn standalone(build: &Build, target: &str) { + println!("Documenting standalone ({})", target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(0, &build.config.build); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -137,6 +137,11 @@ pub fn std(build: &Build, stage: u32, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; let out_dir = build.stage_out(&compiler, Mode::Libstd) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); @@ -146,17 +151,25 @@ pub fn std(build: &Build, stage: u32, target: &str) { let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc"); cargo.arg("--manifest-path") .arg(build.src.join("src/rustc/std_shim/Cargo.toml")) - .arg("--features").arg(build.std_features()) - .arg("--no-deps"); - - for krate in &["alloc", "collections", "core", "std", "std_unicode"] { - cargo.arg("-p").arg(krate); - // Create all crate output directories first to make sure rustdoc uses - // relative links. - // FIXME: Cargo should probably do this itself. - t!(fs::create_dir_all(out_dir.join(krate))); + .arg("--features").arg(build.std_features()); + + // We don't want to build docs for internal std dependencies unless + // in compiler-docs mode. When not in that mode, we whitelist the crates + // for which docs must be built. + if build.config.compiler_docs { + cargo.arg("-p").arg("std"); + } else { + cargo.arg("--no-deps"); + for krate in &["alloc", "collections", "core", "std", "std_unicode"] { + cargo.arg("-p").arg(krate); + // Create all crate output directories first to make sure rustdoc uses + // relative links. + // FIXME: Cargo should probably do this itself. + t!(fs::create_dir_all(out_dir.join(krate))); + } } + build.run(&mut cargo); cp_r(&out_dir, &out) } @@ -170,6 +183,11 @@ pub fn test(build: &Build, stage: u32, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; let out_dir = build.stage_out(&compiler, Mode::Libtest) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); @@ -192,6 +210,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; let out_dir = build.stage_out(&compiler, Mode::Librustc) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); @@ -208,11 +231,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) { /// Generates the HTML rendered error-index by running the /// `error_index_generator` tool. -pub fn error_index(build: &Build, stage: u32, target: &str) { - println!("Documenting stage{} error index ({})", stage, target); +pub fn error_index(build: &Build, target: &str) { + println!("Documenting error index ({})", target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.config.build); + let compiler = Compiler::new(0, &build.config.build); let mut index = build.tool_cmd(&compiler, "error_index_generator"); index.arg("html"); index.arg(out.join("error-index.html")); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 5c8d7cab96..c5bbfd89b2 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -27,7 +27,7 @@ use step; /// Deserialized version of all flags for this compile. pub struct Flags { - pub verbose: bool, + pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose pub stage: Option, pub keep_stage: Option, pub build: String, @@ -37,6 +37,17 @@ pub struct Flags { pub src: Option, pub jobs: Option, pub cmd: Subcommand, + pub incremental: bool, +} + +impl Flags { + pub fn verbose(&self) -> bool { + self.verbose > 0 + } + + pub fn very_verbose(&self) -> bool { + self.verbose > 1 + } } pub enum Subcommand { @@ -56,6 +67,7 @@ pub enum Subcommand { }, Clean, Dist { + paths: Vec, install: bool, }, } @@ -63,7 +75,8 @@ pub enum Subcommand { impl Flags { pub fn parse(args: &[String]) -> Flags { let mut opts = Options::new(); - opts.optflag("v", "verbose", "use verbose output"); + opts.optflagmulti("v", "verbose", "use verbose output (-vv for very verbose)"); + opts.optflag("i", "incremental", "use incremental compilation"); opts.optopt("", "config", "TOML configuration file for build", "FILE"); opts.optopt("", "build", "build target of the stage0 compiler", "BUILD"); opts.optmulti("", "host", "host targets to build", "HOST"); @@ -237,6 +250,7 @@ To learn more about a subcommand, run `./x.py -h` opts.optflag("", "install", "run installer as well"); m = parse(&opts); Subcommand::Dist { + paths: remaining_as_path(&m), install: m.opt_present("install"), } } @@ -256,19 +270,30 @@ To learn more about a subcommand, run `./x.py -h` } }); + let mut stage = m.opt_str("stage").map(|j| j.parse().unwrap()); + + let incremental = m.opt_present("i"); + + if incremental { + if stage.is_none() { + stage = Some(1); + } + } + Flags { - verbose: m.opt_present("v"), - stage: m.opt_str("stage").map(|j| j.parse().unwrap()), + verbose: m.opt_count("v"), + stage: stage, keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()), build: m.opt_str("build").unwrap_or_else(|| { env::var("BUILD").unwrap() }), - host: m.opt_strs("host"), - target: m.opt_strs("target"), + host: split(m.opt_strs("host")), + target: split(m.opt_strs("target")), config: cfg_file, src: m.opt_str("src").map(PathBuf::from), jobs: m.opt_str("jobs").map(|j| j.parse().unwrap()), cmd: cmd, + incremental: incremental, } } } @@ -284,3 +309,7 @@ impl Subcommand { } } } + +fn split(s: Vec) -> Vec { + s.iter().flat_map(|s| s.split(',')).map(|s| s.to_string()).collect() +} diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 9bc5a7c00a..efc460f358 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -13,9 +13,9 @@ //! This module is responsible for installing the standard library, //! compiler, and documentation. +use std::env; use std::fs; -use std::borrow::Cow; -use std::path::Path; +use std::path::{Path, PathBuf, Component}; use std::process::Command; use Build; @@ -23,23 +23,35 @@ use dist::{package_vers, sanitize_sh, tmpdir}; /// Installs everything. pub fn install(build: &Build, stage: u32, host: &str) { - let prefix = build.config.prefix.as_ref().clone().map(|x| Path::new(x)) - .unwrap_or(Path::new("/usr/local")); - let docdir = build.config.docdir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x))) - .unwrap_or(Cow::Owned(prefix.join("share/doc/rust"))); - let libdir = build.config.libdir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x))) - .unwrap_or(Cow::Owned(prefix.join("lib"))); - let mandir = build.config.mandir.as_ref().clone().map(|x| Cow::Borrowed(Path::new(x))) - .unwrap_or(Cow::Owned(prefix.join("share/man"))); + let prefix_default = PathBuf::from("/usr/local"); + let docdir_default = PathBuf::from("share/doc/rust"); + let mandir_default = PathBuf::from("share/man"); + let libdir_default = PathBuf::from("lib"); + let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default); + let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default); + let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default); + let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default); + + let docdir = prefix.join(docdir); + let libdir = prefix.join(libdir); + let mandir = prefix.join(mandir); + + let destdir = env::var_os("DESTDIR").map(PathBuf::from); + + let prefix = add_destdir(&prefix, &destdir); + let docdir = add_destdir(&docdir, &destdir); + let libdir = add_destdir(&libdir, &destdir); + let mandir = add_destdir(&mandir, &destdir); + let empty_dir = build.out.join("tmp/empty_dir"); t!(fs::create_dir_all(&empty_dir)); if build.config.docs { - install_sh(&build, "docs", "rust-docs", stage, host, prefix, + install_sh(&build, "docs", "rust-docs", stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); } - install_sh(&build, "std", "rust-std", stage, host, prefix, + install_sh(&build, "std", "rust-std", stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); - install_sh(&build, "rustc", "rustc", stage, host, prefix, + install_sh(&build, "rustc", "rustc", stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); t!(fs::remove_dir_all(&empty_dir)); } @@ -59,3 +71,17 @@ fn install_sh(build: &Build, package: &str, name: &str, stage: u32, host: &str, .arg("--disable-ldconfig"); build.run(&mut cmd); } + +fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { + let mut ret = match *destdir { + Some(ref dest) => dest.clone(), + None => return path.to_path_buf(), + }; + for part in path.components() { + match part { + Component::Normal(s) => ret.push(s), + _ => {} + } + } + return ret +} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 71cb289573..c98dd4751f 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -64,6 +64,8 @@ //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. +#![deny(warnings)] + extern crate build_helper; extern crate cmake; extern crate filetime; @@ -74,6 +76,7 @@ extern crate rustc_serialize; extern crate toml; use std::collections::HashMap; +use std::cmp; use std::env; use std::ffi::OsString; use std::fs::{self, File}; @@ -167,6 +170,8 @@ pub struct Build { version: String, package_vers: String, local_rebuild: bool, + release_num: String, + prerelease_version: String, // Probed tools at runtime lldb_version: Option, @@ -268,6 +273,8 @@ impl Build { lldb_version: None, lldb_python_dir: None, is_sudo: is_sudo, + release_num: String::new(), + prerelease_version: String::new(), } } @@ -497,6 +504,17 @@ impl Build { cargo.env("RUSTC_BOOTSTRAP", "1"); self.add_rust_test_threads(&mut cargo); + // Ignore incremental modes except for stage0, since we're + // not guaranteeing correctness acros builds if the compiler + // is changing under your feet.` + if self.flags.incremental && compiler.stage == 0 { + let incr_dir = self.incremental_dir(compiler); + cargo.env("RUSTC_INCREMENTAL", incr_dir); + } + + let verbose = cmp::max(self.config.verbose, self.flags.verbose); + cargo.env("RUSTC_VERBOSE", format!("{}", verbose)); + // Specify some various options for build scripts used throughout // the build. // @@ -507,7 +525,7 @@ impl Build { .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); } - if self.config.channel == "nightly" && compiler.stage == 2 { + if self.config.channel == "nightly" && compiler.is_final_stage(self) { cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); } @@ -516,7 +534,7 @@ impl Build { // FIXME: should update code to not require this env var cargo.env("CFG_COMPILER_HOST_TRIPLE", target); - if self.config.verbose || self.flags.verbose { + if self.config.verbose() || self.flags.verbose() { cargo.arg("-v"); } // FIXME: cargo bench does not accept `--release` @@ -556,11 +574,18 @@ impl Build { /// `host`. fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command { let mut cmd = Command::new(self.tool(&compiler, tool)); + self.prepare_tool_cmd(compiler, &mut cmd); + return cmd + } + + /// Prepares the `cmd` provided to be able to run the `compiler` provided. + /// + /// Notably this munges the dynamic library lookup path to point to the + /// right location to run `compiler`. + fn prepare_tool_cmd(&self, compiler: &Compiler, cmd: &mut Command) { let host = compiler.host; let mut paths = vec![ - self.cargo_out(compiler, Mode::Libstd, host).join("deps"), - self.cargo_out(compiler, Mode::Libtest, host).join("deps"), - self.cargo_out(compiler, Mode::Librustc, host).join("deps"), + self.sysroot_libdir(compiler, compiler.host), self.cargo_out(compiler, Mode::Tool, host).join("deps"), ]; @@ -581,8 +606,7 @@ impl Build { } } } - add_lib_path(paths, &mut cmd); - return cmd + add_lib_path(paths, cmd); } /// Get the space-separated set of activated features for the standard @@ -630,6 +654,12 @@ impl Build { } } + /// Get the directory for incremental by-products when using the + /// given compiler. + fn incremental_dir(&self, compiler: &Compiler) -> PathBuf { + self.out.join(compiler.host).join(format!("stage{}-incremental", compiler.stage)) + } + /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. fn sysroot_libdir(&self, compiler: &Compiler, target: &str) -> PathBuf { @@ -703,7 +733,8 @@ impl Build { fn llvm_filecheck(&self, target: &str) -> PathBuf { let target_config = self.config.target_config.get(target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - s.parent().unwrap().join(exe("FileCheck", target)) + let llvm_bindir = output(Command::new(s).arg("--bindir")); + Path::new(llvm_bindir.trim()).join(exe("FileCheck", target)) } else { let base = self.llvm_out(&self.config.build).join("build"); let exe = exe("FileCheck", target); @@ -768,7 +799,7 @@ impl Build { /// Prints a message if this build is configured in verbose mode. fn verbose(&self, msg: &str) { - if self.flags.verbose || self.config.verbose { + if self.flags.verbose() || self.config.verbose() { println!("{}", msg); } } @@ -864,6 +895,30 @@ impl Build { fn python(&self) -> &Path { self.config.python.as_ref().unwrap() } + + /// Tests whether the `compiler` compiling for `target` should be forced to + /// use a stage1 compiler instead. + /// + /// Currently, by default, the build system does not perform a "full + /// bootstrap" by default where we compile the compiler three times. + /// Instead, we compile the compiler two times. The final stage (stage2) + /// just copies the libraries from the previous stage, which is what this + /// method detects. + /// + /// Here we return `true` if: + /// + /// * The build isn't performing a full bootstrap + /// * The `compiler` is in the final stage, 2 + /// * We're not cross-compiling, so the artifacts are already available in + /// stage1 + /// + /// When all of these conditions are met the build will lift artifacts from + /// the previous stage forward. + fn force_use_stage1(&self, compiler: &Compiler, target: &str) -> bool { + !self.config.full_bootstrap && + compiler.stage >= 2 && + self.config.host.iter().any(|h| h == target) + } } impl<'a> Compiler<'a> { @@ -876,4 +931,13 @@ impl<'a> Compiler<'a> { fn is_snapshot(&self, build: &Build) -> bool { self.stage == 0 && self.host == build.config.build } + + /// Returns if this compiler should be treated as a final stage one in the + /// current build session. + /// This takes into account whether we're performing a full bootstrap or + /// not; don't directly compare the stage with `2`! + fn is_final_stage(&self, build: &Build) -> bool { + let final_stage = if build.config.full_bootstrap { 2 } else { 1 }; + self.stage >= final_stage + } } diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index cbcd85fb6b..d6f6a7772c 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -51,8 +51,16 @@ standalone-docs: $(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS) check: $(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS) -check-cargotest: - $(Q)$(BOOTSTRAP) test src/tools/cargotest $(BOOTSTRAP_ARGS) +check-aux: + $(Q)$(BOOTSTRAP) test \ + src/tools/cargotest \ + src/test/pretty \ + src/test/run-pass/pretty \ + src/test/run-fail/pretty \ + src/test/run-pass-valgrind/pretty \ + src/test/run-pass-fulldeps/pretty \ + src/test/run-fail-fulldeps/pretty \ + $(BOOTSTRAP_ARGS) dist: $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS) distcheck: @@ -61,12 +69,12 @@ distcheck: install: $(Q)$(BOOTSTRAP) dist --install $(BOOTSTRAP_ARGS) tidy: - $(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS) --stage 0 + $(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS) check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu: $(Q)$(BOOTSTRAP) test --target arm-linux-androideabi check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu: - $(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-gnu + $(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-musl .PHONY: dist diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 6ba6b8e6c8..4b6fef8edc 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -75,13 +75,18 @@ pub fn llvm(build: &Build, target: &str) { (true, true) => "RelWithDebInfo", }; + // NOTE: remember to also update `config.toml.example` when changing the defaults! + let llvm_targets = match build.config.llvm_targets { + Some(ref s) => s, + None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX", + }; + cfg.target(target) .host(&build.config.build) .out_dir(&dst) .profile(profile) .define("LLVM_ENABLE_ASSERTIONS", assertions) - .define("LLVM_TARGETS_TO_BUILD", - "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430") + .define("LLVM_TARGETS_TO_BUILD", llvm_targets) .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 2992099687..bc439d6f78 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -45,7 +45,7 @@ pub fn check(build: &mut Build) { let target = path.join(cmd); let mut cmd_alt = cmd.to_os_string(); cmd_alt.push(".exe"); - if target.exists() || + if target.is_file() || target.with_extension("exe").exists() || target.join(cmd_alt).exists() { return Some(target); @@ -78,7 +78,11 @@ pub fn check(build: &mut Build) { } need_cmd("cmake".as_ref()); if build.config.ninja { - need_cmd("ninja".as_ref()) + // Some Linux distros rename `ninja` to `ninja-build`. + // CMake can work with either binary name. + if have_cmd("ninja-build".as_ref()).is_none() { + need_cmd("ninja".as_ref()); + } } break } @@ -143,7 +147,7 @@ pub fn check(build: &mut Build) { // Externally configured LLVM requires FileCheck to exist let filecheck = build.llvm_filecheck(&build.config.build); if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { - panic!("filecheck executable {:?} does not exist", filecheck); + panic!("FileCheck executable {:?} does not exist", filecheck); } for target in build.config.target.iter() { @@ -194,10 +198,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake "); } } - - if target.contains("arm-linux-android") { - need_cmd("adb".as_ref()); - } } for host in build.flags.host.iter() { diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 66220f9dde..3932a7cf8c 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -44,7 +44,7 @@ pub fn run(build: &Build) { rules.run(&steps); } -pub fn build_rules(build: &Build) -> Rules { +pub fn build_rules<'a>(build: &'a Build) -> Rules { let mut rules = Rules::new(build); // This is the first rule that we're going to define for rustbuild, which is @@ -86,7 +86,7 @@ pub fn build_rules(build: &Build) -> Rules { // // To handle this we do a bit of dynamic dispatch to see what the dependency // is. If we're building a LLVM for the build triple, then we don't actually - // have any dependencies! To do that we return a dependency on the "dummy" + // have any dependencies! To do that we return a dependency on the `Step::noop()` // target which does nothing. // // If we're build a cross-compiled LLVM, however, we need to assemble the @@ -104,7 +104,7 @@ pub fn build_rules(build: &Build) -> Rules { .host(true) .dep(move |s| { if s.target == build.config.build { - dummy(s, build) + Step::noop() } else { s.target(&build.config.build) } @@ -115,14 +115,12 @@ pub fn build_rules(build: &Build) -> Rules { // going on here. You can check out the API docs below and also see a bunch // more examples of rules directly below as well. - // dummy rule to do nothing, useful when a dep maps to no deps - rules.build("dummy", "path/to/nowhere"); - // the compiler with no target libraries ready to go rules.build("rustc", "src/rustc") + .dep(|s| s.name("create-sysroot").target(s.host)) .dep(move |s| { if s.stage == 0 { - dummy(s, build) + Step::noop() } else { s.name("librustc") .host(&build.config.build) @@ -154,91 +152,153 @@ pub fn build_rules(build: &Build) -> Rules { // Crate compilations // // Tools used during the build system but not shipped + rules.build("create-sysroot", "path/to/nowhere") + .run(move |s| compile::create_sysroot(build, &s.compiler())); + + // These rules are "pseudo rules" that don't actually do any work + // themselves, but represent a complete sysroot with the relevant compiler + // linked into place. + // + // That is, depending on "libstd" means that when the rule is completed then + // the `stage` sysroot for the compiler `host` will be available with a + // standard library built for `target` linked in place. Not all rules need + // the compiler itself to be available, just the standard library, so + // there's a distinction between the two. rules.build("libstd", "src/libstd") - .dep(|s| s.name("build-crate-std_shim")); + .dep(|s| s.name("rustc").target(s.host)) + .dep(|s| s.name("libstd-link")); rules.build("libtest", "src/libtest") - .dep(|s| s.name("build-crate-test_shim")); + .dep(|s| s.name("libstd")) + .dep(|s| s.name("libtest-link")) + .default(true); rules.build("librustc", "src/librustc") - .dep(|s| s.name("build-crate-rustc-main")); + .dep(|s| s.name("libtest")) + .dep(|s| s.name("librustc-link")) + .host(true) + .default(true); + + // Helper method to define the rules to link a crate into its place in the + // sysroot. + // + // The logic here is a little subtle as there's a few cases to consider. + // Not all combinations of (stage, host, target) actually require something + // to be compiled, but rather libraries could get propagated from a + // different location. For example: + // + // * Any crate with a `host` that's not the build triple will not actually + // compile something. A different `host` means that the build triple will + // actually compile the libraries, and then we'll copy them over from the + // build triple to the `host` directory. + // + // * Some crates aren't even compiled by the build triple, but may be copied + // from previous stages. For example if we're not doing a full bootstrap + // then we may just depend on the stage1 versions of libraries to be + // available to get linked forward. + // + // * Finally, there are some cases, however, which do indeed comiple crates + // and link them into place afterwards. + // + // The rule definition below mirrors these three cases. The `dep` method + // calculates the correct dependency which either comes from stage1, a + // different compiler, or from actually building the crate itself (the `dep` + // rule). The `run` rule then mirrors these three cases and links the cases + // forward into the compiler sysroot specified from the correct location. + fn crate_rule<'a, 'b>(build: &'a Build, + rules: &'b mut Rules<'a>, + krate: &'a str, + dep: &'a str, + link: fn(&Build, &Compiler, &Compiler, &str)) + -> RuleBuilder<'a, 'b> { + let mut rule = rules.build(&krate, "path/to/nowhere"); + rule.dep(move |s| { + if build.force_use_stage1(&s.compiler(), s.target) { + s.host(&build.config.build).stage(1) + } else if s.host == build.config.build { + s.name(dep) + } else { + s.host(&build.config.build) + } + }) + .run(move |s| { + if build.force_use_stage1(&s.compiler(), s.target) { + link(build, + &s.stage(1).host(&build.config.build).compiler(), + &s.compiler(), + s.target) + } else if s.host == build.config.build { + link(build, &s.compiler(), &s.compiler(), s.target) + } else { + link(build, + &s.host(&build.config.build).compiler(), + &s.compiler(), + s.target) + } + }); + return rule + } + + // Similar to the `libstd`, `libtest`, and `librustc` rules above, except + // these rules only represent the libraries being available in the sysroot, + // not the compiler itself. This is done as not all rules need a compiler in + // the sysroot, but may just need the libraries. + // + // All of these rules use the helper definition above. + crate_rule(build, + &mut rules, + "libstd-link", + "build-crate-std_shim", + compile::std_link) + .dep(|s| s.name("startup-objects")) + .dep(|s| s.name("create-sysroot").target(s.host)); + crate_rule(build, + &mut rules, + "libtest-link", + "build-crate-test_shim", + compile::test_link) + .dep(|s| s.name("libstd-link")); + crate_rule(build, + &mut rules, + "librustc-link", + "build-crate-rustc-main", + compile::rustc_link) + .dep(|s| s.name("libtest-link")); + for (krate, path, _default) in krates("std_shim") { rules.build(&krate.build_step, path) + .dep(|s| s.name("startup-objects")) .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host)) - .dep(move |s| { - if s.host == build.config.build { - dummy(s, build) - } else { - s.host(&build.config.build) - } - }) - .run(move |s| { - if s.host == build.config.build { - compile::std(build, s.target, &s.compiler()) - } else { - compile::std_link(build, s.target, s.stage, s.host) - } - }); + .run(move |s| compile::std(build, s.target, &s.compiler())); } - for (krate, path, default) in krates("test_shim") { + for (krate, path, _default) in krates("test_shim") { rules.build(&krate.build_step, path) - .dep(|s| s.name("libstd")) - .dep(move |s| { - if s.host == build.config.build { - dummy(s, build) - } else { - s.host(&build.config.build) - } - }) - .default(default) - .run(move |s| { - if s.host == build.config.build { - compile::test(build, s.target, &s.compiler()) - } else { - compile::test_link(build, s.target, s.stage, s.host) - } - }); + .dep(|s| s.name("libstd-link")) + .run(move |s| compile::test(build, s.target, &s.compiler())); } - for (krate, path, default) in krates("rustc-main") { + for (krate, path, _default) in krates("rustc-main") { rules.build(&krate.build_step, path) - .dep(|s| s.name("libtest")) + .dep(|s| s.name("libtest-link")) .dep(move |s| s.name("llvm").host(&build.config.build).stage(0)) - .dep(move |s| { - if s.host == build.config.build { - dummy(s, build) - } else { - s.host(&build.config.build) - } - }) - .host(true) - .default(default) - .run(move |s| { - if s.host == build.config.build { - compile::rustc(build, s.target, &s.compiler()) - } else { - compile::rustc_link(build, s.target, s.stage, s.host) - } - }); + .run(move |s| compile::rustc(build, s.target, &s.compiler())); } + rules.build("startup-objects", "src/rtstartup") + .dep(|s| s.name("create-sysroot").target(s.host)) + .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target)); + // ======================================================================== // Test targets // // Various unit tests and tests suites we can run { - let mut suite = |name, path, dir, mode| { + let mut suite = |name, path, mode, dir| { rules.test(name, path) .dep(|s| s.name("libtest")) - .dep(|s| s.name("tool-compiletest").target(s.host)) + .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) .dep(|s| s.name("test-helpers")) - .dep(move |s| { - if s.target.contains("android") { - s.name("android-copy-libs") - } else { - dummy(s, build) - } - }) - .default(true) + .dep(|s| s.name("android-copy-libs")) + .default(mode != "pretty") // pretty tests don't run everywhere .run(move |s| { - check::compiletest(build, &s.compiler(), s.target, dir, mode) + check::compiletest(build, &s.compiler(), s.target, mode, dir) }); }; @@ -256,34 +316,33 @@ pub fn build_rules(build: &Build) -> Rules { "codegen-units"); suite("check-incremental", "src/test/incremental", "incremental", "incremental"); - suite("check-ui", "src/test/ui", "ui", "ui"); - suite("check-pretty", "src/test/pretty", "pretty", "pretty"); - suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", - "run-pass"); - suite("check-pretty-rfail", "src/test/run-pass/pretty", "pretty", - "run-fail"); - suite("check-pretty-valgrind", "src/test/run-pass-valgrind", "pretty", - "run-pass-valgrind"); } if build.config.build.contains("msvc") { // nothing to do for debuginfo tests - } else if build.config.build.contains("apple") { - rules.test("check-debuginfo", "src/test/debuginfo") + } else { + rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb") .dep(|s| s.name("libtest")) - .dep(|s| s.name("tool-compiletest").host(s.host)) + .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) .dep(|s| s.name("test-helpers")) .dep(|s| s.name("debugger-scripts")) .run(move |s| check::compiletest(build, &s.compiler(), s.target, "debuginfo-lldb", "debuginfo")); - } else { - rules.test("check-debuginfo", "src/test/debuginfo") + rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb") .dep(|s| s.name("libtest")) - .dep(|s| s.name("tool-compiletest").host(s.host)) + .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) .dep(|s| s.name("test-helpers")) .dep(|s| s.name("debugger-scripts")) + .dep(|s| s.name("android-copy-libs")) .run(move |s| check::compiletest(build, &s.compiler(), s.target, "debuginfo-gdb", "debuginfo")); + let mut rule = rules.test("check-debuginfo", "src/test/debuginfo"); + rule.default(true); + if build.config.build.contains("apple") { + rule.dep(|s| s.name("check-debuginfo-lldb")); + } else { + rule.dep(|s| s.name("check-debuginfo-gdb")); + } } rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") @@ -291,38 +350,51 @@ pub fn build_rules(build: &Build) -> Rules { s.target)); { - let mut suite = |name, path, dir, mode| { + let mut suite = |name, path, mode, dir| { rules.test(name, path) .dep(|s| s.name("librustc")) - .dep(|s| s.name("tool-compiletest").target(s.host)) - .default(true) + .dep(|s| s.name("test-helpers")) + .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) + .default(mode != "pretty") .host(true) .run(move |s| { - check::compiletest(build, &s.compiler(), s.target, dir, mode) + check::compiletest(build, &s.compiler(), s.target, mode, dir) }); }; + suite("check-ui", "src/test/ui", "ui", "ui"); suite("check-rpass-full", "src/test/run-pass-fulldeps", "run-pass", "run-pass-fulldeps"); + suite("check-rfail-full", "src/test/run-fail-fulldeps", + "run-fail", "run-fail-fulldeps"); suite("check-cfail-full", "src/test/compile-fail-fulldeps", "compile-fail", "compile-fail-fulldeps"); suite("check-rmake", "src/test/run-make", "run-make", "run-make"); suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc"); - suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps", + suite("check-pretty", "src/test/pretty", "pretty", "pretty"); + suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", + "run-pass"); + suite("check-pretty-rfail", "src/test/run-fail/pretty", "pretty", + "run-fail"); + suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty", + "run-pass-valgrind"); + suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty", "pretty", "run-pass-fulldeps"); - suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps", + suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty", "pretty", "run-fail-fulldeps"); } for (krate, path, _default) in krates("std_shim") { rules.test(&krate.test_step, path) .dep(|s| s.name("libtest")) + .dep(|s| s.name("android-copy-libs")) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libstd, TestKind::Test, Some(&krate.name))); } rules.test("check-std-all", "path/to/nowhere") .dep(|s| s.name("libtest")) + .dep(|s| s.name("android-copy-libs")) .default(true) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libstd, TestKind::Test, None)); @@ -331,12 +403,14 @@ pub fn build_rules(build: &Build) -> Rules { for (krate, path, _default) in krates("std_shim") { rules.bench(&krate.bench_step, path) .dep(|s| s.name("libtest")) + .dep(|s| s.name("android-copy-libs")) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libstd, TestKind::Bench, Some(&krate.name))); } rules.bench("bench-std-all", "path/to/nowhere") .dep(|s| s.name("libtest")) + .dep(|s| s.name("android-copy-libs")) .default(true) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libstd, TestKind::Bench, None)); @@ -344,18 +418,21 @@ pub fn build_rules(build: &Build) -> Rules { for (krate, path, _default) in krates("test_shim") { rules.test(&krate.test_step, path) .dep(|s| s.name("libtest")) + .dep(|s| s.name("android-copy-libs")) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libtest, TestKind::Test, Some(&krate.name))); } rules.test("check-test-all", "path/to/nowhere") .dep(|s| s.name("libtest")) + .dep(|s| s.name("android-copy-libs")) .default(true) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libtest, TestKind::Test, None)); for (krate, path, _default) in krates("rustc-main") { rules.test(&krate.test_step, path) .dep(|s| s.name("librustc")) + .dep(|s| s.name("android-copy-libs")) .host(true) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Librustc, TestKind::Test, @@ -363,19 +440,20 @@ pub fn build_rules(build: &Build) -> Rules { } rules.test("check-rustc-all", "path/to/nowhere") .dep(|s| s.name("librustc")) + .dep(|s| s.name("android-copy-libs")) .default(true) .host(true) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Librustc, TestKind::Test, None)); rules.test("check-linkchecker", "src/tools/linkchecker") - .dep(|s| s.name("tool-linkchecker")) + .dep(|s| s.name("tool-linkchecker").stage(0)) .dep(|s| s.name("default:doc")) .default(true) .host(true) - .run(move |s| check::linkcheck(build, s.stage, s.target)); + .run(move |s| check::linkcheck(build, s.target)); rules.test("check-cargotest", "src/tools/cargotest") - .dep(|s| s.name("tool-cargotest")) + .dep(|s| s.name("tool-cargotest").stage(0)) .dep(|s| s.name("librustc")) .host(true) .run(move |s| check::cargotest(build, s.stage, s.target)); @@ -383,10 +461,11 @@ pub fn build_rules(build: &Build) -> Rules { .dep(|s| s.name("tool-tidy").stage(0)) .default(true) .host(true) - .run(move |s| check::tidy(build, 0, s.target)); + .only_build(true) + .run(move |s| check::tidy(build, s.target)); rules.test("check-error-index", "src/tools/error_index_generator") .dep(|s| s.name("libstd")) - .dep(|s| s.name("tool-error-index").host(s.host)) + .dep(|s| s.name("tool-error-index").host(s.host).stage(0)) .default(true) .host(true) .run(move |s| check::error_index(build, &s.compiler())); @@ -406,6 +485,12 @@ pub fn build_rules(build: &Build) -> Rules { .dep(|s| s.name("libtest")) .run(move |s| check::android_copy_libs(build, &s.compiler(), s.target)); + rules.test("check-bootstrap", "src/bootstrap") + .default(true) + .host(true) + .only_build(true) + .run(move |_| check::bootstrap(build)); + // ======================================================================== // Build tools // @@ -428,42 +513,60 @@ pub fn build_rules(build: &Build) -> Rules { rules.build("tool-compiletest", "src/tools/compiletest") .dep(|s| s.name("libtest")) .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); + rules.build("tool-build-manifest", "src/tools/build-manifest") + .dep(|s| s.name("libstd")) + .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); // ======================================================================== // Documentation targets rules.doc("doc-book", "src/doc/book") - .dep(move |s| s.name("tool-rustbook").target(&build.config.build)) + .dep(move |s| { + s.name("tool-rustbook") + .host(&build.config.build) + .target(&build.config.build) + .stage(0) + }) .default(build.config.docs) - .run(move |s| doc::rustbook(build, s.stage, s.target, "book")); + .run(move |s| doc::rustbook(build, s.target, "book")); rules.doc("doc-nomicon", "src/doc/nomicon") - .dep(move |s| s.name("tool-rustbook").target(&build.config.build)) + .dep(move |s| { + s.name("tool-rustbook") + .host(&build.config.build) + .target(&build.config.build) + .stage(0) + }) .default(build.config.docs) - .run(move |s| doc::rustbook(build, s.stage, s.target, "nomicon")); + .run(move |s| doc::rustbook(build, s.target, "nomicon")); rules.doc("doc-standalone", "src/doc") - .dep(move |s| s.name("rustc").host(&build.config.build).target(&build.config.build)) + .dep(move |s| { + s.name("rustc") + .host(&build.config.build) + .target(&build.config.build) + .stage(0) + }) .default(build.config.docs) - .run(move |s| doc::standalone(build, s.stage, s.target)); + .run(move |s| doc::standalone(build, s.target)); rules.doc("doc-error-index", "src/tools/error_index_generator") - .dep(move |s| s.name("tool-error-index").target(&build.config.build)) - .dep(move |s| s.name("librustc")) + .dep(move |s| s.name("tool-error-index").target(&build.config.build).stage(0)) + .dep(move |s| s.name("librustc-link")) .default(build.config.docs) .host(true) - .run(move |s| doc::error_index(build, s.stage, s.target)); + .run(move |s| doc::error_index(build, s.target)); for (krate, path, default) in krates("std_shim") { rules.doc(&krate.doc_step, path) - .dep(|s| s.name("libstd")) + .dep(|s| s.name("libstd-link")) .default(default && build.config.docs) .run(move |s| doc::std(build, s.stage, s.target)); } for (krate, path, default) in krates("test_shim") { rules.doc(&krate.doc_step, path) - .dep(|s| s.name("libtest")) + .dep(|s| s.name("libtest-link")) .default(default && build.config.compiler_docs) .run(move |s| doc::test(build, s.stage, s.target)); } for (krate, path, default) in krates("rustc-main") { rules.doc(&krate.doc_step, path) - .dep(|s| s.name("librustc")) + .dep(|s| s.name("librustc-link")) .host(true) .default(default && build.config.compiler_docs) .run(move |s| doc::rustc(build, s.stage, s.target)); @@ -474,6 +577,7 @@ pub fn build_rules(build: &Build) -> Rules { rules.dist("dist-rustc", "src/librustc") .dep(move |s| s.name("rustc").host(&build.config.build)) .host(true) + .only_host_build(true) .default(true) .run(move |s| dist::rustc(build, s.stage, s.target)); rules.dist("dist-std", "src/libstd") @@ -482,15 +586,17 @@ pub fn build_rules(build: &Build) -> Rules { // for the `rust-std` package, so if this is a host target we // depend on librustc and otherwise we just depend on libtest. if build.config.host.iter().any(|t| t == s.target) { - s.name("librustc") + s.name("librustc-link") } else { - s.name("libtest") + s.name("libtest-link") } }) .default(true) + .only_host_build(true) .run(move |s| dist::std(build, &s.compiler(), s.target)); rules.dist("dist-mingw", "path/to/nowhere") .default(true) + .only_host_build(true) .run(move |s| { if s.target.contains("pc-windows-gnu") { dist::mingw(build, s.target) @@ -499,27 +605,46 @@ pub fn build_rules(build: &Build) -> Rules { rules.dist("dist-src", "src") .default(true) .host(true) + .only_build(true) + .only_host_build(true) .run(move |_| dist::rust_src(build)); rules.dist("dist-docs", "src/doc") .default(true) + .only_host_build(true) .dep(|s| s.name("default:doc")) .run(move |s| dist::docs(build, s.stage, s.target)); rules.dist("dist-analysis", "analysis") .dep(|s| s.name("dist-std")) .default(true) + .only_host_build(true) .run(move |s| dist::analysis(build, &s.compiler(), s.target)); - rules.dist("install", "src") + rules.dist("install", "path/to/nowhere") .dep(|s| s.name("default:dist")) .run(move |s| install::install(build, s.stage, s.target)); + rules.dist("dist-cargo", "cargo") + .host(true) + .only_host_build(true) + .run(move |s| dist::cargo(build, s.stage, s.target)); + rules.dist("dist-extended", "extended") + .default(build.config.extended) + .host(true) + .only_host_build(true) + .dep(|d| d.name("dist-std")) + .dep(|d| d.name("dist-rustc")) + .dep(|d| d.name("dist-mingw")) + .dep(|d| d.name("dist-docs")) + .dep(|d| d.name("dist-cargo")) + .run(move |s| dist::extended(build, s.stage, s.target)); + + rules.dist("dist-sign", "hash-and-sign") + .host(true) + .only_build(true) + .only_host_build(true) + .dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0)) + .run(move |_| dist::hash_and_sign(build)); rules.verify(); return rules; - - fn dummy<'a>(s: &Step<'a>, build: &'a Build) -> Step<'a> { - s.name("dummy").stage(0) - .target(&build.config.build) - .host(&build.config.build) - } } #[derive(PartialEq, Eq, Hash, Clone, Debug)] @@ -543,6 +668,10 @@ struct Step<'a> { } impl<'a> Step<'a> { + fn noop() -> Step<'a> { + Step { name: "", stage: 0, host: "", target: "" } + } + /// Creates a new step which is the same as this, except has a new name. fn name(&self, name: &'a str) -> Step<'a> { Step { name: name, ..*self } @@ -597,6 +726,14 @@ struct Rule<'a> { /// only intended for compiler hosts and not for targets that are being /// generated. host: bool, + + /// Whether this rule is only for steps where the host is the build triple, + /// not anything in hosts or targets. + only_host_build: bool, + + /// Whether this rule is only for the build triple, not anything in hosts or + /// targets. + only_build: bool, } #[derive(PartialEq)] @@ -618,6 +755,8 @@ impl<'a> Rule<'a> { kind: kind, default: false, host: false, + only_host_build: false, + only_build: false, } } } @@ -653,6 +792,16 @@ impl<'a, 'b> RuleBuilder<'a, 'b> { self.rule.host = host; self } + + fn only_build(&mut self, only_build: bool) -> &mut Self { + self.rule.only_build = only_build; + self + } + + fn only_host_build(&mut self, only_host_build: bool) -> &mut Self { + self.rule.only_host_build = only_host_build; + self + } } impl<'a, 'b> Drop for RuleBuilder<'a, 'b> { @@ -738,6 +887,9 @@ impl<'a> Rules<'a> { if self.rules.contains_key(&dep.name) || dep.name.starts_with("default:") { continue } + if dep == Step::noop() { + continue + } panic!("\ invalid rule dependency graph detected, was a rule added and maybe typo'd? @@ -804,11 +956,11 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), Subcommand::Test { ref paths, test_args: _ } => (Kind::Test, &paths[..]), Subcommand::Bench { ref paths, test_args: _ } => (Kind::Bench, &paths[..]), - Subcommand::Dist { install } => { + Subcommand::Dist { ref paths, install } => { if install { return vec![self.sbuild.name("install")] } else { - (Kind::Dist, &[][..]) + (Kind::Dist, &paths[..]) } } Subcommand::Clean => panic!(), @@ -819,7 +971,9 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? path.ends_with(rule.path) }) }).flat_map(|rule| { - let hosts = if self.build.flags.host.len() > 0 { + let hosts = if rule.only_host_build || rule.only_build { + &self.build.config.host[..1] + } else if self.build.flags.host.len() > 0 { &self.build.flags.host } else { &self.build.config.host @@ -829,14 +983,23 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? } else { &self.build.config.target }; - // If --target was specified but --host wasn't specified, don't run - // any host-only tests + // Determine the actual targets participating in this rule. + // NOTE: We should keep the full projection from build triple to + // the hosts for the dist steps, now that the hosts array above is + // truncated to avoid duplication of work in that case. Therefore + // the original non-shadowed hosts array is used below. let arr = if rule.host { - if self.build.flags.target.len() > 0 && - self.build.flags.host.len() == 0 { - &hosts[..0] + // If --target was specified but --host wasn't specified, + // don't run any host-only tests. Also, respect any `--host` + // overrides as done for `hosts`. + if self.build.flags.host.len() > 0 { + &self.build.flags.host[..] + } else if self.build.flags.target.len() > 0 { + &[] + } else if rule.only_build { + &self.build.config.host[..1] } else { - hosts + &self.build.config.host[..] } } else { targets @@ -862,11 +1025,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? // Using `steps` as the top-level targets, make a topological ordering // of what we need to do. - let mut order = Vec::new(); - let mut added = HashSet::new(); - for step in steps.iter().cloned() { - self.fill(step, &mut order, &mut added); - } + let order = self.expand(steps); // Print out what we're doing for debugging self.build.verbose("bootstrap build plan:"); @@ -885,6 +1044,18 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? } } + /// From the top level targets `steps` generate a topological ordering of + /// all steps needed to run those steps. + fn expand(&self, steps: &[Step<'a>]) -> Vec> { + let mut order = Vec::new(); + let mut added = HashSet::new(); + added.insert(Step::noop()); + for step in steps.iter().cloned() { + self.fill(step, &mut order, &mut added); + } + return order + } + /// Performs topological sort of dependencies rooted at the `step` /// specified, pushing all results onto the `order` vector provided. /// @@ -921,3 +1092,377 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? order.push(step); } } + +#[cfg(test)] +mod tests { + use std::env; + + use Build; + use config::Config; + use flags::Flags; + + macro_rules! a { + ($($a:expr),*) => (vec![$($a.to_string()),*]) + } + + fn build(args: &[&str], + extra_host: &[&str], + extra_target: &[&str]) -> Build { + let mut args = args.iter().map(|s| s.to_string()).collect::>(); + args.push("--build".to_string()); + args.push("A".to_string()); + let flags = Flags::parse(&args); + + let mut config = Config::default(); + config.docs = true; + config.build = "A".to_string(); + config.host = vec![config.build.clone()]; + config.host.extend(extra_host.iter().map(|s| s.to_string())); + config.target = config.host.clone(); + config.target.extend(extra_target.iter().map(|s| s.to_string())); + + let mut build = Build::new(flags, config); + let cwd = env::current_dir().unwrap(); + build.crates.insert("std_shim".to_string(), ::Crate { + name: "std_shim".to_string(), + deps: Vec::new(), + path: cwd.join("src/std_shim"), + doc_step: "doc-std_shim".to_string(), + build_step: "build-crate-std_shim".to_string(), + test_step: "test-std_shim".to_string(), + bench_step: "bench-std_shim".to_string(), + }); + build.crates.insert("test_shim".to_string(), ::Crate { + name: "test_shim".to_string(), + deps: Vec::new(), + path: cwd.join("src/test_shim"), + doc_step: "doc-test_shim".to_string(), + build_step: "build-crate-test_shim".to_string(), + test_step: "test-test_shim".to_string(), + bench_step: "bench-test_shim".to_string(), + }); + build.crates.insert("rustc-main".to_string(), ::Crate { + name: "rustc-main".to_string(), + deps: Vec::new(), + path: cwd.join("src/rustc-main"), + doc_step: "doc-rustc-main".to_string(), + build_step: "build-crate-rustc-main".to_string(), + test_step: "test-rustc-main".to_string(), + bench_step: "bench-rustc-main".to_string(), + }); + return build + } + + #[test] + fn dist_baseline() { + let build = build(&["dist"], &[], &[]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + assert!(plan.iter().all(|s| s.host == "A" )); + assert!(plan.iter().all(|s| s.target == "A" )); + + let step = super::Step { + name: "", + stage: 2, + host: &build.config.build, + target: &build.config.build, + }; + + assert!(plan.contains(&step.name("dist-docs"))); + assert!(plan.contains(&step.name("dist-mingw"))); + assert!(plan.contains(&step.name("dist-rustc"))); + assert!(plan.contains(&step.name("dist-std"))); + assert!(plan.contains(&step.name("dist-src"))); + } + + #[test] + fn dist_with_targets() { + let build = build(&["dist"], &[], &["B"]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + assert!(plan.iter().all(|s| s.host == "A" )); + + let step = super::Step { + name: "", + stage: 2, + host: &build.config.build, + target: &build.config.build, + }; + + assert!(plan.contains(&step.name("dist-docs"))); + assert!(plan.contains(&step.name("dist-mingw"))); + assert!(plan.contains(&step.name("dist-rustc"))); + assert!(plan.contains(&step.name("dist-std"))); + assert!(plan.contains(&step.name("dist-src"))); + + assert!(plan.contains(&step.target("B").name("dist-docs"))); + assert!(plan.contains(&step.target("B").name("dist-mingw"))); + assert!(!plan.contains(&step.target("B").name("dist-rustc"))); + assert!(plan.contains(&step.target("B").name("dist-std"))); + assert!(!plan.contains(&step.target("B").name("dist-src"))); + } + + #[test] + fn dist_with_hosts() { + let build = build(&["dist"], &["B"], &[]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + + let step = super::Step { + name: "", + stage: 2, + host: &build.config.build, + target: &build.config.build, + }; + + assert!(!plan.iter().any(|s| s.host == "B")); + + assert!(plan.contains(&step.name("dist-docs"))); + assert!(plan.contains(&step.name("dist-mingw"))); + assert!(plan.contains(&step.name("dist-rustc"))); + assert!(plan.contains(&step.name("dist-std"))); + assert!(plan.contains(&step.name("dist-src"))); + + assert!(plan.contains(&step.target("B").name("dist-docs"))); + assert!(plan.contains(&step.target("B").name("dist-mingw"))); + assert!(plan.contains(&step.target("B").name("dist-rustc"))); + assert!(plan.contains(&step.target("B").name("dist-std"))); + assert!(!plan.contains(&step.target("B").name("dist-src"))); + } + + #[test] + fn dist_with_targets_and_hosts() { + let build = build(&["dist"], &["B"], &["C"]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + + let step = super::Step { + name: "", + stage: 2, + host: &build.config.build, + target: &build.config.build, + }; + + assert!(!plan.iter().any(|s| s.host == "B")); + assert!(!plan.iter().any(|s| s.host == "C")); + + assert!(plan.contains(&step.name("dist-docs"))); + assert!(plan.contains(&step.name("dist-mingw"))); + assert!(plan.contains(&step.name("dist-rustc"))); + assert!(plan.contains(&step.name("dist-std"))); + assert!(plan.contains(&step.name("dist-src"))); + + assert!(plan.contains(&step.target("B").name("dist-docs"))); + assert!(plan.contains(&step.target("B").name("dist-mingw"))); + assert!(plan.contains(&step.target("B").name("dist-rustc"))); + assert!(plan.contains(&step.target("B").name("dist-std"))); + assert!(!plan.contains(&step.target("B").name("dist-src"))); + + assert!(plan.contains(&step.target("C").name("dist-docs"))); + assert!(plan.contains(&step.target("C").name("dist-mingw"))); + assert!(!plan.contains(&step.target("C").name("dist-rustc"))); + assert!(plan.contains(&step.target("C").name("dist-std"))); + assert!(!plan.contains(&step.target("C").name("dist-src"))); + } + + #[test] + fn dist_target_with_target_flag() { + let build = build(&["dist", "--target=C"], &["B"], &["C"]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + + let step = super::Step { + name: "", + stage: 2, + host: &build.config.build, + target: &build.config.build, + }; + + assert!(!plan.iter().any(|s| s.target == "A")); + assert!(!plan.iter().any(|s| s.target == "B")); + assert!(!plan.iter().any(|s| s.host == "B")); + assert!(!plan.iter().any(|s| s.host == "C")); + + assert!(plan.contains(&step.target("C").name("dist-docs"))); + assert!(plan.contains(&step.target("C").name("dist-mingw"))); + assert!(!plan.contains(&step.target("C").name("dist-rustc"))); + assert!(plan.contains(&step.target("C").name("dist-std"))); + assert!(!plan.contains(&step.target("C").name("dist-src"))); + } + + #[test] + fn dist_host_with_target_flag() { + let build = build(&["dist", "--host=B", "--target=B"], &["B"], &["C"]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + + let step = super::Step { + name: "", + stage: 2, + host: &build.config.build, + target: &build.config.build, + }; + + assert!(!plan.iter().any(|s| s.target == "A")); + assert!(!plan.iter().any(|s| s.target == "C")); + assert!(!plan.iter().any(|s| s.host == "B")); + assert!(!plan.iter().any(|s| s.host == "C")); + + assert!(plan.contains(&step.target("B").name("dist-docs"))); + assert!(plan.contains(&step.target("B").name("dist-mingw"))); + assert!(plan.contains(&step.target("B").name("dist-rustc"))); + assert!(plan.contains(&step.target("B").name("dist-std"))); + assert!(plan.contains(&step.target("B").name("dist-src"))); + + let all = rules.expand(&plan); + println!("all rules: {:#?}", all); + assert!(!all.contains(&step.name("rustc"))); + assert!(!all.contains(&step.name("build-crate-std_shim").stage(1))); + + // all stage0 compiles should be for the build target, A + for step in all.iter().filter(|s| s.stage == 0) { + if !step.name.contains("build-crate") { + continue + } + println!("step: {:?}", step); + assert!(step.host != "B"); + assert!(step.target != "B"); + assert!(step.host != "C"); + assert!(step.target != "C"); + } + } + + #[test] + fn build_default() { + let build = build(&["build"], &["B"], &["C"]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + + let step = super::Step { + name: "", + stage: 2, + host: &build.config.build, + target: &build.config.build, + }; + + // rustc built for all for of (A, B) x (A, B) + assert!(plan.contains(&step.name("librustc"))); + assert!(plan.contains(&step.target("B").name("librustc"))); + assert!(plan.contains(&step.host("B").target("A").name("librustc"))); + assert!(plan.contains(&step.host("B").target("B").name("librustc"))); + + // rustc never built for C + assert!(!plan.iter().any(|s| { + s.name.contains("rustc") && (s.host == "C" || s.target == "C") + })); + + // test built for everything + assert!(plan.contains(&step.name("libtest"))); + assert!(plan.contains(&step.target("B").name("libtest"))); + assert!(plan.contains(&step.host("B").target("A").name("libtest"))); + assert!(plan.contains(&step.host("B").target("B").name("libtest"))); + assert!(plan.contains(&step.host("A").target("C").name("libtest"))); + assert!(plan.contains(&step.host("B").target("C").name("libtest"))); + + let all = rules.expand(&plan); + println!("all rules: {:#?}", all); + assert!(all.contains(&step.name("rustc"))); + assert!(all.contains(&step.name("libstd"))); + } + + #[test] + fn build_filtered() { + let build = build(&["build", "--target=C"], &["B"], &["C"]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + + assert!(!plan.iter().any(|s| s.name.contains("rustc"))); + assert!(plan.iter().all(|s| { + !s.name.contains("test_shim") || s.target == "C" + })); + } + + #[test] + fn test_default() { + let build = build(&["test"], &[], &[]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + assert!(plan.iter().all(|s| s.host == "A")); + assert!(plan.iter().all(|s| s.target == "A")); + + assert!(plan.iter().any(|s| s.name.contains("-ui"))); + assert!(plan.iter().any(|s| s.name.contains("cfail"))); + assert!(plan.iter().any(|s| s.name.contains("cfail-full"))); + assert!(plan.iter().any(|s| s.name.contains("codegen-units"))); + assert!(plan.iter().any(|s| s.name.contains("debuginfo"))); + assert!(plan.iter().any(|s| s.name.contains("docs"))); + assert!(plan.iter().any(|s| s.name.contains("error-index"))); + assert!(plan.iter().any(|s| s.name.contains("incremental"))); + assert!(plan.iter().any(|s| s.name.contains("linkchecker"))); + assert!(plan.iter().any(|s| s.name.contains("mir-opt"))); + assert!(plan.iter().any(|s| s.name.contains("pfail"))); + assert!(plan.iter().any(|s| s.name.contains("rfail"))); + assert!(plan.iter().any(|s| s.name.contains("rfail-full"))); + assert!(plan.iter().any(|s| s.name.contains("rmake"))); + assert!(plan.iter().any(|s| s.name.contains("rpass"))); + assert!(plan.iter().any(|s| s.name.contains("rpass-full"))); + assert!(plan.iter().any(|s| s.name.contains("rustc-all"))); + assert!(plan.iter().any(|s| s.name.contains("rustdoc"))); + assert!(plan.iter().any(|s| s.name.contains("std-all"))); + assert!(plan.iter().any(|s| s.name.contains("test-all"))); + assert!(plan.iter().any(|s| s.name.contains("tidy"))); + assert!(plan.iter().any(|s| s.name.contains("valgrind"))); + } + + #[test] + fn test_with_a_target() { + let build = build(&["test", "--target=C"], &[], &["C"]); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(plan.iter().all(|s| s.stage == 2)); + assert!(plan.iter().all(|s| s.host == "A")); + assert!(plan.iter().all(|s| s.target == "C")); + + assert!(!plan.iter().any(|s| s.name.contains("-ui"))); + assert!(plan.iter().any(|s| s.name.contains("cfail"))); + assert!(!plan.iter().any(|s| s.name.contains("cfail-full"))); + assert!(plan.iter().any(|s| s.name.contains("codegen-units"))); + assert!(plan.iter().any(|s| s.name.contains("debuginfo"))); + assert!(!plan.iter().any(|s| s.name.contains("docs"))); + assert!(!plan.iter().any(|s| s.name.contains("error-index"))); + assert!(plan.iter().any(|s| s.name.contains("incremental"))); + assert!(!plan.iter().any(|s| s.name.contains("linkchecker"))); + assert!(plan.iter().any(|s| s.name.contains("mir-opt"))); + assert!(plan.iter().any(|s| s.name.contains("pfail"))); + assert!(plan.iter().any(|s| s.name.contains("rfail"))); + assert!(!plan.iter().any(|s| s.name.contains("rfail-full"))); + assert!(!plan.iter().any(|s| s.name.contains("rmake"))); + assert!(plan.iter().any(|s| s.name.contains("rpass"))); + assert!(!plan.iter().any(|s| s.name.contains("rpass-full"))); + assert!(!plan.iter().any(|s| s.name.contains("rustc-all"))); + assert!(!plan.iter().any(|s| s.name.contains("rustdoc"))); + assert!(plan.iter().any(|s| s.name.contains("std-all"))); + assert!(plan.iter().any(|s| s.name.contains("test-all"))); + assert!(!plan.iter().any(|s| s.name.contains("tidy"))); + assert!(plan.iter().any(|s| s.name.contains("valgrind"))); + } +} diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index c9e756b6f9..2ab3776ada 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -76,9 +76,9 @@ pub fn cp_r(src: &Path, dst: &Path) { /// Copies the `src` directory recursively to `dst`. Both are assumed to exist /// when this function is called. Unwanted files or directories can be skipped /// by returning `false` from the filter function. -pub fn cp_filtered bool>(src: &Path, dst: &Path, filter: &F) { +pub fn cp_filtered(src: &Path, dst: &Path, filter: &Fn(&Path) -> bool) { // Inner function does the actual work - fn recurse bool>(src: &Path, dst: &Path, relative: &Path, filter: &F) { + fn recurse(src: &Path, dst: &Path, relative: &Path, filter: &Fn(&Path) -> bool) { for f in t!(fs::read_dir(src)) { let f = t!(f); let path = f.path(); diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md new file mode 100644 index 0000000000..52f74ba90d --- /dev/null +++ b/src/ci/docker/README.md @@ -0,0 +1,200 @@ +# Docker images for CI + +This folder contains a bunch of docker images used by the continuous integration +(CI) of Rust. An script is accompanied (`run.sh`) with these images to actually +execute them. To test out an image execute: + +``` +./src/ci/docker/run.sh $image_name +``` + +for example: + +``` +./src/ci/docker/run.sh x86_64-gnu +``` + +Images will output artifacts in an `obj` dir at the root of a repository. + +## Cross toolchains + +A number of these images take quite a long time to compile as they're building +whole gcc toolchains to do cross builds with. Much of this is relatively +self-explanatory but some images use [crosstool-ng] which isn't quite as self +explanatory. Below is a description of where these `*.config` files come form, +how to generate them, and how the existing ones were generated. + +[crosstool-ng]: https://github.com/crosstool-ng/crosstool-ng + +### Generating a `.config` file + +If you have a `linux-cross` image lying around you can use that and skip the +next two steps. + +- First we spin up a container and copy `build_toolchain_root.sh` into it. All + these steps are outside the container: + +``` +# Note: We use ubuntu:15.10 because that's the "base" of linux-cross Docker +# image +$ docker run -it ubuntu:15.10 bash +$ docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +cfbec05ed730 ubuntu:15.10 "bash" 16 seconds ago Up 15 seconds drunk_murdock +$ docker cp build_toolchain_root.sh drunk_murdock:/ +``` + +- Then inside the container we build crosstool-ng by simply calling the bash + script we copied in the previous step: + +``` +$ bash build_toolchain_root.sh +``` + +- Now, inside the container run the following command to configure the + toolchain. To get a clue of which options need to be changed check the next + section and come back. + +``` +$ ct-ng menuconfig +``` + +- Finally, we retrieve the `.config` file from the container and give it a + meaningful name. This is done outside the container. + +``` +$ docker drunk_murdock:/.config arm-linux-gnueabi.config +``` + +- Now you can shutdown the container or repeat the two last steps to generate a + new `.config` file. + +### Toolchain configuration + +Changes on top of the default toolchain configuration used to generate the +`.config` files in this directory. The changes are formatted as follows: + +``` +$category > $option = $value -- $comment +``` + +### `arm-linux-gnueabi.config` + +For targets: `arm-unknown-linux-gnueabi` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Target options > Target Architecture = arm +- Target options > Architecture level = armv6 -- (+) +- Target options > Floating point = software (no FPU) -- (\*) +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 3.2.72 -- Precise kernel +- C-library > glibc version = 2.14.1 +- C compiler > gcc version = 4.9.3 +- C compiler > C++ = ENABLE -- to cross compile LLVM + +### `arm-linux-gnueabihf.config` + +For targets: `arm-unknown-linux-gnueabihf` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Target options > Target Architecture = arm +- Target options > Architecture level = armv6 -- (+) +- Target options > Use specific FPU = vfp -- (+) +- Target options > Floating point = hardware (FPU) -- (\*) +- Target options > Default instruction set mode = arm -- (+) +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 3.2.72 -- Precise kernel +- C-library > glibc version = 2.14.1 +- C compiler > gcc version = 4.9.3 +- C compiler > C++ = ENABLE -- to cross compile LLVM + +### `armv7-linux-gnueabihf.config` + +For targets: `armv7-unknown-linux-gnueabihf` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Target options > Target Architecture = arm +- Target options > Suffix to the arch-part = v7 +- Target options > Architecture level = armv7-a -- (+) +- Target options > Use specific FPU = vfpv3-d16 -- (\*) +- Target options > Floating point = hardware (FPU) -- (\*) +- Target options > Default instruction set mode = thumb -- (\*) +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 3.2.72 -- Precise kernel +- C-library > glibc version = 2.14.1 +- C compiler > gcc version = 4.9.3 +- C compiler > C++ = ENABLE -- to cross compile LLVM + +(\*) These options have been selected to match the configuration of the arm + toolchains shipped with Ubuntu 15.10 +(+) These options have been selected to match the gcc flags we use to compile C + libraries like jemalloc. See the mk/cfg/arm(v7)-uknown-linux-gnueabi{,hf}.mk + file in Rust's source code. + +## `aarch64-linux-gnu.config` + +For targets: `aarch64-unknown-linux-gnu` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Target options > Target Architecture = arm +- Target options > Bitness = 64-bit +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 4.2.6 +- C-library > glibc version = 2.17 -- aarch64 support was introduced in this version +- C compiler > gcc version = 5.2.0 +- C compiler > C++ = ENABLE -- to cross compile LLVM + +## `powerpc-linux-gnu.config` + +For targets: `powerpc-unknown-linux-gnu` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Path and misc options > Patches origin = Bundled, then local +- Path and misc options > Local patch directory = /tmp/patches +- Target options > Target Architecture = powerpc +- Target options > Emit assembly for CPU = power4 -- (+) +- Target options > Tune for CPU = power6 -- (+) +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel +- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc +- C compiler > gcc version = 4.9.3 +- C compiler > Core gcc extra config = --with-cpu-32=power4 --with-cpu=default32 -- (+) +- C compiler > gcc extra config = --with-cpu-32=power4 --with-cpu=default32 -- (+) +- C compiler > C++ = ENABLE -- to cross compile LLVM + +(+) These CPU options match the configuration of the toolchains in RHEL6. + +## `powerpc64-linux-gnu.config` + +For targets: `powerpc64-unknown-linux-gnu` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Path and misc options > Patches origin = Bundled, then local +- Path and misc options > Local patch directory = /tmp/patches +- Target options > Target Architecture = powerpc +- Target options > Bitness = 64-bit +- Target options > Emit assembly for CPU = power4 -- (+) +- Target options > Tune for CPU = power6 -- (+) +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel +- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc +- C compiler > gcc version = 4.9.3 +- C compiler > C++ = ENABLE -- to cross compile LLVM + +(+) These CPU options match the configuration of the toolchains in RHEL6. + +## `s390x-linux-gnu.config` + +For targets: `s390x-unknown-linux-gnu` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Path and misc options > Patches origin = Bundled, then local +- Path and misc options > Local patch directory = /build/patches +- Target options > Target Architecture = s390 +- Target options > Bitness = 64-bit +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel +- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc +- C compiler > gcc version = 4.9.3 +- C compiler > gcc extra config = --with-arch=z10 -- LLVM's minimum support +- C compiler > C++ = ENABLE -- to cross compile LLVM diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile index 8911b4ff0c..4c89ce1253 100644 --- a/src/ci/docker/arm-android/Dockerfile +++ b/src/ci/docker/arm-android/Dockerfile @@ -11,13 +11,14 @@ RUN dpkg --add-architecture i386 && \ python2.7 \ git \ cmake \ - ccache \ unzip \ expect \ openjdk-9-jre \ sudo \ libstdc++6:i386 \ - xz-utils + xz-utils \ + libssl-dev \ + pkg-config WORKDIR /android/ ENV PATH=$PATH:/android/ndk-arm-9/bin:/android/sdk/tools:/android/sdk/platform-tools @@ -34,21 +35,12 @@ COPY start-emulator.sh /android/ ENTRYPOINT ["/usr/bin/dumb-init", "--", "/android/start-emulator.sh"] -ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 -RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ - tar xJf - -C /usr/local/bin --strip-components=1 - -ENV TARGETS=arm-linux-androideabi -ENV TARGETS=$TARGETS,i686-linux-android -ENV TARGETS=$TARGETS,aarch64-linux-android -ENV TARGETS=$TARGETS,armv7-linux-androideabi +RUN curl -o /usr/local/bin/sccache \ + https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-02-24-sccache-x86_64-unknown-linux-gnu && \ + chmod +x /usr/local/bin/sccache ENV RUST_CONFIGURE_ARGS \ - --target=$TARGETS \ - --arm-linux-androideabi-ndk=/android/ndk-arm-9 \ - --armv7-linux-androideabi-ndk=/android/ndk-arm-9 \ - --i686-linux-android-ndk=/android/ndk-x86-9 \ - --aarch64-linux-android-ndk=/android/ndk-aarch64 -ENV XPY_CHECK test --target arm-linux-androideabi -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj + --target=arm-linux-androideabi \ + --arm-linux-androideabi-ndk=/android/ndk-arm-9 + +ENV SCRIPT python2.7 ../x.py test --target arm-linux-androideabi diff --git a/src/ci/docker/arm-android/install-ndk.sh b/src/ci/docker/arm-android/install-ndk.sh index 418ce69c5b..389ec06211 100644 --- a/src/ci/docker/arm-android/install-ndk.sh +++ b/src/ci/docker/arm-android/install-ndk.sh @@ -29,17 +29,5 @@ bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \ --ndk-dir=/android/android-ndk-r11c \ --arch=arm cpgdb ndk-arm-9 arm-linux-androideabi -bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \ - --platform=android-21 \ - --toolchain=aarch64-linux-android-4.9 \ - --install-dir=/android/ndk-aarch64 \ - --ndk-dir=/android/android-ndk-r11c \ - --arch=arm64 -bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \ - --platform=android-9 \ - --toolchain=x86-4.9 \ - --install-dir=/android/ndk-x86-9 \ - --ndk-dir=/android/android-ndk-r11c \ - --arch=x86 rm -rf ./android-ndk-r11c-linux-x86_64.zip ./android-ndk-r11c diff --git a/src/ci/docker/arm-android/start-emulator.sh b/src/ci/docker/arm-android/start-emulator.sh index 93f20b28b8..24c477d87f 100755 --- a/src/ci/docker/arm-android/start-emulator.sh +++ b/src/ci/docker/arm-android/start-emulator.sh @@ -11,5 +11,6 @@ set -ex ANDROID_EMULATOR_FORCE_32BIT=true \ - emulator @arm-18 -no-window -partition-size 2047 & + nohup nohup emulator @arm-18 -no-window -partition-size 2047 \ + 0<&- &>/dev/null & exec "$@" diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index 08b436313f..8f947caf2c 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -9,20 +9,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ - gcc-aarch64-linux-gnu libc6-dev-arm64-cross \ - gcc-arm-linux-gnueabi libc6-dev-armel-cross \ - gcc-arm-linux-gnueabihf libc6-dev-armhf-cross \ - gcc-mips-linux-gnu libc6-dev-mips-cross \ - gcc-mipsel-linux-gnu libc6-dev-mipsel-cross \ - gcc-mips64-linux-gnuabi64 libc6-dev-mips64-cross \ - gcc-mips64el-linux-gnuabi64 libc6-dev-mips64el-cross \ - gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \ - gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \ - gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \ - gcc-s390x-linux-gnu libc6-dev-s390x-cross \ - xz-utils + xz-utils \ + zlib1g-dev \ + g++-arm-linux-gnueabi \ + g++-arm-linux-gnueabihf \ + bzip2 \ + patch ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ @@ -33,43 +26,50 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -ENV TARGETS=aarch64-unknown-linux-gnu -ENV TARGETS=$TARGETS,arm-unknown-linux-gnueabi -ENV TARGETS=$TARGETS,arm-unknown-linux-gnueabihf -ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabihf -ENV TARGETS=$TARGETS,asmjs-unknown-emscripten -ENV TARGETS=$TARGETS,mips-unknown-linux-gnu -ENV TARGETS=$TARGETS,mips64-unknown-linux-gnuabi64 -ENV TARGETS=$TARGETS,mips64el-unknown-linux-gnuabi64 -ENV TARGETS=$TARGETS,mipsel-unknown-linux-gnu -ENV TARGETS=$TARGETS,powerpc-unknown-linux-gnu -ENV TARGETS=$TARGETS,powerpc64-unknown-linux-gnu -ENV TARGETS=$TARGETS,powerpc64le-unknown-linux-gnu -ENV TARGETS=$TARGETS,s390x-unknown-linux-gnu -ENV TARGETS=$TARGETS,wasm32-unknown-emscripten +WORKDIR /tmp -#ENV TARGETS=$TARGETS,mips-unknown-linux-musl -#ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi -#ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf -#ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf -#ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd +COPY build-rumprun.sh /tmp/ +RUN ./build-rumprun.sh -ENV RUST_CONFIGURE_ARGS \ - --target=$TARGETS \ - --enable-rustbuild -ENV RUST_CHECK_TARGET "" +COPY build-arm-musl.sh /tmp/ +RUN ./build-arm-musl.sh -ENV AR_s390x_unknown_linux_gnu=s390x-linux-gnu-ar \ - CC_s390x_unknown_linux_gnu=s390x-linux-gnu-gcc \ - AR_mips64_unknown_linux_gnuabi64=mips64-linux-gnuabi64-ar \ - CC_mips64_unknown_linux_gnuabi64=mips64-linux-gnuabi64-gcc \ - AR_mips64el_unknown_linux_gnuabi64=mips64el-linux-gnuabi64-ar \ - CC_mips64el_unknown_linux_gnuabi64=mips64el-linux-gnuabi64-gcc \ - AR_powerpc64_unknown_linux_gnu=powerpc64-linux-gnu-ar \ - CC_powerpc64_unknown_linux_gnu=powerpc64-linux-gnu-gcc +# originally from +# https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2 +RUN mkdir /usr/local/mips-linux-musl +RUN curl -L https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2 | \ + tar xjf - -C /usr/local/mips-linux-musl --strip-components=2 +RUN for file in /usr/local/mips-linux-musl/bin/mips-openwrt-linux-*; do \ + ln -s $file /usr/local/bin/`basename $file`; \ + done -# FIXME(rust-lang/rust#36150): powerpc unfortunately aborts right now -ENV NO_LLVM_ASSERTIONS=1 +# Note that this originally came from: +# https://downloads.openwrt.org/snapshots/trunk/malta/generic/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 +RUN mkdir /usr/local/mipsel-linux-musl +RUN curl -L https://s3.amazonaws.com/rust-lang-ci/libc/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \ + tar xjf - -C /usr/local/mipsel-linux-musl --strip-components=2 +RUN for file in /usr/local/mipsel-linux-musl/bin/mipsel-openwrt-linux-*; do \ + ln -s $file /usr/local/bin/`basename $file`; \ + done + +ENV TARGETS=asmjs-unknown-emscripten +ENV TARGETS=$TARGETS,wasm32-unknown-emscripten +ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd +ENV TARGETS=$TARGETS,mips-unknown-linux-musl +ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl +ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi +ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf +ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj +ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ + CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc + +# Suppress some warnings in the openwrt toolchains we downloaded +ENV STAGING_DIR=/tmp + +ENV RUST_CONFIGURE_ARGS \ + --target=$TARGETS \ + --musl-root-arm=/usr/local/arm-linux-musleabi \ + --musl-root-armhf=/usr/local/arm-linux-musleabihf \ + --musl-root-armv7=/usr/local/armv7-linux-musleabihf +ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/cross/build-arm-musl.sh b/src/ci/docker/cross/build-arm-musl.sh new file mode 100755 index 0000000000..938e69834e --- /dev/null +++ b/src/ci/docker/cross/build-arm-musl.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# 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. + +set -ex + +MUSL=1.1.16 + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + rm /tmp/build.log + set -x +} + +curl -O https://www.musl-libc.org/releases/musl-$MUSL.tar.gz +tar xf musl-$MUSL.tar.gz +cd musl-$MUSL +CC=arm-linux-gnueabi-gcc \ +CFLAGS="-march=armv6 -marm" \ + hide_output ./configure \ + --prefix=/usr/local/arm-linux-musleabi \ + --enable-wrapper=gcc +hide_output make -j$(nproc) +hide_output make install +cd .. +rm -rf musl-$MUSL + +tar xf musl-$MUSL.tar.gz +cd musl-$MUSL +CC=arm-linux-gnueabihf-gcc \ +CFLAGS="-march=armv6 -marm" \ + hide_output ./configure \ + --prefix=/usr/local/arm-linux-musleabihf \ + --enable-wrapper=gcc +hide_output make -j$(nproc) +hide_output make install +cd .. +rm -rf musl-$MUSL + +tar xf musl-$MUSL.tar.gz +cd musl-$MUSL +CC=arm-linux-gnueabihf-gcc \ +CFLAGS="-march=armv7-a" \ + hide_output ./configure \ + --prefix=/usr/local/armv7-linux-musleabihf \ + --enable-wrapper=gcc +hide_output make -j$(nproc) +hide_output make install +cd .. +rm -rf musl-$MUSL* + +ln -nsf ../arm-linux-musleabi/bin/musl-gcc /usr/local/bin/arm-linux-musleabi-gcc +ln -nsf ../arm-linux-musleabihf/bin/musl-gcc /usr/local/bin/arm-linux-musleabihf-gcc +ln -nsf ../armv7-linux-musleabihf/bin/musl-gcc /usr/local/bin/armv7-linux-musleabihf-gcc + +curl -L https://github.com/llvm-mirror/llvm/archive/release_39.tar.gz | tar xzf - +curl -L https://github.com/llvm-mirror/libunwind/archive/release_39.tar.gz | tar xzf - + +mkdir libunwind-build +cd libunwind-build +cmake ../libunwind-release_39 \ + -DLLVM_PATH=/tmp/llvm-release_39 \ + -DLIBUNWIND_ENABLE_SHARED=0 \ + -DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \ + -DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++ \ + -DCMAKE_C_FLAGS="-march=armv6 -marm" \ + -DCMAKE_CXX_FLAGS="-march=armv6 -marm" +make -j$(nproc) +cp lib/libunwind.a /usr/local/arm-linux-musleabi/lib +cd .. +rm -rf libunwind-build + +mkdir libunwind-build +cd libunwind-build +cmake ../libunwind-release_39 \ + -DLLVM_PATH=/tmp/llvm-release_39 \ + -DLIBUNWIND_ENABLE_SHARED=0 \ + -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \ + -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \ + -DCMAKE_C_FLAGS="-march=armv6 -marm" \ + -DCMAKE_CXX_FLAGS="-march=armv6 -marm" +make -j$(nproc) +cp lib/libunwind.a /usr/local/arm-linux-musleabihf/lib +cd .. +rm -rf libunwind-build + +mkdir libunwind-build +cd libunwind-build +cmake ../libunwind-release_39 \ + -DLLVM_PATH=/tmp/llvm-release_39 \ + -DLIBUNWIND_ENABLE_SHARED=0 \ + -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \ + -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \ + -DCMAKE_C_FLAGS="-march=armv7-a" \ + -DCMAKE_CXX_FLAGS="-march=armv7-a" +make -j$(nproc) +cp lib/libunwind.a /usr/local/armv7-linux-musleabihf/lib +cd .. +rm -rf libunwind-build + +rm -rf libunwind-release_39 +rm -rf llvm-release_39 diff --git a/src/ci/docker/cross/build-rumprun.sh b/src/ci/docker/cross/build-rumprun.sh new file mode 100755 index 0000000000..59b1c9b641 --- /dev/null +++ b/src/ci/docker/cross/build-rumprun.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# 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. + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + rm /tmp/build.log + set -x +} + +git clone https://github.com/rumpkernel/rumprun +cd rumprun +git reset --hard 39a97f37a85e44c69b662f6b97b688fbe892603b +git submodule update --init + +CC=cc hide_output ./build-rr.sh -d /usr/local hw +cd .. +rm -rf rumprun diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile new file mode 100644 index 0000000000..739cd6196e --- /dev/null +++ b/src/ci/docker/dist-android/Dockerfile @@ -0,0 +1,48 @@ +FROM ubuntu:16.04 + +RUN dpkg --add-architecture i386 && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + unzip \ + expect \ + openjdk-9-jre \ + sudo \ + libstdc++6:i386 \ + xz-utils + +WORKDIR /android/ +ENV PATH=$PATH:/android/ndk-arm-9/bin:/android/sdk/tools:/android/sdk/platform-tools + +COPY install-ndk.sh /android/ +RUN sh /android/install-ndk.sh + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +ENV TARGETS=arm-linux-androideabi +ENV TARGETS=$TARGETS,i686-linux-android +ENV TARGETS=$TARGETS,aarch64-linux-android +ENV TARGETS=$TARGETS,armv7-linux-androideabi + +ENV RUST_CONFIGURE_ARGS \ + --target=$TARGETS \ + --arm-linux-androideabi-ndk=/android/ndk-arm-9 \ + --armv7-linux-androideabi-ndk=/android/ndk-arm-9 \ + --i686-linux-android-ndk=/android/ndk-x86-9 \ + --aarch64-linux-android-ndk=/android/ndk-aarch64 + +ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-android/install-ndk.sh b/src/ci/docker/dist-android/install-ndk.sh new file mode 100644 index 0000000000..19c1b94e78 --- /dev/null +++ b/src/ci/docker/dist-android/install-ndk.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# 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. + +set -ex + +# Prep the Android NDK +# +# See https://github.com/servo/servo/wiki/Building-for-Android +curl -O https://dl.google.com/android/repository/android-ndk-r11c-linux-x86_64.zip +unzip -q android-ndk-r11c-linux-x86_64.zip +bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \ + --platform=android-9 \ + --toolchain=arm-linux-androideabi-4.9 \ + --install-dir=/android/ndk-arm-9 \ + --ndk-dir=/android/android-ndk-r11c \ + --arch=arm +bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \ + --platform=android-21 \ + --toolchain=aarch64-linux-android-4.9 \ + --install-dir=/android/ndk-aarch64 \ + --ndk-dir=/android/android-ndk-r11c \ + --arch=arm64 +bash android-ndk-r11c/build/tools/make-standalone-toolchain.sh \ + --platform=android-9 \ + --toolchain=x86-4.9 \ + --install-dir=/android/ndk-x86-9 \ + --ndk-dir=/android/android-ndk-r11c \ + --arch=x86 + +rm -rf ./android-ndk-r11c-linux-x86_64.zip ./android-ndk-r11c diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile new file mode 100644 index 0000000000..217a724fb9 --- /dev/null +++ b/src/ci/docker/dist-arm-linux/Dockerfile @@ -0,0 +1,80 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + automake \ + bison \ + bzip2 \ + ca-certificates \ + cmake \ + curl \ + file \ + flex \ + g++ \ + gawk \ + gdb \ + git \ + gperf \ + help2man \ + libncurses-dev \ + libtool-bin \ + make \ + patch \ + python2.7 \ + sudo \ + texinfo \ + wget \ + xz-utils + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# toolchains we build below chokes on that, so go back to make 3 +RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ + cd make-3.81 && \ + ./configure --prefix=/usr && \ + make && \ + make install && \ + cd .. && \ + rm -rf make-3.81 + +RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ + tar xjf - && \ + cd crosstool-ng && \ + ./configure --prefix=/usr/local && \ + make -j$(nproc) && \ + make install && \ + cd .. && \ + rm -rf crosstool-ng + +RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild +RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +USER rustbuild +WORKDIR /tmp + +COPY arm-linux-gnueabihf.config arm-linux-gnueabi.config build-toolchains.sh /tmp/ +RUN ./build-toolchains.sh + +USER root + +ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin +ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin + +ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \ + AR_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-ar \ + CXX_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-g++ \ + CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \ + AR_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-ar \ + CXX_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-g++ + +ENV HOSTS=arm-unknown-linux-gnueabi +ENV HOSTS=$HOSTS,arm-unknown-linux-gnueabihf + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-arm-linux/arm-linux-gnueabi.config b/src/ci/docker/dist-arm-linux/arm-linux-gnueabi.config new file mode 100644 index 0000000000..f73ad06955 --- /dev/null +++ b/src/ci/docker/dist-arm-linux/arm-linux-gnueabi.config @@ -0,0 +1,560 @@ +# +# Automatically generated file; DO NOT EDIT. +# Crosstool-NG Configuration +# +CT_CONFIGURE_has_make381=y +CT_MODULES=y + +# +# Paths and misc options +# + +# +# crosstool-NG behavior +# +# CT_OBSOLETE is not set +# CT_EXPERIMENTAL is not set +# CT_DEBUG_CT is not set + +# +# Paths +# +CT_LOCAL_TARBALLS_DIR="" +CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_INSTALL_DIR="${CT_PREFIX_DIR}" +CT_RM_RF_PREFIX_DIR=y +CT_REMOVE_DOCS=y +CT_INSTALL_DIR_RO=y +CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y +# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set + +# +# Downloading +# +# CT_FORBID_DOWNLOAD is not set +# CT_FORCE_DOWNLOAD is not set +CT_CONNECT_TIMEOUT=10 +# CT_ONLY_DOWNLOAD is not set +# CT_USE_MIRROR is not set + +# +# Extracting +# +# CT_FORCE_EXTRACT is not set +CT_OVERIDE_CONFIG_GUESS_SUB=y +# CT_ONLY_EXTRACT is not set +CT_PATCH_BUNDLED=y +# CT_PATCH_LOCAL is not set +# CT_PATCH_BUNDLED_LOCAL is not set +# CT_PATCH_LOCAL_BUNDLED is not set +# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set +# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set +# CT_PATCH_NONE is not set +CT_PATCH_ORDER="bundled" + +# +# Build behavior +# +CT_PARALLEL_JOBS=0 +CT_LOAD="" +CT_USE_PIPES=y +CT_EXTRA_CFLAGS_FOR_BUILD="" +CT_EXTRA_LDFLAGS_FOR_BUILD="" +CT_EXTRA_CFLAGS_FOR_HOST="" +CT_EXTRA_LDFLAGS_FOR_HOST="" +# CT_CONFIG_SHELL_SH is not set +# CT_CONFIG_SHELL_ASH is not set +CT_CONFIG_SHELL_BASH=y +# CT_CONFIG_SHELL_CUSTOM is not set +CT_CONFIG_SHELL="${bash}" + +# +# Logging +# +# CT_LOG_ERROR is not set +# CT_LOG_WARN is not set +CT_LOG_INFO=y +# CT_LOG_EXTRA is not set +# CT_LOG_ALL is not set +# CT_LOG_DEBUG is not set +CT_LOG_LEVEL_MAX="INFO" +# CT_LOG_SEE_TOOLS_WARN is not set +CT_LOG_PROGRESS_BAR=y +CT_LOG_TO_FILE=y +CT_LOG_FILE_COMPRESS=y + +# +# Target options +# +CT_ARCH="arm" +CT_ARCH_SUPPORTS_BOTH_MMU=y +CT_ARCH_SUPPORTS_BOTH_ENDIAN=y +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_SUPPORTS_WITH_ARCH=y +CT_ARCH_SUPPORTS_WITH_CPU=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_SUPPORTS_WITH_FLOAT=y +CT_ARCH_SUPPORTS_WITH_FPU=y +CT_ARCH_SUPPORTS_SOFTFP=y +CT_ARCH_DEFAULT_HAS_MMU=y +CT_ARCH_DEFAULT_LE=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_ARCH="armv6" +CT_ARCH_CPU="" +CT_ARCH_TUNE="" +CT_ARCH_FPU="" +# CT_ARCH_BE is not set +CT_ARCH_LE=y +CT_ARCH_32=y +# CT_ARCH_64 is not set +CT_ARCH_BITNESS=32 +# CT_ARCH_FLOAT_HW is not set +CT_ARCH_FLOAT_SW=y +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" +# CT_ARCH_alpha is not set +CT_ARCH_arm=y +# CT_ARCH_avr is not set +# CT_ARCH_m68k is not set +# CT_ARCH_mips is not set +# CT_ARCH_nios2 is not set +# CT_ARCH_powerpc is not set +# CT_ARCH_s390 is not set +# CT_ARCH_sh is not set +# CT_ARCH_sparc is not set +# CT_ARCH_x86 is not set +# CT_ARCH_xtensa is not set +CT_ARCH_alpha_AVAILABLE=y +CT_ARCH_arm_AVAILABLE=y +CT_ARCH_avr_AVAILABLE=y +CT_ARCH_m68k_AVAILABLE=y +CT_ARCH_microblaze_AVAILABLE=y +CT_ARCH_mips_AVAILABLE=y +CT_ARCH_nios2_AVAILABLE=y +CT_ARCH_powerpc_AVAILABLE=y +CT_ARCH_s390_AVAILABLE=y +CT_ARCH_sh_AVAILABLE=y +CT_ARCH_sparc_AVAILABLE=y +CT_ARCH_x86_AVAILABLE=y +CT_ARCH_xtensa_AVAILABLE=y +CT_ARCH_SUFFIX="" + +# +# Generic target options +# +# CT_MULTILIB is not set +CT_ARCH_USE_MMU=y +CT_ARCH_ENDIAN="little" + +# +# Target optimisations +# +CT_ARCH_EXCLUSIVE_WITH_CPU=y +# CT_ARCH_FLOAT_AUTO is not set +# CT_ARCH_FLOAT_SOFTFP is not set +CT_ARCH_FLOAT="soft" + +# +# arm other options +# +CT_ARCH_ARM_MODE="arm" +CT_ARCH_ARM_MODE_ARM=y +# CT_ARCH_ARM_MODE_THUMB is not set +# CT_ARCH_ARM_INTERWORKING is not set +CT_ARCH_ARM_EABI_FORCE=y +CT_ARCH_ARM_EABI=y + +# +# Toolchain options +# + +# +# General toolchain options +# +CT_FORCE_SYSROOT=y +CT_USE_SYSROOT=y +CT_SYSROOT_NAME="sysroot" +CT_SYSROOT_DIR_PREFIX="" +CT_WANTS_STATIC_LINK=y +# CT_STATIC_TOOLCHAIN is not set +CT_TOOLCHAIN_PKGVERSION="" +CT_TOOLCHAIN_BUGURL="" + +# +# Tuple completion and aliasing +# +CT_TARGET_VENDOR="unknown" +CT_TARGET_ALIAS_SED_EXPR="" +CT_TARGET_ALIAS="" + +# +# Toolchain type +# +CT_CROSS=y +# CT_CANADIAN is not set +CT_TOOLCHAIN_TYPE="cross" + +# +# Build system +# +CT_BUILD="" +CT_BUILD_PREFIX="" +CT_BUILD_SUFFIX="" + +# +# Misc options +# +# CT_TOOLCHAIN_ENABLE_NLS is not set + +# +# Operating System +# +CT_KERNEL_SUPPORTS_SHARED_LIBS=y +CT_KERNEL="linux" +CT_KERNEL_VERSION="3.2.72" +# CT_KERNEL_bare_metal is not set +CT_KERNEL_linux=y +CT_KERNEL_bare_metal_AVAILABLE=y +CT_KERNEL_linux_AVAILABLE=y +# CT_KERNEL_V_4_3 is not set +# CT_KERNEL_V_4_2 is not set +# CT_KERNEL_V_4_1 is not set +# CT_KERNEL_V_3_18 is not set +# CT_KERNEL_V_3_14 is not set +# CT_KERNEL_V_3_12 is not set +# CT_KERNEL_V_3_10 is not set +# CT_KERNEL_V_3_4 is not set +CT_KERNEL_V_3_2=y +# CT_KERNEL_V_2_6_32 is not set +# CT_KERNEL_LINUX_CUSTOM is not set +CT_KERNEL_windows_AVAILABLE=y + +# +# Common kernel options +# +CT_SHARED_LIBS=y + +# +# linux other options +# +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y + +# +# Binary utilities +# +CT_ARCH_BINFMT_ELF=y +CT_BINUTILS="binutils" +CT_BINUTILS_binutils=y + +# +# GNU binutils +# +# CT_CC_BINUTILS_SHOW_LINARO is not set +CT_BINUTILS_V_2_25_1=y +# CT_BINUTILS_V_2_25 is not set +# CT_BINUTILS_V_2_24 is not set +# CT_BINUTILS_V_2_23_2 is not set +# CT_BINUTILS_V_2_23_1 is not set +# CT_BINUTILS_V_2_22 is not set +# CT_BINUTILS_V_2_21_53 is not set +# CT_BINUTILS_V_2_21_1a is not set +# CT_BINUTILS_V_2_20_1a is not set +# CT_BINUTILS_V_2_19_1a is not set +# CT_BINUTILS_V_2_18a is not set +CT_BINUTILS_VERSION="2.25.1" +CT_BINUTILS_2_25_1_or_later=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_2_24_or_later=y +CT_BINUTILS_2_23_or_later=y +CT_BINUTILS_2_22_or_later=y +CT_BINUTILS_2_21_or_later=y +CT_BINUTILS_2_20_or_later=y +CT_BINUTILS_2_19_or_later=y +CT_BINUTILS_2_18_or_later=y +CT_BINUTILS_HAS_HASH_STYLE=y +CT_BINUTILS_HAS_GOLD=y +CT_BINUTILS_GOLD_SUPPORTS_ARCH=y +CT_BINUTILS_GOLD_SUPPORT=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_LINKER_LD=y +# CT_BINUTILS_LINKER_LD_GOLD is not set +# CT_BINUTILS_LINKER_GOLD_LD is not set +CT_BINUTILS_LINKERS_LIST="ld" +CT_BINUTILS_LINKER_DEFAULT="bfd" +# CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_EXTRA_CONFIG_ARRAY="" +# CT_BINUTILS_FOR_TARGET is not set + +# +# binutils other options +# + +# +# C-library +# +CT_LIBC="glibc" +CT_LIBC_VERSION="2.16.0" +CT_LIBC_glibc=y +# CT_LIBC_musl is not set +# CT_LIBC_uClibc is not set +CT_LIBC_avr_libc_AVAILABLE=y +CT_LIBC_glibc_AVAILABLE=y +CT_THREADS="nptl" +# CT_CC_GLIBC_SHOW_LINARO is not set +# CT_LIBC_GLIBC_V_2_22 is not set +# CT_LIBC_GLIBC_V_2_21 is not set +# CT_LIBC_GLIBC_V_2_20 is not set +# CT_LIBC_GLIBC_V_2_19 is not set +# CT_LIBC_GLIBC_V_2_18 is not set +# CT_LIBC_GLIBC_V_2_17 is not set +CT_LIBC_GLIBC_V_2_16_0=y +# CT_LIBC_GLIBC_V_2_15 is not set +# CT_LIBC_GLIBC_V_2_14_1 is not set +# CT_LIBC_GLIBC_V_2_14 is not set +# CT_LIBC_GLIBC_V_2_13 is not set +# CT_LIBC_GLIBC_V_2_12_2 is not set +# CT_LIBC_GLIBC_V_2_12_1 is not set +# CT_LIBC_GLIBC_V_2_11_1 is not set +# CT_LIBC_GLIBC_V_2_11 is not set +# CT_LIBC_GLIBC_V_2_10_1 is not set +# CT_LIBC_GLIBC_V_2_9 is not set +# CT_LIBC_GLIBC_V_2_8 is not set +CT_LIBC_mingw_AVAILABLE=y +CT_LIBC_musl_AVAILABLE=y +CT_LIBC_newlib_AVAILABLE=y +CT_LIBC_none_AVAILABLE=y +CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_SUPPORT_THREADS_ANY=y +CT_LIBC_SUPPORT_THREADS_NATIVE=y + +# +# Common C library options +# +CT_THREADS_NATIVE=y +CT_LIBC_XLDD=y + +# +# glibc other options +# +CT_LIBC_GLIBC_PORTS_EXTERNAL=y +CT_LIBC_GLIBC_MAY_FORCE_PORTS=y +CT_LIBC_glibc_familly=y +CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_LIBC_GLIBC_CONFIGPARMS="" +CT_LIBC_GLIBC_EXTRA_CFLAGS="" +CT_LIBC_EXTRA_CC_ARGS="" +# CT_LIBC_DISABLE_VERSIONING is not set +CT_LIBC_OLDEST_ABI="" +CT_LIBC_GLIBC_FORCE_UNWIND=y +CT_LIBC_GLIBC_USE_PORTS=y +CT_LIBC_ADDONS_LIST="" + +# +# WARNING !!! +# + +# +# For glibc >= 2.8, it can happen that the tarballs +# + +# +# for the addons are not available for download. +# + +# +# If that happens, bad luck... Try a previous version +# + +# +# or try again later... :-( +# +# CT_LIBC_LOCALES is not set +# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set +CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_LIBC_GLIBC_MIN_KERNEL="3.2.72" + +# +# C compiler +# +CT_CC="gcc" +CT_CC_CORE_PASSES_NEEDED=y +CT_CC_CORE_PASS_1_NEEDED=y +CT_CC_CORE_PASS_2_NEEDED=y +CT_CC_gcc=y +# CT_CC_GCC_SHOW_LINARO is not set +# CT_CC_GCC_V_5_2_0 is not set +CT_CC_GCC_V_4_9_3=y +# CT_CC_GCC_V_4_8_5 is not set +# CT_CC_GCC_V_4_7_4 is not set +# CT_CC_GCC_V_4_6_4 is not set +# CT_CC_GCC_V_4_5_4 is not set +# CT_CC_GCC_V_4_4_7 is not set +# CT_CC_GCC_V_4_3_6 is not set +# CT_CC_GCC_V_4_2_4 is not set +CT_CC_GCC_4_2_or_later=y +CT_CC_GCC_4_3_or_later=y +CT_CC_GCC_4_4_or_later=y +CT_CC_GCC_4_5_or_later=y +CT_CC_GCC_4_6_or_later=y +CT_CC_GCC_4_7_or_later=y +CT_CC_GCC_4_8_or_later=y +CT_CC_GCC_4_9=y +CT_CC_GCC_4_9_or_later=y +CT_CC_GCC_HAS_GRAPHITE=y +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_HAS_LTO=y +CT_CC_GCC_USE_LTO=y +CT_CC_GCC_HAS_PKGVERSION_BUGURL=y +CT_CC_GCC_HAS_BUILD_ID=y +CT_CC_GCC_HAS_LNK_HASH_STYLE=y +CT_CC_GCC_USE_GMP_MPFR=y +CT_CC_GCC_USE_MPC=y +CT_CC_GCC_HAS_LIBQUADMATH=y +CT_CC_GCC_HAS_LIBSANITIZER=y +CT_CC_GCC_VERSION="4.9.3" +# CT_CC_LANG_FORTRAN is not set +CT_CC_GCC_ENABLE_CXX_FLAGS="" +CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_ENV_ARRAY="" +CT_CC_GCC_STATIC_LIBSTDCXX=y +# CT_CC_GCC_SYSTEM_ZLIB is not set + +# +# Optimisation features +# + +# +# Settings for libraries running on target +# +CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y +# CT_CC_GCC_LIBMUDFLAP is not set +# CT_CC_GCC_LIBGOMP is not set +# CT_CC_GCC_LIBSSP is not set +# CT_CC_GCC_LIBQUADMATH is not set +# CT_CC_GCC_LIBSANITIZER is not set + +# +# Misc. obscure options. +# +CT_CC_CXA_ATEXIT=y +# CT_CC_GCC_DISABLE_PCH is not set +CT_CC_GCC_SJLJ_EXCEPTIONS=m +CT_CC_GCC_LDBL_128=m +# CT_CC_GCC_BUILD_ID is not set +CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y +# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set +# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set +# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set +CT_CC_GCC_LNK_HASH_STYLE="" +CT_CC_GCC_DEC_FLOAT_AUTO=y +# CT_CC_GCC_DEC_FLOAT_BID is not set +# CT_CC_GCC_DEC_FLOAT_DPD is not set +# CT_CC_GCC_DEC_FLOATS_NO is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_JAVA=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y + +# +# Additional supported languages: +# +CT_CC_LANG_CXX=y +# CT_CC_LANG_JAVA is not set + +# +# Debug facilities +# +# CT_DEBUG_dmalloc is not set +# CT_DEBUG_duma is not set +# CT_DEBUG_gdb is not set +# CT_DEBUG_ltrace is not set +# CT_DEBUG_strace is not set + +# +# Companion libraries +# +CT_COMPLIBS_NEEDED=y +CT_LIBICONV_NEEDED=y +CT_GETTEXT_NEEDED=y +CT_GMP_NEEDED=y +CT_MPFR_NEEDED=y +CT_ISL_NEEDED=y +CT_CLOOG_NEEDED=y +CT_MPC_NEEDED=y +CT_COMPLIBS=y +CT_LIBICONV=y +CT_GETTEXT=y +CT_GMP=y +CT_MPFR=y +CT_ISL=y +CT_CLOOG=y +CT_MPC=y +CT_LIBICONV_V_1_14=y +CT_LIBICONV_VERSION="1.14" +CT_GETTEXT_V_0_19_6=y +CT_GETTEXT_VERSION="0.19.6" +CT_GMP_V_6_0_0=y +# CT_GMP_V_5_1_3 is not set +# CT_GMP_V_5_1_1 is not set +# CT_GMP_V_5_0_2 is not set +# CT_GMP_V_5_0_1 is not set +# CT_GMP_V_4_3_2 is not set +# CT_GMP_V_4_3_1 is not set +# CT_GMP_V_4_3_0 is not set +CT_GMP_5_0_2_or_later=y +CT_GMP_VERSION="6.0.0a" +CT_MPFR_V_3_1_3=y +# CT_MPFR_V_3_1_2 is not set +# CT_MPFR_V_3_1_0 is not set +# CT_MPFR_V_3_0_1 is not set +# CT_MPFR_V_3_0_0 is not set +# CT_MPFR_V_2_4_2 is not set +# CT_MPFR_V_2_4_1 is not set +# CT_MPFR_V_2_4_0 is not set +CT_MPFR_VERSION="3.1.3" +CT_ISL_V_0_14=y +CT_ISL_V_0_14_or_later=y +CT_ISL_V_0_12_or_later=y +CT_ISL_VERSION="0.14" +CT_CLOOG_V_0_18_4=y +# CT_CLOOG_V_0_18_1 is not set +# CT_CLOOG_V_0_18_0 is not set +CT_CLOOG_VERSION="0.18.4" +CT_CLOOG_0_18_4_or_later=y +CT_CLOOG_0_18_or_later=y +CT_MPC_V_1_0_3=y +# CT_MPC_V_1_0_2 is not set +# CT_MPC_V_1_0_1 is not set +# CT_MPC_V_1_0 is not set +# CT_MPC_V_0_9 is not set +# CT_MPC_V_0_8_2 is not set +# CT_MPC_V_0_8_1 is not set +# CT_MPC_V_0_7 is not set +CT_MPC_VERSION="1.0.3" + +# +# Companion libraries common options +# +# CT_COMPLIBS_CHECK is not set + +# +# Companion tools +# + +# +# READ HELP before you say 'Y' below !!! +# +# CT_COMP_TOOLS is not set diff --git a/src/ci/docker/dist-arm-linux/arm-linux-gnueabihf.config b/src/ci/docker/dist-arm-linux/arm-linux-gnueabihf.config new file mode 100644 index 0000000000..1feeef1555 --- /dev/null +++ b/src/ci/docker/dist-arm-linux/arm-linux-gnueabihf.config @@ -0,0 +1,561 @@ +# +# Automatically generated file; DO NOT EDIT. +# Crosstool-NG Configuration +# +CT_CONFIGURE_has_make381=y +CT_MODULES=y + +# +# Paths and misc options +# + +# +# crosstool-NG behavior +# +# CT_OBSOLETE is not set +# CT_EXPERIMENTAL is not set +# CT_DEBUG_CT is not set + +# +# Paths +# +CT_LOCAL_TARBALLS_DIR="" +CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_INSTALL_DIR="${CT_PREFIX_DIR}" +CT_RM_RF_PREFIX_DIR=y +CT_REMOVE_DOCS=y +CT_INSTALL_DIR_RO=y +CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y +# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set + +# +# Downloading +# +# CT_FORBID_DOWNLOAD is not set +# CT_FORCE_DOWNLOAD is not set +CT_CONNECT_TIMEOUT=10 +# CT_ONLY_DOWNLOAD is not set +# CT_USE_MIRROR is not set + +# +# Extracting +# +# CT_FORCE_EXTRACT is not set +CT_OVERIDE_CONFIG_GUESS_SUB=y +# CT_ONLY_EXTRACT is not set +CT_PATCH_BUNDLED=y +# CT_PATCH_LOCAL is not set +# CT_PATCH_BUNDLED_LOCAL is not set +# CT_PATCH_LOCAL_BUNDLED is not set +# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set +# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set +# CT_PATCH_NONE is not set +CT_PATCH_ORDER="bundled" + +# +# Build behavior +# +CT_PARALLEL_JOBS=0 +CT_LOAD="" +CT_USE_PIPES=y +CT_EXTRA_CFLAGS_FOR_BUILD="" +CT_EXTRA_LDFLAGS_FOR_BUILD="" +CT_EXTRA_CFLAGS_FOR_HOST="" +CT_EXTRA_LDFLAGS_FOR_HOST="" +# CT_CONFIG_SHELL_SH is not set +# CT_CONFIG_SHELL_ASH is not set +CT_CONFIG_SHELL_BASH=y +# CT_CONFIG_SHELL_CUSTOM is not set +CT_CONFIG_SHELL="${bash}" + +# +# Logging +# +# CT_LOG_ERROR is not set +# CT_LOG_WARN is not set +CT_LOG_INFO=y +# CT_LOG_EXTRA is not set +# CT_LOG_ALL is not set +# CT_LOG_DEBUG is not set +CT_LOG_LEVEL_MAX="INFO" +# CT_LOG_SEE_TOOLS_WARN is not set +CT_LOG_PROGRESS_BAR=y +CT_LOG_TO_FILE=y +CT_LOG_FILE_COMPRESS=y + +# +# Target options +# +CT_ARCH="arm" +CT_ARCH_SUPPORTS_BOTH_MMU=y +CT_ARCH_SUPPORTS_BOTH_ENDIAN=y +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_SUPPORTS_WITH_ARCH=y +CT_ARCH_SUPPORTS_WITH_CPU=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_SUPPORTS_WITH_FLOAT=y +CT_ARCH_SUPPORTS_WITH_FPU=y +CT_ARCH_SUPPORTS_SOFTFP=y +CT_ARCH_DEFAULT_HAS_MMU=y +CT_ARCH_DEFAULT_LE=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_ARCH="armv6" +CT_ARCH_CPU="" +CT_ARCH_TUNE="" +CT_ARCH_FPU="vfp" +# CT_ARCH_BE is not set +CT_ARCH_LE=y +CT_ARCH_32=y +# CT_ARCH_64 is not set +CT_ARCH_BITNESS=32 +CT_ARCH_FLOAT_HW=y +# CT_ARCH_FLOAT_SW is not set +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" +# CT_ARCH_alpha is not set +CT_ARCH_arm=y +# CT_ARCH_avr is not set +# CT_ARCH_m68k is not set +# CT_ARCH_mips is not set +# CT_ARCH_nios2 is not set +# CT_ARCH_powerpc is not set +# CT_ARCH_s390 is not set +# CT_ARCH_sh is not set +# CT_ARCH_sparc is not set +# CT_ARCH_x86 is not set +# CT_ARCH_xtensa is not set +CT_ARCH_alpha_AVAILABLE=y +CT_ARCH_arm_AVAILABLE=y +CT_ARCH_avr_AVAILABLE=y +CT_ARCH_m68k_AVAILABLE=y +CT_ARCH_microblaze_AVAILABLE=y +CT_ARCH_mips_AVAILABLE=y +CT_ARCH_nios2_AVAILABLE=y +CT_ARCH_powerpc_AVAILABLE=y +CT_ARCH_s390_AVAILABLE=y +CT_ARCH_sh_AVAILABLE=y +CT_ARCH_sparc_AVAILABLE=y +CT_ARCH_x86_AVAILABLE=y +CT_ARCH_xtensa_AVAILABLE=y +CT_ARCH_SUFFIX="" + +# +# Generic target options +# +# CT_MULTILIB is not set +CT_ARCH_USE_MMU=y +CT_ARCH_ENDIAN="little" + +# +# Target optimisations +# +CT_ARCH_EXCLUSIVE_WITH_CPU=y +# CT_ARCH_FLOAT_AUTO is not set +# CT_ARCH_FLOAT_SOFTFP is not set +CT_ARCH_FLOAT="hard" + +# +# arm other options +# +CT_ARCH_ARM_MODE="arm" +CT_ARCH_ARM_MODE_ARM=y +# CT_ARCH_ARM_MODE_THUMB is not set +# CT_ARCH_ARM_INTERWORKING is not set +CT_ARCH_ARM_EABI_FORCE=y +CT_ARCH_ARM_EABI=y +CT_ARCH_ARM_TUPLE_USE_EABIHF=y + +# +# Toolchain options +# + +# +# General toolchain options +# +CT_FORCE_SYSROOT=y +CT_USE_SYSROOT=y +CT_SYSROOT_NAME="sysroot" +CT_SYSROOT_DIR_PREFIX="" +CT_WANTS_STATIC_LINK=y +# CT_STATIC_TOOLCHAIN is not set +CT_TOOLCHAIN_PKGVERSION="" +CT_TOOLCHAIN_BUGURL="" + +# +# Tuple completion and aliasing +# +CT_TARGET_VENDOR="unknown" +CT_TARGET_ALIAS_SED_EXPR="" +CT_TARGET_ALIAS="" + +# +# Toolchain type +# +CT_CROSS=y +# CT_CANADIAN is not set +CT_TOOLCHAIN_TYPE="cross" + +# +# Build system +# +CT_BUILD="" +CT_BUILD_PREFIX="" +CT_BUILD_SUFFIX="" + +# +# Misc options +# +# CT_TOOLCHAIN_ENABLE_NLS is not set + +# +# Operating System +# +CT_KERNEL_SUPPORTS_SHARED_LIBS=y +CT_KERNEL="linux" +CT_KERNEL_VERSION="3.2.72" +# CT_KERNEL_bare_metal is not set +CT_KERNEL_linux=y +CT_KERNEL_bare_metal_AVAILABLE=y +CT_KERNEL_linux_AVAILABLE=y +# CT_KERNEL_V_4_3 is not set +# CT_KERNEL_V_4_2 is not set +# CT_KERNEL_V_4_1 is not set +# CT_KERNEL_V_3_18 is not set +# CT_KERNEL_V_3_14 is not set +# CT_KERNEL_V_3_12 is not set +# CT_KERNEL_V_3_10 is not set +# CT_KERNEL_V_3_4 is not set +CT_KERNEL_V_3_2=y +# CT_KERNEL_V_2_6_32 is not set +# CT_KERNEL_LINUX_CUSTOM is not set +CT_KERNEL_windows_AVAILABLE=y + +# +# Common kernel options +# +CT_SHARED_LIBS=y + +# +# linux other options +# +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y + +# +# Binary utilities +# +CT_ARCH_BINFMT_ELF=y +CT_BINUTILS="binutils" +CT_BINUTILS_binutils=y + +# +# GNU binutils +# +# CT_CC_BINUTILS_SHOW_LINARO is not set +CT_BINUTILS_V_2_25_1=y +# CT_BINUTILS_V_2_25 is not set +# CT_BINUTILS_V_2_24 is not set +# CT_BINUTILS_V_2_23_2 is not set +# CT_BINUTILS_V_2_23_1 is not set +# CT_BINUTILS_V_2_22 is not set +# CT_BINUTILS_V_2_21_53 is not set +# CT_BINUTILS_V_2_21_1a is not set +# CT_BINUTILS_V_2_20_1a is not set +# CT_BINUTILS_V_2_19_1a is not set +# CT_BINUTILS_V_2_18a is not set +CT_BINUTILS_VERSION="2.25.1" +CT_BINUTILS_2_25_1_or_later=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_2_24_or_later=y +CT_BINUTILS_2_23_or_later=y +CT_BINUTILS_2_22_or_later=y +CT_BINUTILS_2_21_or_later=y +CT_BINUTILS_2_20_or_later=y +CT_BINUTILS_2_19_or_later=y +CT_BINUTILS_2_18_or_later=y +CT_BINUTILS_HAS_HASH_STYLE=y +CT_BINUTILS_HAS_GOLD=y +CT_BINUTILS_GOLD_SUPPORTS_ARCH=y +CT_BINUTILS_GOLD_SUPPORT=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_LINKER_LD=y +# CT_BINUTILS_LINKER_LD_GOLD is not set +# CT_BINUTILS_LINKER_GOLD_LD is not set +CT_BINUTILS_LINKERS_LIST="ld" +CT_BINUTILS_LINKER_DEFAULT="bfd" +# CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_EXTRA_CONFIG_ARRAY="" +# CT_BINUTILS_FOR_TARGET is not set + +# +# binutils other options +# + +# +# C-library +# +CT_LIBC="glibc" +CT_LIBC_VERSION="2.16.0" +CT_LIBC_glibc=y +# CT_LIBC_musl is not set +# CT_LIBC_uClibc is not set +CT_LIBC_avr_libc_AVAILABLE=y +CT_LIBC_glibc_AVAILABLE=y +CT_THREADS="nptl" +# CT_CC_GLIBC_SHOW_LINARO is not set +# CT_LIBC_GLIBC_V_2_22 is not set +# CT_LIBC_GLIBC_V_2_21 is not set +# CT_LIBC_GLIBC_V_2_20 is not set +# CT_LIBC_GLIBC_V_2_19 is not set +# CT_LIBC_GLIBC_V_2_18 is not set +# CT_LIBC_GLIBC_V_2_17 is not set +CT_LIBC_GLIBC_V_2_16_0=y +# CT_LIBC_GLIBC_V_2_15 is not set +# CT_LIBC_GLIBC_V_2_14_1 is not set +# CT_LIBC_GLIBC_V_2_14 is not set +# CT_LIBC_GLIBC_V_2_13 is not set +# CT_LIBC_GLIBC_V_2_12_2 is not set +# CT_LIBC_GLIBC_V_2_12_1 is not set +# CT_LIBC_GLIBC_V_2_11_1 is not set +# CT_LIBC_GLIBC_V_2_11 is not set +# CT_LIBC_GLIBC_V_2_10_1 is not set +# CT_LIBC_GLIBC_V_2_9 is not set +# CT_LIBC_GLIBC_V_2_8 is not set +CT_LIBC_mingw_AVAILABLE=y +CT_LIBC_musl_AVAILABLE=y +CT_LIBC_newlib_AVAILABLE=y +CT_LIBC_none_AVAILABLE=y +CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_SUPPORT_THREADS_ANY=y +CT_LIBC_SUPPORT_THREADS_NATIVE=y + +# +# Common C library options +# +CT_THREADS_NATIVE=y +CT_LIBC_XLDD=y + +# +# glibc other options +# +CT_LIBC_GLIBC_PORTS_EXTERNAL=y +CT_LIBC_GLIBC_MAY_FORCE_PORTS=y +CT_LIBC_glibc_familly=y +CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_LIBC_GLIBC_CONFIGPARMS="" +CT_LIBC_GLIBC_EXTRA_CFLAGS="" +CT_LIBC_EXTRA_CC_ARGS="" +# CT_LIBC_DISABLE_VERSIONING is not set +CT_LIBC_OLDEST_ABI="" +CT_LIBC_GLIBC_FORCE_UNWIND=y +CT_LIBC_GLIBC_USE_PORTS=y +CT_LIBC_ADDONS_LIST="" + +# +# WARNING !!! +# + +# +# For glibc >= 2.8, it can happen that the tarballs +# + +# +# for the addons are not available for download. +# + +# +# If that happens, bad luck... Try a previous version +# + +# +# or try again later... :-( +# +# CT_LIBC_LOCALES is not set +# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set +CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_LIBC_GLIBC_MIN_KERNEL="3.2.72" + +# +# C compiler +# +CT_CC="gcc" +CT_CC_CORE_PASSES_NEEDED=y +CT_CC_CORE_PASS_1_NEEDED=y +CT_CC_CORE_PASS_2_NEEDED=y +CT_CC_gcc=y +# CT_CC_GCC_SHOW_LINARO is not set +# CT_CC_GCC_V_5_2_0 is not set +CT_CC_GCC_V_4_9_3=y +# CT_CC_GCC_V_4_8_5 is not set +# CT_CC_GCC_V_4_7_4 is not set +# CT_CC_GCC_V_4_6_4 is not set +# CT_CC_GCC_V_4_5_4 is not set +# CT_CC_GCC_V_4_4_7 is not set +# CT_CC_GCC_V_4_3_6 is not set +# CT_CC_GCC_V_4_2_4 is not set +CT_CC_GCC_4_2_or_later=y +CT_CC_GCC_4_3_or_later=y +CT_CC_GCC_4_4_or_later=y +CT_CC_GCC_4_5_or_later=y +CT_CC_GCC_4_6_or_later=y +CT_CC_GCC_4_7_or_later=y +CT_CC_GCC_4_8_or_later=y +CT_CC_GCC_4_9=y +CT_CC_GCC_4_9_or_later=y +CT_CC_GCC_HAS_GRAPHITE=y +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_HAS_LTO=y +CT_CC_GCC_USE_LTO=y +CT_CC_GCC_HAS_PKGVERSION_BUGURL=y +CT_CC_GCC_HAS_BUILD_ID=y +CT_CC_GCC_HAS_LNK_HASH_STYLE=y +CT_CC_GCC_USE_GMP_MPFR=y +CT_CC_GCC_USE_MPC=y +CT_CC_GCC_HAS_LIBQUADMATH=y +CT_CC_GCC_HAS_LIBSANITIZER=y +CT_CC_GCC_VERSION="4.9.3" +# CT_CC_LANG_FORTRAN is not set +CT_CC_GCC_ENABLE_CXX_FLAGS="" +CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_ENV_ARRAY="" +CT_CC_GCC_STATIC_LIBSTDCXX=y +# CT_CC_GCC_SYSTEM_ZLIB is not set + +# +# Optimisation features +# + +# +# Settings for libraries running on target +# +CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y +# CT_CC_GCC_LIBMUDFLAP is not set +# CT_CC_GCC_LIBGOMP is not set +# CT_CC_GCC_LIBSSP is not set +# CT_CC_GCC_LIBQUADMATH is not set +# CT_CC_GCC_LIBSANITIZER is not set + +# +# Misc. obscure options. +# +CT_CC_CXA_ATEXIT=y +# CT_CC_GCC_DISABLE_PCH is not set +CT_CC_GCC_SJLJ_EXCEPTIONS=m +CT_CC_GCC_LDBL_128=m +# CT_CC_GCC_BUILD_ID is not set +CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y +# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set +# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set +# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set +CT_CC_GCC_LNK_HASH_STYLE="" +CT_CC_GCC_DEC_FLOAT_AUTO=y +# CT_CC_GCC_DEC_FLOAT_BID is not set +# CT_CC_GCC_DEC_FLOAT_DPD is not set +# CT_CC_GCC_DEC_FLOATS_NO is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_JAVA=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y + +# +# Additional supported languages: +# +CT_CC_LANG_CXX=y +# CT_CC_LANG_JAVA is not set + +# +# Debug facilities +# +# CT_DEBUG_dmalloc is not set +# CT_DEBUG_duma is not set +# CT_DEBUG_gdb is not set +# CT_DEBUG_ltrace is not set +# CT_DEBUG_strace is not set + +# +# Companion libraries +# +CT_COMPLIBS_NEEDED=y +CT_LIBICONV_NEEDED=y +CT_GETTEXT_NEEDED=y +CT_GMP_NEEDED=y +CT_MPFR_NEEDED=y +CT_ISL_NEEDED=y +CT_CLOOG_NEEDED=y +CT_MPC_NEEDED=y +CT_COMPLIBS=y +CT_LIBICONV=y +CT_GETTEXT=y +CT_GMP=y +CT_MPFR=y +CT_ISL=y +CT_CLOOG=y +CT_MPC=y +CT_LIBICONV_V_1_14=y +CT_LIBICONV_VERSION="1.14" +CT_GETTEXT_V_0_19_6=y +CT_GETTEXT_VERSION="0.19.6" +CT_GMP_V_6_0_0=y +# CT_GMP_V_5_1_3 is not set +# CT_GMP_V_5_1_1 is not set +# CT_GMP_V_5_0_2 is not set +# CT_GMP_V_5_0_1 is not set +# CT_GMP_V_4_3_2 is not set +# CT_GMP_V_4_3_1 is not set +# CT_GMP_V_4_3_0 is not set +CT_GMP_5_0_2_or_later=y +CT_GMP_VERSION="6.0.0a" +CT_MPFR_V_3_1_3=y +# CT_MPFR_V_3_1_2 is not set +# CT_MPFR_V_3_1_0 is not set +# CT_MPFR_V_3_0_1 is not set +# CT_MPFR_V_3_0_0 is not set +# CT_MPFR_V_2_4_2 is not set +# CT_MPFR_V_2_4_1 is not set +# CT_MPFR_V_2_4_0 is not set +CT_MPFR_VERSION="3.1.3" +CT_ISL_V_0_14=y +CT_ISL_V_0_14_or_later=y +CT_ISL_V_0_12_or_later=y +CT_ISL_VERSION="0.14" +CT_CLOOG_V_0_18_4=y +# CT_CLOOG_V_0_18_1 is not set +# CT_CLOOG_V_0_18_0 is not set +CT_CLOOG_VERSION="0.18.4" +CT_CLOOG_0_18_4_or_later=y +CT_CLOOG_0_18_or_later=y +CT_MPC_V_1_0_3=y +# CT_MPC_V_1_0_2 is not set +# CT_MPC_V_1_0_1 is not set +# CT_MPC_V_1_0 is not set +# CT_MPC_V_0_9 is not set +# CT_MPC_V_0_8_2 is not set +# CT_MPC_V_0_8_1 is not set +# CT_MPC_V_0_7 is not set +CT_MPC_VERSION="1.0.3" + +# +# Companion libraries common options +# +# CT_COMPLIBS_CHECK is not set + +# +# Companion tools +# + +# +# READ HELP before you say 'Y' below !!! +# +# CT_COMP_TOOLS is not set diff --git a/src/ci/docker/dist-arm-linux/build-toolchains.sh b/src/ci/docker/dist-arm-linux/build-toolchains.sh new file mode 100755 index 0000000000..ed1406bd7c --- /dev/null +++ b/src/ci/docker/dist-arm-linux/build-toolchains.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# 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. + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + rm /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} + +mkdir build +cd build +cp ../arm-linux-gnueabi.config .config +ct-ng oldconfig +hide_output ct-ng build +cd .. +rm -rf build + +mkdir build +cd build +cp ../arm-linux-gnueabihf.config .config +ct-ng oldconfig +hide_output ct-ng build +cd .. +rm -rf build diff --git a/src/ci/docker/dist-armv7-aarch64-linux/Dockerfile b/src/ci/docker/dist-armv7-aarch64-linux/Dockerfile new file mode 100644 index 0000000000..f26885bbb5 --- /dev/null +++ b/src/ci/docker/dist-armv7-aarch64-linux/Dockerfile @@ -0,0 +1,81 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + automake \ + bison \ + bzip2 \ + ca-certificates \ + cmake \ + curl \ + file \ + flex \ + g++ \ + gawk \ + gdb \ + git \ + gperf \ + help2man \ + libncurses-dev \ + libtool-bin \ + make \ + patch \ + python2.7 \ + sudo \ + texinfo \ + wget \ + xz-utils + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# toolchains we build below chokes on that, so go back to make 3 +RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ + cd make-3.81 && \ + ./configure --prefix=/usr && \ + make && \ + make install && \ + cd .. && \ + rm -rf make-3.81 + +RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ + tar xjf - && \ + cd crosstool-ng && \ + ./configure --prefix=/usr/local && \ + make -j$(nproc) && \ + make install && \ + cd .. && \ + rm -rf crosstool-ng + +RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild +RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +USER rustbuild +WORKDIR /tmp + +COPY armv7-linux-gnueabihf.config /tmp/ +COPY armv7-linux-gnueabihf.config aarch64-linux-gnu.config build-toolchains.sh /tmp/ +RUN ./build-toolchains.sh + +USER root + +ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin +ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin + +ENV CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-gcc \ + AR_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-ar \ + CXX_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-g++ \ + CC_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-gcc \ + AR_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-ar \ + CXX_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-g++ + +ENV HOSTS=armv7-unknown-linux-gnueabihf +ENV HOSTS=$HOSTS,aarch64-unknown-linux-gnu + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-armv7-aarch64-linux/aarch64-linux-gnu.config b/src/ci/docker/dist-armv7-aarch64-linux/aarch64-linux-gnu.config new file mode 100644 index 0000000000..3d30ee4902 --- /dev/null +++ b/src/ci/docker/dist-armv7-aarch64-linux/aarch64-linux-gnu.config @@ -0,0 +1,551 @@ +# +# Automatically generated file; DO NOT EDIT. +# Crosstool-NG Configuration +# +CT_CONFIGURE_has_make381=y +CT_CONFIGURE_has_xz=y +CT_MODULES=y + +# +# Paths and misc options +# + +# +# crosstool-NG behavior +# +# CT_OBSOLETE is not set +# CT_EXPERIMENTAL is not set +# CT_DEBUG_CT is not set + +# +# Paths +# +CT_LOCAL_TARBALLS_DIR="" +CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_INSTALL_DIR="${CT_PREFIX_DIR}" +CT_RM_RF_PREFIX_DIR=y +CT_REMOVE_DOCS=y +CT_INSTALL_DIR_RO=y +CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y +# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set + +# +# Downloading +# +# CT_FORBID_DOWNLOAD is not set +# CT_FORCE_DOWNLOAD is not set +CT_CONNECT_TIMEOUT=10 +# CT_ONLY_DOWNLOAD is not set +# CT_USE_MIRROR is not set + +# +# Extracting +# +# CT_FORCE_EXTRACT is not set +CT_OVERIDE_CONFIG_GUESS_SUB=y +# CT_ONLY_EXTRACT is not set +CT_PATCH_BUNDLED=y +# CT_PATCH_LOCAL is not set +# CT_PATCH_BUNDLED_LOCAL is not set +# CT_PATCH_LOCAL_BUNDLED is not set +# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set +# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set +# CT_PATCH_NONE is not set +CT_PATCH_ORDER="bundled" + +# +# Build behavior +# +CT_PARALLEL_JOBS=0 +CT_LOAD="" +CT_USE_PIPES=y +CT_EXTRA_CFLAGS_FOR_BUILD="" +CT_EXTRA_LDFLAGS_FOR_BUILD="" +CT_EXTRA_CFLAGS_FOR_HOST="" +CT_EXTRA_LDFLAGS_FOR_HOST="" +# CT_CONFIG_SHELL_SH is not set +# CT_CONFIG_SHELL_ASH is not set +CT_CONFIG_SHELL_BASH=y +# CT_CONFIG_SHELL_CUSTOM is not set +CT_CONFIG_SHELL="${bash}" + +# +# Logging +# +# CT_LOG_ERROR is not set +# CT_LOG_WARN is not set +CT_LOG_INFO=y +# CT_LOG_EXTRA is not set +# CT_LOG_ALL is not set +# CT_LOG_DEBUG is not set +CT_LOG_LEVEL_MAX="INFO" +# CT_LOG_SEE_TOOLS_WARN is not set +CT_LOG_PROGRESS_BAR=y +CT_LOG_TO_FILE=y +CT_LOG_FILE_COMPRESS=y + +# +# Target options +# +CT_ARCH="arm" +CT_ARCH_SUPPORTS_BOTH_MMU=y +CT_ARCH_SUPPORTS_BOTH_ENDIAN=y +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_SUPPORTS_WITH_ARCH=y +CT_ARCH_SUPPORTS_WITH_CPU=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_DEFAULT_HAS_MMU=y +CT_ARCH_DEFAULT_LE=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_ARCH="" +CT_ARCH_CPU="" +CT_ARCH_TUNE="" +# CT_ARCH_BE is not set +CT_ARCH_LE=y +# CT_ARCH_32 is not set +CT_ARCH_64=y +CT_ARCH_BITNESS=64 +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" +# CT_ARCH_alpha is not set +CT_ARCH_arm=y +# CT_ARCH_avr is not set +# CT_ARCH_m68k is not set +# CT_ARCH_mips is not set +# CT_ARCH_nios2 is not set +# CT_ARCH_powerpc is not set +# CT_ARCH_s390 is not set +# CT_ARCH_sh is not set +# CT_ARCH_sparc is not set +# CT_ARCH_x86 is not set +# CT_ARCH_xtensa is not set +CT_ARCH_alpha_AVAILABLE=y +CT_ARCH_arm_AVAILABLE=y +CT_ARCH_avr_AVAILABLE=y +CT_ARCH_m68k_AVAILABLE=y +CT_ARCH_microblaze_AVAILABLE=y +CT_ARCH_mips_AVAILABLE=y +CT_ARCH_nios2_AVAILABLE=y +CT_ARCH_powerpc_AVAILABLE=y +CT_ARCH_s390_AVAILABLE=y +CT_ARCH_sh_AVAILABLE=y +CT_ARCH_sparc_AVAILABLE=y +CT_ARCH_x86_AVAILABLE=y +CT_ARCH_xtensa_AVAILABLE=y +CT_ARCH_SUFFIX="" + +# +# Generic target options +# +# CT_MULTILIB is not set +CT_ARCH_USE_MMU=y +CT_ARCH_ENDIAN="little" + +# +# Target optimisations +# +CT_ARCH_EXCLUSIVE_WITH_CPU=y +CT_ARCH_FLOAT="" + +# +# arm other options +# +CT_ARCH_ARM_MODE="arm" +CT_ARCH_ARM_MODE_ARM=y +# CT_ARCH_ARM_MODE_THUMB is not set +# CT_ARCH_ARM_INTERWORKING is not set +CT_ARCH_ARM_EABI_FORCE=y +CT_ARCH_ARM_EABI=y + +# +# Toolchain options +# + +# +# General toolchain options +# +CT_FORCE_SYSROOT=y +CT_USE_SYSROOT=y +CT_SYSROOT_NAME="sysroot" +CT_SYSROOT_DIR_PREFIX="" +CT_WANTS_STATIC_LINK=y +# CT_STATIC_TOOLCHAIN is not set +CT_TOOLCHAIN_PKGVERSION="" +CT_TOOLCHAIN_BUGURL="" + +# +# Tuple completion and aliasing +# +CT_TARGET_VENDOR="unknown" +CT_TARGET_ALIAS_SED_EXPR="" +CT_TARGET_ALIAS="" + +# +# Toolchain type +# +CT_CROSS=y +# CT_CANADIAN is not set +CT_TOOLCHAIN_TYPE="cross" + +# +# Build system +# +CT_BUILD="" +CT_BUILD_PREFIX="" +CT_BUILD_SUFFIX="" + +# +# Misc options +# +# CT_TOOLCHAIN_ENABLE_NLS is not set + +# +# Operating System +# +CT_KERNEL_SUPPORTS_SHARED_LIBS=y +CT_KERNEL="linux" +CT_KERNEL_VERSION="4.2.6" +# CT_KERNEL_bare_metal is not set +CT_KERNEL_linux=y +CT_KERNEL_bare_metal_AVAILABLE=y +CT_KERNEL_linux_AVAILABLE=y +# CT_KERNEL_V_4_3 is not set +CT_KERNEL_V_4_2=y +# CT_KERNEL_V_4_1 is not set +# CT_KERNEL_V_3_18 is not set +# CT_KERNEL_V_3_14 is not set +# CT_KERNEL_V_3_12 is not set +# CT_KERNEL_V_3_10 is not set +# CT_KERNEL_V_3_4 is not set +# CT_KERNEL_V_3_2 is not set +# CT_KERNEL_V_2_6_32 is not set +# CT_KERNEL_LINUX_CUSTOM is not set +CT_KERNEL_windows_AVAILABLE=y + +# +# Common kernel options +# +CT_SHARED_LIBS=y + +# +# linux other options +# +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y + +# +# Binary utilities +# +CT_ARCH_BINFMT_ELF=y +CT_BINUTILS="binutils" +CT_BINUTILS_binutils=y + +# +# GNU binutils +# +# CT_CC_BINUTILS_SHOW_LINARO is not set +CT_BINUTILS_V_2_25_1=y +# CT_BINUTILS_V_2_25 is not set +# CT_BINUTILS_V_2_24 is not set +# CT_BINUTILS_V_2_23_2 is not set +# CT_BINUTILS_V_2_23_1 is not set +# CT_BINUTILS_V_2_22 is not set +# CT_BINUTILS_V_2_21_53 is not set +# CT_BINUTILS_V_2_21_1a is not set +# CT_BINUTILS_V_2_20_1a is not set +# CT_BINUTILS_V_2_19_1a is not set +# CT_BINUTILS_V_2_18a is not set +CT_BINUTILS_VERSION="2.25.1" +CT_BINUTILS_2_25_1_or_later=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_2_24_or_later=y +CT_BINUTILS_2_23_or_later=y +CT_BINUTILS_2_22_or_later=y +CT_BINUTILS_2_21_or_later=y +CT_BINUTILS_2_20_or_later=y +CT_BINUTILS_2_19_or_later=y +CT_BINUTILS_2_18_or_later=y +CT_BINUTILS_HAS_HASH_STYLE=y +CT_BINUTILS_HAS_GOLD=y +CT_BINUTILS_GOLD_SUPPORTS_ARCH=y +CT_BINUTILS_GOLD_SUPPORT=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_LINKER_LD=y +# CT_BINUTILS_LINKER_LD_GOLD is not set +# CT_BINUTILS_LINKER_GOLD_LD is not set +CT_BINUTILS_LINKERS_LIST="ld" +CT_BINUTILS_LINKER_DEFAULT="bfd" +# CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_EXTRA_CONFIG_ARRAY="" +# CT_BINUTILS_FOR_TARGET is not set + +# +# binutils other options +# + +# +# C-library +# +CT_LIBC="glibc" +CT_LIBC_VERSION="2.17" +CT_LIBC_glibc=y +# CT_LIBC_musl is not set +# CT_LIBC_uClibc is not set +CT_LIBC_avr_libc_AVAILABLE=y +CT_LIBC_glibc_AVAILABLE=y +CT_THREADS="nptl" +# CT_CC_GLIBC_SHOW_LINARO is not set +# CT_LIBC_GLIBC_V_2_22 is not set +# CT_LIBC_GLIBC_V_2_21 is not set +# CT_LIBC_GLIBC_V_2_20 is not set +# CT_LIBC_GLIBC_V_2_19 is not set +# CT_LIBC_GLIBC_V_2_18 is not set +CT_LIBC_GLIBC_V_2_17=y +# CT_LIBC_GLIBC_V_2_16_0 is not set +# CT_LIBC_GLIBC_V_2_15 is not set +# CT_LIBC_GLIBC_V_2_14_1 is not set +# CT_LIBC_GLIBC_V_2_14 is not set +# CT_LIBC_GLIBC_V_2_13 is not set +# CT_LIBC_GLIBC_V_2_12_2 is not set +# CT_LIBC_GLIBC_V_2_12_1 is not set +# CT_LIBC_GLIBC_V_2_11_1 is not set +# CT_LIBC_GLIBC_V_2_11 is not set +# CT_LIBC_GLIBC_V_2_10_1 is not set +# CT_LIBC_GLIBC_V_2_9 is not set +# CT_LIBC_GLIBC_V_2_8 is not set +CT_LIBC_GLIBC_2_17_or_later=y +CT_LIBC_mingw_AVAILABLE=y +CT_LIBC_musl_AVAILABLE=y +CT_LIBC_newlib_AVAILABLE=y +CT_LIBC_none_AVAILABLE=y +CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_SUPPORT_THREADS_ANY=y +CT_LIBC_SUPPORT_THREADS_NATIVE=y + +# +# Common C library options +# +CT_THREADS_NATIVE=y +CT_LIBC_XLDD=y + +# +# glibc other options +# +# CT_LIBC_GLIBC_PORTS_EXTERNAL is not set +CT_LIBC_GLIBC_MAY_FORCE_PORTS=y +CT_LIBC_glibc_familly=y +CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_LIBC_GLIBC_CONFIGPARMS="" +CT_LIBC_GLIBC_EXTRA_CFLAGS="" +CT_LIBC_EXTRA_CC_ARGS="" +# CT_LIBC_DISABLE_VERSIONING is not set +CT_LIBC_OLDEST_ABI="" +CT_LIBC_GLIBC_FORCE_UNWIND=y +CT_LIBC_GLIBC_USE_PORTS=y +CT_LIBC_ADDONS_LIST="" + +# +# WARNING !!! +# + +# +# For glibc >= 2.8, it can happen that the tarballs +# + +# +# for the addons are not available for download. +# + +# +# If that happens, bad luck... Try a previous version +# + +# +# or try again later... :-( +# +# CT_LIBC_LOCALES is not set +# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set +CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_LIBC_GLIBC_MIN_KERNEL="4.2.6" + +# +# C compiler +# +CT_CC="gcc" +CT_CC_CORE_PASSES_NEEDED=y +CT_CC_CORE_PASS_1_NEEDED=y +CT_CC_CORE_PASS_2_NEEDED=y +CT_CC_gcc=y +# CT_CC_GCC_SHOW_LINARO is not set +CT_CC_GCC_V_5_2_0=y +# CT_CC_GCC_V_4_9_3 is not set +# CT_CC_GCC_V_4_8_5 is not set +# CT_CC_GCC_V_4_7_4 is not set +# CT_CC_GCC_V_4_6_4 is not set +# CT_CC_GCC_V_4_5_4 is not set +# CT_CC_GCC_V_4_4_7 is not set +# CT_CC_GCC_V_4_3_6 is not set +# CT_CC_GCC_V_4_2_4 is not set +CT_CC_GCC_4_2_or_later=y +CT_CC_GCC_4_3_or_later=y +CT_CC_GCC_4_4_or_later=y +CT_CC_GCC_4_5_or_later=y +CT_CC_GCC_4_6_or_later=y +CT_CC_GCC_4_7_or_later=y +CT_CC_GCC_4_8_or_later=y +CT_CC_GCC_4_9_or_later=y +CT_CC_GCC_5=y +CT_CC_GCC_5_or_later=y +CT_CC_GCC_HAS_GRAPHITE=y +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_HAS_LTO=y +CT_CC_GCC_USE_LTO=y +CT_CC_GCC_HAS_PKGVERSION_BUGURL=y +CT_CC_GCC_HAS_BUILD_ID=y +CT_CC_GCC_HAS_LNK_HASH_STYLE=y +CT_CC_GCC_USE_GMP_MPFR=y +CT_CC_GCC_USE_MPC=y +CT_CC_GCC_HAS_LIBQUADMATH=y +CT_CC_GCC_HAS_LIBSANITIZER=y +CT_CC_GCC_VERSION="5.2.0" +# CT_CC_LANG_FORTRAN is not set +CT_CC_GCC_ENABLE_CXX_FLAGS="" +CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_ENV_ARRAY="" +CT_CC_GCC_STATIC_LIBSTDCXX=y +# CT_CC_GCC_SYSTEM_ZLIB is not set + +# +# Optimisation features +# + +# +# Settings for libraries running on target +# +CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y +# CT_CC_GCC_LIBMUDFLAP is not set +# CT_CC_GCC_LIBGOMP is not set +# CT_CC_GCC_LIBSSP is not set +# CT_CC_GCC_LIBQUADMATH is not set +# CT_CC_GCC_LIBSANITIZER is not set + +# +# Misc. obscure options. +# +CT_CC_CXA_ATEXIT=y +# CT_CC_GCC_DISABLE_PCH is not set +CT_CC_GCC_SJLJ_EXCEPTIONS=m +CT_CC_GCC_LDBL_128=m +# CT_CC_GCC_BUILD_ID is not set +CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y +# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set +# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set +# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set +CT_CC_GCC_LNK_HASH_STYLE="" +CT_CC_GCC_DEC_FLOAT_AUTO=y +# CT_CC_GCC_DEC_FLOAT_BID is not set +# CT_CC_GCC_DEC_FLOAT_DPD is not set +# CT_CC_GCC_DEC_FLOATS_NO is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_JAVA=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y + +# +# Additional supported languages: +# +CT_CC_LANG_CXX=y +# CT_CC_LANG_JAVA is not set + +# +# Debug facilities +# +# CT_DEBUG_dmalloc is not set +# CT_DEBUG_duma is not set +# CT_DEBUG_gdb is not set +# CT_DEBUG_ltrace is not set +# CT_DEBUG_strace is not set + +# +# Companion libraries +# +CT_COMPLIBS_NEEDED=y +CT_LIBICONV_NEEDED=y +CT_GETTEXT_NEEDED=y +CT_GMP_NEEDED=y +CT_MPFR_NEEDED=y +CT_ISL_NEEDED=y +CT_MPC_NEEDED=y +CT_COMPLIBS=y +CT_LIBICONV=y +CT_GETTEXT=y +CT_GMP=y +CT_MPFR=y +CT_ISL=y +CT_MPC=y +CT_LIBICONV_V_1_14=y +CT_LIBICONV_VERSION="1.14" +CT_GETTEXT_V_0_19_6=y +CT_GETTEXT_VERSION="0.19.6" +CT_GMP_V_6_0_0=y +# CT_GMP_V_5_1_3 is not set +# CT_GMP_V_5_1_1 is not set +# CT_GMP_V_5_0_2 is not set +# CT_GMP_V_5_0_1 is not set +# CT_GMP_V_4_3_2 is not set +# CT_GMP_V_4_3_1 is not set +# CT_GMP_V_4_3_0 is not set +CT_GMP_5_0_2_or_later=y +CT_GMP_VERSION="6.0.0a" +CT_MPFR_V_3_1_3=y +# CT_MPFR_V_3_1_2 is not set +# CT_MPFR_V_3_1_0 is not set +# CT_MPFR_V_3_0_1 is not set +# CT_MPFR_V_3_0_0 is not set +# CT_MPFR_V_2_4_2 is not set +# CT_MPFR_V_2_4_1 is not set +# CT_MPFR_V_2_4_0 is not set +CT_MPFR_VERSION="3.1.3" +CT_ISL_V_0_14=y +# CT_ISL_V_0_12_2 is not set +CT_ISL_V_0_14_or_later=y +CT_ISL_V_0_12_or_later=y +CT_ISL_VERSION="0.14" +# CT_CLOOG_V_0_18_4 is not set +# CT_CLOOG_V_0_18_1 is not set +# CT_CLOOG_V_0_18_0 is not set +CT_MPC_V_1_0_3=y +# CT_MPC_V_1_0_2 is not set +# CT_MPC_V_1_0_1 is not set +# CT_MPC_V_1_0 is not set +# CT_MPC_V_0_9 is not set +# CT_MPC_V_0_8_2 is not set +# CT_MPC_V_0_8_1 is not set +# CT_MPC_V_0_7 is not set +CT_MPC_VERSION="1.0.3" + +# +# Companion libraries common options +# +# CT_COMPLIBS_CHECK is not set + +# +# Companion tools +# + +# +# READ HELP before you say 'Y' below !!! +# +# CT_COMP_TOOLS is not set diff --git a/src/ci/docker/dist-armv7-aarch64-linux/armv7-linux-gnueabihf.config b/src/ci/docker/dist-armv7-aarch64-linux/armv7-linux-gnueabihf.config new file mode 100644 index 0000000000..79d6c77c41 --- /dev/null +++ b/src/ci/docker/dist-armv7-aarch64-linux/armv7-linux-gnueabihf.config @@ -0,0 +1,569 @@ +# +# Automatically generated file; DO NOT EDIT. +# Crosstool-NG Configuration +# +CT_CONFIGURE_has_make381=y +CT_MODULES=y + +# +# Paths and misc options +# + +# +# crosstool-NG behavior +# +# CT_OBSOLETE is not set +# CT_EXPERIMENTAL is not set +# CT_DEBUG_CT is not set + +# +# Paths +# +CT_LOCAL_TARBALLS_DIR="" +CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_INSTALL_DIR="${CT_PREFIX_DIR}" +CT_RM_RF_PREFIX_DIR=y +CT_REMOVE_DOCS=y +CT_INSTALL_DIR_RO=y +CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y +# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set + +# +# Downloading +# +# CT_FORBID_DOWNLOAD is not set +# CT_FORCE_DOWNLOAD is not set +CT_CONNECT_TIMEOUT=10 +# CT_ONLY_DOWNLOAD is not set +# CT_USE_MIRROR is not set + +# +# Extracting +# +# CT_FORCE_EXTRACT is not set +CT_OVERIDE_CONFIG_GUESS_SUB=y +# CT_ONLY_EXTRACT is not set +CT_PATCH_BUNDLED=y +# CT_PATCH_LOCAL is not set +# CT_PATCH_BUNDLED_LOCAL is not set +# CT_PATCH_LOCAL_BUNDLED is not set +# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set +# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set +# CT_PATCH_NONE is not set +CT_PATCH_ORDER="bundled" + +# +# Build behavior +# +CT_PARALLEL_JOBS=0 +CT_LOAD="" +CT_USE_PIPES=y +CT_EXTRA_CFLAGS_FOR_BUILD="" +CT_EXTRA_LDFLAGS_FOR_BUILD="" +CT_EXTRA_CFLAGS_FOR_HOST="" +CT_EXTRA_LDFLAGS_FOR_HOST="" +# CT_CONFIG_SHELL_SH is not set +# CT_CONFIG_SHELL_ASH is not set +CT_CONFIG_SHELL_BASH=y +# CT_CONFIG_SHELL_CUSTOM is not set +CT_CONFIG_SHELL="${bash}" + +# +# Logging +# +# CT_LOG_ERROR is not set +# CT_LOG_WARN is not set +CT_LOG_INFO=y +# CT_LOG_EXTRA is not set +# CT_LOG_ALL is not set +# CT_LOG_DEBUG is not set +CT_LOG_LEVEL_MAX="INFO" +# CT_LOG_SEE_TOOLS_WARN is not set +CT_LOG_PROGRESS_BAR=y +CT_LOG_TO_FILE=y +CT_LOG_FILE_COMPRESS=y + +# +# Target options +# +CT_ARCH="arm" +CT_ARCH_SUPPORTS_BOTH_MMU=y +CT_ARCH_SUPPORTS_BOTH_ENDIAN=y +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_SUPPORTS_WITH_ARCH=y +CT_ARCH_SUPPORTS_WITH_CPU=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_SUPPORTS_WITH_FLOAT=y +CT_ARCH_SUPPORTS_WITH_FPU=y +CT_ARCH_SUPPORTS_SOFTFP=y +CT_ARCH_DEFAULT_HAS_MMU=y +CT_ARCH_DEFAULT_LE=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_ARCH="armv7-a" +CT_ARCH_CPU="" +CT_ARCH_TUNE="" +CT_ARCH_FPU="vfpv3-d16" +# CT_ARCH_BE is not set +CT_ARCH_LE=y +CT_ARCH_32=y +# CT_ARCH_64 is not set +CT_ARCH_BITNESS=32 +CT_ARCH_FLOAT_HW=y +# CT_ARCH_FLOAT_SW is not set +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" +# CT_ARCH_alpha is not set +CT_ARCH_arm=y +# CT_ARCH_avr is not set +# CT_ARCH_m68k is not set +# CT_ARCH_mips is not set +# CT_ARCH_nios2 is not set +# CT_ARCH_powerpc is not set +# CT_ARCH_s390 is not set +# CT_ARCH_sh is not set +# CT_ARCH_sparc is not set +# CT_ARCH_x86 is not set +# CT_ARCH_xtensa is not set +CT_ARCH_alpha_AVAILABLE=y +CT_ARCH_arm_AVAILABLE=y +CT_ARCH_avr_AVAILABLE=y +CT_ARCH_m68k_AVAILABLE=y +CT_ARCH_microblaze_AVAILABLE=y +CT_ARCH_mips_AVAILABLE=y +CT_ARCH_nios2_AVAILABLE=y +CT_ARCH_powerpc_AVAILABLE=y +CT_ARCH_s390_AVAILABLE=y +CT_ARCH_sh_AVAILABLE=y +CT_ARCH_sparc_AVAILABLE=y +CT_ARCH_x86_AVAILABLE=y +CT_ARCH_xtensa_AVAILABLE=y +CT_ARCH_SUFFIX="v7" + +# +# Generic target options +# +# CT_MULTILIB is not set +CT_ARCH_USE_MMU=y +CT_ARCH_ENDIAN="little" + +# +# Target optimisations +# +CT_ARCH_EXCLUSIVE_WITH_CPU=y +# CT_ARCH_FLOAT_AUTO is not set +# CT_ARCH_FLOAT_SOFTFP is not set +CT_ARCH_FLOAT="hard" +# CT_ARCH_ALPHA_EV4 is not set +# CT_ARCH_ALPHA_EV45 is not set +# CT_ARCH_ALPHA_EV5 is not set +# CT_ARCH_ALPHA_EV56 is not set +# CT_ARCH_ALPHA_EV6 is not set +# CT_ARCH_ALPHA_EV67 is not set + +# +# arm other options +# +CT_ARCH_ARM_MODE="thumb" +# CT_ARCH_ARM_MODE_ARM is not set +CT_ARCH_ARM_MODE_THUMB=y +# CT_ARCH_ARM_INTERWORKING is not set +CT_ARCH_ARM_EABI_FORCE=y +CT_ARCH_ARM_EABI=y +CT_ARCH_ARM_TUPLE_USE_EABIHF=y + +# +# Toolchain options +# + +# +# General toolchain options +# +CT_FORCE_SYSROOT=y +CT_USE_SYSROOT=y +CT_SYSROOT_NAME="sysroot" +CT_SYSROOT_DIR_PREFIX="" +CT_WANTS_STATIC_LINK=y +# CT_STATIC_TOOLCHAIN is not set +CT_TOOLCHAIN_PKGVERSION="" +CT_TOOLCHAIN_BUGURL="" + +# +# Tuple completion and aliasing +# +CT_TARGET_VENDOR="unknown" +CT_TARGET_ALIAS_SED_EXPR="" +CT_TARGET_ALIAS="" + +# +# Toolchain type +# +CT_CROSS=y +# CT_CANADIAN is not set +CT_TOOLCHAIN_TYPE="cross" + +# +# Build system +# +CT_BUILD="" +CT_BUILD_PREFIX="" +CT_BUILD_SUFFIX="" + +# +# Misc options +# +# CT_TOOLCHAIN_ENABLE_NLS is not set + +# +# Operating System +# +CT_KERNEL_SUPPORTS_SHARED_LIBS=y +CT_KERNEL="linux" +CT_KERNEL_VERSION="3.2.72" +# CT_KERNEL_bare_metal is not set +CT_KERNEL_linux=y +CT_KERNEL_bare_metal_AVAILABLE=y +CT_KERNEL_linux_AVAILABLE=y +# CT_KERNEL_V_4_3 is not set +# CT_KERNEL_V_4_2 is not set +# CT_KERNEL_V_4_1 is not set +# CT_KERNEL_V_3_18 is not set +# CT_KERNEL_V_3_14 is not set +# CT_KERNEL_V_3_12 is not set +# CT_KERNEL_V_3_10 is not set +# CT_KERNEL_V_3_4 is not set +CT_KERNEL_V_3_2=y +# CT_KERNEL_V_2_6_32 is not set +# CT_KERNEL_LINUX_CUSTOM is not set +CT_KERNEL_windows_AVAILABLE=y + +# +# Common kernel options +# +CT_SHARED_LIBS=y + +# +# linux other options +# +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y + +# +# Binary utilities +# +CT_ARCH_BINFMT_ELF=y +CT_BINUTILS="binutils" +CT_BINUTILS_binutils=y + +# +# GNU binutils +# +# CT_CC_BINUTILS_SHOW_LINARO is not set +CT_BINUTILS_V_2_25_1=y +# CT_BINUTILS_V_2_25 is not set +# CT_BINUTILS_V_2_24 is not set +# CT_BINUTILS_V_2_23_2 is not set +# CT_BINUTILS_V_2_23_1 is not set +# CT_BINUTILS_V_2_22 is not set +# CT_BINUTILS_V_2_21_53 is not set +# CT_BINUTILS_V_2_21_1a is not set +# CT_BINUTILS_V_2_20_1a is not set +# CT_BINUTILS_V_2_19_1a is not set +# CT_BINUTILS_V_2_18a is not set +CT_BINUTILS_VERSION="2.25.1" +CT_BINUTILS_2_25_1_or_later=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_2_24_or_later=y +CT_BINUTILS_2_23_or_later=y +CT_BINUTILS_2_22_or_later=y +CT_BINUTILS_2_21_or_later=y +CT_BINUTILS_2_20_or_later=y +CT_BINUTILS_2_19_or_later=y +CT_BINUTILS_2_18_or_later=y +CT_BINUTILS_HAS_HASH_STYLE=y +CT_BINUTILS_HAS_GOLD=y +CT_BINUTILS_GOLD_SUPPORTS_ARCH=y +CT_BINUTILS_GOLD_SUPPORT=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_LINKER_LD=y +# CT_BINUTILS_LINKER_LD_GOLD is not set +# CT_BINUTILS_LINKER_GOLD_LD is not set +CT_BINUTILS_LINKERS_LIST="ld" +CT_BINUTILS_LINKER_DEFAULT="bfd" +# CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_EXTRA_CONFIG_ARRAY="" +# CT_BINUTILS_FOR_TARGET is not set + +# +# binutils other options +# + +# +# C-library +# +CT_LIBC="glibc" +CT_LIBC_VERSION="2.16.0" +CT_LIBC_glibc=y +# CT_LIBC_musl is not set +# CT_LIBC_newlib is not set +# CT_LIBC_none is not set +# CT_LIBC_uClibc is not set +CT_LIBC_avr_libc_AVAILABLE=y +CT_LIBC_glibc_AVAILABLE=y +CT_THREADS="nptl" +# CT_CC_GLIBC_SHOW_LINARO is not set +# CT_LIBC_GLIBC_V_2_22 is not set +# CT_LIBC_GLIBC_V_2_21 is not set +# CT_LIBC_GLIBC_V_2_20 is not set +# CT_LIBC_GLIBC_V_2_19 is not set +# CT_LIBC_GLIBC_V_2_18 is not set +# CT_LIBC_GLIBC_V_2_17 is not set +CT_LIBC_GLIBC_V_2_16_0=y +# CT_LIBC_GLIBC_V_2_15 is not set +# CT_LIBC_GLIBC_V_2_14_1 is not set +# CT_LIBC_GLIBC_V_2_14 is not set +# CT_LIBC_GLIBC_V_2_13 is not set +# CT_LIBC_GLIBC_V_2_12_2 is not set +# CT_LIBC_GLIBC_V_2_12_1 is not set +# CT_LIBC_GLIBC_V_2_11_1 is not set +# CT_LIBC_GLIBC_V_2_11 is not set +# CT_LIBC_GLIBC_V_2_10_1 is not set +# CT_LIBC_GLIBC_V_2_9 is not set +# CT_LIBC_GLIBC_V_2_8 is not set +CT_LIBC_mingw_AVAILABLE=y +CT_LIBC_musl_AVAILABLE=y +CT_LIBC_newlib_AVAILABLE=y +CT_LIBC_none_AVAILABLE=y +CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_SUPPORT_THREADS_ANY=y +CT_LIBC_SUPPORT_THREADS_NATIVE=y + +# +# Common C library options +# +CT_THREADS_NATIVE=y +CT_LIBC_XLDD=y + +# +# glibc other options +# +CT_LIBC_GLIBC_PORTS_EXTERNAL=y +CT_LIBC_GLIBC_MAY_FORCE_PORTS=y +CT_LIBC_glibc_familly=y +CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_LIBC_GLIBC_CONFIGPARMS="" +CT_LIBC_GLIBC_EXTRA_CFLAGS="" +CT_LIBC_EXTRA_CC_ARGS="" +# CT_LIBC_DISABLE_VERSIONING is not set +CT_LIBC_OLDEST_ABI="" +CT_LIBC_GLIBC_FORCE_UNWIND=y +CT_LIBC_GLIBC_USE_PORTS=y +CT_LIBC_ADDONS_LIST="" + +# +# WARNING !!! +# + +# +# For glibc >= 2.8, it can happen that the tarballs +# + +# +# for the addons are not available for download. +# + +# +# If that happens, bad luck... Try a previous version +# + +# +# or try again later... :-( +# +# CT_LIBC_LOCALES is not set +# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set +CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_LIBC_GLIBC_MIN_KERNEL="3.2.72" + +# +# C compiler +# +CT_CC="gcc" +CT_CC_CORE_PASSES_NEEDED=y +CT_CC_CORE_PASS_1_NEEDED=y +CT_CC_CORE_PASS_2_NEEDED=y +CT_CC_gcc=y +# CT_CC_GCC_SHOW_LINARO is not set +# CT_CC_GCC_V_5_2_0 is not set +CT_CC_GCC_V_4_9_3=y +# CT_CC_GCC_V_4_8_5 is not set +# CT_CC_GCC_V_4_7_4 is not set +# CT_CC_GCC_V_4_6_4 is not set +# CT_CC_GCC_V_4_5_4 is not set +# CT_CC_GCC_V_4_4_7 is not set +# CT_CC_GCC_V_4_3_6 is not set +# CT_CC_GCC_V_4_2_4 is not set +CT_CC_GCC_4_2_or_later=y +CT_CC_GCC_4_3_or_later=y +CT_CC_GCC_4_4_or_later=y +CT_CC_GCC_4_5_or_later=y +CT_CC_GCC_4_6_or_later=y +CT_CC_GCC_4_7_or_later=y +CT_CC_GCC_4_8_or_later=y +CT_CC_GCC_4_9=y +CT_CC_GCC_4_9_or_later=y +CT_CC_GCC_HAS_GRAPHITE=y +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_HAS_LTO=y +CT_CC_GCC_USE_LTO=y +CT_CC_GCC_HAS_PKGVERSION_BUGURL=y +CT_CC_GCC_HAS_BUILD_ID=y +CT_CC_GCC_HAS_LNK_HASH_STYLE=y +CT_CC_GCC_USE_GMP_MPFR=y +CT_CC_GCC_USE_MPC=y +CT_CC_GCC_HAS_LIBQUADMATH=y +CT_CC_GCC_HAS_LIBSANITIZER=y +CT_CC_GCC_VERSION="4.9.3" +# CT_CC_LANG_FORTRAN is not set +CT_CC_GCC_ENABLE_CXX_FLAGS="" +CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_ENV_ARRAY="" +CT_CC_GCC_STATIC_LIBSTDCXX=y +# CT_CC_GCC_SYSTEM_ZLIB is not set + +# +# Optimisation features +# + +# +# Settings for libraries running on target +# +CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y +# CT_CC_GCC_LIBMUDFLAP is not set +# CT_CC_GCC_LIBGOMP is not set +# CT_CC_GCC_LIBSSP is not set +# CT_CC_GCC_LIBQUADMATH is not set +# CT_CC_GCC_LIBSANITIZER is not set + +# +# Misc. obscure options. +# +CT_CC_CXA_ATEXIT=y +# CT_CC_GCC_DISABLE_PCH is not set +CT_CC_GCC_SJLJ_EXCEPTIONS=m +CT_CC_GCC_LDBL_128=m +# CT_CC_GCC_BUILD_ID is not set +CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y +# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set +# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set +# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set +CT_CC_GCC_LNK_HASH_STYLE="" +CT_CC_GCC_DEC_FLOAT_AUTO=y +# CT_CC_GCC_DEC_FLOAT_BID is not set +# CT_CC_GCC_DEC_FLOAT_DPD is not set +# CT_CC_GCC_DEC_FLOATS_NO is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_JAVA=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y + +# +# Additional supported languages: +# +CT_CC_LANG_CXX=y +# CT_CC_LANG_JAVA is not set + +# +# Debug facilities +# +# CT_DEBUG_dmalloc is not set +# CT_DEBUG_duma is not set +# CT_DEBUG_gdb is not set +# CT_DEBUG_ltrace is not set +# CT_DEBUG_strace is not set + +# +# Companion libraries +# +CT_COMPLIBS_NEEDED=y +CT_LIBICONV_NEEDED=y +CT_GETTEXT_NEEDED=y +CT_GMP_NEEDED=y +CT_MPFR_NEEDED=y +CT_ISL_NEEDED=y +CT_CLOOG_NEEDED=y +CT_MPC_NEEDED=y +CT_COMPLIBS=y +CT_LIBICONV=y +CT_GETTEXT=y +CT_GMP=y +CT_MPFR=y +CT_ISL=y +CT_CLOOG=y +CT_MPC=y +CT_LIBICONV_V_1_14=y +CT_LIBICONV_VERSION="1.14" +CT_GETTEXT_V_0_19_6=y +CT_GETTEXT_VERSION="0.19.6" +CT_GMP_V_6_0_0=y +# CT_GMP_V_5_1_3 is not set +# CT_GMP_V_5_1_1 is not set +# CT_GMP_V_5_0_2 is not set +# CT_GMP_V_5_0_1 is not set +# CT_GMP_V_4_3_2 is not set +# CT_GMP_V_4_3_1 is not set +# CT_GMP_V_4_3_0 is not set +CT_GMP_5_0_2_or_later=y +CT_GMP_VERSION="6.0.0a" +CT_MPFR_V_3_1_3=y +# CT_MPFR_V_3_1_2 is not set +# CT_MPFR_V_3_1_0 is not set +# CT_MPFR_V_3_0_1 is not set +# CT_MPFR_V_3_0_0 is not set +# CT_MPFR_V_2_4_2 is not set +# CT_MPFR_V_2_4_1 is not set +# CT_MPFR_V_2_4_0 is not set +CT_MPFR_VERSION="3.1.3" +CT_ISL_V_0_14=y +CT_ISL_V_0_14_or_later=y +CT_ISL_V_0_12_or_later=y +CT_ISL_VERSION="0.14" +CT_CLOOG_V_0_18_4=y +# CT_CLOOG_V_0_18_1 is not set +# CT_CLOOG_V_0_18_0 is not set +CT_CLOOG_VERSION="0.18.4" +CT_CLOOG_0_18_4_or_later=y +CT_CLOOG_0_18_or_later=y +CT_MPC_V_1_0_3=y +# CT_MPC_V_1_0_2 is not set +# CT_MPC_V_1_0_1 is not set +# CT_MPC_V_1_0 is not set +# CT_MPC_V_0_9 is not set +# CT_MPC_V_0_8_2 is not set +# CT_MPC_V_0_8_1 is not set +# CT_MPC_V_0_7 is not set +CT_MPC_VERSION="1.0.3" + +# +# Companion libraries common options +# +# CT_COMPLIBS_CHECK is not set + +# +# Companion tools +# + +# +# READ HELP before you say 'Y' below !!! +# +# CT_COMP_TOOLS is not set diff --git a/src/ci/docker/dist-armv7-aarch64-linux/build-toolchains.sh b/src/ci/docker/dist-armv7-aarch64-linux/build-toolchains.sh new file mode 100755 index 0000000000..ebd5ef4cfc --- /dev/null +++ b/src/ci/docker/dist-armv7-aarch64-linux/build-toolchains.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# 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. + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + rm /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} + +mkdir build +cd build +cp ../armv7-linux-gnueabihf.config .config +ct-ng oldconfig +hide_output ct-ng build +cd .. +rm -rf build + +mkdir build +cd build +cp ../aarch64-linux-gnu.config .config +ct-ng oldconfig +hide_output ct-ng build +cd .. +rm -rf build diff --git a/src/ci/docker/dist-freebsd/Dockerfile b/src/ci/docker/dist-freebsd/Dockerfile new file mode 100644 index 0000000000..d824c4041c --- /dev/null +++ b/src/ci/docker/dist-freebsd/Dockerfile @@ -0,0 +1,42 @@ +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 \ + bzip2 \ + xz-utils \ + wget + +COPY build-toolchain.sh /tmp/ +RUN /tmp/build-toolchain.sh x86_64 +RUN /tmp/build-toolchain.sh i686 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +ENV \ + AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-ar \ + CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-gcc \ + CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-g++ \ + AR_i686_unknown_freebsd=i686-unknown-freebsd10-ar \ + CC_i686_unknown_freebsd=i686-unknown-freebsd10-gcc \ + CXX_i686_unknown_freebsd=i686-unknown-freebsd10-g++ + +ENV HOSTS=x86_64-unknown-freebsd +ENV HOSTS=$HOSTS,i686-unknown-freebsd + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/x86_64-freebsd/build-toolchain.sh b/src/ci/docker/dist-freebsd/build-toolchain.sh old mode 100644 new mode 100755 similarity index 83% rename from src/ci/docker/x86_64-freebsd/build-toolchain.sh rename to src/ci/docker/dist-freebsd/build-toolchain.sh index d4bc886d50..5642e6fc93 --- a/src/ci/docker/x86_64-freebsd/build-toolchain.sh +++ b/src/ci/docker/dist-freebsd/build-toolchain.sh @@ -11,10 +11,26 @@ set -ex -ARCH=x86_64 +ARCH=$1 BINUTILS=2.25.1 GCC=5.3.0 +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} + mkdir binutils cd binutils @@ -22,10 +38,10 @@ cd binutils curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.bz2 | tar xjf - mkdir binutils-build cd binutils-build -../binutils-$BINUTILS/configure \ +hide_output ../binutils-$BINUTILS/configure \ --target=$ARCH-unknown-freebsd10 -make -j10 -make install +hide_output make -j10 +hide_output make install cd ../.. rm -rf binutils @@ -76,8 +92,8 @@ cd gcc-$GCC mkdir ../gcc-build cd ../gcc-build -../gcc-$GCC/configure \ - --enable-languages=c \ +hide_output ../gcc-$GCC/configure \ + --enable-languages=c,c++ \ --target=$ARCH-unknown-freebsd10 \ --disable-multilib \ --disable-nls \ @@ -90,7 +106,7 @@ cd ../gcc-build --disable-libsanitizer \ --disable-libquadmath-support \ --disable-lto -make -j10 -make install +hide_output make -j10 +hide_output make install cd ../.. rm -rf gcc diff --git a/src/ci/docker/x86_64-freebsd/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile similarity index 66% rename from src/ci/docker/x86_64-freebsd/Dockerfile rename to src/ci/docker/dist-mips-linux/Dockerfile index 75f3174e2c..38ee95038f 100644 --- a/src/ci/docker/x86_64-freebsd/Dockerfile +++ b/src/ci/docker/dist-mips-linux/Dockerfile @@ -9,29 +9,23 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ - bzip2 \ + gdb \ xz-utils \ - wget + g++-mips-linux-gnu \ + g++-mipsel-linux-gnu -COPY build-toolchain.sh /tmp/ -RUN sh /tmp/build-toolchain.sh +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ dpkg -i dumb-init_*.deb && \ rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 -RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ - tar xJf - -C /usr/local/bin --strip-components=1 - -ENV \ - AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-ar \ - CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-gcc +ENV HOSTS=mips-unknown-linux-gnu +ENV HOSTS=$HOSTS,mipsel-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-freebsd -ENV RUST_CHECK_TARGET "" -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile new file mode 100644 index 0000000000..c9d89d6287 --- /dev/null +++ b/src/ci/docker/dist-mips64-linux/Dockerfile @@ -0,0 +1,31 @@ +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 \ + gdb \ + xz-utils \ + g++-mips64-linux-gnuabi64 \ + g++-mips64el-linux-gnuabi64 + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +ENV HOSTS=mips64-unknown-linux-gnuabi64 +ENV HOSTS=$HOSTS,mips64el-unknown-linux-gnuabi64 + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile new file mode 100644 index 0000000000..640bacc54e --- /dev/null +++ b/src/ci/docker/dist-powerpc-linux/Dockerfile @@ -0,0 +1,81 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + automake \ + bison \ + bzip2 \ + ca-certificates \ + cmake \ + curl \ + file \ + flex \ + g++ \ + gawk \ + gdb \ + git \ + gperf \ + help2man \ + libncurses-dev \ + libtool-bin \ + make \ + patch \ + python2.7 \ + sudo \ + texinfo \ + wget \ + xz-utils + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# toolchains we build below chokes on that, so go back to make 3 +RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ + cd make-3.81 && \ + ./configure --prefix=/usr && \ + make && \ + make install && \ + cd .. && \ + rm -rf make-3.81 + +RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ + tar xjf - && \ + cd crosstool-ng && \ + ./configure --prefix=/usr/local && \ + make -j$(nproc) && \ + make install && \ + cd .. && \ + rm -rf crosstool-ng + +RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild +RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +USER rustbuild +WORKDIR /tmp + +COPY patches/ /tmp/patches/ +COPY powerpc-linux-gnu.config build-powerpc-toolchain.sh /tmp/ +RUN ./build-powerpc-toolchain.sh + +USER root + +ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin + +ENV \ + CC_powerpc_unknown_linux_gnu=powerpc-unknown-linux-gnu-gcc \ + AR_powerpc_unknown_linux_gnu=powerpc-unknown-linux-gnu-ar \ + CXX_powerpc_unknown_linux_gnu=powerpc-unknown-linux-gnu-g++ + +ENV HOSTS=powerpc-unknown-linux-gnu + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS + +# FIXME(#36150) this will fail the bootstrap. Probably means something bad is +# happening! +ENV NO_LLVM_ASSERTIONS 1 diff --git a/src/ci/docker/dist-powerpc-linux/build-powerpc-toolchain.sh b/src/ci/docker/dist-powerpc-linux/build-powerpc-toolchain.sh new file mode 100755 index 0000000000..90a4df0c19 --- /dev/null +++ b/src/ci/docker/dist-powerpc-linux/build-powerpc-toolchain.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# 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. + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + rm /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} + +mkdir build +cd build +cp ../powerpc-linux-gnu.config .config +hide_output ct-ng build +cd .. +rm -rf build diff --git a/src/ci/docker/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch b/src/ci/docker/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch new file mode 100644 index 0000000000..744eb180cd --- /dev/null +++ b/src/ci/docker/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch @@ -0,0 +1,24 @@ +From b3563932f85d60bb0d38b0a5f3b8f4abc133f890 Mon Sep 17 00:00:00 2001 +From: Tulio Magno Quites Machado Filho +Date: Thu, 1 Nov 2012 18:00:06 -0500 +Subject: [PATCH] PowerPC: Remove unnecessary -mnew-mnemonics. + +--- + sysdeps/powerpc/Makefile | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile +index 79dd6fa976d5..7442b6709ad1 100644 +--- a/sysdeps/powerpc/Makefile ++++ b/sysdeps/powerpc/Makefile +@@ -1,7 +1,3 @@ +-# We always want to use the new mnemonic syntax even if we are on a RS6000 +-# machine. +-+cflags += -mnew-mnemonics +- + ifeq ($(subdir),gmon) + sysdep_routines += ppc-mcount + endif +-- +2.9.3 + diff --git a/src/ci/docker/dist-powerpc-linux/powerpc-linux-gnu.config b/src/ci/docker/dist-powerpc-linux/powerpc-linux-gnu.config new file mode 100644 index 0000000000..26e2de863a --- /dev/null +++ b/src/ci/docker/dist-powerpc-linux/powerpc-linux-gnu.config @@ -0,0 +1,528 @@ +# +# Automatically generated file; DO NOT EDIT. +# Crosstool-NG Configuration +# +CT_CONFIGURE_has_make381=y +CT_CONFIGURE_has_xz=y +CT_MODULES=y + +# +# Paths and misc options +# + +# +# crosstool-NG behavior +# +# CT_OBSOLETE is not set +# CT_EXPERIMENTAL is not set +# CT_DEBUG_CT is not set + +# +# Paths +# +CT_LOCAL_TARBALLS_DIR="" +CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_INSTALL_DIR="${CT_PREFIX_DIR}" +CT_RM_RF_PREFIX_DIR=y +CT_REMOVE_DOCS=y +CT_INSTALL_DIR_RO=y +CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y +# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set + +# +# Downloading +# +# CT_FORBID_DOWNLOAD is not set +# CT_FORCE_DOWNLOAD is not set +CT_CONNECT_TIMEOUT=10 +# CT_ONLY_DOWNLOAD is not set +# CT_USE_MIRROR is not set + +# +# Extracting +# +# CT_FORCE_EXTRACT is not set +CT_OVERIDE_CONFIG_GUESS_SUB=y +# CT_ONLY_EXTRACT is not set +# CT_PATCH_BUNDLED is not set +# CT_PATCH_LOCAL is not set +CT_PATCH_BUNDLED_LOCAL=y +# CT_PATCH_LOCAL_BUNDLED is not set +# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set +# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set +# CT_PATCH_NONE is not set +CT_PATCH_ORDER="bundled,local" +CT_PATCH_USE_LOCAL=y +CT_LOCAL_PATCH_DIR="/tmp/patches" + +# +# Build behavior +# +CT_PARALLEL_JOBS=0 +CT_LOAD="" +CT_USE_PIPES=y +CT_EXTRA_CFLAGS_FOR_BUILD="" +CT_EXTRA_LDFLAGS_FOR_BUILD="" +CT_EXTRA_CFLAGS_FOR_HOST="" +CT_EXTRA_LDFLAGS_FOR_HOST="" +# CT_CONFIG_SHELL_SH is not set +# CT_CONFIG_SHELL_ASH is not set +CT_CONFIG_SHELL_BASH=y +# CT_CONFIG_SHELL_CUSTOM is not set +CT_CONFIG_SHELL="${bash}" + +# +# Logging +# +# CT_LOG_ERROR is not set +# CT_LOG_WARN is not set +CT_LOG_INFO=y +# CT_LOG_EXTRA is not set +# CT_LOG_ALL is not set +# CT_LOG_DEBUG is not set +CT_LOG_LEVEL_MAX="INFO" +# CT_LOG_SEE_TOOLS_WARN is not set +CT_LOG_PROGRESS_BAR=y +CT_LOG_TO_FILE=y +CT_LOG_FILE_COMPRESS=y + +# +# Target options +# +CT_ARCH="powerpc" +CT_ARCH_SUPPORTS_BOTH_ENDIAN=y +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_SUPPORTS_WITH_ABI=y +CT_ARCH_SUPPORTS_WITH_CPU=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_SUPPORTS_WITH_FLOAT=y +CT_ARCH_DEFAULT_BE=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_ABI="" +CT_ARCH_CPU="power4" +CT_ARCH_TUNE="power6" +CT_ARCH_BE=y +# CT_ARCH_LE is not set +CT_ARCH_32=y +# CT_ARCH_64 is not set +CT_ARCH_BITNESS=32 +# CT_ARCH_FLOAT_HW is not set +# CT_ARCH_FLOAT_SW is not set +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" +# CT_ARCH_alpha is not set +# CT_ARCH_arm is not set +# CT_ARCH_avr is not set +# CT_ARCH_m68k is not set +# CT_ARCH_mips is not set +# CT_ARCH_nios2 is not set +CT_ARCH_powerpc=y +# CT_ARCH_s390 is not set +# CT_ARCH_sh is not set +# CT_ARCH_sparc is not set +# CT_ARCH_x86 is not set +# CT_ARCH_xtensa is not set +CT_ARCH_alpha_AVAILABLE=y +CT_ARCH_arm_AVAILABLE=y +CT_ARCH_avr_AVAILABLE=y +CT_ARCH_m68k_AVAILABLE=y +CT_ARCH_microblaze_AVAILABLE=y +CT_ARCH_mips_AVAILABLE=y +CT_ARCH_nios2_AVAILABLE=y +CT_ARCH_powerpc_AVAILABLE=y +CT_ARCH_s390_AVAILABLE=y +CT_ARCH_sh_AVAILABLE=y +CT_ARCH_sparc_AVAILABLE=y +CT_ARCH_x86_AVAILABLE=y +CT_ARCH_xtensa_AVAILABLE=y +CT_ARCH_SUFFIX="" + +# +# Generic target options +# +# CT_MULTILIB is not set +CT_ARCH_USE_MMU=y +CT_ARCH_ENDIAN="big" + +# +# Target optimisations +# +CT_ARCH_FLOAT_AUTO=y +CT_ARCH_FLOAT="auto" + +# +# powerpc other options +# +CT_ARCH_powerpc_ABI="" +CT_ARCH_powerpc_ABI_DEFAULT=y +# CT_ARCH_powerpc_ABI_SPE is not set + +# +# Toolchain options +# + +# +# General toolchain options +# +CT_FORCE_SYSROOT=y +CT_USE_SYSROOT=y +CT_SYSROOT_NAME="sysroot" +CT_SYSROOT_DIR_PREFIX="" +CT_WANTS_STATIC_LINK=y +# CT_STATIC_TOOLCHAIN is not set +CT_TOOLCHAIN_PKGVERSION="" +CT_TOOLCHAIN_BUGURL="" + +# +# Tuple completion and aliasing +# +CT_TARGET_VENDOR="unknown" +CT_TARGET_ALIAS_SED_EXPR="" +CT_TARGET_ALIAS="" + +# +# Toolchain type +# +CT_CROSS=y +# CT_CANADIAN is not set +CT_TOOLCHAIN_TYPE="cross" + +# +# Build system +# +CT_BUILD="" +CT_BUILD_PREFIX="" +CT_BUILD_SUFFIX="" + +# +# Misc options +# +# CT_TOOLCHAIN_ENABLE_NLS is not set + +# +# Operating System +# +CT_KERNEL_SUPPORTS_SHARED_LIBS=y +CT_KERNEL="linux" +CT_KERNEL_VERSION="2.6.32.68" +# CT_KERNEL_bare_metal is not set +CT_KERNEL_linux=y +CT_KERNEL_bare_metal_AVAILABLE=y +CT_KERNEL_linux_AVAILABLE=y +# CT_KERNEL_V_4_3 is not set +# CT_KERNEL_V_4_2 is not set +# CT_KERNEL_V_4_1 is not set +# CT_KERNEL_V_3_18 is not set +# CT_KERNEL_V_3_14 is not set +# CT_KERNEL_V_3_12 is not set +# CT_KERNEL_V_3_10 is not set +# CT_KERNEL_V_3_4 is not set +# CT_KERNEL_V_3_2 is not set +CT_KERNEL_V_2_6_32=y +# CT_KERNEL_LINUX_CUSTOM is not set +CT_KERNEL_windows_AVAILABLE=y + +# +# Common kernel options +# +CT_SHARED_LIBS=y + +# +# linux other options +# +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y + +# +# Binary utilities +# +CT_ARCH_BINFMT_ELF=y +CT_BINUTILS="binutils" +CT_BINUTILS_binutils=y + +# +# GNU binutils +# +# CT_CC_BINUTILS_SHOW_LINARO is not set +CT_BINUTILS_V_2_25_1=y +# CT_BINUTILS_V_2_25 is not set +# CT_BINUTILS_V_2_24 is not set +# CT_BINUTILS_V_2_23_2 is not set +# CT_BINUTILS_V_2_23_1 is not set +# CT_BINUTILS_V_2_22 is not set +# CT_BINUTILS_V_2_21_53 is not set +# CT_BINUTILS_V_2_21_1a is not set +# CT_BINUTILS_V_2_20_1a is not set +# CT_BINUTILS_V_2_19_1a is not set +# CT_BINUTILS_V_2_18a is not set +CT_BINUTILS_VERSION="2.25.1" +CT_BINUTILS_2_25_1_or_later=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_2_24_or_later=y +CT_BINUTILS_2_23_or_later=y +CT_BINUTILS_2_22_or_later=y +CT_BINUTILS_2_21_or_later=y +CT_BINUTILS_2_20_or_later=y +CT_BINUTILS_2_19_or_later=y +CT_BINUTILS_2_18_or_later=y +CT_BINUTILS_HAS_HASH_STYLE=y +CT_BINUTILS_HAS_GOLD=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_LINKER_LD=y +CT_BINUTILS_LINKERS_LIST="ld" +CT_BINUTILS_LINKER_DEFAULT="bfd" +# CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_EXTRA_CONFIG_ARRAY="" +# CT_BINUTILS_FOR_TARGET is not set + +# +# binutils other options +# + +# +# C-library +# +CT_LIBC="glibc" +CT_LIBC_VERSION="2.12.2" +CT_LIBC_glibc=y +# CT_LIBC_musl is not set +# CT_LIBC_uClibc is not set +CT_LIBC_avr_libc_AVAILABLE=y +CT_LIBC_glibc_AVAILABLE=y +CT_THREADS="nptl" +# CT_CC_GLIBC_SHOW_LINARO is not set +# CT_LIBC_GLIBC_V_2_22 is not set +# CT_LIBC_GLIBC_V_2_21 is not set +# CT_LIBC_GLIBC_V_2_20 is not set +# CT_LIBC_GLIBC_V_2_19 is not set +# CT_LIBC_GLIBC_V_2_18 is not set +# CT_LIBC_GLIBC_V_2_17 is not set +# CT_LIBC_GLIBC_V_2_16_0 is not set +# CT_LIBC_GLIBC_V_2_15 is not set +# CT_LIBC_GLIBC_V_2_14_1 is not set +# CT_LIBC_GLIBC_V_2_14 is not set +# CT_LIBC_GLIBC_V_2_13 is not set +CT_LIBC_GLIBC_V_2_12_2=y +# CT_LIBC_GLIBC_V_2_12_1 is not set +# CT_LIBC_GLIBC_V_2_11_1 is not set +# CT_LIBC_GLIBC_V_2_11 is not set +# CT_LIBC_GLIBC_V_2_10_1 is not set +# CT_LIBC_GLIBC_V_2_9 is not set +# CT_LIBC_GLIBC_V_2_8 is not set +CT_LIBC_mingw_AVAILABLE=y +CT_LIBC_musl_AVAILABLE=y +CT_LIBC_newlib_AVAILABLE=y +CT_LIBC_none_AVAILABLE=y +CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_SUPPORT_THREADS_ANY=y +CT_LIBC_SUPPORT_THREADS_NATIVE=y + +# +# Common C library options +# +CT_THREADS_NATIVE=y +CT_LIBC_XLDD=y + +# +# glibc other options +# +CT_LIBC_GLIBC_PORTS_EXTERNAL=y +CT_LIBC_glibc_familly=y +CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_LIBC_GLIBC_CONFIGPARMS="" +CT_LIBC_GLIBC_EXTRA_CFLAGS="" +CT_LIBC_EXTRA_CC_ARGS="" +# CT_LIBC_DISABLE_VERSIONING is not set +CT_LIBC_OLDEST_ABI="" +CT_LIBC_GLIBC_FORCE_UNWIND=y +# CT_LIBC_GLIBC_USE_PORTS is not set +CT_LIBC_ADDONS_LIST="" +# CT_LIBC_LOCALES is not set +# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set +CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_LIBC_GLIBC_MIN_KERNEL="2.6.32.68" + +# +# C compiler +# +CT_CC="gcc" +CT_CC_CORE_PASSES_NEEDED=y +CT_CC_CORE_PASS_1_NEEDED=y +CT_CC_CORE_PASS_2_NEEDED=y +CT_CC_gcc=y +# CT_CC_GCC_SHOW_LINARO is not set +# CT_CC_GCC_V_5_2_0 is not set +CT_CC_GCC_V_4_9_3=y +# CT_CC_GCC_V_4_8_5 is not set +# CT_CC_GCC_V_4_7_4 is not set +# CT_CC_GCC_V_4_6_4 is not set +# CT_CC_GCC_V_4_5_4 is not set +# CT_CC_GCC_V_4_4_7 is not set +# CT_CC_GCC_V_4_3_6 is not set +# CT_CC_GCC_V_4_2_4 is not set +CT_CC_GCC_4_2_or_later=y +CT_CC_GCC_4_3_or_later=y +CT_CC_GCC_4_4_or_later=y +CT_CC_GCC_4_5_or_later=y +CT_CC_GCC_4_6_or_later=y +CT_CC_GCC_4_7_or_later=y +CT_CC_GCC_4_8_or_later=y +CT_CC_GCC_4_9=y +CT_CC_GCC_4_9_or_later=y +CT_CC_GCC_HAS_GRAPHITE=y +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_HAS_LTO=y +CT_CC_GCC_USE_LTO=y +CT_CC_GCC_HAS_PKGVERSION_BUGURL=y +CT_CC_GCC_HAS_BUILD_ID=y +CT_CC_GCC_HAS_LNK_HASH_STYLE=y +CT_CC_GCC_USE_GMP_MPFR=y +CT_CC_GCC_USE_MPC=y +CT_CC_GCC_HAS_LIBQUADMATH=y +CT_CC_GCC_HAS_LIBSANITIZER=y +CT_CC_GCC_VERSION="4.9.3" +# CT_CC_LANG_FORTRAN is not set +CT_CC_GCC_ENABLE_CXX_FLAGS="" +CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="--with-cpu-32=power4 --with-cpu=default32" +CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-cpu-32=power4 --with-cpu=default32" +CT_CC_GCC_EXTRA_ENV_ARRAY="" +CT_CC_GCC_STATIC_LIBSTDCXX=y +# CT_CC_GCC_SYSTEM_ZLIB is not set + +# +# Optimisation features +# + +# +# Settings for libraries running on target +# +CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y +# CT_CC_GCC_LIBMUDFLAP is not set +# CT_CC_GCC_LIBGOMP is not set +# CT_CC_GCC_LIBSSP is not set +# CT_CC_GCC_LIBQUADMATH is not set +# CT_CC_GCC_LIBSANITIZER is not set + +# +# Misc. obscure options. +# +CT_CC_CXA_ATEXIT=y +# CT_CC_GCC_DISABLE_PCH is not set +CT_CC_GCC_SJLJ_EXCEPTIONS=m +CT_CC_GCC_LDBL_128=m +# CT_CC_GCC_BUILD_ID is not set +CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y +# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set +# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set +# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set +CT_CC_GCC_LNK_HASH_STYLE="" +CT_CC_GCC_DEC_FLOAT_AUTO=y +# CT_CC_GCC_DEC_FLOAT_BID is not set +# CT_CC_GCC_DEC_FLOAT_DPD is not set +# CT_CC_GCC_DEC_FLOATS_NO is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_JAVA=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y + +# +# Additional supported languages: +# +CT_CC_LANG_CXX=y +# CT_CC_LANG_JAVA is not set + +# +# Debug facilities +# +# CT_DEBUG_dmalloc is not set +# CT_DEBUG_duma is not set +# CT_DEBUG_gdb is not set +# CT_DEBUG_ltrace is not set +# CT_DEBUG_strace is not set + +# +# Companion libraries +# +CT_COMPLIBS_NEEDED=y +CT_LIBICONV_NEEDED=y +CT_GETTEXT_NEEDED=y +CT_GMP_NEEDED=y +CT_MPFR_NEEDED=y +CT_ISL_NEEDED=y +CT_CLOOG_NEEDED=y +CT_MPC_NEEDED=y +CT_COMPLIBS=y +CT_LIBICONV=y +CT_GETTEXT=y +CT_GMP=y +CT_MPFR=y +CT_ISL=y +CT_CLOOG=y +CT_MPC=y +CT_LIBICONV_V_1_14=y +CT_LIBICONV_VERSION="1.14" +CT_GETTEXT_V_0_19_6=y +CT_GETTEXT_VERSION="0.19.6" +CT_GMP_V_6_0_0=y +# CT_GMP_V_5_1_3 is not set +# CT_GMP_V_5_1_1 is not set +# CT_GMP_V_5_0_2 is not set +# CT_GMP_V_5_0_1 is not set +# CT_GMP_V_4_3_2 is not set +# CT_GMP_V_4_3_1 is not set +# CT_GMP_V_4_3_0 is not set +CT_GMP_5_0_2_or_later=y +CT_GMP_VERSION="6.0.0a" +CT_MPFR_V_3_1_3=y +# CT_MPFR_V_3_1_2 is not set +# CT_MPFR_V_3_1_0 is not set +# CT_MPFR_V_3_0_1 is not set +# CT_MPFR_V_3_0_0 is not set +# CT_MPFR_V_2_4_2 is not set +# CT_MPFR_V_2_4_1 is not set +# CT_MPFR_V_2_4_0 is not set +CT_MPFR_VERSION="3.1.3" +CT_ISL_V_0_14=y +CT_ISL_V_0_14_or_later=y +CT_ISL_V_0_12_or_later=y +CT_ISL_VERSION="0.14" +CT_CLOOG_V_0_18_4=y +# CT_CLOOG_V_0_18_1 is not set +# CT_CLOOG_V_0_18_0 is not set +CT_CLOOG_VERSION="0.18.4" +CT_CLOOG_0_18_4_or_later=y +CT_CLOOG_0_18_or_later=y +CT_MPC_V_1_0_3=y +# CT_MPC_V_1_0_2 is not set +# CT_MPC_V_1_0_1 is not set +# CT_MPC_V_1_0 is not set +# CT_MPC_V_0_9 is not set +# CT_MPC_V_0_8_2 is not set +# CT_MPC_V_0_8_1 is not set +# CT_MPC_V_0_7 is not set +CT_MPC_VERSION="1.0.3" + +# +# Companion libraries common options +# +# CT_COMPLIBS_CHECK is not set + +# +# Companion tools +# + +# +# READ HELP before you say 'Y' below !!! +# +# CT_COMP_TOOLS is not set diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile new file mode 100644 index 0000000000..624763ef5d --- /dev/null +++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile @@ -0,0 +1,85 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + automake \ + bison \ + bzip2 \ + ca-certificates \ + cmake \ + curl \ + file \ + flex \ + g++ \ + gawk \ + gdb \ + git \ + gperf \ + help2man \ + libncurses-dev \ + libtool-bin \ + make \ + patch \ + python2.7 \ + sudo \ + texinfo \ + wget \ + xz-utils + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# toolchains we build below chokes on that, so go back to make 3 +RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ + cd make-3.81 && \ + ./configure --prefix=/usr && \ + make && \ + make install && \ + cd .. && \ + rm -rf make-3.81 + +RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ + tar xjf - && \ + cd crosstool-ng && \ + ./configure --prefix=/usr/local && \ + make -j$(nproc) && \ + make install && \ + cd .. && \ + rm -rf crosstool-ng + +RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild +RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +USER rustbuild +WORKDIR /tmp + +COPY patches/ /tmp/patches/ +COPY powerpc64-linux-gnu.config build-powerpc64-toolchain.sh /tmp/ +RUN ./build-powerpc64-toolchain.sh + +USER root + +RUN apt-get install -y --no-install-recommends rpm2cpio cpio +COPY build-powerpc64le-toolchain.sh /tmp/ +RUN ./build-powerpc64le-toolchain.sh + +ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin + +ENV \ + AR_powerpc64_unknown_linux_gnu=powerpc64-unknown-linux-gnu-ar \ + CC_powerpc64_unknown_linux_gnu=powerpc64-unknown-linux-gnu-gcc \ + CXX_powerpc64_unknown_linux_gnu=powerpc64-unknown-linux-gnu-g++ \ + AR_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-ar \ + CC_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-gcc \ + CXX_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-g++ + +ENV HOSTS=powerpc64-unknown-linux-gnu +ENV HOSTS=$HOSTS,powerpc64le-unknown-linux-gnu + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh b/src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh new file mode 100755 index 0000000000..d70947d2dd --- /dev/null +++ b/src/ci/docker/dist-powerpc64-linux/build-powerpc64-toolchain.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# 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. + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + rm /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} + +mkdir build +cd build +cp ../powerpc64-linux-gnu.config .config +hide_output ct-ng build +cd .. +rm -rf build diff --git a/src/ci/docker/dist-powerpc64-linux/build-powerpc64le-toolchain.sh b/src/ci/docker/dist-powerpc64-linux/build-powerpc64le-toolchain.sh new file mode 100755 index 0000000000..8b924ca34c --- /dev/null +++ b/src/ci/docker/dist-powerpc64-linux/build-powerpc64le-toolchain.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# 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. + +set -ex + +BINUTILS=2.25.1 +GCC=5.3.0 +TARGET=powerpc64le-linux-gnu +SYSROOT=/usr/local/$TARGET/sysroot + +# First, download the CentOS7 glibc.ppc64le and relevant header files. +# (upstream ppc64le support wasn't added until 2.19, which el7 backported.) +mkdir -p $SYSROOT +pushd $SYSROOT + +centos_base=http://mirror.centos.org/altarch/7.3.1611/os/ppc64le/Packages +glibc_v=2.17-157.el7 +kernel_v=3.10.0-514.el7 +for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do + curl $centos_base/$package.ppc64le.rpm | \ + rpm2cpio - | cpio -idm +done + +ln -sT lib64 lib +ln -sT lib64 usr/lib + +popd + +# Next, download and build binutils. +mkdir binutils-$TARGET +pushd binutils-$TARGET +curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.bz2 | tar xjf - +mkdir binutils-build +cd binutils-build +../binutils-$BINUTILS/configure --target=$TARGET --with-sysroot=$SYSROOT +make -j10 +make install +popd +rm -rf binutils-$TARGET + +# Finally, download and build gcc. +mkdir gcc-$TARGET +pushd gcc-$TARGET +curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf - +cd gcc-$GCC +./contrib/download_prerequisites + +mkdir ../gcc-build +cd ../gcc-build +../gcc-$GCC/configure \ + --enable-languages=c,c++ \ + --target=$TARGET \ + --with-cpu=power8 \ + --with-sysroot=$SYSROOT \ + --disable-libcilkrts \ + --disable-multilib \ + --disable-nls \ + --disable-libgomp \ + --disable-libquadmath \ + --disable-libssp \ + --disable-libvtv \ + --disable-libcilkrt \ + --disable-libada \ + --disable-libsanitizer \ + --disable-libquadmath-support \ + --disable-lto +make -j10 +make install + +popd +rm -rf gcc-$TARGET diff --git a/src/ci/docker/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch b/src/ci/docker/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch new file mode 100644 index 0000000000..744eb180cd --- /dev/null +++ b/src/ci/docker/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch @@ -0,0 +1,24 @@ +From b3563932f85d60bb0d38b0a5f3b8f4abc133f890 Mon Sep 17 00:00:00 2001 +From: Tulio Magno Quites Machado Filho +Date: Thu, 1 Nov 2012 18:00:06 -0500 +Subject: [PATCH] PowerPC: Remove unnecessary -mnew-mnemonics. + +--- + sysdeps/powerpc/Makefile | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile +index 79dd6fa976d5..7442b6709ad1 100644 +--- a/sysdeps/powerpc/Makefile ++++ b/sysdeps/powerpc/Makefile +@@ -1,7 +1,3 @@ +-# We always want to use the new mnemonic syntax even if we are on a RS6000 +-# machine. +-+cflags += -mnew-mnemonics +- + ifeq ($(subdir),gmon) + sysdep_routines += ppc-mcount + endif +-- +2.9.3 + diff --git a/src/ci/docker/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch b/src/ci/docker/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch new file mode 100644 index 0000000000..47cc8b28d2 --- /dev/null +++ b/src/ci/docker/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch @@ -0,0 +1,26 @@ +From a4f388e111ce05e2ab7912cff3c9070334bb74ae Mon Sep 17 00:00:00 2001 +From: Josh Stone +Date: Fri, 20 Jan 2017 15:41:56 -0800 +Subject: [PATCH] Prevent inlining in PPC64 initfini.s + +Ref: https://sourceware.org/ml/libc-alpha/2012-01/msg00195.html +--- + sysdeps/powerpc/powerpc64/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/powerpc/powerpc64/Makefile b/sysdeps/powerpc/powerpc64/Makefile +index 78d4f07e575f..fe96aae4d43e 100644 +--- a/sysdeps/powerpc/powerpc64/Makefile ++++ b/sysdeps/powerpc/powerpc64/Makefile +@@ -28,7 +28,7 @@ elide-routines.os += hp-timing + ifneq ($(elf),no) + # The initfini generation code doesn't work in the presence of -fPIC, so + # we use -fpic instead which is much better. +-CFLAGS-initfini.s += -fpic -O1 ++CFLAGS-initfini.s += -fpic -O1 -fno-inline + endif + endif + +-- +2.9.3 + diff --git a/src/ci/docker/dist-powerpc64-linux/powerpc64-linux-gnu.config b/src/ci/docker/dist-powerpc64-linux/powerpc64-linux-gnu.config new file mode 100644 index 0000000000..c2d02ee85c --- /dev/null +++ b/src/ci/docker/dist-powerpc64-linux/powerpc64-linux-gnu.config @@ -0,0 +1,528 @@ +# +# Automatically generated file; DO NOT EDIT. +# Crosstool-NG Configuration +# +CT_CONFIGURE_has_make381=y +CT_CONFIGURE_has_xz=y +CT_MODULES=y + +# +# Paths and misc options +# + +# +# crosstool-NG behavior +# +# CT_OBSOLETE is not set +# CT_EXPERIMENTAL is not set +# CT_DEBUG_CT is not set + +# +# Paths +# +CT_LOCAL_TARBALLS_DIR="" +CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_INSTALL_DIR="${CT_PREFIX_DIR}" +CT_RM_RF_PREFIX_DIR=y +CT_REMOVE_DOCS=y +CT_INSTALL_DIR_RO=y +CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y +# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set + +# +# Downloading +# +# CT_FORBID_DOWNLOAD is not set +# CT_FORCE_DOWNLOAD is not set +CT_CONNECT_TIMEOUT=10 +# CT_ONLY_DOWNLOAD is not set +# CT_USE_MIRROR is not set + +# +# Extracting +# +# CT_FORCE_EXTRACT is not set +CT_OVERIDE_CONFIG_GUESS_SUB=y +# CT_ONLY_EXTRACT is not set +# CT_PATCH_BUNDLED is not set +# CT_PATCH_LOCAL is not set +CT_PATCH_BUNDLED_LOCAL=y +# CT_PATCH_LOCAL_BUNDLED is not set +# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set +# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set +# CT_PATCH_NONE is not set +CT_PATCH_ORDER="bundled,local" +CT_PATCH_USE_LOCAL=y +CT_LOCAL_PATCH_DIR="/tmp/patches" + +# +# Build behavior +# +CT_PARALLEL_JOBS=0 +CT_LOAD="" +CT_USE_PIPES=y +CT_EXTRA_CFLAGS_FOR_BUILD="" +CT_EXTRA_LDFLAGS_FOR_BUILD="" +CT_EXTRA_CFLAGS_FOR_HOST="" +CT_EXTRA_LDFLAGS_FOR_HOST="" +# CT_CONFIG_SHELL_SH is not set +# CT_CONFIG_SHELL_ASH is not set +CT_CONFIG_SHELL_BASH=y +# CT_CONFIG_SHELL_CUSTOM is not set +CT_CONFIG_SHELL="${bash}" + +# +# Logging +# +# CT_LOG_ERROR is not set +# CT_LOG_WARN is not set +CT_LOG_INFO=y +# CT_LOG_EXTRA is not set +# CT_LOG_ALL is not set +# CT_LOG_DEBUG is not set +CT_LOG_LEVEL_MAX="INFO" +# CT_LOG_SEE_TOOLS_WARN is not set +CT_LOG_PROGRESS_BAR=y +CT_LOG_TO_FILE=y +CT_LOG_FILE_COMPRESS=y + +# +# Target options +# +CT_ARCH="powerpc" +CT_ARCH_SUPPORTS_BOTH_ENDIAN=y +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_SUPPORTS_WITH_ABI=y +CT_ARCH_SUPPORTS_WITH_CPU=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_SUPPORTS_WITH_FLOAT=y +CT_ARCH_DEFAULT_BE=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_ABI="" +CT_ARCH_CPU="power4" +CT_ARCH_TUNE="power6" +CT_ARCH_BE=y +# CT_ARCH_LE is not set +# CT_ARCH_32 is not set +CT_ARCH_64=y +CT_ARCH_BITNESS=64 +# CT_ARCH_FLOAT_HW is not set +# CT_ARCH_FLOAT_SW is not set +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" +# CT_ARCH_alpha is not set +# CT_ARCH_arm is not set +# CT_ARCH_avr is not set +# CT_ARCH_m68k is not set +# CT_ARCH_mips is not set +# CT_ARCH_nios2 is not set +CT_ARCH_powerpc=y +# CT_ARCH_s390 is not set +# CT_ARCH_sh is not set +# CT_ARCH_sparc is not set +# CT_ARCH_x86 is not set +# CT_ARCH_xtensa is not set +CT_ARCH_alpha_AVAILABLE=y +CT_ARCH_arm_AVAILABLE=y +CT_ARCH_avr_AVAILABLE=y +CT_ARCH_m68k_AVAILABLE=y +CT_ARCH_microblaze_AVAILABLE=y +CT_ARCH_mips_AVAILABLE=y +CT_ARCH_nios2_AVAILABLE=y +CT_ARCH_powerpc_AVAILABLE=y +CT_ARCH_s390_AVAILABLE=y +CT_ARCH_sh_AVAILABLE=y +CT_ARCH_sparc_AVAILABLE=y +CT_ARCH_x86_AVAILABLE=y +CT_ARCH_xtensa_AVAILABLE=y +CT_ARCH_SUFFIX="" + +# +# Generic target options +# +# CT_MULTILIB is not set +CT_ARCH_USE_MMU=y +CT_ARCH_ENDIAN="big" + +# +# Target optimisations +# +CT_ARCH_FLOAT_AUTO=y +CT_ARCH_FLOAT="auto" + +# +# powerpc other options +# +CT_ARCH_powerpc_ABI="" +CT_ARCH_powerpc_ABI_DEFAULT=y +# CT_ARCH_powerpc_ABI_SPE is not set + +# +# Toolchain options +# + +# +# General toolchain options +# +CT_FORCE_SYSROOT=y +CT_USE_SYSROOT=y +CT_SYSROOT_NAME="sysroot" +CT_SYSROOT_DIR_PREFIX="" +CT_WANTS_STATIC_LINK=y +# CT_STATIC_TOOLCHAIN is not set +CT_TOOLCHAIN_PKGVERSION="" +CT_TOOLCHAIN_BUGURL="" + +# +# Tuple completion and aliasing +# +CT_TARGET_VENDOR="unknown" +CT_TARGET_ALIAS_SED_EXPR="" +CT_TARGET_ALIAS="" + +# +# Toolchain type +# +CT_CROSS=y +# CT_CANADIAN is not set +CT_TOOLCHAIN_TYPE="cross" + +# +# Build system +# +CT_BUILD="" +CT_BUILD_PREFIX="" +CT_BUILD_SUFFIX="" + +# +# Misc options +# +# CT_TOOLCHAIN_ENABLE_NLS is not set + +# +# Operating System +# +CT_KERNEL_SUPPORTS_SHARED_LIBS=y +CT_KERNEL="linux" +CT_KERNEL_VERSION="2.6.32.68" +# CT_KERNEL_bare_metal is not set +CT_KERNEL_linux=y +CT_KERNEL_bare_metal_AVAILABLE=y +CT_KERNEL_linux_AVAILABLE=y +# CT_KERNEL_V_4_3 is not set +# CT_KERNEL_V_4_2 is not set +# CT_KERNEL_V_4_1 is not set +# CT_KERNEL_V_3_18 is not set +# CT_KERNEL_V_3_14 is not set +# CT_KERNEL_V_3_12 is not set +# CT_KERNEL_V_3_10 is not set +# CT_KERNEL_V_3_4 is not set +# CT_KERNEL_V_3_2 is not set +CT_KERNEL_V_2_6_32=y +# CT_KERNEL_LINUX_CUSTOM is not set +CT_KERNEL_windows_AVAILABLE=y + +# +# Common kernel options +# +CT_SHARED_LIBS=y + +# +# linux other options +# +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y + +# +# Binary utilities +# +CT_ARCH_BINFMT_ELF=y +CT_BINUTILS="binutils" +CT_BINUTILS_binutils=y + +# +# GNU binutils +# +# CT_CC_BINUTILS_SHOW_LINARO is not set +CT_BINUTILS_V_2_25_1=y +# CT_BINUTILS_V_2_25 is not set +# CT_BINUTILS_V_2_24 is not set +# CT_BINUTILS_V_2_23_2 is not set +# CT_BINUTILS_V_2_23_1 is not set +# CT_BINUTILS_V_2_22 is not set +# CT_BINUTILS_V_2_21_53 is not set +# CT_BINUTILS_V_2_21_1a is not set +# CT_BINUTILS_V_2_20_1a is not set +# CT_BINUTILS_V_2_19_1a is not set +# CT_BINUTILS_V_2_18a is not set +CT_BINUTILS_VERSION="2.25.1" +CT_BINUTILS_2_25_1_or_later=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_2_24_or_later=y +CT_BINUTILS_2_23_or_later=y +CT_BINUTILS_2_22_or_later=y +CT_BINUTILS_2_21_or_later=y +CT_BINUTILS_2_20_or_later=y +CT_BINUTILS_2_19_or_later=y +CT_BINUTILS_2_18_or_later=y +CT_BINUTILS_HAS_HASH_STYLE=y +CT_BINUTILS_HAS_GOLD=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_LINKER_LD=y +CT_BINUTILS_LINKERS_LIST="ld" +CT_BINUTILS_LINKER_DEFAULT="bfd" +# CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_EXTRA_CONFIG_ARRAY="" +# CT_BINUTILS_FOR_TARGET is not set + +# +# binutils other options +# + +# +# C-library +# +CT_LIBC="glibc" +CT_LIBC_VERSION="2.12.2" +CT_LIBC_glibc=y +# CT_LIBC_musl is not set +# CT_LIBC_uClibc is not set +CT_LIBC_avr_libc_AVAILABLE=y +CT_LIBC_glibc_AVAILABLE=y +CT_THREADS="nptl" +# CT_CC_GLIBC_SHOW_LINARO is not set +# CT_LIBC_GLIBC_V_2_22 is not set +# CT_LIBC_GLIBC_V_2_21 is not set +# CT_LIBC_GLIBC_V_2_20 is not set +# CT_LIBC_GLIBC_V_2_19 is not set +# CT_LIBC_GLIBC_V_2_18 is not set +# CT_LIBC_GLIBC_V_2_17 is not set +# CT_LIBC_GLIBC_V_2_16_0 is not set +# CT_LIBC_GLIBC_V_2_15 is not set +# CT_LIBC_GLIBC_V_2_14_1 is not set +# CT_LIBC_GLIBC_V_2_14 is not set +# CT_LIBC_GLIBC_V_2_13 is not set +CT_LIBC_GLIBC_V_2_12_2=y +# CT_LIBC_GLIBC_V_2_12_1 is not set +# CT_LIBC_GLIBC_V_2_11_1 is not set +# CT_LIBC_GLIBC_V_2_11 is not set +# CT_LIBC_GLIBC_V_2_10_1 is not set +# CT_LIBC_GLIBC_V_2_9 is not set +# CT_LIBC_GLIBC_V_2_8 is not set +CT_LIBC_mingw_AVAILABLE=y +CT_LIBC_musl_AVAILABLE=y +CT_LIBC_newlib_AVAILABLE=y +CT_LIBC_none_AVAILABLE=y +CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_SUPPORT_THREADS_ANY=y +CT_LIBC_SUPPORT_THREADS_NATIVE=y + +# +# Common C library options +# +CT_THREADS_NATIVE=y +CT_LIBC_XLDD=y + +# +# glibc other options +# +CT_LIBC_GLIBC_PORTS_EXTERNAL=y +CT_LIBC_glibc_familly=y +CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_LIBC_GLIBC_CONFIGPARMS="" +CT_LIBC_GLIBC_EXTRA_CFLAGS="" +CT_LIBC_EXTRA_CC_ARGS="" +# CT_LIBC_DISABLE_VERSIONING is not set +CT_LIBC_OLDEST_ABI="" +CT_LIBC_GLIBC_FORCE_UNWIND=y +# CT_LIBC_GLIBC_USE_PORTS is not set +CT_LIBC_ADDONS_LIST="" +# CT_LIBC_LOCALES is not set +# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set +CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_LIBC_GLIBC_MIN_KERNEL="2.6.32.68" + +# +# C compiler +# +CT_CC="gcc" +CT_CC_CORE_PASSES_NEEDED=y +CT_CC_CORE_PASS_1_NEEDED=y +CT_CC_CORE_PASS_2_NEEDED=y +CT_CC_gcc=y +# CT_CC_GCC_SHOW_LINARO is not set +# CT_CC_GCC_V_5_2_0 is not set +CT_CC_GCC_V_4_9_3=y +# CT_CC_GCC_V_4_8_5 is not set +# CT_CC_GCC_V_4_7_4 is not set +# CT_CC_GCC_V_4_6_4 is not set +# CT_CC_GCC_V_4_5_4 is not set +# CT_CC_GCC_V_4_4_7 is not set +# CT_CC_GCC_V_4_3_6 is not set +# CT_CC_GCC_V_4_2_4 is not set +CT_CC_GCC_4_2_or_later=y +CT_CC_GCC_4_3_or_later=y +CT_CC_GCC_4_4_or_later=y +CT_CC_GCC_4_5_or_later=y +CT_CC_GCC_4_6_or_later=y +CT_CC_GCC_4_7_or_later=y +CT_CC_GCC_4_8_or_later=y +CT_CC_GCC_4_9=y +CT_CC_GCC_4_9_or_later=y +CT_CC_GCC_HAS_GRAPHITE=y +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_HAS_LTO=y +CT_CC_GCC_USE_LTO=y +CT_CC_GCC_HAS_PKGVERSION_BUGURL=y +CT_CC_GCC_HAS_BUILD_ID=y +CT_CC_GCC_HAS_LNK_HASH_STYLE=y +CT_CC_GCC_USE_GMP_MPFR=y +CT_CC_GCC_USE_MPC=y +CT_CC_GCC_HAS_LIBQUADMATH=y +CT_CC_GCC_HAS_LIBSANITIZER=y +CT_CC_GCC_VERSION="4.9.3" +# CT_CC_LANG_FORTRAN is not set +CT_CC_GCC_ENABLE_CXX_FLAGS="" +CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_ENV_ARRAY="" +CT_CC_GCC_STATIC_LIBSTDCXX=y +# CT_CC_GCC_SYSTEM_ZLIB is not set + +# +# Optimisation features +# + +# +# Settings for libraries running on target +# +CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y +# CT_CC_GCC_LIBMUDFLAP is not set +# CT_CC_GCC_LIBGOMP is not set +# CT_CC_GCC_LIBSSP is not set +# CT_CC_GCC_LIBQUADMATH is not set +# CT_CC_GCC_LIBSANITIZER is not set + +# +# Misc. obscure options. +# +CT_CC_CXA_ATEXIT=y +# CT_CC_GCC_DISABLE_PCH is not set +CT_CC_GCC_SJLJ_EXCEPTIONS=m +CT_CC_GCC_LDBL_128=m +# CT_CC_GCC_BUILD_ID is not set +CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y +# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set +# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set +# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set +CT_CC_GCC_LNK_HASH_STYLE="" +CT_CC_GCC_DEC_FLOAT_AUTO=y +# CT_CC_GCC_DEC_FLOAT_BID is not set +# CT_CC_GCC_DEC_FLOAT_DPD is not set +# CT_CC_GCC_DEC_FLOATS_NO is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_JAVA=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y + +# +# Additional supported languages: +# +CT_CC_LANG_CXX=y +# CT_CC_LANG_JAVA is not set + +# +# Debug facilities +# +# CT_DEBUG_dmalloc is not set +# CT_DEBUG_duma is not set +# CT_DEBUG_gdb is not set +# CT_DEBUG_ltrace is not set +# CT_DEBUG_strace is not set + +# +# Companion libraries +# +CT_COMPLIBS_NEEDED=y +CT_LIBICONV_NEEDED=y +CT_GETTEXT_NEEDED=y +CT_GMP_NEEDED=y +CT_MPFR_NEEDED=y +CT_ISL_NEEDED=y +CT_CLOOG_NEEDED=y +CT_MPC_NEEDED=y +CT_COMPLIBS=y +CT_LIBICONV=y +CT_GETTEXT=y +CT_GMP=y +CT_MPFR=y +CT_ISL=y +CT_CLOOG=y +CT_MPC=y +CT_LIBICONV_V_1_14=y +CT_LIBICONV_VERSION="1.14" +CT_GETTEXT_V_0_19_6=y +CT_GETTEXT_VERSION="0.19.6" +CT_GMP_V_6_0_0=y +# CT_GMP_V_5_1_3 is not set +# CT_GMP_V_5_1_1 is not set +# CT_GMP_V_5_0_2 is not set +# CT_GMP_V_5_0_1 is not set +# CT_GMP_V_4_3_2 is not set +# CT_GMP_V_4_3_1 is not set +# CT_GMP_V_4_3_0 is not set +CT_GMP_5_0_2_or_later=y +CT_GMP_VERSION="6.0.0a" +CT_MPFR_V_3_1_3=y +# CT_MPFR_V_3_1_2 is not set +# CT_MPFR_V_3_1_0 is not set +# CT_MPFR_V_3_0_1 is not set +# CT_MPFR_V_3_0_0 is not set +# CT_MPFR_V_2_4_2 is not set +# CT_MPFR_V_2_4_1 is not set +# CT_MPFR_V_2_4_0 is not set +CT_MPFR_VERSION="3.1.3" +CT_ISL_V_0_14=y +CT_ISL_V_0_14_or_later=y +CT_ISL_V_0_12_or_later=y +CT_ISL_VERSION="0.14" +CT_CLOOG_V_0_18_4=y +# CT_CLOOG_V_0_18_1 is not set +# CT_CLOOG_V_0_18_0 is not set +CT_CLOOG_VERSION="0.18.4" +CT_CLOOG_0_18_4_or_later=y +CT_CLOOG_0_18_or_later=y +CT_MPC_V_1_0_3=y +# CT_MPC_V_1_0_2 is not set +# CT_MPC_V_1_0_1 is not set +# CT_MPC_V_1_0 is not set +# CT_MPC_V_0_9 is not set +# CT_MPC_V_0_8_2 is not set +# CT_MPC_V_0_8_1 is not set +# CT_MPC_V_0_7 is not set +CT_MPC_VERSION="1.0.3" + +# +# Companion libraries common options +# +# CT_COMPLIBS_CHECK is not set + +# +# Companion tools +# + +# +# READ HELP before you say 'Y' below !!! +# +# CT_COMP_TOOLS is not set diff --git a/src/ci/docker/dist-s390x-linux-netbsd/Dockerfile b/src/ci/docker/dist-s390x-linux-netbsd/Dockerfile new file mode 100644 index 0000000000..589b5fd530 --- /dev/null +++ b/src/ci/docker/dist-s390x-linux-netbsd/Dockerfile @@ -0,0 +1,84 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + automake \ + bison \ + bzip2 \ + ca-certificates \ + cmake \ + curl \ + file \ + flex \ + g++ \ + gawk \ + gdb \ + git \ + gperf \ + help2man \ + libncurses-dev \ + libtool-bin \ + make \ + patch \ + python2.7 \ + sudo \ + texinfo \ + wget \ + xz-utils + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +# Ubuntu 16.04 (this contianer) ships with make 4, but something in the +# toolchains we build below chokes on that, so go back to make 3 +RUN curl https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - && \ + cd make-3.81 && \ + ./configure --prefix=/usr && \ + make && \ + make install && \ + cd .. && \ + rm -rf make-3.81 + +RUN curl http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2 | \ + tar xjf - && \ + cd crosstool-ng && \ + ./configure --prefix=/usr/local && \ + make -j$(nproc) && \ + make install && \ + cd .. && \ + rm -rf crosstool-ng + +RUN groupadd -r rustbuild && useradd -m -r -g rustbuild rustbuild +RUN mkdir /x-tools && chown rustbuild:rustbuild /x-tools +USER rustbuild +WORKDIR /tmp + +COPY patches/ /tmp/patches/ +COPY s390x-linux-gnu.config build-s390x-toolchain.sh /tmp/ +RUN ./build-s390x-toolchain.sh + +USER root + +COPY build-netbsd-toolchain.sh /tmp/ +RUN ./build-netbsd-toolchain.sh + +ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin + +ENV \ + AR_x86_64_unknown_netbsd=x86_64-unknown-netbsd-ar \ + CC_x86_64_unknown_netbsd=x86_64-unknown-netbsd-gcc \ + CXX_x86_64_unknown_netbsd=x86_64-unknown-netbsd-g++ \ + CC_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-gcc \ + AR_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-ar \ + CXX_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-g++ + +ENV HOSTS=x86_64-unknown-netbsd +ENV HOSTS=$HOSTS,s390x-unknown-linux-gnu + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-s390x-linux-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/dist-s390x-linux-netbsd/build-netbsd-toolchain.sh new file mode 100755 index 0000000000..654b458ea4 --- /dev/null +++ b/src/ci/docker/dist-s390x-linux-netbsd/build-netbsd-toolchain.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# 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. + +# ignore-tidy-linelength + +set -ex + +BINUTILS=2.25.1 +GCC=5.3.0 + +# First up, build binutils +mkdir binutils +cd binutils +curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.bz2 | tar xjf - +mkdir binutils-build +cd binutils-build +../binutils-$BINUTILS/configure \ + --target=x86_64-unknown-netbsd +make -j10 +make install +cd ../.. +rm -rf binutils + +# Next, download the NetBSD libc and relevant header files +mkdir netbsd +# originally from: +# https://ftp.netbsd.org/pub/NetBSD/NetBSD-7.0/amd64/binary/sets/base.tgz +curl https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-01-16-netbsd-base.tgz | \ + tar xzf - -C netbsd ./usr/include ./usr/lib ./lib +# originally from: +# https://ftp.netbsd.org/pub/NetBSD/NetBSD-7.0/amd64/binary/sets/comp.tgz +curl https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-01-16-netbsd-comp.tgz | \ + tar xzf - -C netbsd ./usr/include ./usr/lib + +dst=/usr/local/x86_64-unknown-netbsd +cp -r netbsd/usr/include $dst +cp netbsd/usr/lib/crt0.o $dst/lib +cp netbsd/usr/lib/crti.o $dst/lib +cp netbsd/usr/lib/crtn.o $dst/lib +cp netbsd/usr/lib/crtbeginS.o $dst/lib +cp netbsd/usr/lib/crtendS.o $dst/lib +cp netbsd/usr/lib/crtbegin.o $dst/lib +cp netbsd/usr/lib/crtend.o $dst/lib +cp netbsd/usr/lib/gcrt0.o $dst/lib +cp netbsd/usr/lib/libc.a $dst/lib +cp netbsd/usr/lib/libc_p.a $dst/lib +cp netbsd/usr/lib/libc_pic.a $dst/lib +cp netbsd/lib/libc.so.12.193.1 $dst/lib +cp netbsd/lib/libutil.so.7.21 $dst/lib +cp netbsd/usr/lib/libm.a $dst/lib +cp netbsd/usr/lib/libm_p.a $dst/lib +cp netbsd/usr/lib/libm_pic.a $dst/lib +cp netbsd/lib/libm.so.0.11 $dst/lib +cp netbsd/usr/lib/librt.so.1.1 $dst/lib +cp netbsd/usr/lib/libpthread.a $dst/lib +cp netbsd/usr/lib/libpthread_p.a $dst/lib +cp netbsd/usr/lib/libpthread_pic.a $dst/lib +cp netbsd/usr/lib/libpthread.so.1.2 $dst/lib + +ln -s libc.so.12.193.1 $dst/lib/libc.so +ln -s libc.so.12.193.1 $dst/lib/libc.so.12 +ln -s libm.so.0.11 $dst/lib/libm.so +ln -s libm.so.0.11 $dst/lib/libm.so.0 +ln -s libutil.so.7.21 $dst/lib/libutil.so +ln -s libutil.so.7.21 $dst/lib/libutil.so.7 +ln -s libpthread.so.1.2 $dst/lib/libpthread.so +ln -s libpthread.so.1.2 $dst/lib/libpthread.so.1 +ln -s librt.so.1.1 $dst/lib/librt.so + +rm -rf netbsd + +# Finally, download and build gcc to target NetBSD +mkdir gcc +cd gcc +curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf - +cd gcc-$GCC +./contrib/download_prerequisites + +# Originally from +# ftp://ftp.netbsd.org/pub/pkgsrc/pkgsrc-2016Q4/pkgsrc/lang/gcc5/patches/patch-libstdc%2B%2B-v3_config_os_bsd_netbsd_ctype__base.h +PATCHES="https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-01-13-netbsd-patch1.patch" + +# Originally from +# ftp://ftp.netbsd.org/pub/pkgsrc/pkgsrc-2016Q4/pkgsrc/lang/gcc5/patches/patch-libstdc%2B%2B-v3_config_os_bsd_netbsd_ctype__configure__char.cc +PATCHES="$PATCHES https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-01-13-netbsd-patch2.patch" + +for patch in $PATCHES; do + curl $patch | patch -Np0 +done + +mkdir ../gcc-build +cd ../gcc-build +../gcc-$GCC/configure \ + --enable-languages=c,c++ \ + --target=x86_64-unknown-netbsd \ + --disable-libcilkrts \ + --disable-multilib \ + --disable-nls \ + --disable-libgomp \ + --disable-libquadmath \ + --disable-libssp \ + --disable-libvtv \ + --disable-libcilkrt \ + --disable-libada \ + --disable-libsanitizer \ + --disable-libquadmath-support \ + --disable-lto +make -j10 +make install + +cd ../.. +rm -rf gcc diff --git a/src/ci/docker/dist-s390x-linux-netbsd/build-s390x-toolchain.sh b/src/ci/docker/dist-s390x-linux-netbsd/build-s390x-toolchain.sh new file mode 100755 index 0000000000..b4995e20dc --- /dev/null +++ b/src/ci/docker/dist-s390x-linux-netbsd/build-s390x-toolchain.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# 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. + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + rm /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} + +mkdir build +cd build +cp ../s390x-linux-gnu.config .config +hide_output ct-ng build +cd .. +rm -rf build diff --git a/src/ci/docker/dist-s390x-linux-netbsd/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch b/src/ci/docker/dist-s390x-linux-netbsd/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch new file mode 100644 index 0000000000..cba416ed2f --- /dev/null +++ b/src/ci/docker/dist-s390x-linux-netbsd/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch @@ -0,0 +1,63 @@ +From 2739047682590b1df473401b4febf424f857fccf Mon Sep 17 00:00:00 2001 +From: Andreas Krebbel +Date: Sun, 17 Apr 2011 20:43:59 -0400 +Subject: [PATCH] Use .machine to prevent AS from complaining about z9-109 + instructions in iconv modules + +--- + sysdeps/s390/s390-64/utf16-utf32-z9.c | 5 ++++- + sysdeps/s390/s390-64/utf8-utf16-z9.c | 5 ++++- + sysdeps/s390/s390-64/utf8-utf32-z9.c | 5 ++++- + 3 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/sysdeps/s390/s390-64/utf16-utf32-z9.c b/sysdeps/s390/s390-64/utf16-utf32-z9.c +index 14daf2118fe5..5bcaaaedec9c 100644 +--- a/sysdeps/s390/s390-64/utf16-utf32-z9.c ++++ b/sysdeps/s390/s390-64/utf16-utf32-z9.c +@@ -169,7 +169,10 @@ gconv_end (struct __gconv_step *data) + register unsigned long long outlen asm("11") = outend - outptr; \ + uint64_t cc = 0; \ + \ +- asm volatile ("0: " INSTRUCTION " \n\t" \ ++ asm volatile (".machine push \n\t" \ ++ ".machine \"z9-109\" \n\t" \ ++ "0: " INSTRUCTION " \n\t" \ ++ ".machine pop \n\t" \ + " jo 0b \n\t" \ + " ipm %2 \n" \ + : "+a" (pOutput), "+a" (pInput), "+d" (cc), \ +diff --git a/sysdeps/s390/s390-64/utf8-utf16-z9.c b/sysdeps/s390/s390-64/utf8-utf16-z9.c +index 5f73f3c59e21..812a42fae44c 100644 +--- a/sysdeps/s390/s390-64/utf8-utf16-z9.c ++++ b/sysdeps/s390/s390-64/utf8-utf16-z9.c +@@ -151,7 +151,10 @@ gconv_end (struct __gconv_step *data) + register unsigned long long outlen asm("11") = outend - outptr; \ + uint64_t cc = 0; \ + \ +- asm volatile ("0: " INSTRUCTION " \n\t" \ ++ asm volatile (".machine push \n\t" \ ++ ".machine \"z9-109\" \n\t" \ ++ "0: " INSTRUCTION " \n\t" \ ++ ".machine pop \n\t" \ + " jo 0b \n\t" \ + " ipm %2 \n" \ + : "+a" (pOutput), "+a" (pInput), "+d" (cc), \ +diff --git a/sysdeps/s390/s390-64/utf8-utf32-z9.c b/sysdeps/s390/s390-64/utf8-utf32-z9.c +index 17ef8bc890c3..0ffd848c8124 100644 +--- a/sysdeps/s390/s390-64/utf8-utf32-z9.c ++++ b/sysdeps/s390/s390-64/utf8-utf32-z9.c +@@ -155,7 +155,10 @@ gconv_end (struct __gconv_step *data) + register unsigned long long outlen asm("11") = outend - outptr; \ + uint64_t cc = 0; \ + \ +- asm volatile ("0: " INSTRUCTION " \n\t" \ ++ asm volatile (".machine push \n\t" \ ++ ".machine \"z9-109\" \n\t" \ ++ "0: " INSTRUCTION " \n\t" \ ++ ".machine pop \n\t" \ + " jo 0b \n\t" \ + " ipm %2 \n" \ + : "+a" (pOutput), "+a" (pInput), "+d" (cc), \ +-- +2.9.3 + diff --git a/src/ci/docker/dist-s390x-linux-netbsd/s390x-linux-gnu.config b/src/ci/docker/dist-s390x-linux-netbsd/s390x-linux-gnu.config new file mode 100644 index 0000000000..fa5e451098 --- /dev/null +++ b/src/ci/docker/dist-s390x-linux-netbsd/s390x-linux-gnu.config @@ -0,0 +1,508 @@ +# +# Automatically generated file; DO NOT EDIT. +# Crosstool-NG Configuration +# +CT_CONFIGURE_has_make381=y +CT_CONFIGURE_has_xz=y +CT_MODULES=y + +# +# Paths and misc options +# + +# +# crosstool-NG behavior +# +# CT_OBSOLETE is not set +# CT_EXPERIMENTAL is not set +# CT_DEBUG_CT is not set + +# +# Paths +# +CT_LOCAL_TARBALLS_DIR="" +CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_INSTALL_DIR="${CT_PREFIX_DIR}" +CT_RM_RF_PREFIX_DIR=y +CT_REMOVE_DOCS=y +CT_INSTALL_DIR_RO=y +CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y +# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set + +# +# Downloading +# +# CT_FORBID_DOWNLOAD is not set +# CT_FORCE_DOWNLOAD is not set +CT_CONNECT_TIMEOUT=10 +# CT_ONLY_DOWNLOAD is not set +# CT_USE_MIRROR is not set + +# +# Extracting +# +# CT_FORCE_EXTRACT is not set +CT_OVERIDE_CONFIG_GUESS_SUB=y +# CT_ONLY_EXTRACT is not set +# CT_PATCH_BUNDLED is not set +# CT_PATCH_LOCAL is not set +CT_PATCH_BUNDLED_LOCAL=y +# CT_PATCH_LOCAL_BUNDLED is not set +# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set +# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set +# CT_PATCH_NONE is not set +CT_PATCH_ORDER="bundled,local" +CT_PATCH_USE_LOCAL=y +CT_LOCAL_PATCH_DIR="/tmp/patches" + +# +# Build behavior +# +CT_PARALLEL_JOBS=0 +CT_LOAD="" +CT_USE_PIPES=y +CT_EXTRA_CFLAGS_FOR_BUILD="" +CT_EXTRA_LDFLAGS_FOR_BUILD="" +CT_EXTRA_CFLAGS_FOR_HOST="" +CT_EXTRA_LDFLAGS_FOR_HOST="" +# CT_CONFIG_SHELL_SH is not set +# CT_CONFIG_SHELL_ASH is not set +CT_CONFIG_SHELL_BASH=y +# CT_CONFIG_SHELL_CUSTOM is not set +CT_CONFIG_SHELL="${bash}" + +# +# Logging +# +# CT_LOG_ERROR is not set +# CT_LOG_WARN is not set +CT_LOG_INFO=y +# CT_LOG_EXTRA is not set +# CT_LOG_ALL is not set +# CT_LOG_DEBUG is not set +CT_LOG_LEVEL_MAX="INFO" +# CT_LOG_SEE_TOOLS_WARN is not set +CT_LOG_PROGRESS_BAR=y +CT_LOG_TO_FILE=y +CT_LOG_FILE_COMPRESS=y + +# +# Target options +# +CT_ARCH="s390" +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_SUPPORTS_WITH_FPU=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_FPU="" +# CT_ARCH_32 is not set +CT_ARCH_64=y +CT_ARCH_BITNESS=64 +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" +# CT_ARCH_alpha is not set +# CT_ARCH_arm is not set +# CT_ARCH_avr is not set +# CT_ARCH_m68k is not set +# CT_ARCH_mips is not set +# CT_ARCH_nios2 is not set +# CT_ARCH_powerpc is not set +CT_ARCH_s390=y +# CT_ARCH_sh is not set +# CT_ARCH_sparc is not set +# CT_ARCH_x86 is not set +# CT_ARCH_xtensa is not set +CT_ARCH_alpha_AVAILABLE=y +CT_ARCH_arm_AVAILABLE=y +CT_ARCH_avr_AVAILABLE=y +CT_ARCH_m68k_AVAILABLE=y +CT_ARCH_microblaze_AVAILABLE=y +CT_ARCH_mips_AVAILABLE=y +CT_ARCH_nios2_AVAILABLE=y +CT_ARCH_powerpc_AVAILABLE=y +CT_ARCH_s390_AVAILABLE=y +CT_ARCH_sh_AVAILABLE=y +CT_ARCH_sparc_AVAILABLE=y +CT_ARCH_x86_AVAILABLE=y +CT_ARCH_xtensa_AVAILABLE=y +CT_ARCH_SUFFIX="" + +# +# Generic target options +# +# CT_MULTILIB is not set +CT_ARCH_USE_MMU=y + +# +# Target optimisations +# +CT_ARCH_FLOAT="" + +# +# Toolchain options +# + +# +# General toolchain options +# +CT_FORCE_SYSROOT=y +CT_USE_SYSROOT=y +CT_SYSROOT_NAME="sysroot" +CT_SYSROOT_DIR_PREFIX="" +CT_WANTS_STATIC_LINK=y +# CT_STATIC_TOOLCHAIN is not set +CT_TOOLCHAIN_PKGVERSION="" +CT_TOOLCHAIN_BUGURL="" + +# +# Tuple completion and aliasing +# +CT_TARGET_VENDOR="unknown" +CT_TARGET_ALIAS_SED_EXPR="" +CT_TARGET_ALIAS="" + +# +# Toolchain type +# +CT_CROSS=y +# CT_CANADIAN is not set +CT_TOOLCHAIN_TYPE="cross" + +# +# Build system +# +CT_BUILD="" +CT_BUILD_PREFIX="" +CT_BUILD_SUFFIX="" + +# +# Misc options +# +# CT_TOOLCHAIN_ENABLE_NLS is not set + +# +# Operating System +# +CT_KERNEL_SUPPORTS_SHARED_LIBS=y +CT_KERNEL="linux" +CT_KERNEL_VERSION="2.6.32.68" +# CT_KERNEL_bare_metal is not set +CT_KERNEL_linux=y +CT_KERNEL_bare_metal_AVAILABLE=y +CT_KERNEL_linux_AVAILABLE=y +# CT_KERNEL_V_4_3 is not set +# CT_KERNEL_V_4_2 is not set +# CT_KERNEL_V_4_1 is not set +# CT_KERNEL_V_3_18 is not set +# CT_KERNEL_V_3_14 is not set +# CT_KERNEL_V_3_12 is not set +# CT_KERNEL_V_3_10 is not set +# CT_KERNEL_V_3_4 is not set +# CT_KERNEL_V_3_2 is not set +CT_KERNEL_V_2_6_32=y +# CT_KERNEL_LINUX_CUSTOM is not set +CT_KERNEL_windows_AVAILABLE=y + +# +# Common kernel options +# +CT_SHARED_LIBS=y + +# +# linux other options +# +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y + +# +# Binary utilities +# +CT_ARCH_BINFMT_ELF=y +CT_BINUTILS="binutils" +CT_BINUTILS_binutils=y + +# +# GNU binutils +# +# CT_CC_BINUTILS_SHOW_LINARO is not set +CT_BINUTILS_V_2_25_1=y +# CT_BINUTILS_V_2_25 is not set +# CT_BINUTILS_V_2_24 is not set +# CT_BINUTILS_V_2_23_2 is not set +# CT_BINUTILS_V_2_23_1 is not set +# CT_BINUTILS_V_2_22 is not set +# CT_BINUTILS_V_2_21_53 is not set +# CT_BINUTILS_V_2_21_1a is not set +# CT_BINUTILS_V_2_20_1a is not set +# CT_BINUTILS_V_2_19_1a is not set +# CT_BINUTILS_V_2_18a is not set +CT_BINUTILS_VERSION="2.25.1" +CT_BINUTILS_2_25_1_or_later=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_2_24_or_later=y +CT_BINUTILS_2_23_or_later=y +CT_BINUTILS_2_22_or_later=y +CT_BINUTILS_2_21_or_later=y +CT_BINUTILS_2_20_or_later=y +CT_BINUTILS_2_19_or_later=y +CT_BINUTILS_2_18_or_later=y +CT_BINUTILS_HAS_HASH_STYLE=y +CT_BINUTILS_HAS_GOLD=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_LINKER_LD=y +CT_BINUTILS_LINKERS_LIST="ld" +CT_BINUTILS_LINKER_DEFAULT="bfd" +# CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_EXTRA_CONFIG_ARRAY="" +# CT_BINUTILS_FOR_TARGET is not set + +# +# binutils other options +# + +# +# C-library +# +CT_LIBC="glibc" +CT_LIBC_VERSION="2.12.2" +CT_LIBC_glibc=y +# CT_LIBC_musl is not set +# CT_LIBC_uClibc is not set +CT_LIBC_avr_libc_AVAILABLE=y +CT_LIBC_glibc_AVAILABLE=y +CT_THREADS="nptl" +# CT_CC_GLIBC_SHOW_LINARO is not set +# CT_LIBC_GLIBC_V_2_22 is not set +# CT_LIBC_GLIBC_V_2_21 is not set +# CT_LIBC_GLIBC_V_2_20 is not set +# CT_LIBC_GLIBC_V_2_19 is not set +# CT_LIBC_GLIBC_V_2_18 is not set +# CT_LIBC_GLIBC_V_2_17 is not set +# CT_LIBC_GLIBC_V_2_16_0 is not set +# CT_LIBC_GLIBC_V_2_15 is not set +# CT_LIBC_GLIBC_V_2_14_1 is not set +# CT_LIBC_GLIBC_V_2_14 is not set +# CT_LIBC_GLIBC_V_2_13 is not set +CT_LIBC_GLIBC_V_2_12_2=y +# CT_LIBC_GLIBC_V_2_12_1 is not set +# CT_LIBC_GLIBC_V_2_11_1 is not set +# CT_LIBC_GLIBC_V_2_11 is not set +# CT_LIBC_GLIBC_V_2_10_1 is not set +# CT_LIBC_GLIBC_V_2_9 is not set +# CT_LIBC_GLIBC_V_2_8 is not set +CT_LIBC_mingw_AVAILABLE=y +CT_LIBC_musl_AVAILABLE=y +CT_LIBC_newlib_AVAILABLE=y +CT_LIBC_none_AVAILABLE=y +CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_SUPPORT_THREADS_ANY=y +CT_LIBC_SUPPORT_THREADS_NATIVE=y + +# +# Common C library options +# +CT_THREADS_NATIVE=y +CT_LIBC_XLDD=y + +# +# glibc other options +# +CT_LIBC_GLIBC_PORTS_EXTERNAL=y +CT_LIBC_glibc_familly=y +CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_LIBC_GLIBC_CONFIGPARMS="" +CT_LIBC_GLIBC_EXTRA_CFLAGS="" +CT_LIBC_EXTRA_CC_ARGS="" +# CT_LIBC_DISABLE_VERSIONING is not set +CT_LIBC_OLDEST_ABI="" +CT_LIBC_GLIBC_FORCE_UNWIND=y +# CT_LIBC_GLIBC_USE_PORTS is not set +CT_LIBC_ADDONS_LIST="" +# CT_LIBC_LOCALES is not set +# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set +CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_LIBC_GLIBC_MIN_KERNEL="2.6.32.68" + +# +# C compiler +# +CT_CC="gcc" +CT_CC_CORE_PASSES_NEEDED=y +CT_CC_CORE_PASS_1_NEEDED=y +CT_CC_CORE_PASS_2_NEEDED=y +CT_CC_gcc=y +# CT_CC_GCC_SHOW_LINARO is not set +# CT_CC_GCC_V_5_2_0 is not set +CT_CC_GCC_V_4_9_3=y +# CT_CC_GCC_V_4_8_5 is not set +# CT_CC_GCC_V_4_7_4 is not set +# CT_CC_GCC_V_4_6_4 is not set +# CT_CC_GCC_V_4_5_4 is not set +# CT_CC_GCC_V_4_4_7 is not set +# CT_CC_GCC_V_4_3_6 is not set +# CT_CC_GCC_V_4_2_4 is not set +CT_CC_GCC_4_2_or_later=y +CT_CC_GCC_4_3_or_later=y +CT_CC_GCC_4_4_or_later=y +CT_CC_GCC_4_5_or_later=y +CT_CC_GCC_4_6_or_later=y +CT_CC_GCC_4_7_or_later=y +CT_CC_GCC_4_8_or_later=y +CT_CC_GCC_4_9=y +CT_CC_GCC_4_9_or_later=y +CT_CC_GCC_HAS_GRAPHITE=y +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_HAS_LTO=y +CT_CC_GCC_USE_LTO=y +CT_CC_GCC_HAS_PKGVERSION_BUGURL=y +CT_CC_GCC_HAS_BUILD_ID=y +CT_CC_GCC_HAS_LNK_HASH_STYLE=y +CT_CC_GCC_USE_GMP_MPFR=y +CT_CC_GCC_USE_MPC=y +CT_CC_GCC_HAS_LIBQUADMATH=y +CT_CC_GCC_HAS_LIBSANITIZER=y +CT_CC_GCC_VERSION="4.9.3" +# CT_CC_LANG_FORTRAN is not set +CT_CC_GCC_ENABLE_CXX_FLAGS="" +CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-arch=z10" +CT_CC_GCC_EXTRA_ENV_ARRAY="" +CT_CC_GCC_STATIC_LIBSTDCXX=y +# CT_CC_GCC_SYSTEM_ZLIB is not set + +# +# Optimisation features +# + +# +# Settings for libraries running on target +# +CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y +# CT_CC_GCC_LIBMUDFLAP is not set +# CT_CC_GCC_LIBGOMP is not set +# CT_CC_GCC_LIBSSP is not set +# CT_CC_GCC_LIBQUADMATH is not set +# CT_CC_GCC_LIBSANITIZER is not set + +# +# Misc. obscure options. +# +CT_CC_CXA_ATEXIT=y +# CT_CC_GCC_DISABLE_PCH is not set +CT_CC_GCC_SJLJ_EXCEPTIONS=m +CT_CC_GCC_LDBL_128=m +# CT_CC_GCC_BUILD_ID is not set +CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y +# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set +# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set +# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set +CT_CC_GCC_LNK_HASH_STYLE="" +CT_CC_GCC_DEC_FLOAT_AUTO=y +# CT_CC_GCC_DEC_FLOAT_BID is not set +# CT_CC_GCC_DEC_FLOAT_DPD is not set +# CT_CC_GCC_DEC_FLOATS_NO is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_JAVA=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y + +# +# Additional supported languages: +# +CT_CC_LANG_CXX=y +# CT_CC_LANG_JAVA is not set + +# +# Debug facilities +# +# CT_DEBUG_dmalloc is not set +# CT_DEBUG_duma is not set +# CT_DEBUG_gdb is not set +# CT_DEBUG_ltrace is not set +# CT_DEBUG_strace is not set + +# +# Companion libraries +# +CT_COMPLIBS_NEEDED=y +CT_LIBICONV_NEEDED=y +CT_GETTEXT_NEEDED=y +CT_GMP_NEEDED=y +CT_MPFR_NEEDED=y +CT_ISL_NEEDED=y +CT_CLOOG_NEEDED=y +CT_MPC_NEEDED=y +CT_COMPLIBS=y +CT_LIBICONV=y +CT_GETTEXT=y +CT_GMP=y +CT_MPFR=y +CT_ISL=y +CT_CLOOG=y +CT_MPC=y +CT_LIBICONV_V_1_14=y +CT_LIBICONV_VERSION="1.14" +CT_GETTEXT_V_0_19_6=y +CT_GETTEXT_VERSION="0.19.6" +CT_GMP_V_6_0_0=y +# CT_GMP_V_5_1_3 is not set +# CT_GMP_V_5_1_1 is not set +# CT_GMP_V_5_0_2 is not set +# CT_GMP_V_5_0_1 is not set +# CT_GMP_V_4_3_2 is not set +# CT_GMP_V_4_3_1 is not set +# CT_GMP_V_4_3_0 is not set +CT_GMP_5_0_2_or_later=y +CT_GMP_VERSION="6.0.0a" +CT_MPFR_V_3_1_3=y +# CT_MPFR_V_3_1_2 is not set +# CT_MPFR_V_3_1_0 is not set +# CT_MPFR_V_3_0_1 is not set +# CT_MPFR_V_3_0_0 is not set +# CT_MPFR_V_2_4_2 is not set +# CT_MPFR_V_2_4_1 is not set +# CT_MPFR_V_2_4_0 is not set +CT_MPFR_VERSION="3.1.3" +CT_ISL_V_0_14=y +CT_ISL_V_0_14_or_later=y +CT_ISL_V_0_12_or_later=y +CT_ISL_VERSION="0.14" +CT_CLOOG_V_0_18_4=y +# CT_CLOOG_V_0_18_1 is not set +# CT_CLOOG_V_0_18_0 is not set +CT_CLOOG_VERSION="0.18.4" +CT_CLOOG_0_18_4_or_later=y +CT_CLOOG_0_18_or_later=y +CT_MPC_V_1_0_3=y +# CT_MPC_V_1_0_2 is not set +# CT_MPC_V_1_0_1 is not set +# CT_MPC_V_1_0 is not set +# CT_MPC_V_0_9 is not set +# CT_MPC_V_0_8_2 is not set +# CT_MPC_V_0_8_1 is not set +# CT_MPC_V_0_7 is not set +CT_MPC_VERSION="1.0.3" + +# +# Companion libraries common options +# +# CT_COMPLIBS_CHECK is not set + +# +# Companion tools +# + +# +# READ HELP before you say 'Y' below !!! +# +# CT_COMP_TOOLS is not set diff --git a/src/ci/docker/dist-x86-linux/Dockerfile b/src/ci/docker/dist-x86-linux/Dockerfile new file mode 100644 index 0000000000..4e4f5dd6f1 --- /dev/null +++ b/src/ci/docker/dist-x86-linux/Dockerfile @@ -0,0 +1,80 @@ +FROM centos:5 + +WORKDIR /build + +RUN yum upgrade -y && yum install -y \ + curl \ + bzip2 \ + gcc \ + make \ + glibc-devel \ + perl \ + zlib-devel \ + file \ + xz \ + which \ + pkg-config \ + wget \ + autoconf \ + gettext + +ENV PATH=/rustroot/bin:$PATH +ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib +WORKDIR /tmp + +# binutils < 2.22 has a bug where the 32-bit executables it generates +# immediately segfault in Rust, so we need to install our own binutils. +# +# See https://github.com/rust-lang/rust/issues/20440 for more info +COPY shared.sh build-binutils.sh /tmp/ +RUN ./build-binutils.sh + +# Need a newer version of gcc than centos has to compile LLVM nowadays +COPY build-gcc.sh /tmp/ +RUN ./build-gcc.sh + +# We need a build of openssl which supports SNI to download artifacts from +# static.rust-lang.org. This'll be used to link into libcurl below (and used +# later as well), so build a copy of OpenSSL with dynamic libraries into our +# generic root. +COPY build-openssl.sh /tmp/ +RUN ./build-openssl.sh + +# The `curl` binary on CentOS doesn't support SNI which is needed for fetching +# some https urls we have, so install a new version of libcurl + curl which is +# using the openssl we just built previously. +# +# Note that we also disable a bunch of optional features of curl that we don't +# really need. +COPY build-curl.sh /tmp/ +RUN ./build-curl.sh + +# CentOS 5.5 has Python 2.4 by default, but LLVM needs 2.7+ +COPY build-python.sh /tmp/ +RUN ./build-python.sh + +# Apparently CentOS 5.5 desn't have `git` in yum, but we're gonna need it for +# cloning, so download and build it here. +COPY build-git.sh /tmp/ +RUN ./build-git.sh + +# libssh2 (a dependency of Cargo) requires cmake 2.8.11 or higher but CentOS +# only has 2.6.4, so build our own +COPY build-cmake.sh /tmp/ +RUN ./build-cmake.sh + +RUN curl -Lo /rustroot/dumb-init \ + https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && \ + chmod +x /rustroot/dumb-init +ENTRYPOINT ["/rustroot/dumb-init", "--"] + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + xz --decompress | \ + tar xf - -C /usr/local/bin --strip-components=1 + +ENV HOSTS=i686-unknown-linux-gnu +ENV HOSTS=$HOSTS,x86_64-unknown-linux-gnu + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-x86-linux/build-binutils.sh b/src/ci/docker/dist-x86-linux/build-binutils.sh new file mode 100755 index 0000000000..80aa1f2a01 --- /dev/null +++ b/src/ci/docker/dist-x86-linux/build-binutils.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# 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. + +set -ex + +source shared.sh + +curl https://ftp.gnu.org/gnu/binutils/binutils-2.25.1.tar.bz2 | tar xfj - + +mkdir binutils-build +cd binutils-build +hide_output ../binutils-2.25.1/configure --prefix=/rustroot +hide_output make -j10 +hide_output make install + +cd .. +rm -rf binutils-build +rm -rf binutils-2.25.1 diff --git a/src/ci/docker/dist-x86-linux/build-cmake.sh b/src/ci/docker/dist-x86-linux/build-cmake.sh new file mode 100755 index 0000000000..82e46455cb --- /dev/null +++ b/src/ci/docker/dist-x86-linux/build-cmake.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# 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. + +set -ex +source shared.sh + +curl https://cmake.org/files/v3.6/cmake-3.6.3.tar.gz | tar xzf - + +mkdir cmake-build +cd cmake-build +hide_output ../cmake-3.6.3/configure --prefix=/rustroot +hide_output make -j10 +hide_output make install + +cd .. +rm -rf cmake-build +rm -rf cmake-3.6.3 diff --git a/src/ci/docker/dist-x86-linux/build-curl.sh b/src/ci/docker/dist-x86-linux/build-curl.sh new file mode 100755 index 0000000000..b7d22755a5 --- /dev/null +++ b/src/ci/docker/dist-x86-linux/build-curl.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# 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. + +set -ex +source shared.sh + +VERSION=7.51.0 + +curl http://cool.haxx.se/download/curl-$VERSION.tar.bz2 | tar xjf - + +mkdir curl-build +cd curl-build +hide_output ../curl-$VERSION/configure \ + --prefix=/rustroot \ + --with-ssl=/rustroot \ + --disable-sspi \ + --disable-gopher \ + --disable-smtp \ + --disable-smb \ + --disable-imap \ + --disable-pop3 \ + --disable-tftp \ + --disable-telnet \ + --disable-manual \ + --disable-dict \ + --disable-rtsp \ + --disable-ldaps \ + --disable-ldap +hide_output make -j10 +hide_output make install + +cd .. +rm -rf curl-build +rm -rf curl-$VERSION +yum erase -y curl diff --git a/src/ci/docker/dist-x86-linux/build-gcc.sh b/src/ci/docker/dist-x86-linux/build-gcc.sh new file mode 100755 index 0000000000..06198eb0c9 --- /dev/null +++ b/src/ci/docker/dist-x86-linux/build-gcc.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# 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. + +set -ex + +source shared.sh + +curl https://ftp.gnu.org/gnu/gcc/gcc-4.7.4/gcc-4.7.4.tar.bz2 | tar xjf - +cd gcc-4.7.4 +./contrib/download_prerequisites +mkdir ../gcc-build +cd ../gcc-build +hide_output ../gcc-4.7.4/configure \ + --prefix=/rustroot \ + --enable-languages=c,c++ +hide_output make -j10 +hide_output make install +ln -nsf gcc /rustroot/bin/cc + +cd .. +rm -rf gcc-build +rm -rf gcc-4.7.4 +yum erase -y gcc binutils diff --git a/src/ci/docker/dist-x86-linux/build-git.sh b/src/ci/docker/dist-x86-linux/build-git.sh new file mode 100755 index 0000000000..92fa66b496 --- /dev/null +++ b/src/ci/docker/dist-x86-linux/build-git.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# 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. + +set -ex +source shared.sh + +curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf - + +cd git-2.10.0 +make configure +hide_output ./configure --prefix=/rustroot +hide_output make -j10 +hide_output make install + +cd .. +rm -rf git-2.10.0 diff --git a/src/ci/docker/dist-x86-linux/build-openssl.sh b/src/ci/docker/dist-x86-linux/build-openssl.sh new file mode 100755 index 0000000000..64b1abf82a --- /dev/null +++ b/src/ci/docker/dist-x86-linux/build-openssl.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# 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. + +set -ex +source shared.sh + +VERSION=1.0.2j + +curl https://www.openssl.org/source/openssl-$VERSION.tar.gz | tar xzf - + +cd openssl-$VERSION +hide_output ./config --prefix=/rustroot shared -fPIC +hide_output make -j10 +hide_output make install +cd .. +rm -rf openssl-$VERSION + +# Make the system cert collection available to the new install. +ln -nsf /etc/pki/tls/cert.pem /rustroot/ssl/ diff --git a/src/ci/docker/dist-x86-linux/build-python.sh b/src/ci/docker/dist-x86-linux/build-python.sh new file mode 100755 index 0000000000..a7a450f3c8 --- /dev/null +++ b/src/ci/docker/dist-x86-linux/build-python.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# 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. + +set -ex +source shared.sh + +curl https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tgz | \ + tar xzf - + +mkdir python-build +cd python-build + +# Gotta do some hackery to tell python about our custom OpenSSL build, but other +# than that fairly normal. +CFLAGS='-I /rustroot/include' LDFLAGS='-L /rustroot/lib -L /rustroot/lib64' \ + hide_output ../Python-2.7.12/configure --prefix=/rustroot +hide_output make -j10 +hide_output make install + +cd .. +rm -rf python-build +rm -rf Python-2.7.12 diff --git a/src/ci/docker/dist-x86-linux/shared.sh b/src/ci/docker/dist-x86-linux/shared.sh new file mode 100644 index 0000000000..97e6d2908c --- /dev/null +++ b/src/ci/docker/dist-x86-linux/shared.sh @@ -0,0 +1,25 @@ +# 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. + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} diff --git a/src/ci/docker/emscripten/Dockerfile b/src/ci/docker/emscripten/Dockerfile new file mode 100644 index 0000000000..84e12eb6c3 --- /dev/null +++ b/src/ci/docker/emscripten/Dockerfile @@ -0,0 +1,41 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + lib32stdc++6 + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +WORKDIR /tmp +COPY build-emscripten.sh /tmp/ +RUN ./build-emscripten.sh +ENV PATH=$PATH:/tmp/emsdk_portable +ENV PATH=$PATH:/tmp/emsdk_portable/clang/tag-e1.37.1/build_tag-e1.37.1_32/bin +ENV PATH=$PATH:/tmp/emsdk_portable/node/4.1.1_32bit/bin +ENV PATH=$PATH:/tmp/emsdk_portable/emscripten/tag-1.37.1 +ENV EMSCRIPTEN=/tmp/emsdk_portable/emscripten/tag-1.37.1 + +ENV RUST_CONFIGURE_ARGS --target=asmjs-unknown-emscripten + +# Run `emcc` first as it's got a prompt and doesn't actually do anything, after +# that's done with do the real build. +ENV SCRIPT emcc && \ + python2.7 ../x.py test --target asmjs-unknown-emscripten + diff --git a/src/ci/docker/emscripten/build-emscripten.sh b/src/ci/docker/emscripten/build-emscripten.sh new file mode 100755 index 0000000000..88bf583007 --- /dev/null +++ b/src/ci/docker/emscripten/build-emscripten.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# 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. + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + rm /tmp/build.log + set -x +} + +curl https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ + tar xzf - +source emsdk_portable/emsdk_env.sh +hide_output emsdk update +hide_output emsdk install --build=Release sdk-tag-1.37.1-32bit +hide_output emsdk activate --build=Release sdk-tag-1.37.1-32bit diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile index 1da33c94c7..1ffb24981c 100644 --- a/src/ci/docker/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/i686-gnu-nopt/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils @@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile index 9e5b0e0435..6583f09be3 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils @@ -24,6 +23,4 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu -ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj +ENV SCRIPT python2.7 ../x.py test && python2.7 ../x.py dist diff --git a/src/ci/docker/linux-tested-targets/Dockerfile b/src/ci/docker/linux-tested-targets/Dockerfile new file mode 100644 index 0000000000..2a43201ed0 --- /dev/null +++ b/src/ci/docker/linux-tested-targets/Dockerfile @@ -0,0 +1,44 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++-multilib \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + xz-utils \ + sudo \ + gdb \ + patch + +WORKDIR /build/ +COPY musl-libunwind-patch.patch build-musl.sh /build/ +RUN sh /build/build-musl.sh && rm -rf /build + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +ENV RUST_CONFIGURE_ARGS \ + --target=x86_64-unknown-linux-musl,i686-unknown-linux-musl,i586-unknown-linux-gnu \ + --musl-root-x86_64=/musl-x86_64 \ + --musl-root-i686=/musl-i686 + +ENV SCRIPT \ + python2.7 ../x.py test \ + --target x86_64-unknown-linux-musl \ + --target i686-unknown-linux-musl \ + --target i586-unknown-linux-gnu \ + && \ + python2.7 ../x.py dist \ + --target x86_64-unknown-linux-musl \ + --target i686-unknown-linux-musl \ + --target i586-unknown-linux-gnu diff --git a/src/ci/docker/linux-tested-targets/build-musl.sh b/src/ci/docker/linux-tested-targets/build-musl.sh new file mode 100644 index 0000000000..260dc11509 --- /dev/null +++ b/src/ci/docker/linux-tested-targets/build-musl.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# 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. + +set -ex + +export CFLAGS="-fPIC" +MUSL=musl-1.1.14 +curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf - +cd $MUSL +./configure --prefix=/musl-x86_64 --disable-shared +make -j10 +make install +make clean +# for i686 +CFLAGS="$CFLAGS -m32" ./configure --prefix=/musl-i686 --disable-shared --target=i686 +make -j10 +make install +cd .. + +# To build MUSL we're going to need a libunwind lying around, so acquire that +# here and build it. +curl -L https://github.com/llvm-mirror/llvm/archive/release_37.tar.gz | tar xzf - +curl -L https://github.com/llvm-mirror/libunwind/archive/release_37.tar.gz | tar xzf - + +# Whoa what's this mysterious patch we're applying to libunwind! Why are we +# swapping the values of ESP/EBP in libunwind?! +# +# Discovered in #35599 it turns out that the vanilla build of libunwind is not +# suitable for unwinding 32-bit musl. After some investigation it ended up +# looking like the register values for ESP/EBP were indeed incorrect (swapped) +# in the source. Similar commits in libunwind (r280099 and r282589) have noticed +# this for other platforms, and we just need to realize it for musl linux as +# well. +# +# More technical info can be found at #35599 +cd libunwind-release_37 +patch -Np1 < /build/musl-libunwind-patch.patch +cd .. + +mkdir libunwind-build +cd libunwind-build +cmake ../libunwind-release_37 -DLLVM_PATH=/build/llvm-release_37 \ + -DLIBUNWIND_ENABLE_SHARED=0 +make -j10 +cp lib/libunwind.a /musl-x86_64/lib + +# (Note: the next cmake call doesn't fully override the previous cached one, so remove the cached +# configuration manually. IOW, if don't do this or call make clean we'll end up building libunwind +# for x86_64 again) +rm -rf * +# for i686 +CFLAGS="$CFLAGS -m32" CXXFLAGS="$CXXFLAGS -m32" cmake ../libunwind-release_37 \ + -DLLVM_PATH=/build/llvm-release_37 \ + -DLIBUNWIND_ENABLE_SHARED=0 +make -j10 +cp lib/libunwind.a /musl-i686/lib diff --git a/src/ci/docker/linux-tested-targets/musl-libunwind-patch.patch b/src/ci/docker/linux-tested-targets/musl-libunwind-patch.patch new file mode 100644 index 0000000000..99cd685b72 --- /dev/null +++ b/src/ci/docker/linux-tested-targets/musl-libunwind-patch.patch @@ -0,0 +1,15 @@ +diff --git a/include/libunwind.h b/include/libunwind.h +index c5b9633..1360eb2 100644 +--- a/include/libunwind.h ++++ b/include/libunwind.h +@@ -151,8 +151,8 @@ enum { + UNW_X86_ECX = 1, + UNW_X86_EDX = 2, + UNW_X86_EBX = 3, +- UNW_X86_EBP = 4, +- UNW_X86_ESP = 5, ++ UNW_X86_ESP = 4, ++ UNW_X86_EBP = 5, + UNW_X86_ESI = 6, + UNW_X86_EDI = 7 + }; diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index ce8b49a92d..0ddab8c416 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -25,22 +25,32 @@ docker \ -t rust-ci \ "`dirname "$script"`/$image" +objdir=$root_dir/obj + mkdir -p $HOME/.cargo -mkdir -p $root_dir/obj +mkdir -p $objdir + +args= +if [ "$SCCACHE_BUCKET" != "" ]; then + args="$args --env SCCACHE_BUCKET=$SCCACHE_BUCKET" + args="$args --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" + args="$args --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" +else + mkdir -p $HOME/.cache/sccache + args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache" +fi exec docker \ run \ --volume "$root_dir:/checkout:ro" \ - --volume "$root_dir/obj:/checkout/obj" \ + --volume "$objdir:/checkout/obj" \ --workdir /checkout/obj \ --env SRC=/checkout \ - --env SCCACHE_BUCKET=$SCCACHE_BUCKET \ - --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ - --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \ + $args \ --env CARGO_HOME=/cargo \ + --env DEPLOY=$DEPLOY \ --env LOCAL_USER_ID=`id -u` \ --volume "$HOME/.cargo:/cargo" \ - --interactive \ - --tty \ + --rm \ rust-ci \ /checkout/src/ci/run.sh diff --git a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile b/src/ci/docker/x86_64-gnu-aux/Dockerfile similarity index 88% rename from src/ci/docker/x86_64-gnu-cargotest/Dockerfile rename to src/ci/docker/x86_64-gnu-aux/Dockerfile index 0d9835e86d..0ec0bfd189 100644 --- a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile +++ b/src/ci/docker/x86_64-gnu-aux/Dockerfile @@ -9,10 +9,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ libssl-dev \ sudo \ - xz-utils + xz-utils \ + pkg-config ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ @@ -24,7 +24,5 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu -ENV RUST_CHECK_TARGET check-cargotest +ENV RUST_CHECK_TARGET check-aux ENV NO_VENDOR 1 -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index eec8844229..f54e4e562f 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils @@ -27,6 +26,4 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-debug \ --enable-optimize -ENV RUST_CHECK_TARGET "" -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj +ENV SCRIPT python2.7 ../x.py build diff --git a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile new file mode 100644 index 0000000000..57a2c103f1 --- /dev/null +++ b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile @@ -0,0 +1,26 @@ +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 \ + gdb \ + xz-utils + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu +ENV SCRIPT python2.7 ../x.py test distcheck diff --git a/src/ci/docker/x86_64-musl/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile similarity index 62% rename from src/ci/docker/x86_64-musl/Dockerfile rename to src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile index 96b38067cb..206103b92e 100644 --- a/src/ci/docker/x86_64-musl/Dockerfile +++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile @@ -9,30 +9,20 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ - xz-utils \ sudo \ - gdb + gdb \ + xz-utils -WORKDIR /build/ -COPY build-musl.sh /build/ -RUN sh /build/build-musl.sh && rm -rf /build +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ dpkg -i dumb-init_*.deb && \ rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 -RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ - tar xJf - -C /usr/local/bin --strip-components=1 - ENV RUST_CONFIGURE_ARGS \ - --target=x86_64-unknown-linux-musl \ - --musl-root-x86_64=/musl-x86_64 -ENV RUST_CHECK_TARGET check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu -ENV PATH=$PATH:/musl-x86_64/bin -ENV XPY_CHECK test --target x86_64-unknown-linux-musl - -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj + --build=x86_64-unknown-linux-gnu \ + --enable-full-bootstrap +ENV SCRIPT python2.7 ../x.py build diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile new file mode 100644 index 0000000000..3e084f4a3c --- /dev/null +++ b/src/ci/docker/x86_64-gnu-incremental/Dockerfile @@ -0,0 +1,27 @@ +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 \ + gdb \ + xz-utils + +ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 +RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ + tar xJf - -C /usr/local/bin --strip-components=1 + +RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ + dpkg -i dumb-init_*.deb && \ + rm dumb-init_*.deb +ENTRYPOINT ["/usr/bin/dumb-init", "--"] + +ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu +ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache +ENV RUST_CHECK_TARGET check diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile index 4c9198d88e..aabfc0cd1b 100644 --- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ llvm-3.7-tools \ @@ -30,5 +29,3 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-3.7 ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu-make/Dockerfile b/src/ci/docker/x86_64-gnu-make/Dockerfile index 1c503aea13..c6071d704f 100644 --- a/src/ci/docker/x86_64-gnu-make/Dockerfile +++ b/src/ci/docker/x86_64-gnu-make/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils @@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile index 66de6ea13a..d28dc3de1b 100644 --- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils @@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index 3d71b7ffb9..6919487e17 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ git \ cmake \ - ccache \ sudo \ gdb \ xz-utils @@ -24,6 +23,4 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini ENTRYPOINT ["/usr/bin/dumb-init", "--"] ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu -ENV RUST_CHECK_TARGET check -RUN mkdir /tmp/obj -RUN chmod 777 /tmp/obj +ENV SCRIPT python2.7 ../x.py test && python2.7 ../x.py dist diff --git a/src/ci/docker/x86_64-musl/build-musl.sh b/src/ci/docker/x86_64-musl/build-musl.sh deleted file mode 100644 index 2bfbd646b7..0000000000 --- a/src/ci/docker/x86_64-musl/build-musl.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -# 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. - -set -ex - -export CFLAGS="-fPIC" -MUSL=musl-1.1.14 -curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf - -cd $MUSL -./configure --prefix=/musl-x86_64 --disable-shared -make -j10 -make install -make clean -cd .. - -# To build MUSL we're going to need a libunwind lying around, so acquire that -# here and build it. -curl -L https://github.com/llvm-mirror/llvm/archive/release_37.tar.gz | tar xzf - -curl -L https://github.com/llvm-mirror/libunwind/archive/release_37.tar.gz | tar xzf - -mkdir libunwind-build -cd libunwind-build -cmake ../libunwind-release_37 -DLLVM_PATH=/build/llvm-release_37 \ - -DLIBUNWIND_ENABLE_SHARED=0 -make -j10 -cp lib/libunwind.a /musl-x86_64/lib diff --git a/src/ci/run.sh b/src/ci/run.sh index 152694346a..5f0abb02cc 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -18,35 +18,54 @@ if [ "$LOCAL_USER_ID" != "" ]; then exec su --preserve-environment -c "env PATH=$PATH \"$0\"" user fi -if [ "$NO_LLVM_ASSERTIONS" = "" ]; then - ENABLE_LLVM_ASSERTIONS=--enable-llvm-assertions +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache" +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-quiet-tests" +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules" + +# If we're deploying artifacts then we set the release channel, otherwise if +# we're not deploying then we want to be sure to enable all assertions becauase +# we'll be running tests +# +# FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` +# either automatically or manually. +if [ "$DEPLOY" != "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=beta" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" + + if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" + fi +else + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-debug-assertions" + + # In general we always want to run tests with LLVM assertions enabled, but not + # all platforms currently support that, so we have an option to disable. + if [ "$NO_LLVM_ASSERTIONS" = "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-assertions" + fi fi +# We want to enable usage of the `src/vendor` dir as much as possible, but not +# all test suites have all their deps in there (just the main bootstrap) so we +# have the ability to disable this flag if [ "$NO_VENDOR" = "" ]; then - ENABLE_VENDOR=--enable-vendor + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-vendor" fi set -ex -$SRC/configure \ - --disable-manage-submodules \ - --enable-debug-assertions \ - --enable-quiet-tests \ - --enable-sccache \ - $ENABLE_VENDOR \ - $ENABLE_LLVM_ASSERTIONS \ - $RUST_CONFIGURE_ARGS +$SRC/configure $RUST_CONFIGURE_ARGS if [ "$TRAVIS_OS_NAME" = "osx" ]; then ncpus=$(sysctl -n hw.ncpu) else - ncpus=$(nproc) + ncpus=$(grep processor /proc/cpuinfo | wc -l) fi -make -j $ncpus tidy -make -j $ncpus -if [ ! -z "$XPY_CHECK" ]; then - exec python2.7 $SRC/x.py $XPY_CHECK +if [ ! -z "$SCRIPT" ]; then + sh -x -c "$SCRIPT" else - exec make $RUST_CHECK_TARGET -j $ncpus + make -j $ncpus tidy + make -j $ncpus + make $RUST_CHECK_TARGET -j $ncpus fi diff --git a/src/doc/book/casting-between-types.md b/src/doc/book/casting-between-types.md index 296384ab6e..a8f8224c58 100644 --- a/src/doc/book/casting-between-types.md +++ b/src/doc/book/casting-between-types.md @@ -16,18 +16,18 @@ function result. The most common case of coercion is removing mutability from a reference: - * `&mut T` to `&T` +* `&mut T` to `&T` An analogous conversion is to remove mutability from a [raw pointer](raw-pointers.md): - * `*mut T` to `*const T` +* `*mut T` to `*const T` References can also be coerced to raw pointers: - * `&T` to `*const T` +* `&T` to `*const T` - * `&mut T` to `*mut T` +* `&mut T` to `*mut T` Custom coercions may be defined using [`Deref`](deref-coercions.md). @@ -59,11 +59,11 @@ A cast `e as U` is valid if `e` has type `T` and `T` *coerces* to `U`. A cast `e as U` is also valid in any of the following cases: - * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast* - * `e` is a C-like enum (with no data attached to the variants), - and `U` is an integer type; *enum-cast* - * `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast* - * `e` has type `u8` and `U` is `char`; *u8-char-cast* +* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast* +* `e` is a C-like enum (with no data attached to the variants), + and `U` is an integer type; *enum-cast* +* `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast* +* `e` has type `u8` and `U` is `char`; *u8-char-cast* For example diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index a3c7333c6b..115fe1f766 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -283,7 +283,7 @@ fn call_with_one(some_closure: F) -> i32 # some_closure(1) } ``` -We take one parameter, and it has the type `F`. We also return a `i32`. This part +We take one parameter, and it has the type `F`. We also return an `i32`. This part isn’t interesting. The next part is: ```rust @@ -293,7 +293,7 @@ isn’t interesting. The next part is: ``` Because `Fn` is a trait, we can use it as a bound for our generic type. In -this case, our closure takes a `i32` as an argument and returns an `i32`, and +this case, our closure takes an `i32` as an argument and returns an `i32`, and so the generic bound we use is `Fn(i32) -> i32`. There’s one other key point here: because we’re bounding a generic with a diff --git a/src/doc/book/documentation.md b/src/doc/book/documentation.md index f30a95b4e7..dafcffc39c 100644 --- a/src/doc/book/documentation.md +++ b/src/doc/book/documentation.md @@ -460,8 +460,9 @@ not actually pass as a test. ``` The `no_run` attribute will compile your code, but not run it. This is -important for examples such as "Here's how to start up a network service," -which you would want to make sure compile, but might run in an infinite loop! +important for examples such as "Here's how to retrieve a web page," +which you would want to ensure compiles, but might be run in a test +environment that has no network access. ### Documenting modules diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index b53af69442..8d29f11aa0 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -56,9 +56,9 @@ almost any function that takes a pointer argument isn't valid for all possible inputs since the pointer could be dangling, and raw pointers fall outside of Rust's safe memory model. -When declaring the argument types to a foreign function, the Rust compiler can -not check if the declaration is correct, so specifying it correctly is part of -keeping the binding correct at runtime. +When declaring the argument types to a foreign function, the Rust compiler +cannot check if the declaration is correct, so specifying it correctly is part +of keeping the binding correct at runtime. The `extern` block can be extended to cover the entire snappy API: @@ -309,7 +309,7 @@ However it is often desired that the callback is targeted to a special Rust object. This could be the object that represents the wrapper for the respective C object. -This can be achieved by passing an raw pointer to the object down to the +This can be achieved by passing a raw pointer to the object down to the C library. The C library can then include the pointer to the Rust object in the notification. This will allow the callback to unsafely access the referenced Rust object. @@ -574,6 +574,31 @@ The [`libc` crate on crates.io][libc] includes type aliases and function definitions for the C standard library in the `libc` module, and Rust links against `libc` and `libm` by default. +# Variadic functions + +In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can +be achieved in Rust by specifying `...` within the argument list of a foreign function declaration: + +```no_run +extern { + fn foo(x: i32, ...); +} + +fn main() { + unsafe { + foo(10, 20, 30, 40, 50); + } +} +``` + +Normal Rust functions can *not* be variadic: + +```ignore +// This will not compile + +fn foo(x: i32, ...) { } +``` + # The "nullable pointer optimization" Certain Rust types are defined to never be `null`. This includes references (`&T`, @@ -685,7 +710,7 @@ Please note that [`catch_unwind()`] will only catch unwinding panics, not those who abort the process. See the documentation of [`catch_unwind()`] for more information. -[`catch_unwind()`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html +[`catch_unwind()`]: ../std/panic/fn.catch_unwind.html # Representing opaque structs diff --git a/src/doc/book/lang-items.md b/src/doc/book/lang-items.md index 6a08c1b6bb..0d6a142ca4 100644 --- a/src/doc/book/lang-items.md +++ b/src/doc/book/lang-items.md @@ -16,15 +16,12 @@ and one for deallocation. A freestanding program that uses the `Box` sugar for dynamic allocations via `malloc` and `free`: ```rust,ignore -#![feature(lang_items, box_syntax, start, libc)] +#![feature(lang_items, box_syntax, start, libc, core_intrinsics)] #![no_std] +use core::intrinsics; extern crate libc; -extern { - fn abort() -> !; -} - #[lang = "owned_box"] pub struct Box(*mut T); @@ -34,7 +31,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { // Check if `malloc` failed: if p as usize == 0 { - abort(); + intrinsics::abort(); } p @@ -58,7 +55,7 @@ fn main(argc: isize, argv: *const *const u8) -> isize { } #[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { loop {} } +#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } } # #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} # #[no_mangle] pub extern fn rust_eh_register_frames () {} # #[no_mangle] pub extern fn rust_eh_unregister_frames () {} diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 140e27d192..546e66fc8a 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -128,7 +128,7 @@ _descriptive_, not _prescriptive_. This means that how long a reference is valid is determined by the code, not by the annotations. The annotations, however, give information about lifetimes to the compiler that uses them to check the validity of references. The compiler can do so without annotations in simple -cases, but needs the programmers support in complex scenarios. +cases, but needs the programmer's support in complex scenarios. [traits]: traits.html diff --git a/src/doc/book/match.md b/src/doc/book/match.md index d01a20083e..52d3c6ae92 100644 --- a/src/doc/book/match.md +++ b/src/doc/book/match.md @@ -82,7 +82,7 @@ fn process_message(msg: Message) { match msg { Message::Quit => quit(), Message::ChangeColor(r, g, b) => change_color(r, g, b), - Message::Move { x: x, y: y } => move_cursor(x, y), + Message::Move { x, y: new_name_for_y } => move_cursor(x, new_name_for_y), Message::Write(s) => println!("{}", s), }; } diff --git a/src/doc/book/no-stdlib.md b/src/doc/book/no-stdlib.md index a06de35c0c..79f0593be1 100644 --- a/src/doc/book/no-stdlib.md +++ b/src/doc/book/no-stdlib.md @@ -37,9 +37,10 @@ The function marked `#[start]` is passed the command line parameters in the same format as C: ```rust,ignore -#![feature(lang_items)] +#![feature(lang_items, core_intrinsics)] #![feature(start)] #![no_std] +use core::intrinsics; // Pull in the system libc library for what crt0.o likely requires. extern crate libc; @@ -69,7 +70,7 @@ pub extern fn rust_eh_unwind_resume() { pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, _line: u32) -> ! { - loop {} + unsafe { intrinsics::abort() } } ``` @@ -79,10 +80,11 @@ correct ABI and the correct name, which requires overriding the compiler's name mangling too: ```rust,ignore -#![feature(lang_items)] +#![feature(lang_items, core_intrinsics)] #![feature(start)] #![no_std] #![no_main] +use core::intrinsics; // Pull in the system libc library for what crt0.o likely requires. extern crate libc; @@ -112,7 +114,7 @@ pub extern fn rust_eh_unwind_resume() { pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, _line: u32) -> ! { - loop {} + unsafe { intrinsics::abort() } } ``` diff --git a/src/doc/book/patterns.md b/src/doc/book/patterns.md index b50fa01b8e..24f71608a5 100644 --- a/src/doc/book/patterns.md +++ b/src/doc/book/patterns.md @@ -23,6 +23,33 @@ match x { This prints `one`. +It's possible to create a binding for the value in the any case: + +```rust +let x = 1; + +match x { + y => println!("x: {} y: {}", x, y), +} +``` + +This prints: + +```text +x: 1 y: 1 +``` + +Note it is an error to have both a catch-all `_` and a catch-all binding in the same match block: + +```rust +let x = 1; + +match x { + y => println!("x: {} y: {}", x, y), + _ => println!("anything"), // this causes an error as it is unreachable +} +``` + There’s one pitfall with patterns: like anything that introduces a new binding, they introduce shadowing. For example: diff --git a/src/doc/book/strings.md b/src/doc/book/strings.md index 6af15d8768..a2146b669e 100644 --- a/src/doc/book/strings.md +++ b/src/doc/book/strings.md @@ -163,8 +163,8 @@ let hachi = &dog[0..2]; with this error: ```text -thread 'main' panicked at 'index 0 and/or 2 in `忠犬ハチ公` do not lie on -character boundary' +thread 'main' panicked at 'byte index 2 is not a char boundary; it is inside 'å¿ ' +(bytes 0..3) of `忠犬ハチ公`' ``` ## Concatenation diff --git a/src/doc/book/syntax-index.md b/src/doc/book/syntax-index.md index 28403711cd..5fa78001fa 100644 --- a/src/doc/book/syntax-index.md +++ b/src/doc/book/syntax-index.md @@ -45,7 +45,7 @@ * `%` (`expr % expr`): arithmetic remainder. Overloadable (`Rem`). * `%=` (`var %= expr`): arithmetic remainder & assignment. Overloadable (`RemAssign`). * `&` (`expr & expr`): bitwise and. Overloadable (`BitAnd`). -* `&` (`&expr`): borrow. See [References and Borrowing]. +* `&` (`&expr`, `&mut expr`): borrow. See [References and Borrowing]. * `&` (`&type`, `&mut type`, `&'a type`, `&'a mut type`): borrowed pointer type. See [References and Borrowing]. * `&=` (`var &= expr`): bitwise and & assignment. Overloadable (`BitAndAssign`). * `&&` (`expr && expr`): logical and. diff --git a/src/doc/book/testing.md b/src/doc/book/testing.md index ebeb992319..940367b397 100644 --- a/src/doc/book/testing.md +++ b/src/doc/book/testing.md @@ -384,7 +384,7 @@ currently trying to run the tests. This can save compile time, and also ensures that our tests are entirely left out of a normal build. The second change is the `use` declaration. Because we're in an inner module, -we need to bring our test function into scope. This can be annoying if you have +we need to bring the tested function into scope. This can be annoying if you have a large module, and so this is a common use of globs. Let's change our `src/lib.rs` to make use of it: @@ -589,11 +589,10 @@ please see the [Documentation chapter](documentation.html). # Testing and concurrency -One thing that is important to note when writing tests is that they may be run -concurrently using threads. For this reason you should take care that your tests -are written in such a way as to not depend on each-other, or on any shared -state. "Shared state" can also include the environment, such as the current -working directory, or environment variables. +It is important to note that tests are run concurrently using threads. For this +reason, care should be taken to ensure your tests do not depend on each-other, +or on any shared state. "Shared state" can also include the environment, such +as the current working directory, or environment variables. If this is an issue it is possible to control this concurrency, either by setting the environment variable `RUST_TEST_THREADS`, or by passing the argument diff --git a/src/doc/book/trait-objects.md b/src/doc/book/trait-objects.md index a0396a75fa..00a841a75d 100644 --- a/src/doc/book/trait-objects.md +++ b/src/doc/book/trait-objects.md @@ -263,10 +263,7 @@ any resources of the vtable’s type: for `u8` it is trivial, but for `String` i will free the memory. This is necessary for owning trait objects like `Box`, which need to clean-up both the `Box` allocation as well as the internal type when they go out of scope. The `size` and `align` fields store -the size of the erased type, and its alignment requirements; these are -essentially unused at the moment since the information is embedded in the -destructor, but will be used in the future, as trait objects are progressively -made more flexible. +the size of the erased type, and its alignment requirements. Suppose we’ve got some values that implement `Foo`. The explicit form of construction and use of `Foo` trait objects might look a bit like (ignoring the diff --git a/src/doc/book/variable-bindings.md b/src/doc/book/variable-bindings.md index 37b6c0513f..e1947310a9 100644 --- a/src/doc/book/variable-bindings.md +++ b/src/doc/book/variable-bindings.md @@ -102,7 +102,7 @@ mutation, then the solution is quite easy: add `mut`. There are other good reasons to avoid mutable state when possible, but they’re out of the scope of this guide. In general, you can often avoid explicit mutation, and so it is preferable in Rust. That said, sometimes, mutation is -what you need, so it’s not verboten. +what you need, so it’s not forbidden. # Initializing bindings diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 690d44cc2c..c81f2e2282 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -510,8 +510,9 @@ unit_expr : "()" ; ### Structure expressions ```antlr -struct_expr : expr_path '{' ident ':' expr - [ ',' ident ':' expr ] * +struct_expr_field_init : ident | ident ':' expr ; +struct_expr : expr_path '{' struct_expr_field_init + [ ',' struct_expr_field_init ] * [ ".." expr ] '}' | expr_path '(' expr [ ',' expr ] * ')' | diff --git a/src/doc/nomicon/atomics.md b/src/doc/nomicon/atomics.md index 1efca08abd..7b4c44ff05 100644 --- a/src/doc/nomicon/atomics.md +++ b/src/doc/nomicon/atomics.md @@ -24,10 +24,10 @@ exactly what we said but, you know, fast. Wouldn't that be great? # Compiler Reordering -Compilers fundamentally want to be able to do all sorts of crazy transformations -to reduce data dependencies and eliminate dead code. In particular, they may -radically change the actual order of events, or make events never occur! If we -write something like +Compilers fundamentally want to be able to do all sorts of complicated +transformations to reduce data dependencies and eliminate dead code. In +particular, they may radically change the actual order of events, or make events +never occur! If we write something like ```rust,ignore x = 1; diff --git a/src/doc/nomicon/coercions.md b/src/doc/nomicon/coercions.md index 6a9ebd6edf..b699946cec 100644 --- a/src/doc/nomicon/coercions.md +++ b/src/doc/nomicon/coercions.md @@ -17,6 +17,7 @@ Coercion is allowed between the following types: * `&T` to `*const T` * `&mut T` to `*mut T` * Unsizing: `T` to `U` if `T` implements `CoerceUnsized` +* Deref coercion: Expression `&x` of type `&T` to `&*x` of type `&U` if `T` derefs to `U` (i.e. `T: Deref`) `CoerceUnsized> for Pointer where T: Unsize` is implemented for all pointer types (including smart pointers like Box and Rc). Unsize is @@ -27,8 +28,9 @@ only implemented automatically, and enables the following transformations: * `Foo<..., T, ...>` => `Foo<..., U, ...>` where: * `T: Unsize` * `Foo` is a struct - * Only the last field of `Foo` has type `T` + * Only the last field of `Foo` has type involving `T` * `T` is not part of the type of any other fields + * `Bar: Unsize>`, if the last field of `Foo` has type `Bar` Coercions occur at a *coercion site*. Any location that is explicitly typed will cause a coercion to its type. If inference is necessary, the coercion will diff --git a/src/doc/nomicon/destructors.md b/src/doc/nomicon/destructors.md index c6fa5b079d..be4730cf8b 100644 --- a/src/doc/nomicon/destructors.md +++ b/src/doc/nomicon/destructors.md @@ -26,7 +26,7 @@ this is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: ```rust -#![feature(alloc, heap_api, drop_in_place, unique)] +#![feature(alloc, heap_api, unique)] extern crate alloc; @@ -57,7 +57,7 @@ use-after-free the `ptr` because when drop exits, it becomes inaccessible. However this wouldn't work: ```rust -#![feature(alloc, heap_api, drop_in_place, unique)] +#![feature(alloc, heap_api, unique)] extern crate alloc; @@ -135,7 +135,7 @@ The classic safe solution to overriding recursive drop and allowing moving out of Self during `drop` is to use an Option: ```rust -#![feature(alloc, heap_api, drop_in_place, unique)] +#![feature(alloc, heap_api, unique)] extern crate alloc; diff --git a/src/doc/nomicon/dropck.md b/src/doc/nomicon/dropck.md index ad7c65032c..f54933827b 100644 --- a/src/doc/nomicon/dropck.md +++ b/src/doc/nomicon/dropck.md @@ -125,7 +125,7 @@ is that some Drop implementations will not access borrowed data even though their type gives them the capability for such access. For example, this variant of the above `Inspector` example will never -accessed borrowed data: +access borrowed data: ```rust,ignore struct Inspector<'a>(&'a u8, &'static str); diff --git a/src/doc/nomicon/meet-safe-and-unsafe.md b/src/doc/nomicon/meet-safe-and-unsafe.md index 978d051872..15d84fdbf2 100644 --- a/src/doc/nomicon/meet-safe-and-unsafe.md +++ b/src/doc/nomicon/meet-safe-and-unsafe.md @@ -22,7 +22,7 @@ Well, Rust *has* a safe programming language. Let's step back a bit. Rust can be thought of as being composed of two programming languages: *Safe Rust* and *Unsafe Rust*. Safe Rust is For Reals Totally Safe. Unsafe Rust, unsurprisingly, is *not* For Reals Totally Safe. In fact, Unsafe Rust lets you -do some really crazy unsafe things. +do some really, *really* unsafe things. Safe Rust is the *true* Rust programming language. If all you do is write Safe Rust, you will never have to worry about type-safety or memory-safety. You will diff --git a/src/doc/nomicon/races.md b/src/doc/nomicon/races.md index f0732cf265..5145987158 100644 --- a/src/doc/nomicon/races.md +++ b/src/doc/nomicon/races.md @@ -21,11 +21,11 @@ prevent *all* race conditions would be pretty awful to use, if not just incorrect. So it's perfectly "fine" for a Safe Rust program to get deadlocked or do -something incredibly stupid with incorrect synchronization. Obviously such a -program isn't very good, but Rust can only hold your hand so far. Still, a -race condition can't violate memory safety in a Rust program on -its own. Only in conjunction with some other unsafe code can a race condition -actually violate memory safety. For instance: +something nonsensical with incorrect synchronization. Obviously such a program +isn't very good, but Rust can only hold your hand so far. Still, a race +condition can't violate memory safety in a Rust program on its own. Only in +conjunction with some other unsafe code can a race condition actually violate +memory safety. For instance: ```rust,no_run use std::thread; diff --git a/src/doc/nomicon/unbounded-lifetimes.md b/src/doc/nomicon/unbounded-lifetimes.md index 1f2961b586..1f3693f542 100644 --- a/src/doc/nomicon/unbounded-lifetimes.md +++ b/src/doc/nomicon/unbounded-lifetimes.md @@ -11,7 +11,7 @@ lifetime can be regarded as `'static`. Almost no reference is `'static`, so this is probably wrong. `transmute` and `transmute_copy` are the two other primary offenders. One should endeavor to -bound an unbounded lifetime as quick as possible, especially across function +bound an unbounded lifetime as quickly as possible, especially across function boundaries. Given a function, any output lifetimes that don't derive from inputs are diff --git a/src/doc/reference.md b/src/doc/reference.md index e7cfe4bb2e..dfdfe32882 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -650,16 +650,16 @@ Rust syntax is restricted in two ways: [RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md -## Procedrual Macros +## Procedural Macros -"Procedrual macros" are the second way to implement a macro. For now, the only +"Procedural macros" are the second way to implement a macro. For now, the only thing they can be used for is to implement derive on your own types. See [the book][procedural macros] for a tutorial. 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 procedrual macro. The -`#[proc_macro_derive(Foo)]` attribute is used to mark the the deriving +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: ```rust,ignore @@ -1677,6 +1677,15 @@ Functions within external blocks may be called by Rust code, just like functions defined in Rust. The Rust compiler automatically translates between the Rust ABI and the foreign ABI. +Functions within external blocks may be variadic by specifying `...` after one +or more named arguments in the argument list: + +```ignore +extern { + fn foo(x: i32, ...); +} +``` + A number of [attributes](#ffi-attributes) control the behavior of external blocks. By default external blocks assume that the library they are calling uses the @@ -1751,7 +1760,8 @@ of an item to see whether it should be allowed or not. This is where privacy warnings are generated, or otherwise "you used a private item of another module and weren't allowed to." -By default, everything in Rust is *private*, with one exception. Enum variants +By default, everything in Rust is *private*, with two exceptions: Associated +items in a `pub` Trait are public by default; Enum variants in a `pub` enum are also public by default. When an item is declared as `pub`, it can be thought of as being accessible to the outside world. For example: @@ -3795,7 +3805,7 @@ impl From for String { } ``` -The notation `Self` in the impl refers to the implementing type: `String`. In another +The notation `Self` in the impl refers to the implementing type: `String`. In another example: ``` diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py index eb562877c8..5e3ff5246a 100644 --- a/src/etc/debugger_pretty_printers_common.py +++ b/src/etc/debugger_pretty_printers_common.py @@ -45,6 +45,7 @@ TYPE_KIND_SINGLETON_ENUM = 13 TYPE_KIND_CSTYLE_ENUM = 14 TYPE_KIND_PTR = 15 TYPE_KIND_FIXED_SIZE_VEC = 16 +TYPE_KIND_REGULAR_UNION = 17 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$" ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR" @@ -188,15 +189,18 @@ class Type(object): union_member_count = len(union_members) if union_member_count == 0: return TYPE_KIND_EMPTY - elif union_member_count == 1: - first_variant_name = union_members[0].name - if first_variant_name is None: + + first_variant_name = union_members[0].name + if first_variant_name is None: + if union_member_count == 1: return TYPE_KIND_SINGLETON_ENUM else: - assert first_variant_name.startswith(ENCODED_ENUM_PREFIX) - return TYPE_KIND_COMPRESSED_ENUM + return TYPE_KIND_REGULAR_ENUM + elif first_variant_name.startswith(ENCODED_ENUM_PREFIX): + assert union_member_count == 1 + return TYPE_KIND_COMPRESSED_ENUM else: - return TYPE_KIND_REGULAR_ENUM + return TYPE_KIND_REGULAR_UNION def __conforms_to_field_layout(self, expected_fields): diff --git a/src/etc/installer/README.md b/src/etc/installer/README.md new file mode 100644 index 0000000000..dbefe753be --- /dev/null +++ b/src/etc/installer/README.md @@ -0,0 +1,28 @@ +# The Rust Programming Language + +This is a compiler for Rust, including standard libraries, tools and +documentation. Rust is a systems programming language that is fast, +memory safe and multithreaded, but does not employ a garbage collector +or otherwise impose significant runtime overhead. + +To install to /usr/local (the default), run the included `install.sh` script: + + $ sudo ./install.sh + +To uninstall: + + $ sudo /usr/local/lib/rustlib/uninstall.sh + +`install.sh` has a few options, including the possibility to set an installation +prefix. You can display these options by running: + + $ sudo ./install.sh --help + +Read [The Book](http://doc.rust-lang.org/book/index.html) to learn how +to use Rust. + +Rust is primarily distributed under the terms of both the MIT license +and the Apache License (Version 2.0), with portions covered by various +BSD-like licenses. + +See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details. diff --git a/src/etc/installer/exe/modpath.iss b/src/etc/installer/exe/modpath.iss new file mode 100644 index 0000000000..35cc009703 --- /dev/null +++ b/src/etc/installer/exe/modpath.iss @@ -0,0 +1,219 @@ +// ---------------------------------------------------------------------------- +// +// Inno Setup Ver: 5.4.2 +// Script Version: 1.4.1 +// Author: Jared Breland +// Homepage: http://www.legroom.net/software +// License: GNU Lesser General Public License (LGPL), version 3 +// http://www.gnu.org/licenses/lgpl.html +// +// Script Function: +// Allow modification of environmental path directly from Inno Setup installers +// +// Instructions: +// Copy modpath.iss to the same directory as your setup script +// +// Add this statement to your [Setup] section +// ChangesEnvironment=true +// +// Add this statement to your [Tasks] section +// You can change the Description or Flags +// You can change the Name, but it must match the ModPathName setting below +// Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked +// +// Add the following to the end of your [Code] section +// ModPathName defines the name of the task defined above +// ModPathType defines whether the 'user' or 'system' path will be modified; +// this will default to user if anything other than system is set +// setArrayLength must specify the total number of dirs to be added +// Result[0] contains first directory, Result[1] contains second, etc. +// const +// ModPathName = 'modifypath'; +// ModPathType = 'user'; +// +// function ModPathDir(): TArrayOfString; +// begin +// setArrayLength(Result, 1); +// Result[0] := ExpandConstant('{app}'); +// end; +// #include "modpath.iss" +// ---------------------------------------------------------------------------- + +procedure ModPath(); +var + oldpath: String; + newpath: String; + updatepath: Boolean; + pathArr: TArrayOfString; + aExecFile: String; + aExecArr: TArrayOfString; + i, d: Integer; + pathdir: TArrayOfString; + regroot: Integer; + regpath: String; + +begin + // Get constants from main script and adjust behavior accordingly + // ModPathType MUST be 'system' or 'user'; force 'user' if invalid + if ModPathType = 'system' then begin + regroot := HKEY_LOCAL_MACHINE; + regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; + end else begin + regroot := HKEY_CURRENT_USER; + regpath := 'Environment'; + end; + + // Get array of new directories and act on each individually + pathdir := ModPathDir(); + for d := 0 to GetArrayLength(pathdir)-1 do begin + updatepath := true; + + // Modify WinNT path + if UsingWinNT() = true then begin + + // Get current path, split into an array + RegQueryStringValue(regroot, regpath, 'Path', oldpath); + oldpath := oldpath + ';'; + i := 0; + + while (Pos(';', oldpath) > 0) do begin + SetArrayLength(pathArr, i+1); + pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1); + oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath)); + i := i + 1; + + // Check if current directory matches app dir + if pathdir[d] = pathArr[i-1] then begin + // if uninstalling, remove dir from path + if IsUninstaller() = true then begin + continue; + // if installing, flag that dir already exists in path + end else begin + updatepath := false; + end; + end; + + // Add current directory to new path + if i = 1 then begin + newpath := pathArr[i-1]; + end else begin + newpath := newpath + ';' + pathArr[i-1]; + end; + end; + + // Append app dir to path if not already included + if (IsUninstaller() = false) AND (updatepath = true) then + newpath := newpath + ';' + pathdir[d]; + + // Write new path + RegWriteStringValue(regroot, regpath, 'Path', newpath); + + // Modify Win9x path + end else begin + + // Convert to shortened dirname + pathdir[d] := GetShortName(pathdir[d]); + + // If autoexec.bat exists, check if app dir already exists in path + aExecFile := 'C:\AUTOEXEC.BAT'; + if FileExists(aExecFile) then begin + LoadStringsFromFile(aExecFile, aExecArr); + for i := 0 to GetArrayLength(aExecArr)-1 do begin + if IsUninstaller() = false then begin + // If app dir already exists while installing, skip add + if (Pos(pathdir[d], aExecArr[i]) > 0) then + updatepath := false; + break; + end else begin + // If app dir exists and = what we originally set, then delete at uninstall + if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then + aExecArr[i] := ''; + end; + end; + end; + + // If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path + if (IsUninstaller() = false) AND (updatepath = true) then begin + SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True); + + // If uninstalling, write the full autoexec out + end else begin + SaveStringsToFile(aExecFile, aExecArr, False); + end; + end; + end; +end; + +// Split a string into an array using passed delimeter +procedure Explode(var Dest: TArrayOfString; Text: String; Separator: String); +var + i: Integer; +begin + i := 0; + repeat + SetArrayLength(Dest, i+1); + if Pos(Separator,Text) > 0 then begin + Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1); + Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text)); + i := i + 1; + end else begin + Dest[i] := Text; + Text := ''; + end; + until Length(Text)=0; +end; + + +procedure ModPathCurStepChanged(CurStep: TSetupStep); +var + taskname: String; +begin + taskname := ModPathName; + if CurStep = ssPostInstall then + if IsTaskSelected(taskname) then + ModPath(); +end; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +var + aSelectedTasks: TArrayOfString; + i: Integer; + taskname: String; + regpath: String; + regstring: String; + appid: String; +begin + // only run during actual uninstall + if CurUninstallStep = usUninstall then begin + // get list of selected tasks saved in registry at install time + appid := '{#emit SetupSetting("AppId")}'; + if appid = '' then appid := '{#emit SetupSetting("AppName")}'; + regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1'); + RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring); + if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring); + + // check each task; if matches modpath taskname, trigger patch removal + if regstring <> '' then begin + taskname := ModPathName; + Explode(aSelectedTasks, regstring, ','); + if GetArrayLength(aSelectedTasks) > 0 then begin + for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin + if comparetext(aSelectedTasks[i], taskname) = 0 then + ModPath(); + end; + end; + end; + end; +end; + +function NeedRestart(): Boolean; +var + taskname: String; +begin + taskname := ModPathName; + if IsTaskSelected(taskname) and not UsingWinNT() then begin + Result := True; + end else begin + Result := False; + end; +end; diff --git a/src/etc/installer/exe/rust.iss b/src/etc/installer/exe/rust.iss new file mode 100644 index 0000000000..a61a19f909 --- /dev/null +++ b/src/etc/installer/exe/rust.iss @@ -0,0 +1,80 @@ +#define CFG_RELEASE_NUM GetEnv("CFG_RELEASE_NUM") +#define CFG_RELEASE GetEnv("CFG_RELEASE") +#define CFG_PACKAGE_NAME GetEnv("CFG_PACKAGE_NAME") +#define CFG_BUILD GetEnv("CFG_BUILD") + +[Setup] + +SetupIconFile=rust-logo.ico +AppName=Rust +AppVersion={#CFG_RELEASE} +AppCopyright=Copyright (C) 2006-2014 Mozilla Foundation, MIT license +AppPublisher=Mozilla Foundation +AppPublisherURL=http://www.rust-lang.org +VersionInfoVersion={#CFG_RELEASE_NUM} +LicenseFile=LICENSE.txt + +PrivilegesRequired=lowest +DisableWelcomePage=true +DisableProgramGroupPage=true +DisableReadyPage=true +DisableStartupPrompt=true + +OutputDir=.\ +SourceDir=.\ +OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD} +DefaultDirName={sd}\Rust + +Compression=lzma2/ultra +InternalCompressLevel=ultra +SolidCompression=true + +ChangesEnvironment=true +ChangesAssociations=no +AllowUNCPath=false +AllowNoIcons=true +Uninstallable=yes + +[Tasks] +Name: modifypath; Description: &Add {app}\bin to your PATH (recommended) + +[Components] +Name: rust; Description: "Rust compiler and standard crates"; Types: full compact custom; Flags: fixed +#ifdef MINGW +Name: gcc; Description: "Linker and platform libraries"; Types: full +#endif +Name: docs; Description: "HTML documentation"; Types: full +Name: cargo; Description: "Cargo, the Rust package manager"; Types: full +Name: std; Description: "The Rust Standard Library"; Types: full + +[Files] +Source: "rustc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust +#ifdef MINGW +Source: "rust-mingw/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: gcc +#endif +Source: "rust-docs/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: docs +Source: "cargo/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: cargo +Source: "rust-std/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: std + +[Code] +const + ModPathName = 'modifypath'; + ModPathType = 'user'; + +function ModPathDir(): TArrayOfString; +begin + setArrayLength(Result, 1) + Result[0] := ExpandConstant('{app}\bin'); +end; + +#include "modpath.iss" +#include "upgrade.iss" + +// Both modpath.iss and upgrade.iss want to overload CurStepChanged. +// This version does the overload then delegates to each. + +procedure CurStepChanged(CurStep: TSetupStep); +begin + UpgradeCurStepChanged(CurStep); + ModPathCurStepChanged(CurStep); +end; diff --git a/src/etc/installer/exe/upgrade.iss b/src/etc/installer/exe/upgrade.iss new file mode 100644 index 0000000000..29da7c333b --- /dev/null +++ b/src/etc/installer/exe/upgrade.iss @@ -0,0 +1,61 @@ +// The following code taken from https://stackoverflow.com/questions/2000296/innosetup-how-to-automatically-uninstall-previous-installed-version +// It performs upgrades by running the uninstaller before the install + +///////////////////////////////////////////////////////////////////// +function GetUninstallString(): String; +var + sUnInstPath: String; + sUnInstallString: String; +begin + sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\Rust_is1'); + sUnInstallString := ''; + if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then + RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString); + Result := sUnInstallString; +end; + + +///////////////////////////////////////////////////////////////////// +function IsUpgrade(): Boolean; +begin + Result := (GetUninstallString() <> ''); +end; + + +///////////////////////////////////////////////////////////////////// +function UnInstallOldVersion(): Integer; +var + sUnInstallString: String; + iResultCode: Integer; +begin +// Return Values: +// 1 - uninstall string is empty +// 2 - error executing the UnInstallString +// 3 - successfully executed the UnInstallString + + // default return value + Result := 0; + + // get the uninstall string of the old app + sUnInstallString := GetUninstallString(); + if sUnInstallString <> '' then begin + sUnInstallString := RemoveQuotes(sUnInstallString); + if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then + Result := 3 + else + Result := 2; + end else + Result := 1; +end; + +///////////////////////////////////////////////////////////////////// +procedure UpgradeCurStepChanged(CurStep: TSetupStep); +begin + if (CurStep=ssInstall) then + begin + if (IsUpgrade()) then + begin + UnInstallOldVersion(); + end; + end; +end; diff --git a/src/etc/installer/gfx/banner.bmp b/src/etc/installer/gfx/banner.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b5459a797d23bec0b7dec97c18ea9aedfe8842a8 GIT binary patch literal 114514 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 literal 0 HcmV?d00001 diff --git a/src/etc/installer/gfx/banner.xcf b/src/etc/installer/gfx/banner.xcf new file mode 100644 index 0000000000000000000000000000000000000000..53296518ee2b710665e146d556a9dad7b134569c GIT binary patch literal 148261 zcmd?SYm8)DmY8+&QB_&_s;F01R%Jw-T@m$uWz^%=^Y%>GXt0p5oR+|vKcJi$-)^^< znNH0#W(H}TA^5>VNNEWPOGY?_ELk#tQUVDfF(Mlb7UEAL3n2u^iTuOD2q=MJOy66X zhwoeaoXE(ky6x%F%#XIK6uI{MoU_(`thM%9dw=iyzqXZr>sP*;zWe=O{i-O6ssDpN zZ~6J}BEP9A{#@oa_s9QYQTXHE6@Ih)`utYvu;s2&{!ajxzDKiq>16KX5-`x78U-|y8e=j|4o<-tse=f03d;Bl{`uBgBzW?jL^5?$#P3!;QyWjoI zuYNdwL2G}Slv7Su6%X~lssF5)TK&ah>U(#Jso(lfi>ZHevB@clX@dR&!&iTSSN-a{ zf8%$*_rtH!FZ}XXzy4L~KQ%K-0MGK1ZqND6)nQ3#lKJ#oBv!*CUQzrlp7Y<)+yBRJisFC%V@2_I{*|Km-~N74{O|v9QT(6Z zEsEd!Yen(luqcjs$KwY@QT_MD)a<`sOfCGeV(Q|5RZOjnz{M?bvEBOUxA3y~I`w znRa=mJnFW1m*Y-3M{w2G>68oQ(_*QN;G&>g3YI5+b<$4(+R+A&j1~pH%WQgG9HlbN zqz`2Zq@<&+NLfl?q)ZEm=kh!5rbR*d8DRcD{1;!IHb_No7G%( zv>T+@s1_<7dJ*jnwD)8%oe zcxm4}TOPOV!d<%XaaVkG%Z2iItpG`_a>=yE_Ua4eaZ7Y{%a%33mRa|UtL5=(akp5p zK@hc8Ub7&G>XfS%1W(=ax@B(`9m|$Q*Rr5!tt*Pk58Y0;oGL-YT6s&*$)FqH4k`Hu zUe?OnC7_)_x4h#MKu@>4XPcLbN99qc1%jT$$OJ#D<$8=v@Y61zSseVd$}cQFYsJ^) zH`M5q+tdF-nfp>;Ck1xWnRHY-uoyveDbTYRDfT7Dm${FNR=|hF#efeSXqQqAEI~(# zoZH1}zEPF%ooq2(7E`Y9G;Ev%k*O(%U8ZlQ()(D%GlZ2pV~j# z+Y~)J)tTz(a433qnFNk^>^-AuzB)P>(0z_t@0kdW-f!7~Hmc?7XfJxusJalIo5k^7bt9^Pwu5RdYJs-FPC=)t ze!RP}`@X6icZ2Fy1*$eO7-g`R!9jpKRTR4|7*+vBfTO*kh}^C2R!94r^e*1_e)ZvS z(;oIXPk;`=YCR@Ey4bLK8nr-YYp;49)j;Ryef6^XvGq0&tGB%AVYNN|sM;=$i>dUM z^)03d=ki{Ex}V_;kYPXDUo8GV^IZY?{KO2mV8)p|^_=UUk80;)7U-IDmL$M@zZ*Gc z`*T)Xuzb5XZ_L$^*bUR?`qIAFUoz#od8S;-^U`^Om-{Q0o9~|$T<%{j77h0LSD2BO za`19Iy%h~DF!fN-sne+{9!5&9zY-}+W-j&ZWIZNT3xPwQKU+9?rUE?n`pZP~v^p0h zm-{nT%t_~pi$;6>PE?5JwQ@?=&&Z9p`qNgq$<()EFlNDMjM=dGPW+CF)c>-7RP@Gw zDYiZHnmSWys(9^$I$L}Zk2zbs2zah|?nBNO&mwxhcp7jXNb*845G+mrzi{2eB@&mL zV4YF}`@+#$yLdy-aW;J8EHzWo2U_KFPVFRg%lVR6t2|di`8DVEuKmE6oCz`dL7Uk>CdOqGt{3yhV$$z8gu1j!r*P7| z>YO@X(gRk@NVrlg8taxU2u{INTOff2VXbKS;KdRGwaZALKlo4*x-JxJpoFZYlBu}m zDzOHtE*R^SH~bFzLbqHdfu*Ab=gmVel#qV4j08G@F;HSQt#(+QW|*}2h-mU+3E|u2 z&2p-{Vz67jEvJ0eJ3%MFcgmw;wfvI5UH%>y<@U^PmtS`~$O+{uSB%->rQmGAs?lQo zcy9CO1uc7liyFi?aRC644blP35G==U-PEPxG-#%PsXQ%bc5Zsi*1ayyrbXt6ulYhI z<6dztN%3?xFB@l)gTGAYVh-;XbHvF#pN`9-6FFzoT(OjRaNAYj95M12O}J6ar#$ON zJ|n+ObEI5iSy=!Qy_i;t#dMa%3!;~4p5RJi%mayDj)ywtT?o$<*CH-~d4L2?E0MBP zTu6CI$t4)=Wm+OBuXOXQo{*|p10C&UT23=XH)_X=Tp(IT^bGF@!OPV38*;O)G+p!p ze~g>UM0hl7Rx~914nJzVOUFg}PX2R5b6+MB8S1Qa;>!Y z?l*ZLB@RhAdOu+7X9j?-Fs!ad5}m`BAZ6FJok9%%Aujv!g-v?_YYuu9dB_eP_= z{e3=&gx%_GMVH|%ggpA4U?0E|QGLnZQT#pRFYE^Wh6R0RV~8yKvO3xy()bs={;;6m z)bI1$XVPyXO1~l7#qDWzyv0N@sE!Z$R=_BOSS3uP167bRz~~dOUHpg%;XB0?OVqn! zCYGMp#caS=MQ{bLinFd;y%WY^p*Yv?xdKN1Jh9_mk=cXHILwjc+S@6DPnd&G=vbbZ z62*A|9j9g-BBACMf^Rs7I8KY#;2X}_LZZi9Cb$T zALQ6xWk%=~czDH&yo4?LqCXE4kze>}=HmjO#e&a!#*YRDf^-6yTl)T_{84+Y__9EH z>!QP)bpd)^u>7}>%7Y7l^e&>1zSWgcU@nI*fb=z&0O_q83_&moa|L1_@=p0>;0U7WCAve6jxzuM$sCk41l30ac2UFl^E|rXd zhDTtWM@5KSrt_Ad16ZDA!gU+6rnMX-j}BlS>q9p!8Den59$ZS07vA8KNzh$z1ug+P z!XB&uvyhy5gUe<^a3AIfFVjjo15dDAhe?Ls7IJKtDRT*sG%ZB@MuPhB(wR57VNtUI znStrR5?tb`*6tF%7^Nk!Y(fde;R;FyXPIuM>EfMl0J^1}Pj)rFNap~SOJETZ?VbE$tXQZBjj z-6@Vx9A4?)ws>eidyyGII$y2*baqkgdA)EcMFB&lHS4bii(+P%%-cTi+60hWQ2R+n z6AWeN3aJzg&}#r4EcNe(2DAlYdBg(?EfQv-ePq~?=h{gSRHy!P7VBhi zA{x-Y?3_FuTEQ=zb6GLFg(|+R0Yzn9OUY!8L$*Y1KM$*)*8^#vh5O7b=N=@H9AD5vj&th#cdaFuw=CWuCON> zP&J_x05?7%K(_&)s9oMIFWc(Q;Wg{;sS=h_+WoSZ+#Oq{D=tVT4f4Ml?+*1>} z6DS%U=9!pYw1XtY)B%bH2S`ZFH)uk)vL@7yp$T;W#_YETrjB+7jzKD}F(ZjOCNNZ?%yaZEr+v_6 z{Q%DG#P%{c0Ng=SddFgPE}s}+l)KRLLRG!TxSn+|Kck^u|9t-$Vgpg+ zLnjO*M`P<*a9BUJ(-*SDIOq2ltDBkt@jC5px3kLYID+7>+rAAW2$s2nt~;1o-X!+> zNa2|dDBh+#+3%~9ek#z;O-%sbW;VUb9d;%^U51md4R@})8PK$Rj)-VI?MM*B-pXT*@w^I-B*6YDu$N<_pB4;rg$c0z z$rkb7FOF01OmCKtcad9naa!s#eXB=)OeSj_z@_dnGT%5jkz%SHZMmt&s3p48G)9}M ztyvtDfwvcUWT$(kJKH8j>4<#SidZt1OP-*j63`8Bk>KQy88>oWRO%{#7Mjkw9l$Eh z)s6c&H*lL-_gHq^dTBY)Fh7D91m(8_i`l?3HCy})FD0KB-~#OvTukw88>2I$*&$Di znTtZQggkMFxr@gn<}JWZ2KyN}nUQ#q!CnS(jyxCkX4(4cadb zhWqIl+v@D}fBL&v%pkNZp<0h=V;X_I4==*Dg$fL~N(ebuC!(h^F{=?Su%F7(qnsgC z7g115^^VvvRhE$WFl4E}T31Cq1Rt@S#dg&N{nmsC-$R6_cnwYj`fnBLDZ0+fHNcHr zVuEE8pPT?U4aj)XzhK5=!1_s$jK}>}@udDy;1NMmAN4P?PkhlT4^1({n#=KRkNeXp zvrMo2l4<{JPyaxmY9pb>05=62$65RFCNw2eFjSe%dmV75fI<^S38!P4L459av6ybd znA{+nmx-xWhG>O27?Alo>b6;7mXwKC;kMWzZb2mmh)FBPSD_I_mldSf&;r=Nl$^|k zEMY6^Q5sy5Pzp1?LJ9RQ}GdU~s$#_DLi~wr@a9jV#d`u9; zJT9S3{Uh}eK~f);P$qsvO{Hvyvb1MIQ|)8-6?l#9>G$wzC3=Tes3X)$yp?;KDgsOw zZ;VNW(-S*bXHEF@SC15A?+@-OPqVW-m5}db<{T$(0hn|-CuMMpOtc^YLu&tJ z$?`~X9$6@EL`|5Fm}3?S753ev6rV-m24-29CO#I6Nm}PEn1lpR;|EI0^n~{%Rgm@R z;HylJ(-^E1T!*iF!jGIsb?`|7&-_Sw7)h40`}=G=f0+>G!SYt3$d~yKmNW&7Ue*n~ ziItXKA8@*O9WZ+Rgb510ej*0mF@pK@N3S2kve4@*(BEQrdb;}NaBoXqi%D| z4u)-iG^G1Sq9kzc{APb=!!e)~yQoaKk1+ks!7d9llNI%rDmwX~TBW*eGFia{E}OWe zK74-%iJeF-U!DeTTSJ!IY)G7=ENX5{N}RmUIxoqrA7CQ`cfTReVf93?o55xV0{}#N zUp*G=Ww4dO5CFya@hOi4qYQ=s=*EvmA2u1(-=qfA<69qBQ^Ob|N3Fx^73|0U^ge}| zzZAof&JS7@68k}`sNRAk1^726f|U%RWT*gUitX9oVa{i|Y$mu@5oJuhl)*g9Uau40 z96PsRcs9>W8-c~*Q4TB@4|1SY+{=MW#oefMr4eQO5nV0Zie5t+wZ*lf8?eJR_Z0Ea zQK#a1B%)jQ>3!7Emc0!mdPiM)uegVn-PHTF`uaiWz5B%@xM0&CXWjXehEvYgPftY1QJaePji_Ck%<>Fz$R&hTd7z+r-6j@h_TQb|LMNfYE z2K%{ITEkWd>9^xvFnZXcZBYi44+LS(gxFab17GHWFH7FjRB26gMKcdn7I(lF^8A{} zvLeW`=s+d5to^)s&(wcw;}$w|FlCXKD%v}!<V6Hkk7}D2nG9zr+ z*{Y)*J6o6Z0lkgwMbg0>4`pd6t`py&!>xvF3+5sY<|3ayr!JN;ieNhsdGR=qN3l)E zXrzO@s7}9A0Wc^qnxa+k7un#Cr$^UQnLyXG6kSiX=PMP(>@DMV&ol4*19|CGFl%KapE+iqhDpxm zk>{9i;J9I%7m830o?#0x=ExRtXOJ1@nq1;au}Vt6H`S{Rd9O1KMp-n~p*R%9gjUr% zY9Mq+u+m4r=GGwEHg%Grt-K77O~2Gfl>)rjN4o-S^&bUP*fXw3CsdXbYR)UvY*;vt zZb5jy|2*Ja|3$!aebj@ge@??v&92_iOF_+4fBWo@8Z(Z@xC5P92V?@Y{J<8(jW=0K ztV23YyuWVZvx_Qm)#Ln`d&jtdOQ0 zb=~heA9jxD{Is&1?rMnKQFE_G(ID9D$`!*mgU&96K&K`*ptH*+8|duP80hTsT&*}k zX$un`^qVcTnhymR%SVD%`B)H=svP&aY--4+YY4tijV+YV1oI^du(k4h`9d&Pg1^=B zTnYZPl?H#Uu=EsvGIHxoi*(Hz$nXtP;LpvHr)FlJaVK>4v4yRJy#NUX%&qn;93%Q zX(frfbTx@Pw3*;dZrHAvtv-bp$7)c!ViwAU%HBfdZsCbgZ&%dB#;)kjoLy0F+^*>6 zUDm^%Wg0a;n^na@5P?!8CX z=-dHftA8NhN#`8GS(*lNVNiEB2X@cRNZh1V0;%vCm7dK1dQ*} zEEwPAiD3MIw*lku!j~!rKk#D3;0LxUFb>RGhl8wc2=*9^1Jy7HHB=YQS701?z5?UG zxeAN}&sAc4A5$7Ij`ni4viok1(D{mV81RW5dSdmqy#T~0{?m8a=_mNCHqjKWUTz$oXOO(9Pl6aGkeXwZv^EYHYZfUavB#USUGbmJ#quF@ZmD1)X0&tw&%yD+)o1Db&%6N7%vcoj6lg|@&VTxbhs04}sO$%XospwI`7+0dDIcM#a6 z)r`QCy=IW9tedA%f=?5c2O!5ml%@&M7;|t}%btiV(8_8$?$Q};uxHS&NHZP7c16P14d2XFoMW#s!LBg7 z%7I>C8wu`{nV+5*ke(RuQ!aEd(&>o->4^b9$C3JupwZ{*Lu2!=m`=lo=5_JG<)rS3 zDa*gZ3`Q9o02t$gyi>aepg#`T-vF=3qe4X5E6j*{hwMt*HJ!G853a0eu{-Rhx41oU z_9T&!KG@tnWC{bfTWR8|0Rjzlej}Bv6wUd4rjNDlIFrxKqa)*rd)+RIgO(P&! z!}pG15Nw!TqFoTo>=oNcTXt5L06MFH&MH7k5(L8va|ym<5dhx-gK=e12*wpCR{N4wlyr4i-4c!OCxgZ(jp^)7*ymu7a5d-@7av;(L2`*pG?q9n+f=;Tuf2BH<;| zB~#TGx`$yGy>{GBk&M~X9RSYiNIY<&}{5Z<5$D(YfQImq0YsmJmO_-E#HBS zo$9sw?5`#EvE8GT8NFq66=u}vRk=|u+*yfwu*DyMgUIj68Tl8V2qzNGGXms{E3kUzTF4Rf;Wza;3Go}_J@H!+cRDovDpR6RZu2TrqT$S9s$f;h z`5bGh0{Gk5Nzs?&CeI~p%`jEB`t9Q&zN5kFf z4Ys*#{T{Nf3-&hl!@%Weu*+O1_IBQfsxUT()dWW1Aqu_-+^-m^?l9i1>~Xu5-Z)1| z2OY3CJg9mV*h86#r7!tARat?(fyO*wkNI+~5_@_BFj%j36*{rSRsYyD??;ML0xsk_$43w2~P_?WAE4VKC2C;BYtiLrR^g z=z^QUB_0jc?1IU``)aBJlfX($QYm`j!AUPX*~E4x{Wt~zKfB+x#(vjD@~*{v;0zJm z(^6LWU8+;Fns1SEa$YXgOf1<#cA?f3HazAPgnx4|BdjaK6{=6cVz#!7#ok>;@iV}3 zY7hL?9x$~|p$4DzhpCkiwRYmPl0v)RCq7MI8GQM25Rgb|Ho6|0swX6=f{W;5Nokp4 zMy~0nBO3(@&a=k*F5rtl+td1o_P^72j{UO#p#Z$=PtjAf6>1isnTWq;Au|0{A2w}b zSN`J|1Y^?r^v9gJ+Ma4dGbU3f;p{lPM4ZW%xf*^?&zDd|GGY{y;S$vXgpv{tR(AC& z`UH|YP{~H%LD!@a>|kb1p@Xd9XMm=cC(gwqmx4m3rj3?Zt+k zo;p}cwb=KX5xA-WUYDmgytH}%^Pm0Y;j+kdkDgRcRCnpF{UXvXMOxNdGFpNiY#7_+ zI+kI>1Yfo(NE4Y;QT;|*kWuYwfZA+yoxllw#w2f!wnL*=Kq!q;-t;=riiq^af#iv0 z!EXk6!;7JjK($FZn4^pYlOP1SmV6Q~3dsWExD=aS=P8ta&OcbcqGD$)wD)V}WbZFo z6Yc$Fdd=D>e3h{67#3mM@i_qgnKD29(fiYIYIspq=RPF(X0Qe83jg;Wz7Qf*7%DMo z1!s)f6Xp^!G(2!?V`m>BUNcW-t;luO+T2wIKy#3R#7!qInsxF&h80!oNLtkv3Iyu#q>M@T9rPyvr{-s7Rhcqp9VXv=lB0SJybbOxVNTa48+s(8L(w+n6TfoJ{7n;wzCB7%x;(<+Dj0c1D zw++vZ=swy;xof~9m3nxj{f7or#PJ+s0roRE%-|q{y$swfpx%4x0Y(7(e|&6il(qx4 z#@5jqAZ0Ap3|y!K?2&Uye=D&(%zRWG)-Rx<6 zX96g*sK2p1VjB@n{ zN^C^Pjk^g^3xAmK>Q{s`qpdT{C7B@#=Ix2=Y*CoB((F;7wA4}>;Ks#m_Hb*l5nvT$ zaHZDOe!);fQc-yxQcgRhoW&DKXF)}}PPYI(dLfinhk(_rR_~%#ueIwCN@++tW+eYXFN;qeBg?mshQEtC1z4R=4c&oDeHlL#(7|%05V? z0MV_HF(Fi!?F|UUkBksEJBXXmNp7fLgygA{5D3qE9@iU->^tneK$un3bpREF(5I15 z>*6;P`_i5;Mx>4MsVUll72&ugU>XlO+EAlkm0{iDek&u#&xwc|! z2NeV*m0ZcWJ|V!~NFZ8w9!H5zKj;Aj;JyAu?ycfR^5@{_Y7Sn2|FEZl1pA?Gn##H@Lg^~4m(ki9}OV?|RkBN`w9pvW#_8X#q9O>I7CA7-IVUs}ksnZYmv6DhKh zOCAEKzDf0GjFcfF?>Y7teoSa*-#vsoSS$}myZVr(;_JbN!Bxc7Zw8~igRr?i8tfy$ zg7;12S*N=90WpTTU9HfIk#+&Y47M`Z$Y20~c88P%YyxN|pIhMq-bXy9V!vV(jY3F< z1-PlK%rlgg`HECQ$6X|5=-AQ=mN{<#U?^!71U2{BgkjpFJ;i9MtW^+nCxmI*yRJ+< z$TBrmVq-?h8k*AH3J9Rk3Q=%uDrExf0~l2;Y5+z6>AQ1Cpg4RL;uv1_0nZfMOXt}K zVcK?kwTI`1Qk!a++MgpfRBEw~iS$zcN^horDe_zWE5$TFJXR7+B+Cx!P|5@^LY#&` zZ^Tn^u{f>|;)(1>W@K&!H%f((+2WPJH(H1j01&#qK)>#xF;0buDzP)Wim~3Y@(mNo zrSeJ_-l)4U{|qITs8)`vgTVcgYj0H0#nO)i?>2wW?#XC0mlXmhx!-dV$op-4f;15di2UqU-B7;ezA zg?8n5Z*+MyE&qyQapQdj53>(irc41lnF&uxlI+7n+4@M9^$g1P#p| z!4Z*>*&y_I#Ry9Ms6W%w=l1izx=cCK)l>8HzbLa@B=SG|tJ|n%M(<#vKmW^Z=&6iK z0an+uqrM&F(tpP8K*65?>SojZ(k+pXe|2tke7JviA7%c?)_wx8{LlG{+e;N}Ro-Ci z_v`(^V31Oum0muk1H0k~ywQ(Zykki%R`*av+`NGcK8#}6*ji~7{3@xG zwwLx3THmDT?Sj^4#fh0djTaX^SX@eaC!;JwK81h32JsV;@SN==qp zs&$JZ+eHy%%z$juhfa+?g!PCeklQ0?4i9ot=Wr$`^_+lnK{QwF6=%nDs#e{M+h(fe zARAri8>{WND74;~G*i5_m1%(v@ioBp9iF}Mfd3M8SnUjtqAbGWXx>n6A=0Ygg!tlq+tvx z4tbne+r>@CmAoaf>sl0cB#((QrA)I|i+fJcSBm?B%f$nWT*5RFfFLeF+7cj$3nq0| z>g#IdS#9T|<_$X^&ep-(o8}>u4}(x9LLr>OUz&2(Wya%b09^oUkKU*Nz42<3Zh(e9 zZ_8P2y>%A^=)IojFjAn8Df+8V*S`;IScunt>wqq??7prGd-JPZ+1ugJKJk~AlsMDr z%VH*Fs~Sd59eM`K8ylob(Gg&+ip4@lzesS~)~(ezcat!;A$5l04cD;*<_?# zMyodR6g8|8cY_oGAw@t)fnv;|f=M`9Ge{AuH>4oG#c1h898wV9aJ*EgD)b9H+IPTU zJb5@^#M~o$;E-`OXUODbp5=ejAtM;;uGU@VLv=+BRcLv48#SBSyIME*T+JdgT4!dW;Ipox#qVcL;DG@q7oUWwQbF`NqXtJ9)rX z274L22cSe7U^RZ?_C3n6{R|EOU!q|9PW+hXh#d_-{>#g=qt6=pvbOB`qS?o$_pz7F zLL4SSJxqk)akJ}C=6V;S-p3w6c~`>{`uGUl?|#gBLgfcFOYF`!>-T-QVp8w1{e6GD z1rA@ODuwxPtad@B@L)ccU!B8XTVgQ=otC29((8CoDg{;2rI#5cyLUST;#KvqcZ zozFfHQlTSv|`Vmy!!|rB)W5d-_uuC%TUp%jj7cztx&^IUlmMj z>94}>L5&GD%oAb4_-ISz zQ=xX77XWy|C%k=DClR|1dr8I6A!SvP-$KQ^@kxALo3D$HyjuPPnTSHmuJd}mucEq= zJK!(~_|mf`DV(wPgI85yfhoi*C`jTZs_ytSJD^`~AsUX>e;5Z)&VhP=zgc=k)O}aGEUUp|P`B8FY>#@Yh zW|2GYrUw9%v@>{!IQJldlrm*&gEHNLx4xIaqY5BZ3|Yl<2lWm~YI#iRo!0d9lQd2V zV6K{;n+XaBgvuthS(ximuu)0crkgZl1>r4z6zuVY+s(t&NlDpsi&xPbpP*_f>on>q z>fGTI?l+&|7fIA~C6VP24t>}hpL-><77!J2_bdsN%4|nQ;%tqYi-9!`e<7~4OR;H! zG}p>cnF5^%zh$9iWSNw4Bl8;1VkDY}KLQAxnQ}zLr8%8iK} z4hjd=5YPaNk=a1#do>KIBee3E5!G9!#OXA<)wBtrWEjEEfV`v$SxOPIT>gg9@L}A|x@B+;4#lPTHV0>0U-D z5S}1|LCBEueoGxSr!Hi9s=Cm)r4vf3se~qo=DQ@`DfEpqM7Jb+iiNKcO!J{L3WOln z2Yqh8Wt`>mhbZe2HMip3jiQNQ+3cAN@*~-(!Z4o$>LbZ$m#{K3B|&^78wKr_WQ>>t z<|Bupmq4^hjEzVV5-)R{F3F8?;zJhTi5};xTvO;7`29gU= z7oi)RK+9-PNEHTCg;WYTZ4Yvi>2YsZZErE4uxHtmqS2m^LJTo+47n{6U>`sYJz(pK zH>wYZJI<(@*(=RCL*@-}W?vVA*o70YOan*bu!ul-xmyCwxM?7BW5( z|0)tcq(fm##_Q1As=J;1p{->~PBDQy7Q4ya{12&%M8aYbnXxonAya{g`CEqu^6wg6 z&P5&=&H~VrBpuUJ^qYWZ3Ei`qyj+={r>x~v)0uxz%VZC%g$i%;9l~45k#bu8G=4Mr;ePL=9=-tx(R74p%E;KvBIzbF8F=5!vZzgl6be)dH6HRO zO)7udbXX$*CuPo?Y}|z?T8o%9*bGTiGyP=ckuoNYBFyzeX58gr&BGx&Ru%Vn(W92H z2;nz8D#Wg;tj%{(|A~S*^#_569q<6*dHLtc_N{${dI_(r58?N#R~6LW4D(2YL9HY~ zrQq#JFfy1&vX41)c5O!xiol2H2HCN4Wqcs$0XW^-0~Dx05l`-*PGk|%bBNr#bto^e za2pi4>Pb+Zis^o`y`wQ}SaBh-R;)JHBBuD1SDm`Fr+283bTL__2xorh{rURD&P7r} zC_2Z?!it8hrQobEdEAHX<+KkC;xxV|V{D3F8(=&Nk?exj_9{{CM>L;!(xlO} zRF$-aT0(~_Xszs}LaO#*T|_KZD~hQGtN~)1>d^Bfb?`^XjKg?SlP%6{$se1Z-f{ED z)>_TJ=slklC$xC>Xg}KJ*bHC`J{XbFV+Y)dZNuX>TeEJ}%9XB|eFs#SeGioRR-B3v zM-)I^v!O1@Yw-NF*nPfKh~}*z;K!hy6Hf#E471ejrt(k!yHQ+161+Es`XeHhV|Fwxrp7d0uPPWh>6kYU5t2ciOY{pofN29l$CfVxIhSA{ z=Ms;K#V7%-qr}sA;}9Qxxh&2rqJQqE6hHZ^CHg-cz`)*8*SG1w9vIRp`=T-$384nu z&mokE13SRJ>crg~qFl`M@3njyIoji}(FFh95RZabETw9cJCn3lD}J`-~5v&s1*PUSOx!mgzGH zq#H$?rgPwRAo;ee6{KR^I%48S{v0_mc#h7dGeg*n(P#3D&}S&YJty>;>S$kgWR9KK z9fGh{E34mwz1cQZ^F#ygA`N26^9VCds$|BcJz^3_pLC@=!T!&;6+X zlgv|pmh#$n+k8&>u?_7Xb^I!<7kK<%(^VI#pKPD|vruGrcy|aM^%6*kj<*zFzvZwt z7#?NWkae#J(&W)?Apmopfv0GAxZJk^<>U~dFE>rp4c5)yfgAQrj@toOcq8N2#{OEh zGnYoj-UQXoLT?vEu7*Oio~FZHZF}zTdPkO53h_~&J2LH>XIOY)5ij7eX@E6AeR`U{ zQ@m#oY_U!GV@Cfb%2%Bt+VPl#tu~VUKHft%r+Kl@IXslYB zdpFkKwJ~_(Z{v+*FWH}It~2#q9d9N3_&!rD(Anux1BEKcQzSK4e;f*&WfVXva*zlD zq9q7;ajX%#XO$}_1_kV&MTu);Q~BCr!1HkN-5c8o)W!jgqUfW8aU0uwZ2=ndfW}Tg z-yh3nwU5ReT)-}BJeD2RfNNt5gbzX(cRP*=zVh z)y+9A$~!26y-n=7_2c?cPk~_j#^W3Y)`wgI$ivSSX7F7} zC14NKrr7*c%>>abIzEZ_rg>p4uvWB-t`*qUR6WIZrX|Pc@ivMd_WnDCd;jWz*n#vr zFhjOVSQS8@rk!L1VYk1=GkQLsEnPvF@7ER)z7((MdGQ~aPfy(BRohtuy2XjP^*dDz z&?AG!X#1^EuLXl92D7cVD*xAs?}I3zu`miPA`FERcFC58CXr;+qZLT{{9U0>69lnA zL~Bc_j!{>_ND9bE3dl$b2zf$70(q>Z`8!+K35rBE!zdu6F*{EDr8S08BtsmNu_%b> zXAk~Gg~N6+)AsdvkR}AakOl@qwvLm(Xr^hkG1)({T(Ibg>3;Kax1)&_EToSn?V?jr zX*Z2|_4}fzFt6UvU^j!U3^cudt11LqRVXw9Y-ZqqB5%*Zq_T!H@GTjp-lGg+SgDzT zbm&G>K$tHE6ww%1*5p24#eN7Fg@mNeVT4ZWac}3L1MDfe9x3tE+&BD65>!Y;!qO3MGI}oJ!>)0WCg?6Kq~{y3%r*H;{_@~PYcC4#He+kC&>c` zTg7G*^hEJ8WX!CEBIeX_#5*ceunE|7yu}kCDYb*7JY?vIQyavH^BD}icqAh+p25@@ zuYx^F!0ZK}Jw@}18dP{*Jv&9UPo>t*XrJq?5ck;o;34N~4tCrJOLAUpl`uEBt>NAV zhxC3ns!}SpMJPEL_Fios5_>1n2+=U*j%P$}9nG)6Zm6s$5tbGrGKgXEP{&p@d(euz z&T}aXqPj=dMJ2;d)`qVZtI(`_a-3RByv3hY2@Pr&g*G&6k!EWg|u-HxfX-?zuV3 z1CB0_i$TtINl9l>{tykz@rdd`bk%3CmiCo6xLH3k*jD2n$^;2KV6KkE+9^Am6IOfy zdRDuf(tsdtJ$EL6t)Di*^P5@q_~tb%(n*LrPS^ZsPqbTP!F1uI@l}l4`3QG$+$5n( zVfuc~q*Y{qneHOnKjg-JCE4tPwsar>gz?2H77aYOgS!APq`3v12th&%iz5UHZ7bY3 zn(*n&at3TJ*&eW<)yeokKl%`MB_8ExwueQVeZljgJ8^oS$sP%9qjB~`eQL#N(B>oP zKoj7n-?urv*JB4tt#lpf;zDuJwKfMM6>AW?jgm<#5pjp}auYaqlP3}viz`il#7j9$ zS1^#f2#JKE7eY46)DPkmbe^pz+gnbdEF)7wfYm&L{iDM;0BQ^Eb#Z za6e_+le@_&Mq3M~m~M6;2m_VVj=KtU_1O)c{tzWjL_+5o1+$}J z>1mXhPtS8kK0)Ji+drqbewu9{+B(aw&>se%+w5jzZ^pxB9l5D(FDN>XJ({b$5;K8kG$= zJ~Zk%-EcX)NUEF+V&`bnd1xo%TL`VZlXfTXBVmNt3L}8W%1$*-kQZX;53zNp%@Go< z90znCcvK-tn+Ufi(f3H2HpwexWI*VC8{PuPn|q|}(a1?jdy6wB?IH!UzvNNjM_9w0 zGYz)_*oFPk)aZk!Wt?aCigMZPBwrWfLp%^t7_JfNAPi5AxEN3`h@;H|jAiJDNY|cz z5l2aCT!QIL?E=2pxPU8v#~Bm89m}1U3+59b@gPU8*HyryA7lH=Q^KRfvWGq5M($yc z-fZW|B5@dHoEtLYLztRsu$5!OPr&KDq-I|U0>^P9e+ZzHjUceRu0`0fdByE)C!sqW zJq>@%9A^hV2XHYmLvM08FN8*c(msjWYGMgyFuce=1+}Aj4I20JkJSW?!+PVu{v=*< ziC5rRh@1k9cLf*20saA8j5p+Ddl6Z$t7DIZMhI`*=^G)vaVuyrkZm>Pb$ESc`T!{S z3bYE2IZ>p~gU#!H=7}f?^p3;qqbtP(7aQx3 z`X%rAuAwT>*PxcePpb-$*jvn0$nS3dqA~C`m2960y?k4v4Gymx{EeMNEU8 z`iT#Gf1UG1&e$yT{ZDtO4 zvY7(J3YnO9%LWYCl;<1{4T$BLv6gdqmz<-ig$p?(lQZBw1liW|h0H-?g?R$&+%yU$J2st$&py;tK9W>%69{8^! z9@>`@f=xKyPpD_=U=2Fehl5RTJ4cY+)eIjq1g+oo1i(XHtA9M!_coj%^Ew69at>4@ zXDHPw1Z-Z*b(hiOTFuM3tkRV#`Vhm)#7W?sNfC`R0V4n|>@1+ru~JkH^#O6{80iZr z4$Oy+A)rG?9|s);j5!-&%(-@7LTv!JjJiMr4+t7fLePMpQykbd1dT^z4ML2)Fu8=N zzP&5(|q zVP^w+jhV9-y>OsiBj@=BJ<{CEyxoHJlPp7=T4i8y% z@&vts@e>CEIWLb3XukWrwVx9WFy{+@s{@9MKKUP?JRrjc=IT3Cb+QP-f9zrpC#kWh zCj~@6-1rin0T8MK&&-dUIQGy@LH2MwG+#YETTt%F%_1r>6EWj0&`&0Ps{{%1jlVSs=_COcuge6)$d{Nqr+DSDSJ}<4oUe|svSh~7k7DL?M2c)k-M8i z6rq+IuWIxeYMa=vLo{vMoi{agM?4GDcZe3I@D4al%x2rp{D!{uFVXFCjjczP5?^KC9dUeuZG<}@TN}e zz@CjF820g|5Z>}(z!N_JL|J_j7=d~yFamW3fRuVKgfRce?+DihzKbUHun?~My}-fP zH9|b-D#6&wo)gFVQ8w77y z2;i~P%O%PgMI6qiHp7##*V~|>{H$Gcqd05e`ERwgMz8=u3N9Z5>oi{24Lol_@R5P3 z3n`zIE1WkOEM$<+Lg%%U=8J79z*YvM4E8fP0L*hT?YyPI zfcnA!I#Ltc%is{OppXG7Y%su9274Lkj=g9R@M0?gb}~2sESU#(%nPuS!2w{|JUWQn zc7VO%lOcUXV@!-le#U-K`*(e7>?(f7evHfC^{vy-)^B_EgKuna`Pur>$A7olp7~4t zdt9N&s)7CGKgu9svO8P!`QY+i_p0i&+RN-8RiIJtY*B8{{5viJKNqHq**fu$+OGF= z?O$bmf&ljt?}K_{ba!-Bea_Fm(eF?ChA;@8Ef{4mUSUbAYC+rD32j1sMd`^Ig>Eux z$DlN(76$jHY|d~81;cHWFhteD^v4R8S`AYlJjm(4)Qd|TGBDb~@PT>(w6nl^ss5pe zP(R_J#{P(|Y3!@>E5{R^1j+Ei2QU8fM}h18nN*H#2+5DrGdj&lM)iS4@l=@8aXJOD zLiF^FC_e@i41>nFeBz@}ygcW0=vfz)Cllh8Ba6@qLwr=ubzhIR)wXWF#bp?w$@Nbco=@W|lx6o^Mh zI%PXKi?R^{*CvbsWy9Q%_l`3&%;KFR4MbaZ3@D3*q6w63LfT_*&;0AzNcnlPb8EG{ zj-nuBc8}}}Sv?=r*G(rvyxlwB2k7Ms9?5qbMaA#;#s$|KZlp126Kp3?%a0s)=b4^zYii=Lv`pQ?bB4(63iwl}q?DgYjupoBOdY=k znI|uUvYly05cJmHz?5*bW?soDP@4ziyduP7*52-fpIqr-W;8Fp$1X8oGlLcY zB<@vl_rYccoOoA(L$7WHc{D}x~bgz`fOcbgew^Xt{jkmqdj0FSPx&w9fGEIfTS z1Il7{X9C5WkmYmQAcyF$CP0RLUMq)o#-WXIh)*|{M|x*N4(*RaqjAWq9CB`pjsD3E zP>ld;>uk4T8yEiOZ1R&$Q5Yt7l9_ch`zD6E-xwEK856iQs$DqIF^JQF#-`)71$n&> z4bWPz2JA|^!&+}npX^cR)6U8B&~qw`foAIU=5@U*osHKi!zPWbu{$#c`CN3i+f3nD zXYAfV-6h~M*13wL|BciFm(3*OM#vVG}s;`J`3dT;h;>)ZJ>HmVO8 z*Up#460@<%~!=x8QZ1xq2$^= zzx5#=I?iJ?en0B8%I(?xve{g0HvaA<3gm-4n?1k>>9_<(d27-M$8AbV<%{Va8)U~l zfgXdPC-(ia!}_{)K|?Z1F32&3TPBkmh@_l4-uroqP1h0xdD3@2?VCcN#cJ&4k?Jn1 zzk1X4Gh4D>SQrc>HzNsp5;(1R2snT}sdz*BOF+z+DU^QRKlGR6_FTPV#x|U1WV5A5 zkI9>O?4MzMbIGl}eS40nm_tMzchlH=bWf80NVmy*f=`Tr7h?jOr{8EM6yOjrP^|!V zEE7QgaZHsrM39LA-UHa)9N2;6NCO-I*zAlxWCf7rTLd@&ykH7vQ?uR$b#If{UIuP> zezGSza`0Ki-M$!cfPJy(i-1LeJ9|g__NljgkSA|r433vKx7RVDfk)l4Yx_}{rL&)y zl71ogHa0d5UhX1u1W8QnvUvcRELO-rz;9fY`BfI~1Z2L_?JhFLw}-KSa&j0c<0G+a zKDAwB_VwHM1$k6#2L}IJZ%R6ydN_pJml(*TsdQZMXS%mNyCo*R^-K$}(kjP>lwd{n z1x(;2CXfXJA%EZ>Xpp-C$Zi2L>lb%($qa%Nc{Z@Yo*K+m@QkvKU}F{L1#EZ@mp4bV zoO5NDJ8bo(Vjjl@`(K~N)h_RP8kc)&TFWeE{&v0me>k$Fjd^_ATgt!&m|)zU{lxaK z(Q9Vd7!uk|F!7zMd8cEo7C}p9VEza}x8|cV{|4UVr@&JEBML_bAC@Hv3Q&7H`_P zu_w5(x8K@7_O4@aHH7Z~XlDnINBJWH@1yCsq)OHZq-|tSvvP7%^tV=K_ck)v12_(Y z7li36-FixyPuv60`8MGm8I5cq#TFAVwwQ)_i-|h1v&1&o9k!G-3dCdtW0FPrSlHLc z)&ITESs6oooQB-_b--NpgDP8kofw1FwqbhKX)4y3jy0xa>o6L@Cdo84MrRGbRokRB zCTb1G)|jwmgSN4C8{E6h3kDnwpbs$>ofybDmuLqk{B|$5<}uA< zkqrjMR+Hm1fUn!K#|ZNrK^!0KxxsJbp)fYVGNCpTtBuCKFatW)7G-c>8kp6LT5Ws= zljjLcjb$3Fp@wR;*;-@8RvWd|CT_LCTkTDEVhoo};~*rnD5)Cn)Mj+GQC;ngR~y{b z=6ChMzx5OE`#Qm))|c66#CO7$W_~nV81fx0`Zvs`#(;dBhDz|08VbTWhWU<+A8UOX z%wsk!1P3hiq9Q;xLW~-kCQ@IAZvBsJVt2wOG z!fGz8%^K^o#u}}$PHU{y8tb*jnoWl`t=k%FH*Dat@f+;zghd>qj#b3FaI)Q;_H^M5 z2MljG;HTbjja^>z@S5X?)7OX(PG6HgID8HK#;m>8b#n398nCer^m`qIjrCw-O$g^* zGvGDn9doA4d9d6ya3oT4AA$ph4o07P@#49ZoXJ3f*a^8~NL#c$vHac_sRRyei|>qpXRqhm$IqAoVL`8C+~BbZ`g zx6$a{g%QCco_T$TxJ=&iF<|zBX zhSdU&Ld^?f$4Rq z=nv?^6L0px`(bYIVc)Fg+l^0dJRVS2 zWrIXs%M8%Z?YW;5H#g@CoENa_ppE%3?tnaA_UygS(8VjD0bKxe;WS5qw=qMOR=F(b z0yO7hB<0I<)d+iuF41dAyDvwQr))qbmAsND-AF2h9Y!jM;nNj#$^vPF<;gLWXeWp%gh+CIagblI2&`Zd!b zns~(Gbk?gcr13S#3T=#spXv@}D5B?Ez8OGoG9Nq#)cS;`yk%K)6N2+8+n5ksNZGK2 zx{E1WlMq}=4v#WmOH^~9uSbx01PD_Z>gTxe)_ZUnBHCs_1H=g-g|4eG_6A*siAq?= zfHGPbQWHbPyLTBX>WNicA7QAES>5LWU{i|vrT$Dy1BeK-)Ow&jm8uA98X?< zd~zu==-)(4gldP`>&Y9GU-`jt$#Q+Wa(&lweaW)-FjGOflZ7Ap&3@*5e@LhXol1fk1oJ2z=^L~66^w?EUgJ?ZMoW>=k~PT ziI9^u-3m7-+)gXEKh|Sgh=n=|!9@jR-BrX0RrJKAoUb|IT{ofT`pq{{SiLii^rm{- zQ^P)QQeNtw@agrXlX?OpX9TYx6O6`B5KOxoV%Tie!Z6+H@jhnSDXD%Jpl%nrAmp2l zN;vDqu_RtC$?+v#`ObTk+w;GcDBmb)@Vmx11O#Ty))u|qx zF?pNfi6-@HW`!dBrp2jC3}w`n+6_dV0Vyxp`2ILuv!*j79ZQcSDSL#jm5gV3lC zy0-GjU7jSYVK{QCTNnW4M1WUQZ_f{t51oqXnW-675(Z;AIv-@d%Z$y9Xc4|y=d47` zSzd)x7uR9S^di-ROO8vPuV8cEpjOxU#}+|;YEk|C$mf1D*g~^1U41w}^YR2fYh!1h z@h$UyxA?j>9PN3llm4hT>$3Q;#xWV(4@^<^)He8ROYW=Z$sVt0;`c>>Jn?0L7g58W z*ZO$5bYeU4{Xy|FKWYdNA#jpYd`m*Jl8fnF&M!js8AT@v@LG|@St^zo14@MUAsF3{ zLcs&aeMYB3x=_#rON$;9ABW_!Nn;(7(f&B3r2uIxVIF{yL!OI4C|L6=b;yI+NaNV6 z@u}ppx|dA6N2kuA`(~qS_n=#|;|z}nW=H5@z7X+|rNSupF$TF5ejJ4{=(Q(VFHC^f zBZzIVM!z%>A*S;l%r0q}(T&@$Tn=E3No2K1oVDRldtFTTrXb5V+#*buW;gp3fN#2y z6JW9;1PM$S14^JyFahSQ3AJ*FLq*Jzm2yx;sGUQhgy7O=v#yy%sFOnoKPCj%yi$i& zF&!Wc0(eqH4z1=81n}55(g=AD93co0Lpnk&2e*f1^9h#>fq&0g$e~safqoAmC+(px za={Q3kZmLc1u}r0Trw1lCG&?@VUf0A2=upLPYHp3Iaoq0w(`V;z~CtU@2cAXYjvT6CaIuOxKmlB6jkaRI|R}j2q+-l!V7ZTs?p#u$H zXXh)^BHW*F0fta0+ejnl;UbNC6oK$8S4jzBSy}B~7qhwBIhimAXeW?EnhNBQ)&e=C z!2lt8T?X(c$jc_cel($taj2C;;Ozjei*kfU*M0+@1gk(@J8Kfu1DFs7&qBri5#!P_Y zM9Ux)7~~LLanq9#hIYkW*epVi<;|9I$SR8l<;D)+*a$)rg7XHU3Qj8L4bmfb;Qa_O zA#A*dRU`;`TAn*V@MUqtr0^ zSgNO!Q@V$k)J6@N*Y?(rVJ-GI6EUg`nW0@l8|9QqpUi0CDG) zzLENW>0SCQ-j{P0e&H3*z5W+){IBbaoUHT;b9Lcsx})$d{bzgXOSt}`ya=r^*t;nC z!gWwD#|zT?F}5L)_KCpDfO#GLAs3yT!;f$+`w_N2@gwA2y5$S3IRIaHM^Pu=QPe44 z;mb$Uuge+18@eXo9sOy0>N_z1m+c=9P=zxQ>JaxNi5jn^T@LsdNY<026reeVNYUNz zQ>QqJ=@18ak(2_!NaB8^G#fQuB{AYHJ7T0vZ=y>n2)siOD5{I2qv3n##+&S9f3A({ zQN_zZ{_NLvz?K{@vx{37h#6sM24XgywWZXT;OJl zOJKmwCXR7u1l|E-)mIho27FD|6~3{bZeg7;^{xtLjEmT0(@$=r%%@S31b-0x2`q#q zIPg%wfrs)ha4C^l)}{&MbWaRPWozJMEDu{^c{uwh?=BvxoRA>EN83#F(2?ok7OVB$ zoaA~j5ha<>LGT{R|?Qv zTUxVfURg@8#~e)=GqYI-LHusac=3r}nJB<3#>_ELwRze_%WqjZd)fbPqD(z)EjqW2esRH@%6I-8#?JRA*W5*a7N`JL_va>q|Yuiil#= z@X~48@ETCWIFG=*i74p7m}@Q!UK)CGk?6_gqT~BU;pV)5RKpS2Id3JcuPl|HgRS%C z()!9$?=#H?COp+Dd~4k?ZGkyCg` z&liaOz*MvZOe1wey2?of|vWO?c8R z!Obq(>M5T&o#mEo1~SBZKQ3D7iKj&>Jih{B&l9H34fY5cvOu*0}DX|C1r+* zk~WwQ)(bKyR5M(x!cfuHO#9bt5t~%NFjlPMZktlM+iJAOoaWXR;22%LXP0)X?I`)E6fY+6t^@As`GOaH*J&>AyOO*6F5vs?OClVM>#=>1N z`w7aqGN434fZ7qzOIP8GYo9-PVi;zxXAKrQ-1~MNS+)jAZChY#3@uxGOah$9a-R#T z>L1Yy1Z!Ywlj8ZEb#b^+cZdeT96v)M=$+{y@+=j!=WSOZWqRq==^u>71#?#cw4?wU zd~IxWxWhqHo$i_LY&$o_a9B<>!H?jDZv{$k7PC!i*d~hkMsQQ9U$^%jIfJ$oJOFzc z9At2qftUD@=P7Og4|k*09qQ4l%3)e%m0wV+yfHd6njPBo_VmBOveKXS&w7747@f&W zNwH!5=webXBQ!<665x%c@KN!*VCrKJO!agRYu3SKGrZ_jpBXX@23Rt~n@}5&??okV z%$CCS$ejZ6-Kiei{VbnR`c&XSA)f(VKd6<PsQOR%QSG6W&eo%O%4ozU0teA zAi0pag3Jgn*2j~~)s-*#s0Cg;WUT2rbtR`>EM}M@^UCe&{qZk!K(Sd_?^*snfZLkX z6KqfasGMrEuAG-)jw3_r!!J8<(NH1ZJo*?eJECn^>^c?N5R8K|+mwYMy3s(J_(296 z0(4IJa4oi>$SMy4bTY_CZ;mfNt(kOyx2!^u_(2B`HUW5O$7g`N2KpRw6#ZQ3r}Btf z&IS67`n`#D`*U1c9` zsrq~gs7rN}*;0MpDM6RKTOiHx;K@-W`#BJYzD*Qw*;r=vJ_>Gs>raEU_ksJjAHi0H z$`-c;gH2w(a~_rdyU^3<)*3?qqVu@WH?yPyEjh zF>Szu&Zd+ZmE7UaPOR*Dz#B+@A5luD8P#`4Qc#Q~uEd>UQEYyU6Ol(7^}ju_Mw2{Q z@yT39<5>f{eR7>eTf+C5cw13}_Z?b-wb2DcF9r<^&-0s}06P~yEe}xL9L73iO>9wy zxP?nTZo<*Za~77Y;e8AQMOnb_fTRF#sac~NugFkb;VI4DwgmzJt8@7^`~tlB7Wn** zD0jOX!b$E*dXw9H7)E`0zkrF)K0e(MlXB?dwFEb>5OM^6TaY8T2kPUBPspTJUU(Ge zb4>VNoX^$Xh=pO{q4K>q&bf}biU!Ek*m1*%u7$!K_wa_WLSG(+@GR@r1foD*p5pNe z7B^B+$Ki)Z(b~n~!)o=bA}99W_P!~RW!H@^yg+h037D~W~9eAlQkeb2*I5WGXwiNJ77SzW>8)uFN zh!RwV$sQDgg>ZD`-W8vCaSsoA73jw0T>pN&;^#el6oS-Hm#3H{s5RwE*Xw3YP{rGv zcBg{fR7up+`B_!Qpl! zC|w+`j}GS}9cPHb*7?ZD@4@g)D~DxzXvJYp)QdUUI)i42Pf(@p``=J(?^YVHqjdV38Iq zp$u2@UC?qZn92e^f1$24sb_)oA?|?WqhJwXOr;)hnv`6{^;@(+Ao9Tuw6Z=% zEKq|FgBd(Xvw(|w11oT&2?fBL!vg?{0)9v*bfG}_wGssZ))2~jAiKcTN-7hQ40$sK zC*g5Vws_@=-gz9xE4AfRDOpmJ#>ZW((ydL58aUPiJ|8^$Wo5fls1(FHm15;0))iUV zxD_gelV!1bQ=gg|Yr#w{u4l@%G83&aXjOI!3$kz=*~Nt~A_^e}Pe$mIlY_i1zcCu2 zC1a6maI_V}aVX%E-f(QZp=U!dx^3Tzap0P#xL@Ja)W&hjVPQ^Q;r1Dr?BYgC9DMi9 zmt78Kiws1k0eR#&$O+34v-xo38d#;``Z$Up4>H3saw$WYLogsKC4(^3ijxZTH5l$O zUBNYmM^?LVl+p>_X-OwSnOYhs(-V%8$!rx43CIj}kY;mskY>+7T9j|Q_$r#mN{kAc z>Oi!QGc3w*09RUqZ$At0y+0;>u(ut{>c~fkW=S1h{$d+lo^Vtr)w+yJIhABn%NGeF z`5FqTDSDH$I=oNqD=(_1at26+oHo^yk=b}_ODtB;!K`7~_>PvAC9y>iEV|AXw4iH< zFfDl>dX)6fU}mtK1amubjDaHY*>{AKM1sNOX@7gxqqYXlQYI$#!6!ip<{z9--3O&Q zJ9!Y27#E)vGIPRO5)VRr=n(HJ(IH=1x)?9!5l?fnRAd1LbC_0?RFBa4McuGpolG?9 ziAljS%cvjb`=%-|-L?|ZGdYlHNiD*o%RT7=k3w{$NIH;36AXqphZSoMX-c&vcP0yx${ULlBXn8@s0$PC@oE!jcF@$I9*6hk=) zVgg}`>k&jS+JkM{mLvBk=bA9rs|*{y=~)lV-L#X3`e1HmqP~gqhz4f+IPp5X!fa{9 zoFdRvA72!UwcyTBk=MC+ia_o*!dt}^SGwS=9PrR(hl0K_B82;Vze4jfR(8c465@V{ z%qsEb3W6&{5$5MeW?WOCLqo1u`#)DLm>%P=MP5K^rpjFs>vWMh4pt_6$9! z&}<%h!1+8VU^Wk)R$&Jk=mE1==s`bwH2?`PI^ukEbP3T^!aJa#k_FtF4Y#C#2|5If zd-y6K?}+DiK0mMsr<|i?Ph}$?hIZZnj+F$)eR1SU`l2U-;4Aoq!if(-UJ0@C;86)2 zixEaJtOaVyK@E57fyg;y5<-?~Rg%1O5%F&EU8J!mcU6KPmBrcGuAPFJxxrBE#dFO^XC_=i=bRKYnQQ2mP zQjXxXFJZ!}qXpnCD)y1KG;4kz5Y|F{tw^)x5S~s*sM4$Abq?REEfVZz_FpHSavIrW0G(LnPtwIghkqu@c>w2cV zd`pHiDUh_eh1#$z8(@v)%#yj_JF;OZXk{WU>G5)mmC^E9V-an$Neia3piV4b3z(`y zQ5bDeU#5Ajq$adz0mtd^9AXQg0d)kBU(m#Y9eFjD5pQt~2)CNJPi2R7=n#67MUsxI zCAfk%)C+6q9)NKh+{&?v-$ zsmRh%01-EV;TVWxI*$3qc$T8O;HL@<6EWEj2l9hH)wgB~IEe(y|5hPEL|%wEQ4XmV zWf>9mz|47s`Z2sI-=XtR#}-&S#6NJ%3|BnZudj0l zF5aUrnD~+j4fzQKs_uJW;!3yx85z7*q&( zR#f0!5Mm$pe`KJL-Bmd{qOX@2-w{H230K6`e>AY8E=R?1;Bc6}UgB#e0fYlbx^Q4v z=W=d!jA{@BZ^%Kv`oLQcqJd>yctZ|VlnH{ST_%WMsE;L_eGiDCSfWGkFmOR6%<*Lk z45UOvpwIn~b@T?bGVMl|mqYD-=%f@Yb8t(zVpfH~FhxZl67+NOQu)TO!c;&8-}-t9 zav=}E{Qu2Cmi#5wWAHBaiD;<$AaUv57Aas_lxqmd>OvgjVj$)vf1?;C^se`EX*7!< z20eH$m&Pz`5EO3ei=_jikOND>e3s^3EZH@PI7-CR{1;0+N3^QqM-au1251HnQ#}CJ zWr8?k5Nq@#R4`QvsrD??D$sl0>>(|6Ob=SmB6)LAf zn$5Jf;PukVEWXEXRUNPA+aX35+2phd92-TKDm#_5lFJBvD5*z@y@5juu0|v7jphyT zSjT*D;7AV+J8&4o*a1#+K!9D;>^UdcYW zkX;Kx6e9>k!|(`~B%hcRNIM9Jg>XrL$ryxT0|tpwd`_2%)|+}*#J_#L1hioh#Qr}$ z#Iz<4^00;Z5qYyb-r)MDpdaCI^VBr#i`^Qw`z*Nms0 zV_q+(!!UhdQis_$!hWQYQB3>h5`S<~d?$+~5M?_=t_FZi(H^3D#RH~n>hQ?muBQOR z5;^q8{M|S{;>2Jm^G}YlG1=jSf*KTf^L=qc7N5a)AN*pA$l=ot|Klxvhd6}od&tfG zxeIa)zq9aCq2a79V zhjUzWKUCmX{ZLRja3dXXi=!J=)%XaU(`qr6#|#3Ds$_;Cs|es*EY9&nGx?kfY#LbI zm$}Gb%z#0QA$Y<^U2upM!6CcjFBl}>KVcIsQY3C^H1A5b0{+OSP28*jXJJwf_TVud z!@h7^;ZGgt6yo&cXq<0ppz9OG4e7(-SUJb5Rg{krdnj^7t1Xl`BlV;k#*q1(+JnZU z6Gh1^oa*dSemt+Mz=A3Kp58xjHmUx=plBS6uo4BiJy1YWo$PC^0a8$n@oS8X$vN~) zj)UzG0@R4l$3$g+Jsl1w%gf<##5_`iXx}{d+$|Y|XW@)82;&L7Nd*!P!D}gp;6_`s zlQ4eWRPNwui0iiSGg^MXfi+8(b0HFboP%{umWlmw@`;!)?JtYQ4i^sfdZ@zz%)t-Y$zUG%%{vY;JxtX@9S-1KHolBYb!ExBl^C{Vpa<{j zmau@|XK^!hXqkL_6{D8%t0}&LftuCXXFKpw8iJ2}Mr0H4QMPN1QQu;G>_!tP9G`^w zI0%N~4Op?n80cIKk9(YO3Z5>5D?=QD(k;P5C7Y3_OIl1zdU=yFH5B8s(jm2Jr>1s_ z|2K+rEVyZZw0L|oLerK*6g!QXnm)AwmdIlk^^}u9q=Z|H^U)J7LrSJWTGR`U zwv?wF((a9(E30tE$(tthC#hXaMY zE!)rV>m&|>bLfmix5NsoE3gPp{`7@tG6A(Wf8*U+g;gr0m7&3}4Ns;kBmVZ$JFya;P#n4`0vF<4mrGe5$G^@qp#8@dB$) zbpVb8CIxTHNfwZeJb-Z@JUFXz7T~oBof{;Bkw!TMo&7LKiZ+#eHp8?IHY;O+e4olk zuWneW42AHEdu=8XER=*K3papIRF>4pdW{kxt(VTz7&#E zjE3~X5Hn(e_)>m$fM$g(umiv_Brb0PB-saOgLEp8f}ntt4^aT=V6`x5hAUYMCc*+X z12qs0{Vznr*Gs4Y(cp2jvtJc>Q&mpU48#qHhJ&~`a9HqU}p>-hahSoyD?cv zCKk<9M-Pdnooc>VcW^3yAd>3nJ#;nNzdM`{$owJHStiUFp>0aHpT>J345!=>JZ(J2Mt-e@#*$q-r;7K3B&D1^a}Ql<0m(LPQIPJ2Z0AdVwzmlAE73kNYN5P(F<0Ay?h z0D)5(y^TaE4U8$HfVRT%V;yGJ`3zX9AxdeW7`*3DGTx9!6Oaai5LU5>;!Q4oY#4~r zL^wV>2~{K&%$Z0m3!i&PHtn=#@h;kl$=@jcLKH38$via4fxdE57SdRzhkC4Z5?>yR zEpKUozlB7&APTZ}@Dnx5S;D0s`78#0PSp}FgUu3fhts+tnilczT=zkz1fr-3-_x=Z zEQn*23J?w-k9rUgM>+v;8U4OI=pyJyNj+cBqXc5&3L+2_XIHQUViHG>BKba+O9!Br zV%CXr%(jVUh>caF-EnZ35cSG1i3=gAS^uiEu#=IELngtM(GeGu&R13!1rvd z0#Po9JOa=O+ggMoNR!b955j|p40q`6j4oP&Z`j1V>QDl^ ziecCjV#UyLAPceL=w{*h$`Q)5&J;w=dTU`Vj8BM6_`1#ii>%v=Pm?ieF^c(XSWFwQ zot-`iOf^ic4T24QG2~!ll#3GFz-tt^TkLRvSGp+CKqMc?xiVJBwd+`8AYzj|-|7dK z18^zNuAG45g{T0F7?)Ut#SUuForDp-DY1(l1QB+Khz2G}tV5{OQ}=?wR4fE0S^t2O z^8l|BGaMpe_2K*#3X!mgTF|k8JVVF zK^M#=!@4eb$VEtk=|eIINi|G-4V^uvdco+cs}Y1SFvz80;9_NT5JI6lFK1-x2NB6* zzZBqop+5b?pvoDXIB~5T-v)ApFo1+O*nt!vIMJ(0A`VL$$lz3=1)RNzg5C&1h#@v4 zNj}esaWEKp!HJht4kC)Y+p9$QlzDXay&uLPDxI)X#2J1Jjs*xhfG$@OmLL;MNWeWw z|07NT(USsHgv;YxNPg7^IwUNy00OZw2?Am4gh0xx7?wEtDZ%PM9?BsP%nFoG&gE$d z=7YH^i`_#YkCteLktkj5ha$wI$#9kqXMP#%{gi~icMyoszj1nE@`Ai*8ie@NU19;{ z!kAPI-uFNxpvT3#I~_$)*I$WC9bMEwG=Q~PqgZMWh{9A@q;u6Y=&(hZ-0s7!AsHTM zCwxl=#^(j1o@@*wK`iP642pT#3n2;eLLlnFOO|2*nJ5^|OPEJh6cD+9dJ#q?aV60R zoM$227Yo2;>4k!bq8$ZM5Umy*^iF{jW_=_DyvsRvcy-`KBTmcX0t}3pFbO%rBs3D` zOrnL62r;PD;oq42jXH=usTM~LO*l-#t2h`3j&P=sL)Nq;8H5mwFcb&p1&1#-vW(HF z6|(5gVM)FNUWsS~=L*ZnV)&7Md?lh03>f|kt;Bz!XaMhm>pCLIO8x2nVIzbG(bRDr z2lgUG^$xrkiuw>CNQVbV2PM6U5xkhxg%?8+Ci}Glml6V$5QKsl3J@!})D2=1f)QOU z3h2>L0A!a#YDKJw5M+Z<*g-UDrTAn9-VTt10+~_A*asXSLAHbhmoXI8p#aeaSVM?5 z7D22W>V<;?ks691N1}oN6hpYdBM?lAjcHN{Ma%GNOy9;@uX9kY)A;KfIDz8r*7G7FGghxWFTv zF+M6}&AbCX*5wWTp4y(`5JibS(D$;BDlP>HZ;VGvAR}LRQ-ygdK3#@-YNSLamDI9V zIonTK^r{^yH!BF?}iwvq$qN#_sq?8gdV5goD|2IAoAFb~$)arg}ray_maALY}9-Tz01dB81M zSEteei@5A0I@ynPdsh!--Coth;VAHw0+v+hv~8Smx;Z)<#aoCjc-_EY0zc19G*Jdu zFQXV09OkJ4YXH!d0WRT=)8-BHICuz%<`46X6OW=UR+l!Yiq=JSu5pxKDT${ZMhDdc z0;!JfPbbw&PKQKu!#o_!*^jlr5Iy9Ec=`bdSI^-8-9Ef3vAZR#TO3I@n<=8DseaQ{+==oSMCkk&&=CCBhQ*b9L+=*f| z0=nb0Wz((9&oRW~@P#*qc(D2wQs*Y_cgxWZ@CWa=51^M|X0{BYJ!*4I9XahmUX%}` z`GZSnwm;nnxP(^w(fdGw*jNsnRm%-xCNZG~i)cvhhossp|p@ffeZP1YbgPzNf|Q^`5rix|nbz<((JXbJj1(E610}0uu*h1qzqv{4atZ`{RGT@Z)(I zFXTVdztAz2SLPucbWHzYD4UDl&+)s+R#bva{~zH#?)5(hzsvCZ1Ah16_Y8iovF_rs zSoZ(RUm51&{`dD^9{g7a{_oTQxP(3URnj-$zYFp6{Ldjcr+>nKzQgS1Im_sAvwm^f zT;BWNx=ezno1>e=QyiY4a&Fe^VUr#v@X%Av z0|i=iA`i##Ph-cJ4zqjvuAN`+*s;BB+t#gLZP~oJqoche#Je>erv2;P-py@#a})~A zE);&foh`mXi%lJ)J9g}5*$$Mop&rY65Jdlubo;KIW@o$BCWuWP1R-!y--6hT!tLz> zLkij17S=?ekAa}qrLe7Sn_tsI3owC#5aQ#?GLO1q;#Dmu?98WoQ-|D%cI<8!QWUo> zW=m#s$1t`r-$a{~o83Ff4e8dSZ?9tg_4YQ?7T>m2_@Pw$U3wT=0?D7YE(EeB3x)4_ zOtU=Rmp{S^+mXWDsWSB>ly2WGf)Kity#bOnRAr~Nw^4Q!hUKOOkyqG7mU&`R7JF1d zz`K;x?clplzu9GWnjNOC(^DKzz&lCRwr$#cM8~%Fj&_xT6f0XRh;5lC1Y(xsji)>^*q zQF;c7`KC(sPKbI#lg-wohhm6+I%CglrFUGSoT?PZO<6P~}LH z7hjpL%;qs2X)wa?J4I4iH zZ2kJyb!*qIUcKtmPe1v{eAN2E`|rK??!W%E@}KX#{q|dL{^K8ifBp5>UVHWBmtT6R z<%JiXf9~18nZKD8=FeN6d3w{A3gNR>Kv=V8H2{1J2x zX#eM@zcgRQ%*B8JDu{zn0USR1@Iz41g$NJCi!CiLJWnbFL>>*~0%%wT8i>OCJ_&EV z`6e*{3a<(ZX#d=^&sq|m5gthYBw_U`v5FLEjUB`66b1Es6vdC=1B~qVOK2_)j5$ED#pHEFySr9}!Rq zTBW_uLLmXoL4&Ua6oC~XIoO2-!b0}Hsw)Y?0%)P_A8Ke>m?wgqAy^SWgV;Ys2pLcb z*`6ZM{zV0B|1czBA+^}D@S7_5#^0?9stlfc&f@=PF(bD3%!r0a9hUw*E7JZ!zE3|z zNcx|F3T@o*x%u3z|B5!CI!qG~2L5a1JLaAB;NY8z0YQioJ)cwJFE^TvF$X|=J)|Cp z5Oa1QAXJa??ci^|9;qHH6MQ{Z9LU4B-ulOz{}3jK5NQXhhrSR+2&x2K`?o@%9l{W; z9e%UDFj4H7b|_3#A^NTadTd^gIq$)pfRS_sRt|rLDTyhP1vxo-daSNQ^w4@UG*>+m zQxZAQ6^JS4SitsTN_qZN^oT6*^$^~W{Y!i5L7qdlb_6}79f&Ise=M#*{4o`A#fm?h zKVRYdV<8~lol=oSj}?G8Gm8K?(AAKH0eO1#ZwOFB5MPFXuw9kF=U{8=TC>)yHml4h zU->Mc6g(EbW?qXq+dVF5OaK*mT#&FN-bAe-r-&eent-4rNQgC43gS@JAxlijIdm~5 zap=T=-ULEmRHH5U4l&;$TW_?M-hlnXm>82N1=@jUjr0cWKhL3(2kK448{`b(J@eic z8xisW0KyCA1@m0Yxjf$~3k->iYy6;)3u@|-XiTKR;vn`6rw)%|L;Gi9Od6Evk$fJ$ z;|DbjDqc_|3(TLlt1601S55fTeEN#d1=VG$lKMoIBF&K)00O1xB^MHw*Q_$DV$N?r zRj)=t(4uo;A?H?wk$=raCb%S31ULkSCh>|)E@%#KgOB+h#S;YETes@bkaNp$Nano< zRS-gh&qZsGFb7`~AWF|KOM)b!S^P3EpiA?!6Y&QS5K8P+NQko>5N zF6J2&qbud`QO=@s(S4unM3k9c?N(u;=4iR_F52k1buaheEcfSL3|1=+E)acBej`MmF7q(+Tdj43PTeC#GFSNp9n%NihT6tpeY93 zlF9*oQBoA~i#EUTE!vZVjqkok=o(r?jy6A_MJf;8XLz?Mn!1EMkK$Pq#b`E~4G9Sh z;?`o$jW$g}ng|%g!8$fC#@jT>_evzeOY_!=GJZ-yf(N#}^-5ljA#BtLt!(t{Nn(Sa zrfQm|uKi8(<_byH86VZHVsZoXTx*}k|naf_9Wc|()Bz&LayyaCmR|5iB!+L zW!`*SnBcp18(uxHnhQ_4=OqZyyqAU)%s(&B^ULzsCjm}S@Y0-(e!83|MhPyyIZLLd ze%%X@T{1-#156WwO*h_f!|#9hyX%)+ckQ*;Tz%D*SN`^j z%P+g^HmPmi;fEe1fcx&f=bpRozH`|fcieuP0Js?d{&0i2;UfT0 z2v=YA+uvRR5EcSJEC&Vz@TWfkzYrq`jixxA#$af+!FNFoEswz4sn4VVPN$1{2KE6}R3( z4E_KNe)l^durCJ620%~@$VRY%To5)a1sA0~xDa#NNyK&6fs>LL^BPZWc-YzN;kJ{!%jW$;Z+EW0Zqv zf-(W^mr4It2wgPcsw*i*wiithIa(%y1NTu8M3cxv^T)?UiU5#9fQqm$0U`uQ;Q=7P z_9TD|AObh546YXjTy3uYP&7$&QPjW}qpBi>pa5=PdaJoLW_}@>^aqa!k)skJLJ%hU zLI4UNA`gV(VD-QkqSC*AVWOI& zRRRi8c%VFlCSQGJ7aqbK#S$Px;i2lGuLMfJSQ3pjB0~>F2j~rA=48rI%^6M&?m$owTUIvGmI*>_ z$y0;-=@cy&h=PcbY_ud?O|L30(QE$%)lh6ve4>y*Q@s6lv{zfq^-mI@#?&IO{k~ij zHTKldx+Bk>`MyMbviJgz1rMtl=k-sgPBr+0r^a~>S$zqmh^VqW&kWH19!8ZezAVQ- zm~zaNUL{hbH?mR`P0lF--63N_js^Q_A~o4lB+nAWl5AXpPxrORYBFV@T9oIGFL@di zPz2%*)e?Lyx^Py=jW+^2tui{g&0JGAat+f$3Rf3&ysQ-n`HX`Xyrbcpew zOHlIsdCrx2W&i@NFjwrL5L5}R5}Ak1gP-LhitkXxkR+m9zr-wAPfHRWyX%9 z(-ZY3)I+#*39EuWOqpTX>cJJ4iz(8hO8*kp)s*Q9XbLtz5>pb7Y;zmy(LFuVuPq~G0xihPjU+A5_Ua0#$2t1hzhow~BXdX0Ecd;c1{Ken<*BlGGf^ZBYCZ_@MqXf6 zZ=j~+u~2hFo1W#XfaaJsGqEa=ORo0GF>`TUy)DNmO zWl@2=#6ncavm`W!3TTci0YO~>4bjqnkC#`_8+syuC3g)dbY-Ff>|glzZ7Q^nD-aWs zXyT~=0}{RIL*^m#r%xnBrVfca_rsBA153~zHuzh(f>z%d=9Ks$j{ZY$ouF4qw*2~ zAo-9rsvuM3QTkncLTX6NF9jEDbP7f_U9ebM=8uoFap>q{$K#JcZsT z#k<70#KfLmeDOsW{p!LCE;#?ZbANfxIcNXk7iTS6bmkd9``PKIEnGN%e)GI}b5ET! zd)BO`nKNcgpEm83pZ?^>C!hSIAN}yeAN=5isoy_77F)ddqKhsx7n<`QKkwXg3E-?8 zfCUTYH#g@1Ob39U{)7Nd0)P_*z^@lCzW8DvfnT0Y1bz+#&iL7B=Cr3500RXu8yL)- zAqW7#Nj?VO|8)!ienkq-BLx6(*3SXpOrL`0xk5pcX)-g`OeX~dKn#BHgQ-)$|9xTr z7X0c$aNyiu{_>n(m|rXv6a)fDn6Eq_1~WiH9)J^1IAQ8k@&EuXypSwZ9tsA^LsG!@ zWTI`aJUr=#=7%xoBg+MWkuL^dAYwS}w1vV1O9VlX2@u1Ng@zNA28zLF0=PgXvi<24 zBcw2I9x%wE!1k7jLIRm6YH&W8=(o2_^rSdvcGJuzs)6*cQdBiSdjKE{s7Aj$+njCA zGK(-O>1h&CAQKb?%2BwWas&!ilSqOU0~F!sKR*+Sa5`8(5}GX&yXZll7^w$TBq2c+ zkvvc-QVPn#Su@Q{Grh$kkkiDRB9Vr3sfnt|U?OB7JXA#zF`i;h$^7KU=ErZHe9{lq z7^WVdugm9&F;Ni~Sw&a?O{NrJOoD=$W`1gZe6NZ@)qq;y8^gJx%hni9KV7WR>ay5^ zr-?#>Rb^icY76GE`rXMHN*Kd6QbG@ zIXGJg@byS3IN|$LWV6^@w8pYPyt;%18q?|GkE}GAclN*0Iw<@$t-#)4*_bT$T4S(;!`CoXk?->YHXw>{QT!Uo@vqrikrdcuP5;aJTPBu;XDR}^cVxpEy zbMo9G0<@i&-$UCCaE(Fo5B z!7~R*5pqoQGCcsWsiK;*CTc%cmymPpvdZgW6f)SvN?GNd7v2rd4OEgTo`jQxd?0d z2oO14@^x{a@Vak!q&amB4teRWB;1}V{!kpV*n+i3>lJf(lF*}5Z&M65 zyuzN(^s^+U+e{ScRsFyqxhDGe9Q(z;0t?owBKdAzQVey=bc(Z)@xRs8CFMMdq*;Q2 zrdiZv&#l6#trkT@y6Z(~eQ1FY#GEzJlc%1T8AXrK)gUG5r!tF2(bzyP+VIpRN$HX# zEXpMrJ{P@=o7U*X2JuMr2PDB-6Sw4X9*65CJ6wMTQd z-+zAqz}6;%231#McdfkkM@jp`(Lb6`1_B46d$b=n_J9NGMvpS1ZXG$C2q*v|P+eJB zG4QzKjy?96#>R&4eNPZL8~}*Go&bK72NfEtJx@@SwIkO!&;q=8bXIPO?;Y^SjC zsH2WFN1E^a#>znzA;$%g!wAY@$dJLJ2qFhn1YZtEekUhKQ6ypjMW}-&l8YioaA2^f zh_*eY@V)N}0{@GZ5mb(o4?f5o6m#yQI*%6^zBz#lo*YDuR0Us`R22>*4wS<| z!bNgHaZowXoX7=Vo2@ykIeJX+%$d4OCXN4)4 zmmxAmAC3I0UNVC^cvb z(Yh3INkl+>DpYYjIB>YA;uI*t!Ri!!DMFXcuvJ4<7d>;NQv(3XfMOJ5fLAnA%%o4O zJ&RlPbWyBHR1s<*JWyqhIqSqAJkKijpsHj&t2o9{)+Go8aZ8>{@FIhCYxGLsV!l18 zWA!|{azRlb4bom6v*>|uP7+zvo@mh09uC2}RnM_|dgNIXBa=#T;zVe{xC6`qW{eqS zMrO#xE!LRm6a|7BQ-f(RM}2KUXl#HcnuE+lcl>s>M)Ay0BsitPX0WOGR9rLM>OSV^ z>9Piwi4)8OGtL~a#M+Y>1ATkGUxhN#o*7=POYrR(;gzZ^;SH*!;Zgm8sG=tXZ7+%d z1mIGj2r=i*t^v-fg6|mV+Vet#j{=oxA8W`nCvhnfp1c5QLxbp|7vAVtAqMN1CyXZv zk|78Qk|Dq`n?W(>W+n*$;kksII$PHauck=?U5dtN#(3d^7$icpwx=ptbD$Wy1W0mG zLW8Q(Fo{k!!b*(y43dtSNsg)iyXuln61)&E?Ipa?qBXoqc+1%%E&2$E0T@sh$plGL zyfg{M1YLaDTC@t%<~cUJ+2C@R8DyYNugh)8i;3CHSomfrw9{rAzn$?Ur2bI23=JJCig1Xb4f?1@19NsaH<#i=q?6n`RmsDZ&8Y!1v!9B;;(vF3n3C525KhzNE^7FnPQV4@A0#*<6G92+} zc}n1AIFN!+@HxFY0f-*u42c*ZK``~0Bih9)GCEn81R9uVQIH-E`rMSWMcNXYlZzmN z9>r5c$x-s#!xXG7Aw}>MLEAGhm`NS*NDAP9I#Xvx$DFIIOZYZ(INHy1)E`KMww|3d zkdeMBs75PQ57_}(Vn;G`(<&fVvn1wM}b!a7c^H?RWJu^5@pJ< zQ6W$gPQ|)`1N!&t+owiF; z2~q?Fq`IR&zfy$#1+|hHkR(#QP47*B)xCQ+RI{jiSOJtGrJ(ZZD-`;O`Zp^9QW@wg zBojh@e>u#hyBw!{CRogc36`DYlx3$t0;7bye&B(}PSWR9B0H7mg1GR2-GS#|LNRd? zqyhmCl9isvf->c%Fv>zAH~X`@UcJb2WoHo~f#o5~0uiywMf5Q9;+Z8Nylztb_~7P7$9nJx_dEiR$Tdp`--rV#TMd5(2Hdcrq5O ztc-obZhf)k3_7HiPcwRmTIvui%JZvOreRGkO`(#VbZV%({BUSm^|$+ zx~_~64fXH>D4IdyP|;9DO0CpWb+red4b&@Z zrKbPq$}AwR+F+4VTXwA)TiJLb%=PDCzCLHlVx?3W$_8Slm7+US>BLnTXrEeadBuxLfI?x`b$JVX_6m#}HjHtps9yH(0?hr1B zFIL?vHKnF_H;s^7$hTB0Ku_D%gGwc+9?`POU=`H*bx$~A^ol%5^i&317bl~76&6pV zwdmOWTKfnGXi;VI-7&FOMHUf~?|HrmplF4jVp-Rx6pE?t>$7dRv6^KeWd`&&{XffN zDJ`{&A`2gEDDn7^!z!Qg`*uiBd0s{pYX==e&YH`+K{`9T+Ly4w3xeX-td1&2tqt0E zsvfy37p#X=5i06=@zjqc;8mzALp>j(vVmtP^u3xO)t0BpUIZ{j9bGJEeOL8U)IBF7 z?gRFmGYSbN%1`ajN|_pyvwG7rNo6QAWnY6=f>%zJ7Z;6n@ZW#1IFmCT_4qUR_5SXH zGn(hld*!+2v*$+bVol>v{=Z(P>DyMeBb@(XWjpf>>ICrnww3L;RFwW_nm5=p4|%L? z*Sxn&nVB!EPn9}*YaFMxmj8@nYF+%|yl}X`L~5|ZVr;+Y)XE=LNYy%nu_dKkV+BU1 z)^N9qTF1q@;aHNs*69ftTok=mZPKX$s9sJb7MztDrP#NlRBIJ01gvjP2&G(f+` zrPv~hh#0Kw9mgJxzyymsVtIFV5J53cjI)=;z+({3fscbdEu`y^w8pBCa)k{JYHM(s ziV6@c*ozg-rFwyG)lm&{uxMBxbw1uEj-da9q#`~N?nJf z^aJaZEM8k0d*dX|QvAc>w%RXtBtZe!i)X6opWW9?m@3Gi6+Vw>{$h12y$paSm1d@Y*OJ7t? z17>#|Q!L>AEB1oI5&{N6Tm?>Yu!B`asbr)J%qQxZ;n*mp0D?f>6txjrH3CaCW8+J7 ziKSEzVG-8*78!tUgWWqVU(?VfAM6(2ST!B7)FclDH870*q9h*UW{DlvqSyllmxo)Ze*wCCOFi?yfP-{tN1q~FMBr?Tj=fnU8 zitP<3*8mIT7B&(<2@I5UlP!XT+=8VDH*gCE3WdU5{|}Z5r-4GW(J21`N)%j*#(9By zFwjAu6G|1uRtEBi6=1c4XrL^_^1e>gK&vxRP|-UIDxx${tnTYXvD>**4Nx%9C=8S} zN~17Ptpx*R;|hgPiq(QMmC+!tN~17OR7?&cYA)~@T0ID7g;AI%p+s;KCooUoi4IT? za_4ziVME!XQbq6qQwCKz8YTe*wt+2nq;|1yM?$732m&BMK{(3|Oktz%rpPBK@HzVPXRX!s2E>I4R_xetHJYL|=WQiAumG z9W1a!^~MQpkTLH<%i~D|HEJBs@&KJ{ zs>3rn2#D3S%H$AmfMvq+&=a}NUQ3`;`$b`G?3uf0;KYVQsGuJXp%~InFYOi92FFeq z0T#$DS0KXLh&nOFde-(9)E;aR#e=os7XIb^DTigG3%j9$`6+nWtq`PSLb%+0*Vc*7 z_*81VGjZ!(xJF^6vt`(QCpnd^+4U#Ckj=hu^7?FRrE}7K!<-6d%bdinrI*LE*^X2; zo9f7BLXXBa6ozPGAg9#>npWS}(t0+o7Q_%kd z922izygmDS+(}=S!p=g;S&nlhj_K58a0~I0vyXBvO##sEcP~F9^Krw;+d39r{w}WL zsY{)s&c?>KPU6T!DxS&)vpen|h6lO1iBx*$@s1l9c0bB^D{&-hrAyV*R8wvVHhNw-t^1ipZx750cymQ9hES8;r`@SnDL0>XgbEm3L@K7^w zBVk{SvUK0|sFBH_Ndha`Ht%H*>-#zZr~UYBcE>}{r}upP?p7d`j;~r1Sd-q60ngi? zb4pgEUV3G3HVaNUy8?$@na%#jah`8GICvxLuIf|c)+7gwIX{i7?e9DF>DwIhU^aW@ zVF9P;i8l1O_hQF+HhZQc8$EqMCOn6#dmnJF&tBpG zA`uC0Vcqe8%d^?5f1f~=_}vkw_<;=1cE53)k*evf7yl;koAlD%sM~o>&?!1^bs7~? znFor=nF+)qz2ZpnWeN5pNhNP6!Fj4^_8Yv>HUX7VKlxV*7nu{l4ylwmpP2rL*ropU z6X#@d@i^~hx^;|$U5JiDVe;gPx7k_dM7ggY~gUa;7 z1*m}?vjW-9T~i&$9M?u1ULX$F;(q2s;`bEJ;$Mca=6fqJO|%_n%BZL5_zB0E^ufLJdGw9{0cP3Uwmt4du9sOc#h9V?)u`PXHb^@Dv0KZ3EB4D1eZvDu|0bO zY9wFE?%a;%iOlZy?0A4k9x`R9B0VOB)6Uh?Z%<_Y&XH}HFYX+1+cgq1&FdyR(V29TRlnakm`%_9jEpY1O|IRC>a46De0-!=*(qbhROoWDS; z`PgC<=KL!ibLD3I+8uM1-u9?5=VKp%^Iya7L;N=4*8w|5{JWsHV=lgzm9e+L|GPi) zf@89W;5QkY4oz}`*Z?miKkRjwJ2``x!mjaJnXDn zUf#;!I^Jmy44nSRr){07H1q>?-5$r@zj5#GueNpU;8yv#rZntdmHJ`*2tFIhW7-02a^{l5hCsUj5 zJ+`)j*O3tyyt*}!X@C2=GZx7GiW9GYbz3U6C>~KVmyOG|9-LMW< zZB`g}e%6u9?2(Jo`s<(l=axj8@{0^=Xu9-`_6*NWL61QvulPDi5t~5I6P{SJUgTbO z*d;gLN~H+*t2_93o|r(SWCWEaFo1tek#mTXamAhwh7+pAmNxyJzS&+*KkT4XnJsgw zv27=RgR(_V4Yv8L#rB~5?U$83+Z?1887Etgt0CEt{PxcVouS#lH-5viE_U4R`Wv3b zYXkx)#tAR>t>9hn3lRGxIY{?{*!&L9h3L5e`;B(Tu@E@&x){Hnz-lmdIQ4KQ{vJJ5 z*=|n%Y){bI8#`?e0Nof6$u@#V|K-Aex!~zS((o03jkD8@6a)iBefksyf&~$#TANG& zZ)&>@JD{q^&=XD=+M{ahux=%TUij1AC4+(VBHz+LP({wl6ln`<6EF_MV?j z8T*~tOP*b~E0x~8`t=uYYwV6;E$7ojs&mt8H_n_mu%w{-gkRiwYxC%`f|3CfXWsbQ zrp{Di&$eey=p6w&Le8h@J!>C3>(GHkK-cXy>gez7kKEJ*iUuBX)}w3pq%*r)7EB)2 zGl-gd_pZ5j_5pp03k%$Wcv1KM{kjzvn1Z%QC|ow|l-obeVAAyKyFt4*K1zv7x7)|N$^p86`4TzAv=hxHEg znb2f`yLJS2q;?|`yV>oT_BR#{8Gg>|8{0bK8}C0(03}|3?!#TY zn~ZOG`Kc$&6N#r=KHkZK9m&?;9s1qh{q6CmKlysqb%%5(;KVg&Kkx+ucOtX1<(wZJ zZ;p?jF#C7!?#ZBNdurotQ|I2lbng5|zG%IF-gq=HPU7qnu3M9o25pZVTiM6-iTB&@ zlxMaxtZh%My849kpIJJ+=}#MXu3CQj5R5!KiRs_Ha&@W4}CSI{h>vz0&$7R1ZzutKHP0wyjU{LAnf5gW3 zKj_RqKJm`BWMchojlBe+^3j*0KIl#D{Or?D%qJUHeZC`spt|er-`4jGm+#;3%cnM_ zIzPH2n2m%e13_oXOJiTZ29gVOvTiM0<*RId8UiO-eyOOB=MSSh8-|gsJ<7;j?wm-+> z5(T5L5GL-*?09nliihR zd$_TGkMgqKM=aeyIk#nY{CWD&VKZ0kNQ0wWo|;`P@K3+wFI#wf7u4YF6OK7zc+dUM zdoK?Bx5wAqea^Y}t?2|u6I)-sU?hjG5^ul%vL<6pCRJd=#alO&@vx#q@WstP$K zQj*=1Tzl2%(s93QO&}kLC)eL{I7EkWgmkhf*|B%kZ$}kYp89-SJQ+-;kz}HAx^vT$ z(*{tV(`_4C3tQXQymbE1aPj!qi=VD*bz66BXo~~=_O&nFa+1{A`_}!p{PFhNZd`I* z;JOXhTzK4oK%mFu)2_JT)}=S!eBWE(OlreJiyDU%(`ffRfBB+we|^pm4mzMNP`7dT z0N@ztRx|O3zqnx0X_q{=EuBra-f$RP6db^wHGg^F(Px&OQdJlZgi|3n1>Yt+`7)Vl|Hp5d8V5xPXLskSB|kdjna6)xQG_S| zptIEt77d#F=f~#$@o#(2}Up#x`eII^s%d|;@dzWHfMp0?+!INg* z@!>m5fB(|v&Fj}baY9dwCWM{U&wsIb?S|dE);zcLylKZAQGeJG$4oo#*5}vm+Ocl+ zmW?mmdh;cRLBrtRZ}@cQ&W>a{vFnTXUtO{M!3USGc;)>sb|uou_MJOFz2W$S59kLI zi8yP{Z+Yj$bM9+xNzkxNKkZ=09INe?$qRPl2=h2N#`p?w>y2y9YUL zCLK(h%EC~K z;Lwp(U{bNOJ`|1&IPtn`&xpPJ#Ro6G+qUi97eDyo<=7e5UU%XEOv1zHzO&I3?N>i> z@OQ3#^vVTSz541^3$A+fn(qvrSic_t^l&!0h24q@DjRlfoKI@z_PUZFg4Z|w%YW6>K)r)%O;|$+>)q2N00yc6)DSrLC+&5R3IOb~X zE_>tO9rN^Sj(P8wj@f~E2j#~)?x^Qk7sDzG@oT_u+=zwo1q<>2g8A2YxlXv`EIDBCk1?lGb%>mxmOSd_JkGXMo*upg6 zg%`L&n)1Y z0K_rSJRIOUlq=|Fesi$dMHfNT>f|N=$66Tkh6|;^1#zk5vu?z~kdFr|2{mRx*mmZE zcbR5%79=eSHjPy!hzhyxQWN_o3qAG2zJs1xxE4<%+)!!zreN7ex&x>u{fNA4PTp_8hj(LG?A1BYhcMQ*5(LJwID&4Z2Ps;l%}nE=JUNJe1SeuHC>-n; zN$dPFw^6Dd*x+i_Ls(Vtkn#X8r`Y}lqkz2_&pY15I9?oy?xfKeTSXents>l-#5(dv zDoJ@g%Yt2RT);~~ak7OoiX}O84sD1l!y4*%qmX|NR$f{LqCmihv~;m^nVyVbRp~CE z1rt~xeI3p-X(achY#7Um_y-@BHl`t@U*R}noEe`PH$FJtOvsF%5SoygIBwXu`1o=1 ze_(t83xc&;lmA*Be8U>Q3L31((O8lZ=R`lR%4#>b_{@%T8FcgUAi z4%^U#QR7lM(CTSR zGqcGwxidpE($i;54@?hC%QVk(=OyQ2U75LDvx_U-1m}cir)SNcWo9LtX5s%}lbM;C zf%R708D@G$n*{+rjoP^`!n49n!I@@8X66ht!=0X)Hr<`>5EZ1NF$-d z%-cH`>lA^Oxu?3P2Ir(_&zT)U-885$s4rA_9hvE&X`y-U+ysdxd^0D`6@u{3we+W& zuu@F`4GT#5wCM&E1?Gk422TxxM*-jv1P-a`SPRDmv>>37g>z300ho5~dSnJ?rf1BY z5t;M3orsOOva3oymB+I$Xj+vguS~;O<%E%BHY38(Z5gcF& zG0mP8fMA1NL=+T6$@c(|Edb9cP!}Q!X}!RV!1Oryj5YcoAaIR*6E0-tfE9r`DMB~1 z!vfl+RNWb2K|LUXS819#dsz>w7E)bApl(ya%pjRoltRMMQ}EGoe=)b zbX5~wkV$nS%foXcr@C_@=v=rA*df?~iX)&p7D5FxoBEZS1)|I>QGg&6AUGp9Jq#cP zbD<-!5mH0}2WKZhI@HT;O3j4iTu>xBsmce>VFDyU z2nL7-pkF}|S71g2Y!A*0LXZjci+}E%1iD7Q0S`elGYM6pj6&9YLi4QM1OZDiHM26L zDFTb5Dh6llrQ!-pvFa%5XXc^r%&D+d7mYHrL1SQc0dNg~Q3a4_P%F9cEbg2P5uq%t zl>}!-EVpSSovKiCPYqhqiG!*ksTZSn1rJZUL9~kG`K<7)P*WOGa%YPA1z>{k3e%?% z4bS-)ViAD6gth=$gdhOlR+-n%4U4`SU@R&a5}hVsGqZyxMyDe#BthNE`763Nk9q14 z0uV?9*r@MJiYmJE0(0RyARM~Q$gBWJqpQ(c!RbMm0Yyho>{_3oc+yBx6uklA>LP=u z?m;ygir7kk0;5xiK>ySP%(MiJ_LO#k}aX zR1*T!S=J6Ug{=gLr|St<+^u_R2=sU|Fg9WYDS}g=sx&4sen^#?7^YEyr{pR-&NA)YVK@X5=~`c4&BuUmaf(C)BH}h8Zn7An4pQ^!EM0Myh#!7%3W8J@L}cay zy&yE099JU^fDUTCxc?9=nWCfL^SCZ-ROy7lN`?!{5pjuxTmK#qNru4}crnIP(hNT% z)}d~OijVn>V#NqRW{!bY1g!5>sMJrdGG%B^%`jF$k!fxr1S?;Fg}{`SAAtg^Q>G2M zP_hX64dX6_mZG7#5U!ciX>|u4HYCwF3=czEsbg`j#E5@Jy9}Uy&Ls!IPS1o4 zX49m$I0aX+43Ko1v6!2ymT$yLgJ2X93i!4uOa%+Hg*a4KFy9OPpwZ2kPWnVS1CST^ zpfTR>MZ<&(EhSDKAy!YxI@^WSB4yy$Pt28aNJ{*o4I| zxX?VC5)pa&Tr<6c4w^n1j>#2$HFI||y%AB1r+~B>+=FmE>eXztb`h{t#ls$}0unf2 zuLcUDp2~{_jDrPySZruCjXUrN=sm0RdA*^LPtB$=!xQ|Gv!I?Or6$J%`0yBNXh%bN z_Gh`R%{mQ@k;ask#cd6F_%scH#y~?Fl?egE2KYaOvv6aArxr%ozvl{exFL5Hl0LMu zf78Ih3j9-afUBSxYHZgQ`ZtU|J3SCVG;;+3i>*9?8(U&8a%6JPZkcG+{9<}R0qbCHD8MY_7vyBXKnHr*v5TM5Df$t> zg{4UV385~ap;=IHq~L?7B_ylVtq3d&LONDs;SjzGD?rAQ`Q%#;c(@T~qK|>*GYfaG^ zO9WVJZ7QI`^v2<=0;$GnJD!s;ixCJ4Sh{`5pdUN>6wFtoJ(e=*OMw}mWhy1y64rXg zuTFvt;INkpNstx9Lli-QYL9S(G88S~=v*MrzR{RU_{11Q)3d0&R#c%lxb2n7Z|+91c{I3OyO zt+aWMje=wq`V(t#DP~;IYE+;R>zjzL01y~dpAx8-jIy%CG*E~2pXXayYCR-r7F9$I zYu5#KAkwuM3IsqR5DEsu&U4IScm#}M(k1F)PgvV?x@gS*X{+j$$u;X{_VxQYuN3ll z?0N`G5A<)IatRpFDEKLcJ8Wm#C2xu1n8vSBB89dx2(g~lVyvhk@(Bd|v5+EkDm=%( z5ZX`}{GY@SXdYP4SSSYuL{IPa=vtv#J5>Kck5(WR3oY-%ISpbb>aLA%>eg3UKPh9l zAz>?>sUQ19J?VJ5spks$PKOGnU3>W1n9l%7I!Tc#o^NedI|GedJWkkpLcUkM3w_pO zvopHR7IvHX;i+>-5A+qd@*=-)=($L|Nj|QiSVkrl(9+U!T~daUlxz39!X>^&K^MI zaSe42glksZdq4dX793r7^DRX#Hf+X}bNmT)|3$KLt+T3+j@Fqg%()5zh%R@3>i*4xA^ z&&tqpb8)V+<y65#jfwqfFRWag;YGPLqs`W#m?{*GL#_?8xgu65 z9{J+*0!E}EEIn?otTpRtBLnT33!{ro^w=s?{Q$@`c;fgs5&!n$RG_z)ib#+yPd1s@ zAVkMPUBD~2{&DAFrs4xwmuH)onf7Sxk@kHAb497!nBkT2O2Fz4Mwi;l(@mO=(*63# zg}Mu(RzSU)sDZE0|)D3EjHQZU#u@zXA#$%O!Zl50*n1Ich7Ks3D?H#g>*% z2ty(-h=6$5K|u#9Z)E%`imE7B+ij~QF4+fJhfq0hE?$shiddE%d7wgbd8~;c5#8Zy z*H3oMi}^$iur_o~Q{xMi~Vo#+@!ZrK*>JE0cCfgTV!bt z&J?GdtXD?mQ`*vAToEuN3E^3>gY9~^G1tDwJ(&p)FJ4NQrpn(DT~Be5(14tjtudFH zP^$*GEp3i_x^xuH(sF`@noev6RZ*r|+Jadnw4_;(bsW5|!Uur^# zR*7~E_6VBT2ubE5^~o22E_SXmwFC&Fw$NTNnUGfzFH2$l3in#v%NX3l&C%rw9#GoB?u~cwEBR34Vbn8u!n6w)iwOh++shMr68}^w4;>Ns zY{64eqFF9Zuuc>>mWldFm*H;BAbDj8)CkjUjI4ZBukv6bg1;D8kYR~X$YrU#ucKUh zX$77(Lt57HC)Ae=4HuLF65s|Z64jmz`JCXO9v4uLaiG}{sC51l?m3VFdrjI?%!Ar> zxNIF)W$rj4+CjL_3Ahx|S?cjB%#L(T_O%*9#U7?{!^7adti zB5jfq?SRK{ixBi^86Ns!Y-XjdO&F~YkqtW34D#ruC|$a|5(+ya6aiaxmQcnJ$KX*V ztzTQARJt%RM+%zZBH|V7D2UH0XmHaYE|tN77}%;FG{b-d0~`A*D&aR=P}2AgMq{z> zVbY}&nFvVT!17fWm2gqCjzz^WB!O0Gy^DL1fW0?c@`c$(NV@~>fvXNQjLDnz7A6ca z**3_cYE3uX86fi-YhpC(kdpIjBkm0>>`ED_p2Owl%cTe|BzgJO%ltCG80$>N7tiza z{#o<%=!p(q(knkMkJ7{WqleAI?!o+!DYf)+_TuG>@}fMSKYN~@H_yt`^kn|@NqI7( ze0khH$`7XxIOZik_~r1yAJVLmr~%mz=K1&lsCI zIVL|l(Q#BZJY)F$(c^?|&BNJ)hYw^u6H1^sfB7QW&4Ov^={)=_k7th_Kk6QJm@_`a zmN37?l;&ywL=9ncHWt|}W?E#j@8$Hr0+)bg`k3&P#}itWufi}@OD2a8j83gtp3j~= zf7Z}Xt(5|x#;`uXcy%=mle!ljxI6p{c-lwp!{)*C@WBJ7M$*gqi$F#}YMv*DvU{4t zqD=5jmO_>FxC)C=ifH9vexmqKg-U^jZd?9MXj>r_bMuQH(k2))eTp3lrlKQT3Pzh; z3cf?x+L%K76UvI@6~ETOti{C>iZ{4Aea1OO&9hAN>1lb=;bZe~0?Yz>1`*R&!bEn9 zO`kxpOibsl`smmP-XRbShKQp~j^K*kjB%66!ht z4Pi)TQdxpKmefl`j!>!4dJ+56z(A=}7Bsk>BS`xaT5FKKL z%}x>A62dLu2kRx=U|10XA6^Cs_9KJ&#fSt8f_5ZtiZP*umB+*FfRwG?KGX!rl+@?} zVGO%SsrYoD*FT%op`b&V)KH87S;J98B@@1}2|na=#>xq@r@Mgspd3zW9#!Y+ZARm9 zM$(?1{1m}Q10(}g1sI(oo8pF`@#qmqh=QH_5ZLoW)L5*oVpdRsq}vmzJh?{~&67{W zNaD26r$jROmctd5;~GVj9|ey-x*BQg(28W~(SOJ?&NhYd7AOm7v$!dX#I2baNvn8; z29TG_-vv6ahRt25E4qmi>N$5#GeWow?Y~M;@&LA7b~ZReGeDeTG+gd zrgIfqg{FU!AD>{pfb|_hX0SEgxTBPibVG`yg(!r(r-r)8LmB_s;a_g%gXZQ5N0A)x z;yL;Ok8h{?J>BFSHoa~hqys%T{^I7u#r~i|{NZ4J^PoAH+~nkjgL3et{>l?h)nLx) zV3med=)^4?@Mx9mpX)j*^grX zaP!kpNj=y?e^g&Eoi6@_Q8Q}td|1vV>dv^34vzR^yks-abPxVXMR-75KWv3vO$Sr` zm&fp~pwbljLLa>#vte>gf2W49;h}c4$3y}h=7Yr_ z{dcc5$tpzIc^nbNF+SlO9wtx_H)Nj$Z8x+OtcdL?m#pNN*jJ@ilgMY>#8N~#P%2j63 zvu(&jAZ?&!p=t+VP?;(qs+hr`M6|zLB=o9^iOZjCgfL$M7%16K6Ip=}KNLa#!FliN z)w~sY5F{101#cZW7py5~OGjYvak$v&wQ zGlR6%ADo({tI$wrNCzQqKpg@7>)_^p7aD&!g>4mG42mHe|G25tF5r3O=!49ycj9t@2BH~Hbx`l!EH z?9ANH=^gY=rwzvbAN*CZLiTixuW|Xm;*4YBL8Er`|5Q`zf1)q-$sJWAvs^6)MyDBaUZk?(FZ|`J6Ew`>OarYeEXqyy zGUSz;6@eGyKkRl}t`W2j)(Pn$NFp%p2tB?9pT-oV%x~pk7 zUoE@iy~~@J-PzBEwkb;4E6tS&<*w{B?xVe$caN{`?(Oc;cr#d?wr1N~+c_MaQ0WQ| z1JMp0&8XY%Ot4QLm)#TUs-q_G>9>OVOpB)OO3Q*b%JR1x!o=Jgiw)@j`PrGALQ7Ei#_BOPGjt;qEqZpRm zDHv|{hA>4UG&Z$!-_3#+m9xgPQnuS#!PK;^5Srp-n(SP-KN{HAI5?(IhR#FJyW)@8 z??g;w7H;(JKS!fQnWaWaU!_;KJKrPbebBCu>~k?$w9Aev#EYnQiy&+sInl^o)S>dU zTv^?js%5vEuJ*JGPn6@lbI_%AyU4;$&5|L*Os)cH)H2D-dzE~Y72TCKl4QlQ(Qi&9 z8>mLjKUr%wr<%2C=V#f0i^NLdYAVIL&0?uBC{=ITzf0CEmS=(p%lk-IRWgdT7f~pO zuaUR?ZVtIL=mjZL;`YjL>6B4v291*N(IRk5^{TY45}Ol;W#?)`rcHxoH8L~1yGk~8 zJLziLX#}p!I|IL}WGT7{q;!2jmq>w3vW|(uAXf#BA?KySRYC$XDwoJc_t^%CnuuDh z&_ynYJHfcTJ65!mWau}criZQVRs_mJNP1d7sgbA(68RpYTd^(MzY=M^NK#=2aD|Kt z?H4ZuTj0=cqqY=HgPdeLz2YPwa?+<}6ER8P{Lv>GE;T@PP^@5LOxf%zpI3-dr9?8~)#4SdFH)}|oM6C6 zCrcaq*48n$hhP(s*60HzHC(mBm|O<(5X`FMeFRa2tZi!GT#O7FMlORDy0^)IGZtV9 z;;Iv)(vk`dXq|Y>QR!7n#v zgHiOHcZ=jBo8NU@ttmGew6D3k5;q6`HsItiLF_G3A(IMuC-W1bHT#;~d^txRuY`iN z+>jw$vb5}slh-sMcza=X9P9+X?{?b)5%ck-Rt z-8+Znu-tF%&F|hz_a=Am+`W6J+)20RDw}W34sLNLKIN40Tjf@BySX#JdzcSr_Yd!< z`~AK4E-l=?b35Oj-MW3NxyAoSxuyRPbZdTaE8UuL2yLOt$sxsEV}?EX-bW0&cju0~ zN_Wa_ir=RA^nkO_%R%dU>2|`16y4?fQPCzATp7z1892SgvDINEx6!xME46Or+wGmO zvfR)2#_I1L+uX4^I_E2A`If+e|KCUrYGY?}8>bJ`ePAo@E!~?@t--AK}Cy-U$tvSX?PlX?~Zj*wgK)4)X18b<}82gIDgCd(GVws`JK}Q)uS_?P{mu zlsvgLNw5yZLael(+|N%Dv9*-?`o0F5z*5RgOwW0(`2i9^StY*cYXy>d8s_+$@YnDzXf|R@vys3;O+xuqJwg0F22>Q zB9&PlL>7>R++y#kXO!zRjgp(787e59HRj4_jU zrel+aJeHOS3Ue<~iR8u@cy2tMB z7F~i4ZKuP&`j&?rt6&U5DEkLGTAZYvE##Wq3vQ*`$0h~k64)IF(9*${=07P_9C&1~ z4Z902OFeVdqZW8*+CjixBs?6In@~)iAYm1xeDI4y>TU?I@;GDCT-1s%1qBpQ^@6&Z z0r^%JdQ=XZ`(vWy@Rv%L9A1PVn_*GDfn7F8<(pc#C9)b)jwC-dim ze5Z4TfrI%rGV?&PJHd>lhE|bN;f~fr0-8Gw_BM;mm#CQ`jA&$-6^>zx0m4AnJTB5D zB``D*!vY8;zeFkB{&>q~i-HVpCDK7=w|226zJ|j(Ms@V0bRbzY9CoHa8$nYV3uB&b zVRU6yqlCYQcP(v}s@%on!XnycwnkPB4g##8*^JZXh9Iyel-oa<%uK;n-CfEqW0eTv z;bcLP?jYl$ekN2DttPHH465o$0-55jQjTOuhzx%Ww;8D`@wLzKvq|#{9@E2`Ni_cO9mVP$*^DoW4$mBZq@q{fmB zJ(k1?i@4_-jIhYL3L}`%ldz}z)P(MxM?oO4y*(-6_$1$LNo@a1v-C>zCCdFBJy!Jt zR32Vx7Nd;^>3`AV;Wi$J`$4gugKAPqa}&d*f2uQXdYD@dKI%zseS4bYk1DvTj}ntA zwZ&1L^>stOeuifMZjO^$jjH}mA766alMH@9-|{a%zShHZ_w)}cB>T9H=FzT(v~Y?C z+P~Mezt%2Ye}${=+jT$J_1YZ2b*HA#7Ly8^{?pU$|E99)UZ}+ne-Lc?QLk?DpTi0_ z>gJcd8PdajY_NZzoOvMTXa@^oxNLvR_SL~gC2EO3Q+!6fTDSb z8qfv37AF5mWn5cPcWT&d^ZSbd3~@s+3ICz|Uol*iig~(W;=@-JKAYj#m>aTfF)QVE zh!bskdPFVXJaF=w0Pfs%|8ZcGs8aKBp%{YmfAXWYnewZz$~z3Pt^YbOqs|k_TTR4p z{a+ToXvWI@{a^7X8!x7)(*LQyIjXKTFwAM|XxPCOmFhy0WD4(yN6gd2jApv&9659F ziwnd@HPm_94E|Q8$%1OkGC%(ie==Ut2VLtIaY)?eeL7BD^*>ELfVK?=+E~@*2ES~A zJaCC+u`k2HA<%fh%YE^SiSx&>>-WxgU8{J}zZ>T-?$Ce!0(HEDhhIJ#Lps>%Ovn`Hqua3X|ySZ!mU}72bEaD?`tck{ZRtu-+mJzM7|n@ z%ggNMrUHu=^6Mi1DzF>o9=qiQcWB3L(LWx1c5}MN6S=ZCzP7h_ZSPvSmi8yt_V=&t zm;KrG{p+LaEMmSszj3`>KiR*2eSiP@e%ha3xmN8;_ZD9lb@6$h9 zY+Sz~L;C&WYx_*&@y>hmYkZ_@Q%X~hPOq2!e0_!`Y{q~&EybtTc;=XP?c_C#PS<7> z?x~c_~!p*Y;QUtKqD%S5dWI_UD3xc>+0*YVpaQ z%+IRChYGaUS!FGwR<5`E6C2;|HP=q|uTk=vKvgM0-b6_@JfH)5;orK5YZcAr+Ss-D z(=TDFZBgS90{q8;c7Ljg($*$5*Cs+JtZDX3^fAQDAj$p?C<#CSWS`6aaqZ)JzRn&W z5dv^a*Sq}*?JEfBT2bWosmLD{eXQ=H@XGbPPkf^FMR?P-mM}T4E3klHXnnuz&BetD zkndeN>NZk(9+%JQkAoM`;S$*8!k zTq8K**q|IiM+2S+FH_%0%&BMbZMqZ_>pRy2WkcdxHW0dx^(Ib$~+N_Hv;p1Y2)mfev_ zY8WTgva{e=W`~+NLIOn*65pt_0;P@=8+TOG9AiRpVEzpvL=QHd=?98eJrg!Ypi`kl z7F5w`uKz;&daDCb91%==BjQSVqG-afvw{q3@O((rw09zvhhJTQUm*^?6h^jh;8rsX z3b~3$3<*lNYDq^>L(3YvA3_;~WqTU>4}ov?XV_VWr0r^ZNCix&5?SGH z7P4aG>Y&s?l0Z)CPGlur=vRX+3jAW68HOgpPn5+_(gECd_nN)7TGQ>XFvcv6hOe?g zMf!lNUFh>iM?4}geZ~lyP5U2lQ*T+)4uWVW7yQmQJ_j{=cK5|$BR|DHcubS+jm`w> z_w#O#3>=$1d^C)-DqxDT6$P*byhv%dV&|12um$HMWyALl7FdKmWGclapOQtBxhhQ+ zG9nThrm*!Oq+AMoly7;dnT*8Zpay}V#X2}qCFI8eI}Pl>I&Kd1BB0t5zXpP}XN zgeln2fySpuq-%!T$Tnogk!49Agj`s{7fe^|Jme&X2?=2tZak=|#Irs&6=(zmF$g{I zC1)qXML=BeBb}0SCPjs@j^IS63c?V>5%(RwPs++7@uB1H#Q98`h4>ElCq0RAcN0`@hsx;=6A$;8eYdG-rk==mQ{#yz(+zkk@Usz&Qr%7f-%^C)Y1 zC#xEsl&AUGr>DVIq;x;c%(HUTBpUL!lQuSVPh>F6JMT*Wa`sy1nR6p;#D43uKO|9m8pBxXIQSchqE6}2OT%JtKB=MrvWDh9u`0~&TfoWaf zvV;>Zuz*X(v)YP~#nadTrvuFPQBPA1S6QjVj1<%Ie#oq;KuR$ih=*gb-~sDjSUgID zV!f6jvYhM=50`lgE82)P3KHvo#T=WU#a8<19mGv)zlfS$<@?u^=*1eo?K|No*`@4?j}F3!7jLD}+cy8N@qfOQ6lmO0o3xNZcn55(KMHFrQ_G^w2yg1~gQN)lm`Kh8236 z`!Y@~9Oxdfgjg$^#NtA+svwn-9mX*6h@7!Tn&|s#QQAGz({xFU0?I2x+NmHPm?r|r zvyi^@)a&wKL8ZCEBnq;mtdMyQX}FjoIa)fS8-e1fa1s zrYk!@V$qkFuauMHtT7hzLvPZ(pM+G9SvfUmeXZox@hmrVP1cRmgC(K23@S>r?U07` zHCJQBt28;R>8hMD1q1Iem`chJF9IS*&reltQ2SB zGE{OHA;w;xXI4gnq^FBWrMoSZ*H;D55VVy^be<3m+?^sV#A72&m7N*4GgjSJ~Z2xEL_YDh)}o6?izqF&c+xzdnMvUx}k zulYJhRX0}u2T56O8${9|tPz-ZL$%22?jAFOXaiC!Oj)nJ)E{ZCR+6%G-K&I=b#c!D z5t|xNijkM?20W%{n*e2h3>qp}QzmYeG_q@Xvn4k@ISP9)O3-TD9g&q9F4Qtg%R*OV zvmJ)evK-VK3V!lnWDvc}Kn!njcl0-LHEyS#KJ{(DAcQd*$sVymKVo@#G=k*{Rz;pk zZIU7G6{0}gl0@1TfM?tfX%t0U%R=+;co2`GI}zEC$#53VF4QpB90);%`da^*7;qyQ z<4!6RN`f3I)gXZc2K0jO3A9-h`>exC-8_u|sxgDuO(BLd4VEmZM_8Xe`|R0bo`h%b znrx~QMt(S&PtE*z(TbN{X{iT`MzoH@4^{oVITokHf)hVkc1vo~D^KdWl`>4WML#?a zu9G6sx1LLT*~zeUuP*%218;ZM9{i_D>W5eSQrDpJ?_phwuAE_ppiZOcmw4)~DF$0R zOgU;LiXVhWQ#9H$)28V-H%>=d&z6_ZjI~@4-@TAV7ig_M&SuV{*3$HZA6EO{{I#x{ zq2BM8kN+3bjP8k|EIy({O!3sUH;Wakb;S_ZH9rv3Nqk{RT`COmhsDgC%4pSI^iPSv zudR#4N-BpK&{mI?^y67yP&2XHayoz#i zBMJ^pP-ylr@Q=l1!|$*Kt7Wp5PK!>4t<)I`Ri-(+APXZEVyPo7HcXLJeEBLG*P|Q7 zB<2%sOkHjnJcU*2rJ_-pQi0ch7GRhGUJ|M4p$MF2gklbAScWBkH4|uh+3^Jskvxit zoE0B_=6AX4k0l<91#iYwTtdRIROHlu z%NHb^pTo>sERa)uXPFn#h9gx~YCg-qs$a6NuDX@~xa(DT5zF9G8M>*9QDq9X1-k!} z4%p3_e-d#1qq+RQPwtp!9$`wf$hNWkZX3(NzXg73FtE|*X(?srQD2C1J(E?IkzjW$ zqVsjd(JMvOl+s5fDs_k4tGy}`p*!YA{m@?)>wK4Mn?*7+c$jOieTJQ;u3Y<36Sl9J|a&XwVV3FphiXhE2}D(Z z3V+C{*=mGj){yA-&hD~rwv7p#wN_GSI`b+MYmO>zS{bU&&I}P;;Ev6!w7;C6RXN!d zGGCSC^ip}zXxK+Vy{i2%PY4Ec07U^~+^A-`)FPAWgt3gW(L-;)hL!Od%Q~x}bzF4t zLzxDJl{rSmWQq1#5Um*;ZaCZ?ofm!9eEwZcx>&C*gWQD3EcQei2!Hju2z}tZ657Sz zD>wbsD3_~+7x@y3A$TIk^<4}b^;1~ve*J6kQ$4HK<>!H}ItG;j2ylL$nb2t#2{_ zzK4%K`e+aS-8D>rg>m7SD)|OQZE&roXm~H1Z6kXt4{*kU@+eGscec#y#1~ zMOd2@1aEc6qdo<15R31F*O(|2j7T!v#@D`ui${z)blYIA$sjD%<>7ls8hG{R_~BR$ zH-Y|1zCt5nGn&Y0=ZG)CF&u4)MzOCedA z(_NWrjS%aOGgTWfV6s~fcfHDCF~Yx4Nm+Qt-~)rURIqgQiS zo23O*GwQJ3SqqD_Xp{{DHi6>WR{q!z(N^BBhRMI7G0wi4eOD0{~NO=Bu zXQOG2z1>cWE#*3^Vbj%COQ)+Ji$HiP($jo1CRLcwjQKXeWziw7YdP6qU%FDZKjQz^ z7Kk~1ee_ekV%;4z+MWK&C$9z50xst8I%2_m6E7B30u&atIK%3{phdYd1JYr=T|}Di zdoanPuR&BMu_#T#5Kikw({2=IhXe|{yi8{yu~^|G zQY6gnKDf<_Vlk=RVNt8S^r}rWL6ds@9;+}#1lIUt1#678ptX=>KW%M?Pnt^9grcW> z6Xh#$6yr$$$bq`yL$h4~xZ7iKp%P4)pROKNPRfwRhO|J^8;sGi$y`&)2FIHH%E$Q@ zaqBVH%@#M?MMNYgShCPJ6S4_H@)Z#m_0|)T*~)S++JzL#3pB+9Qk8^0hs`|^k?Lqc za`jA6sb4y3nS54|tIjHGoqH@Q4M{j6{em3bw!Yru;Dh2deW?TDx3HsM=uLB_-R>b} zHXs%mMhEGE;A2U*nhl0T7%P#P3??vowSf4ut=P2&Ql2%`S5EAra^K%qV_sdvXZjTr z2300D(*0`qDJ03jk&UWf92l0$#x@IH>d*Sw7>wAhL0Mj+pQLX%U>4s(!ZugWi~`~q zq0ItRBx7+cq0@S1RHW7St0WHWgmD$m+d3YF+bmuU716iKq)K&+GaH3{Xlq?{-&|p* z3%)}zXhMvi-m|2F$wKfeNJt}P2yv{+D1$>(jlb2b+TD;tb%l5xZ(D!AMUm=vSv@ zSGoGs4FgLZg;xo79ZvZ=qEsk&QN>_oz@D|gw6YpJC@7G=qM>aY>i8^qWs43RAX5|` z=U=ib{+?d_#+>|R;kgq8)v8%K1cxtS;zMV}%HTrKdp8b{wxU+;Q9 zHqWS)znwFek0^87M!+AF6mw_o?)lyAH5T1+^`1nomilWc^l%_-R$@~atM zahmKmzkdDA(hg39{=UOGTO4lXm%Yn!m^dx|Tn+y2d;I(E`@*TWuQ>eq+4J^!_oAg} z`?XFN4aa&M>OjETAZH4cmmD|xlKpy{uUl}M%a0jQsoNIMwHd9CrjPseXIc!v2Le+xRCLtiNT>v!M(K;tz3>JKOBKDSP{Y&xU^e7 zyZho=iZrqn2`EmKtGqdP*nTQsTrE9k=Ut^Ydy9Yd5l8h7-H05lhs)L;m#lO(cKQ|5 z3cM^nj*it=(SCHU&=j_7di{dZGY zUAZd$i5HQyEsmBU8SH2zTF_hci;Q5CW}0T>bSz;XcNmzy>H%m4Sxn#mA{>E4c*x=* z4?++U8kQr6TdW0dvB*-xcFtt5_XX$R_W^KIdugr+32VCl;1h>M^k>TGZ@D>GpHZ|W=sZ>$k z=+Jnd0bNI~W*E7CX8fQBbIi)Z_S|sXMV90b4LdwoC*V9&2l8jl3Gp zIB?l{VGUF;PK|t3I7D=fejS5pm7y3^IQAP@l=w)dl%@q6D;N9Je?3<$T4JrVm|*qy zKcH~Wj?5|zK+?H-Z*hbr5(!0n7*sk7Vr(MaK#jOx(7yG@5>UO8qacrmXlrPfl4^Vj z(eHkfsB;~wE$uxeM&XP!Vg3rSZl9wb;Kc6Z3=`13b1%~0kaq@)LgDnMfRs+IS<)^e?99T+AAg)ofve6OBlmv1TQ)mm4j>rVg zzqz|PsvJ==cD~Dr98}EHa3?X`AyiSUW585*KAgUSgi9faqmumyW(kAug1p~PbuXh^ zz>gLQ$*poXzvO%d?f^9|t1pgaHw9`J0;K8?$FJ189|S~6!Fl5#p)}7weD;c6Uv&~; zoE98swdxSfdW19^a`IeQ9~=s(6A$BDM?EO!f$13?k?7M7V_(hF4f%LNl`l8`H?`nX zWVJzXJ^Heq)XCFV?{6IE^72T&cGz*0>++~y`uZacF+s?|u{ytS(Yg=F^s`^>s9aAj zJbjEN2Kt~>{#(1W$L?u3Xq4yZxEzPKs{h5Y*Z$6ijzrWk$MQ9fcGT3t-y3XTxXyN{ zI#Dt9)wOrbjB&zasqO@b`9^I2eBSQDGxW9=knR0D!Mo|)8VRdl9y^h zZB`)pjeTW>_Hh0she`Uf-B4`)CG4)Js0)tjM?L>ot^MceB5&k+<@SjGwVKjYyYC13_dY!qcdhv1zodg?R4~M(zpjJgn{17KGW|25G z0~c{(PiIURHgK*mW}QB-F4T|Two^`z#h))hpH`qG89-GT-x!a%|Q#5WV z0u;XMSmcFoN2vaA*NM@VXDeI_AW@S zlcPy*x^t&$!PC4h$jn(SC}W57tC^w>Bn_u0z4;=9b{Y=Ri_@niHhNk5)HYK@OPV+c zvd;(I3OpNOLtL%OsGGGBQVbsfi>;LoN)6NHAC~BvQZ_966jn7RGbBki)s89D5+QSY z;0#*@-#`|JqlPV7s;d5sx4qIv6-tkE6FGI@~sVpewr2OUJ$s{Buv9 zdR(fMQL7TdHz_KtF6o#mzopmi$bB%?8_hf0__e+957lK8K*491ZZ0eZ+wD13*sNNR zR>@O}RwrUmx_M(1ryk$XChg&y%8QMzQ~y(w)?=$u#@|f%>!4dt-B{^R7BFFM|7da7FZF2UYcGl$C zEIZ1w@vQcdOcc(SI98J*LsgjbLoa-k9XjQbH)qAF)v~p+$!W8jI>%6l1?$|(i|Hb# z`Kijxc5}9@%Fow%pm>D4-p!H@yq_t@KB`i=H1_G77wOE$ONP@4`{@OMT#enb0gC;> zFSGM)_+lHIOYOyx&SaG@8GN)+EhX_rwl$Y~HLnix#R)d)=;9epbQEs!8B5p~7UcWO zoYSmwoHlvECll(pT1u7;EMS(EZ9=ubDLZyvo^cE%z3aqIj+2$qqYKT(Y+XRcR=L$y zEZ~UQO9?!65+dhnUf{${on$J+kGGA7EU2)n;f7+hO%7(>9&L3v&0e7F2FlTnmpU%j z5SQ?~**H-Qd39Ut11%mUjD$$M;s{1gbiI%+`jqEzKjA*lwYM@MPtZdMgkK%J;|#|k z)Y`^0X&2lG9sd!RI3`)l=<ξ$xegoDC#BZDn z!kmaN_VCOmhmY&n-yR@>f66={QBsI4Q}K0V%#=t@J00SwzFQ)}Il%&e58>t3TJ@{b zmN`>e$uhdoZg|^Wl~I~RbIs*d=-Cg+(QG%Eu5EJJR#sVSK@j6OZJW*tPQZIUbaHMZ zVG!wSKDC?ubYciEMB zpwbGdQN1Wt<+@GI0>;4Zk~9e81V=J?*yUHiu|IfpST2thH=PBn)4-dHM@n|b#9%Au z=8>PS$d1#{qq4NYMpBMb&%=3+EkC8SL|c5W(pk*qAW+&k5}mWKq6D|6x9{b^T6w^+)H%~6cp}!*srXdlW zjd^1#0*=J6&a~byHo>nqRJ-c41~glXju*W zn&@IULMKInKiZht%uvHpWb3SzGt)W;$8OtTjX!LSO{sKRL!=89n|xtX1KL>XNm=cS z?f7sgu&|RZk0CSp(~vwhYnl9tF;2-LQi*uYrJtgp<3ht1IUYA{=mcZHGgH}|+lDMg zsyORB0k>3v!=g7nQJnW;fXG`tNvig%nkqWLUWFAo2JU#^LZzh~+RHdjIVuse6r0`9{Mzc|C>JCU7vnzkSRXdJK z;W?B0vLb`B$hwxn;MYY8lRj+Au0sc8oNL7R5t_;=-Ael4_-Jdixne&@%J4xCxUJ*p z^Uu~jQf`PnEd$R#~)ucue#ThH*ep*dE2~A z@8)mc<#*Wynh#?Y(0ot#diLh^oBXDG+o_2U@6-FTsNVWwdQ;xc-o1U-yc@rN_wN1s z56y?>$L3X2FV5dmy?NWbo4tQWZC&J9>g)L{Oq+*&9ro#J!`1R*`>NEcGfb21x^~L+ z4?n&ti{?MRee;H5Z{P7w?>gI`WWPMjuV$}by>4IUHxtUdd7Eu$e%HKj7fy6sovM-a zwtv@RL4Z?SwY+ZLwAH)(zW;CpF0X!g{p!{0^182nr*{+VlW!f?H?Laiq_>HB^Y@0d zcauW%1Z!Tse*LDS>Qojt?}`y2Vyal)$mR6*6L7u-OWw`<^r8K+!{6+SVNI%dr4KVK z%0DuZrxw79?$GLFq9zBJV|z{9}+KzfNzIUO6nxu;++&g;s#ofau?_@r_`rh!&`q zew+b8eziga5%3Wm!`i5t1z~#C6LFeWJdRvjQLQP5oW|$ex zkZTJ4TktGoa(9a6Wyr$(_C$78n8xq$L<|z;)sswW0i(Rl@1S=DU6jY#;!Amu5u=>Q zmnBq{HUsfOX!4RSO~gq;QQlA0wYk8&i#m-+H}6h}v=DA-Ipf(l@<~?p@1_BeSfXT7 z+(LDl%FV$V#iglIa8z?evL$vY2}3O8WQ}?b@lk#*#tNN?{8?_D{^~!IgeIuug_)=iRAP^RhV&M@`=|`CmNnRYI zzKZ4`){Bfx3-6Q=EsCE$%oS$|Nvh0FSSGPhR-`I_ZD=NjG^l_m7sfPz42WjSa%{=3 zMpdvva~WUWlYXJ_L;9!@VK~AHWn>6e*LT<&%F7gpE{{zj%QUoU~Bc*M~&4dm;M*~l`i`}qY|Ij z=SClI_@NwTs0*3kr$&CTO9xH-la+n(i+TzZ{;21dl;EvLW%XgFi`i6mDdGyNUTS$? z>D9`g=*CaBG&3`*mltOHL6)BD@pkY3L~#M6$5k$+U-XBO8f*1%SueKqieKD&6Nvv# ztyj-@Xs3B1`@V=nQ>|2cY{jKs7Z5sTY;AYyIicKlr+j=_+s@GyTl9q)T>8BVEgtad z&o;bT#Ue?+3lb4zr+E`8iW=7w!)udW=h~FT7qIA$R8JlE7Z2<_hD9T zTeE63MFGsJa;52`do7-{+lh5bDBTpiVgOa)n(FGY!q3uOa>_lR#l_2h2MP5 zANf?KhthvG zxygC{bH1D}=T6R^J9qZ%xwDx9v-OSjvOZs1PwRPYu5vByrSr3M=g*aM>Fiv^l8dSB z`TAN}o6$~petPb_dY#cwqM@`tS4*`>bXHC4&yCM+tZ!_rH|rD3USG>@BAuVh9`%&Y z9i7J}y=g4EYu9HKZPw1u2bHb*(!;=7JlYpQYtOd;R)o zEuEKdwz}Br=IjLLH`cQ;n+m6Xt%(vqdiI7%{y)iT z6_Rz~U>jxV^4#=1rZiY_a&9P-)~10%Mc_zCQcBhe&P*Vi=&WB`wV(OiROl!a(?F7F z4Y6p6DGaFLN@ppt&g00k-mi^i>VR?&juV+WpxCeFh(YImTUuXTUjYLUl-c>*Pnct_ z7%6-t%;HK}`%lwJjZ@O*XJICG2@3VmI?V0)2~8=+W@$dV;=pz$uF(u}oy7kx!?%xTVj3il}}zm_RPKax%jfxvv}zHEAR{lBc{@A}-Fk9(`)C>sRGjXxG~Lnr-d5 zNwsY%e3$?{6^TODLM`#zIjJ1@B!X?wju=2PDf&}!(Im*Wi1Z|T6JUnMol2NSEFrK% zI`q-qXy_^19;M?{?iz0SOPpY>avr*pXXm)8JabA2?1IbA#eA+iJF8h}lt;nkFs(-p z=Bg^oT9QeWbQD2MB<>>C3tem1JC|8xrUEJlHTOw7mEfa6zIrYz(}ktuA;>HJS8$+; zTSFE_k_N?8&7Q&YHoVGf<6)qw;%QL`F44aE+*G#7ja<{cB_GBL(#CqnfK=nN2)N}; z{`Hl{jUBB1JJbpuq+LW{AiNqg;e)XGEY{YssfoN>shT;kiUR%mzl$wqo+Z(`m5Eji vV0Jr$2d(3c2EqtR3{TLnBWRy}_Sq+X{)Hd?@BilK3;*`nXPf-D*YE#7LJmA1 literal 0 HcmV?d00001 diff --git a/src/etc/installer/gfx/dialogbg.bmp b/src/etc/installer/gfx/dialogbg.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7e4674a4fea5bc8099c9c74b07b09e4eac25d044 GIT binary patch literal 615402 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

4b}ik%G&(NZD@Yb{ue9c7G(%hdzH(R(csEx`Sxi zR&_;Xe9($1X)DfFh&FLw?L*>u)s&(=a=V-=)z*Mj4zcx(8H`;pa@Y;C$HWh(4y}8% zz2E;!vH8I()T!j4+-|6wvWxMUE!a%=aa&6lf#)MSl${GW4CL9^4Hb-T06InqCxP2Z z+))OLlma*xRwrs0YG19o8)Ct|+8Asw2da%t0xftm6~^m0QL9&-3KQTTOocjN&E0it zgK@7mhTMOd2yX2p=pC6@6|3cp{DgZuHu|JWFJm~bE)HWr({zMv^M zM8a-2P5fJo(V|1p{xJOq9{9Vf$^Ml`q+ZT+kXN}9A7@PFQ zr<)i~4WEfexWcDi74-!Um2uwloQWd<2H7AJzzo5T_)VF*J-Zc@TL7*K+-(y&H_%7x zu4G$sP~{x=)^)O*+1A_<&$r}^zxK>s{Ed8T?BST6Cr<8AzSh9(yE$8O+=1mhxMumS z#K<2t;b1nLr(HktS^1h%XOKBoMu0?jVQGCd-@@U=pf~bif@3*r9!M0wZyX%1c@M(P z+5U(-z&yYK&c`BUdzL&TH}X`1)vhaQR(oU*b9ypVk)1>v5#7xD zG2o57?l+{9s+tdE&FDYY%^o5=nlmdJ5HLmHI<}vBdD$U)KlgLu%oU?B;PCP$| z)gF-5UcA5sAH_IFl+_+^m^fog8<}S*k~jROjP}8F&cGMHSl-iZmiNO|PJ^B!U0v!8 z^b#BdatxrOfaxme-T9I%YH=WIIix`Y^VYHsD|i)B97+d>kD6ozpZ9d%CK zE$DG_p5c0B!GT|-Gzkmf&Lptf+nm-OQ8y4-BZaYFjub4p@9eG3y5c*uN8fjQTxHL? z=&@sg<|tsd2^@>vl+e+YS{#nEJdhI0B&^<;c4hI=#tA;W0D3 zJ}Jv^%lXdqlxmL|(uT+W&|;^v*zNK`BrNo<_Lwrfg^)*I6LbL_5xsl(+ljx+`~}@$ z-f*B_pJ`)I{!(wX+jidY`k3897Aw6E7rzV6n}{-R$QDUB*IS!oqnPfkE%U8_P6BaC zn8*a`F_Zy1j{x)8eQXHOELi32;4z{q*LbxJ|M4Mb!`jP0_Hb#nm5mw1s&pk){Ft8y1V zU*TNB;{xQwFt@~y2Bro1I$&?XjoP`EBfnakKx6^xP48zoEUhy39RF2^-b9ApLzJPf z)HW-mGygxof$n5hwyg1t>y2Ydj`Ugn?dTg?oAmAx8p1 zeMOw63ckQTGzodh3rsfd5&_dwFQd+n{PPK8J13~(ic7JNX48(d*)-eOBAaD)+(IE6q5^XQ{(Ij$7*5=UU2M@0s?kq=pd31E4S3D0eY zHOG6oLGqXY=CRJ}`F2ArZqS3>Il~KXu-hcYU9cA{fpG*q7y~9EIpGF-%x1uC&=uau z$MVhK1Urf_$&9y!T-zmwxRge873XY}Kx6K-(OqGkgU0y7Cpu$!k^x=wgkly-nc z6Osq1frf5d@w{HZms(r`3!nYZ^z zm*|D$>y~w$GrEoZJish{*X=s+HSJMnip>pdorf`M-D=5)K$?Og@ySjj>3E`#jI3ec(s zeWZa6z+GZ&v+xI)HH)~5^_y0@!)ZZLR}aCoP1hXb;-chFy7{odoIX9KZ9GCe{z-fI{P!9MD~GK!3(P8UI!s zju+i?IWg;*EWX46g=Jk($#6jH(54&~bXgU`lXK*xH8^c#eUiJoaa>|_Z{wJa?rYFl zRgbJ13zmX#Kqpsl zP&mG?y9R5GV~stwdZNK{t4=mfB??rI!WnDOM;ukqrGYNjIG^|qmcb;)7f#2hF+cFt za6##zJbEanhuqLM=S3GmA`)_1N%Tz>P`c?l%R$+g}#(yl5SoM7j5BC%Dwm)G+HeGaIc&?9EkPYIZ^&IOfU%B${;hNHyp z2p-Roi=#q*Do2{$z?nE`>iJY08|g?%#9pE=gA8uV81KRa?lyP4g!X_fufj@>^vp)SDK{TAt|)$7x)K`P?-Yss!-1A`UHKBsB~+dkc8{Q&Om z#1<1+0wjk<6k~Gv!~mTH7VOOSB8*X9l+K*(qVLUetiseh=~l~fl(;=@MVI4(jL}8s zn$@6#IOXV4>IFA6vm)HkkOHkaR86HGthkf;D!`aooGACYOGqK+snpiQ?@mS zgEa8GkDRP;u5YT5B6UQ*XGI(tI~qJeMkSygU>CuSKX%;6^-w9Q0IG00i*^9xG*>k4 z8&rQHgrqV~Uq6ffu>N1UpPT zyAHfGAmeOnrx|AeQ|m!8&b06>SNte&njopCTPQQ~BjuDSW>|AaeA}7UK%P*h%j}@7 zaLhhG@GQf!Hgeb)^i9UaapHd59h{O12vtJ!t^^#+7@-Y93Ae@+gSgWVm%KG7^Mhpb zGO@La5RDP12SmPfp}w0axbHaF7B|FIMu`Pt(wOma#)zUjB%~+c0@y%BOlD`IuqE}W zNp2l7`w^hlr@c4Q-;>}*JaV1>rt*~UG?{>x$%&ay##w@71egHOx5balGX&|FGYv+j z_>p>=AgQMtj7<{O zmEt}!k{yhiARn>EjASzG>$y~XB85ws=wO<-oh&A4inm}B5}b=4UDC+U^1h@B510jbzgQejQ+>D^pf;DBbcqMmjc*QT+ubMuC6vRQ!yYA+h< z5q^00IutvRg1)>Jcx}zFq-KNS>?BfiW+TPP`%LkY?D_#_67cq$;aSGg9$+DX*#xEm z4AKp3^8pqUm`k7yV8rd#Vx(c@ds^eXLGBdgWr-eu5_ z?m(Bq>|c`MQ0Gh49u)ghHS1lalO*8pHj!RQkdX`)z#wwPKfs>Pc3Ez4mm|uWx+H?R zg}YuiylvdvhTz#SJ8c9;v(qWCBRiP_ReWMc*6!?BRN7mTvaN`YXI@25K#khs1g^7% zlU#FGfWf2AvjdR`Z{4T2U`Jc#2$1MedFf5WaFcivLeP@--grOzbZ`PmXv zPSQ`fL5(sU(Yt~sDDD>I4a(aDd}C7r`M-cyvlUNHT!-`b9*!2QiT*Ji z_dH4H#@(@5b5#y>E8?nj(r$|#c^h0z>Fi0K~<*sNwz7L*U9!`umR4sMM8GLQbUiPET3nl8p9A*m7{+YcT8Z+C4#64G6Ag z6`xB_HLCVhwdkoIaBI010ymZHa=Pjr?B6q9hzw>J8Fd*MXHyAgSPC%1Qh*tj0`yl@ z+6(O~@jaHc0y4z{(q)m)B#StcEMOx`m#)mSh{L4`$V3ZxBuj!yM}a5csoFOE7Hu)j zBF;1mc!u-E{IfthEW%8(fK0N0bX`uLT?8anbs}A^WCM}S3=7B%V=s<=yJd#`KyPJv zE_dxN$dkKFwBsD(rmZ{UBqL+mwb@&_0U=J$5ugM;mjd)$3ea;YK+jRB3Ms36PxM@G zb*arn&Ext09}(~Grvpmt8JDCJO3Miq z=M^e8EF6ZnARKC42)GSVa^qWDum^L%Wx?jw-ON(DrqY_+?pPYHH4P7A7yGlHO0#ki+LQ-e00fbczMY@~5sFx-FvHqjVr z+$Gr7p#R1jTO0JBveNWlH6%UlKM}bpwne690Yvzw^XNY>O3s;?aK?#z0J#qL8YU!I zCTMH1Pca$6)Dj+=b}lAk;GvKSQG>Zy?wyFAu)Q)Dqrg74K6dLmyv^8lnTRQ1*X0LN zCHpQPhhquYpWAo&SZ?3t`*QmZZYKREHtbYPQlG+IeKx35F%jiLX>Xx)w{V@PcPc7k z<5cu!&Z#Ii?o{;hF7aWvu#Fnulyloh|=?VN80g-dUW*q1YY)gw4ERVabTrbLi2<330q=y7`i^v? z&sB%UgXJ>YX(55R;&D>U#5~cz?F2drECE>K)9I#m5x{(GbH72qLXQd|Y4@@tE-rH` z?bLMJdJwEEt8zQ+rMG>%R$5hw)?1FT?YrV4^+p3dvWxC_V z(n^Qc_lq5})~mDZ92eW%EdbvL5Wc3JOvI>~20w${<5LS>& z`a2E*`a57Ct{e)1xB^97mDi`g<8=dr<+THY1#ZM(#kc8iUxWUpxf%Pr7s&jTY-NFi z!~UM%)NaK_c8%@Ljqq+nxFX>a+a+7o#r{Uh`gO;XV;TW@q7gU+!!rV^%S7N9B4{>t zwA8EN_BFQKiD2geiAPPp~ltl8KzPMJF09%N%IXX;m;!4)IC0So&<79hyE< zR2)2Wf-TuYTRtrqrmWkurUr&7tCtRQKL)j&yalzaf?CpB3b@l--pnCAJK5Nz(0mP{ z`Kz`v(6}b3H11*MHyZX99L}9=jl7vN*?@WOWUCWW_R?)I-Fr{u93{l@ zJsNO4KOE5Q(DZ$5i9)f>eQb$_6N)K=RVwFBsHF_xM?)v=zFcf_Yp#sBGfj4|Gp&(V za%UQ^8#9fub*4q%^=DddC7)aFU1M)rZ7=lhMmCqL-(~J~>Ajh52)L|HFR&Ndd)IFS zt1vEy^-%C=)IX6V2|`3x9p;i#`l3gipmA%I0xoP2Tr@)I{6mB80o;^m4cg-?!}bV zN5K%`Nsfph(n>-Qm6HZR1i{>j!2r-v@k2^&?lA>t14~?O%h{zTr?nhUPXc@PB$Z+o zF0IeP^-FAb(%WMU;2rO~Cb;j~Mc)3{58NRFd)l5Dewd77cksqbjBAu~LXT=TmLwrN zQg8}O9CI(kzd48z7L~yY<)(M zLb>0wK22R2boo*ckdsngbe%C(O-ND&yWq!?QZ>blRMSs~Hi|A7;*9rQ=r8`v52zp7 zdQ8hb_MX;C2DsL$FjJHjDi5H+h+p9#GW~K3G;PDJ{OvIYj7{s2KlaS=S_KPv+u2Or zgp=a%cH(Td?A73VYQ6+3k`*JF43;PtAefY3u%fH`;3tqg$tc+fIOv391Ui^dQ^rBm z@D4!HpTvy_=0s9dp&|8E*br}5TPau>rS{5{t)VT9Iw5&&{IALeG(soB$;#;y>0v#+7+Z{zL!4e7HV^a)GWMaLBCJ*K# zBC2%-P|J(1b-00_u@N_i+o8}aAecsZy7XG-irDF;0?Ap+(!U9$3on*NPFI_hf+@;M zFo}U6*OF)BMH#YyL)nG6^ctd2{#gGY{R)env(VYEl#{c+!I|jnZ{$}v8-A-Fj`2kHv`cLThTLFgf<#HJOPF>FteONODufvYpu zyAbh;d9rIouDjOkf-C@pI0H~%$IQMs<%{ry9LgHbPtDv{kh1 z(?-F8Mq}dhBv%?W1xaqEYLNC^FpmOu<$R&}yj#xqL|Z(tY>V|^u=uw2mJZWL*(h%l zc%+kqM>>CKKt>$TF&3bkz;Xgh2`nbyZ2|ReP!G@nIRE2gQ=_yUU2AL#t^riWXn`;g zl+xgUle;|%XPcl5?gDt4$>$~-Ks{i%wHuh;m$)Yc!^wjrkq6%AgBvVz0MaZMxm(1n zW?pG-gZD0!02+Z@GQ3xk3V5(JQD7Ge1k-X0@n6X@U*<6ISkg2;x&cVHjajx2phlWu zB;i=pM&yy&t+K&`=5mi9I0P_L5|0-0q|wv>m|BP6BemW_C|7+TJh1RHXQCwj5aDgM z4nlAN4s0X^)Ahswt|%-&R^Cy-v{X_W;Kc<7Lrby|LdYu6;8LyQt&F7xr6Th@sGM3* zIiu^8&WMb3m2LrQ^fFLN9RkJ^TfGijz2L4hP*Ow6F*7n!M3dkb0D11FkU2@F<)|`A z&GVkNHh3D=0WyxzT1T^+}t)wv-s5;jh3=}^y zg4~>h++>`@hOnY7#PEpA6 z=Rr&*w+hWv9TNl3|3TwAhr5*7p{rCiB5uz`R* znA6d!^SDY>`hgE1px=vMhv=cCqA~UJvGJxu{R6oy3 zX+!dE<$mEILf5}C0Gdg5D?GqkkjGSPVIi2WmPiH#I0Wz+(#m{A zj>%v;p#hLJS%-3lZ&~lLl#~i$G`n2Fuj9_9r@MP-fVy$8Y{|na_qnkrA*)=#A%4`jd-5z%GMAN zag&bh(`F=W1+6QIkxkiUfp0Vt762f+F2Y~eXpCDSq)Ob(jw7tMCVj)UvAeOij_}8% zt*iNn^(t)Sb+qmr*wOL-zZpfjj*29`k=1&l6Y>2Kn9 zSFqUa9p&WYUBk~~eVqZ>moQ<$@dOeAXTczRzL#{!%-omQl^1Ui{nE&*6sG4;+|6OZ z$wjh7o)4xmO@E-<42%vy@mI9b8|);P#gqe?zV(;dP*WL}0;sOG zqaGck(qHFvpy1~LMYH*dhF2oD|BBq++H&_;7iNCP);s&v8FY8Cf` zfgt5API{NfBX9;xKx^u82dP(UT4SIfr2k8=GiY1-(it<@4LS zIb7dd(%S>A#fcL;ecnG@)L`*c@qscyqjs;-WgDV)Z(sKWd!#hqa_n|1)9fSeY;qdi z%U0X&V$^1q9mJ|mCkwIeYiPzr0Lz|GHx-ZV#3=(UPl3~Dsh{E({4*~=-7v7y6cFEi z0oUz&X>O*K)scl^&C~$g6l5(U2LRUX>$4p*bzff)@Ob2E!3(c4>|OG!{4X0x~`U86O}L(jbNuXL#IM zYuO>!mAECb148{|A|r%S_$5hW8dKtdcr@yP`0fTX^z3VZomO{(m*P-x%qmzQ*K2J(Bd z!8}RTuyTsfc~IWCAeD-a0B2Pk7ApEhg4ecQt%j8|AmbBp#wQ>)X`%wMn*mus0Wnt) zkTn#LLGqMRfzQK;MHFx^sI74pQO+XDSwuODC{H}DBu`|%3^gH~9F9YP;^%kej7=mn zDz?s0!k;)LcPG% zt_ud?$>nKQ%yF`(T{52LESYr7bNtV`WCVTQ)s)A4u&$^f3oYGl!)B9vSMcU8$XR5E z3;q^EQSnwz z9x#`{Vgfe+Fwv%w8edoY?xa{ZfhB;xJsuN3_Bmp!?c4wI^4#cihF&TpdoGsu*vT3Q z2XTl9H4za4$4weU3F{q=dbeu?rCSY4sN*B_zWWU436)P4D6u!+oZlzFib*}r_4kSX z6*zd6tQ7XYKHCMFLW`7;g8XcfBj1V}m?#uDBo8IAQY<4Ag{YV2VhxAlS8!R1f{-It z1IUR1TcDaSnl3Gis10u84r@MpwO;Vb|A%qT-b|v{4NL$Q4w$9tKN=@ zMk5v4qBfrp<f`CzZ8GnHv+zf4jP}*yGP$>0` z$S<{u$XAt!e6Q)rKh@why{rdRnr1pVA05pDcCU8V8c*f7ED~} zkAvO zIKv^gR?o4UA4$p?oPwM?nbRqaJV_fg@}uC^$8-8o29PX<#Ns&$dxs>sJSH`7<@B_2 z$2iXc=E~_glrzEs8D*1d9Lz;2(5T$8%@5Ix6@-WRQLxDqj+76RC*{cIhj|sX@d?V7 zvQEjKqRvr1;Y9fvevyNk@6E|_2?sxH8=t#3p%x4(^EIullEP@h?zp6Y7VskS43M51&31Gk zev$V|vJEglwA$glifU6<>FY+ZfICV5DJec#NIfSDDf|Ehe5%JQF7!?U%vBNs_RI;q zOF}^(?=i~VUPwj2(Fs10oFTeY<`Dy3m6ya@YuS{sUW7VwtZ%>!VqoSr@`PyikSw9= z5Kc-_+z6f!WfZ0eF41gC=>jO%j&i(PE?+4Rz7mxW(Xf?;@c_Uw&*AB_@pN9e!)!;-dI9s~C?VbP%Zg_!4a9ZPM8l4{HJ|xVp^g*e86_(R3Xh2OJ ztgumimq3w3Z(K0Vrb&tN#w9Gdnd+@ek;4BT^bq;_*d5;E$OY$o;zcdOndf;_Iav;j4-^tf{&h2e=i7lL=u&Weg3=eVb=)K>{HP!VD*AY(~G z3k0iO9AOi5BE;$hLsi&;IhxKMFH#D+6;N}Oe60Z5WhFKdfKl?5u-(BSOB<-+*rEz` zAOtd`PB5t|Ih-JxuakH*Q#Z~K(~|582VY5; zCZjVFgmkVCy3>72Kg;6}QdSc+hvVIi!inJ6Y?@5xN3v0gVLpehk0hgY!qUu?q~jym zDBW&J)`&UueB`k7ayr^1)2|>@KKPT4Q8vE%evAjLH^U3(!u$M2gI$lFI<9 z&qgaZm*?89n9<%tXpR_$Q`dXAyWnxaM@4XEn!ahE=DqM|J|E z7=)}48k2?OK~#t6rcW5lXirEL7E=$Zl;N~JhLcRqy&<(d$AUthWzi9h_JkB-iP^^t zw`Br!0n|_fwy1cpx3YZQ9aS-VsX2GZbRo{}>p>8g(Og)kKy2R}gxcBKosy21Qq>sS zQdN+=DVUOwN7J@2WGE#5wwV?3fza&9-1uF022tk%a@2=)aTFxO}D*qJ^a&g}Pi2Dj^`0x)p8|4lpi7dpjAMhv+~M z!jiHFGfjh*&6STSA1h)4(al{4t)1+X=U{t;!$X5<~zN%@Y)$WpEa%DQ@qp2zDRhn2^3XT#`;8mrz6}`f}b7m^BDY z1~P86)Jr6E&c+zXTA@)xu-dpwJC@oBTLE}`eo{2UIsmrf;d7Lgf8 z!(K8anApEnXdwTXVVp=>|D@qW0G-Vp$NU`pO~Cma-m{s!obDVFms3t>`Y~E2OPad& zZnaoxe46Hj5~sqm5U9SUw~MrY8Y&8K3exKI24d8bQlY{le24IG?n=3p{xp6l_rv|( zjg+UG)#1NMh1n zC<*qGfM*C5a%8;t5mfH60Jo>Gr&ecmI>FA(=gcf{4;5!a+;MXiPX3&d>+IGH<%|Ry zTR%fNjW9e1P?w>MA}~;uFI2_wEEFV!%(O=a1GNBY$@b1js$0adM5x=l&;wKvu#fbO zASaP(Ud{p}Q=O?x)E$OSO6Dc|gevJ0s>Ze3A%&zl4j!uU4M32l9Y|AF#%v-rbFH8m z7kF6ta0VTzisQWKYSmX{;Ab=y;#8H^=DVnWR>GY6)6oyt=?4a$m%kuwU+qHFJMhx_ z41BkDxyNYFhIk~zpi+`_rQqs%Ff!Ojl8!lhb|FU)jKEXy2D!2FWIQQo0>qmJ+85-XTNM z!(^Ny*!)iS^M%FEQBr~^+RDzti3Y7D;Vdz^)&lLt+J^#h3g45_7sW3GFird@HS;Bzo^a$~Xie7e$fGK&>j-7&wlgX(XQH zqBdL}orcDyy{W!_X=%hHk-_v5h^L*k5hRkDYLR#g;LZ_R`|tCMV+28tNzhTw3{{ul z4I0~xI2{bf35Vaql;M~BIU&#r2?xZUQvHbv#l=5szUHXc5btNyB^LG*=*x_Z5rIaj zIpkWy-kuHk3>N7`0~2wuDrpP0gbG)TwX~NEsX~W!6tYyVD54sm29RyCLx)J3L?0m` z4*g3_t~iqZ^Z!K4r(d!R-m3?qPo3Q{=$C; zv)xdFyK;tsu_U-w$k8y?N#zPq&3PmA*ETqLQd5;WNkW5+Jr-ePm8=;vhp;0{Rut5y z#~9QagPHHm4ge93fU0yIDU#Y816*EZB1yw1S#7nQO`F~ zJg-?NX%L+CeRgDLOkr4yhED}#4F?RHGCXkIrc5)n&LU1+SQc@V3~MrVsAJwdNJtiO zD$&Z&0HzHFI<9J6xQt=yq1x5c416bH| z^7>|7*wcoT%HAc7MnbRwyD0<{aoP#cm7TbdLX?Z0{)UoI9anpJ%D7=joikctrw^qC z6$wBVmG2(2mZmJ448fF=x_? zFlQ)%pA+UxZ?&sBGG-?h+H_bom0-?LVz$aCAWh$$aetu1H2VW;BIq6m%c1L%x63zz zxfE;P3B(?Okf$Dh%O5O=f?4qo01yyp{WJePs;C|P^3NeJPeLMh7AO2?koO4jNWS@> zP1@%Z{QP3dgXJ*4?Y`FM6HonO%Bvl#@i~p#WoZAg*)wt~S5zL;A?lr4S!=CzEOW zwPB&dB3?kVX@ChpVLeUVDc(~LM}XR$K#`Y9Ml<878C#=mX~3ht!WcJYfc?ISWFER0 z(sz7{<~8^fw6|(7KPBoKurxy^yV=-N8>r83`zQ)g(hLW3zat;dY3o+=WsO{m68m$% z1A;`dg;!2y%t+Cinbvpi^ovpjonu{_aRhAA5s-Ru1SDBd9RZH#rChf|P=_q3C31yV zlkBO>bPKH~Mj+?a;msUSYoxFPb{(XaPATkwErmG;km0^LFg{`$#F-CBR>5GQX&ek* zP5`Z$5xW)4q{L1F)}xi2RshNzFc$i(c8U9$(w(Vxb@WPhyFXJU(7EZ6 z0|hHcE0T(NksiRYIzO@hRKMZ6M_KCwNBF=X0ei2=VfK2omX(|th7R6H9uVY<1w}L#mNoI`E7{KgMj;`o+Ymyh z_3+!d>;gMSt|leUnHvTnI<7F=4<^ZCFiGT&Fp|AKmxMSY8F5AuzC{&o$#HA3&_o48 z*gz=*#S8SygYW{C7*7j@9b(uzj3>#{F18+*O^hdumo{r=A{a5Zm?OR}GXqvEqCNOD`VDN{nZ)HO8wTj}kCx0Vq#VzM=vZ+NPdv7g@_1ZNIVp=F~uH~;x6($%0l>|k|gnyCKxy8ytzr~r16GP^Fi@0 z=^*mXso5G#ViBoSJbOz@Da6mXaiY{#)6}fvrJ4!p9EzKsJBT`@>zj2ke_jPq0R`TL zT1v1*Md#xVN3n)Now-(4%D<$leA` z4iRpmZmm=$nw*vrh>m zy;J+plVQEjWKBZbXxN@8tXA9#YJ3C}XaisZ{XOn(*6TQd@@jqn>SAZM%d<8GBNb^7 zr;U_JH7DW?=bkdK<|R)gj%Ity0ExR(n5keOO%W0a#VlmlEK@uPE9g91O}ODKu5y&H z;*cE9#yP#iyy!4RJU7ua$VW&v>}I1-BAZRblQ_cw@pLS^)9Cw)0at>=OCU{4I3@Bz zl+SIZo^K^h!NtOs#8B?MxJ{ztPWlGv1y1Bi_T*UZ7Ne|%TTDGE5QOx}t%|!6bcO8( ztv^JGb&}A1MuPHW%Bbd=hvEHqg*E2GR#A$Ypq{|DM^J(5S=Mhz-LPpaOv-`G2z>B-055}S%5@? z9J*dr0Zl)~^_Nz{qr?u4J)%agu}3}IX;~zUQHI@+4j;nSRDih@Yd-?4-y@axNkRrV z%#Hj5fXO5Tf#h{T!uG{0jwCq=)!~?F=wqfhH~1-lijf&=lY@CdGzz5lNmN!7Nic(< zMgB-oD4G|bR6oC+O;9SVmkR7><0ZHA3OoyvQ-JWUU{@%>p9G81Lr#(x5%t>F*GMRd z@KT+=B+^T@g0csatfsgQuP;p>00v(MSHU%B7pe1L^QtYR$CQr^_p#`$Mlv^y0XL}P zSDN;mb?h@?Vwbe&D!3`RGDk^fYr>GL00Cmw}7bxjTYc5>c z_I?<4L6yCzd?HK&wc`-`s5@eUU8VF#@sh`V*I*T>Yf#YPx3UVL*sJVR(C=RV!ZFaB zN|MiHynI`uC9p#%DwamYIu&V6iI}o?iYK1*{Z-DlbNXueFgnKRs)Fso$7$*ELX-)f zi4Ha3sYvs|XpzHmcgSe+5%Od<%4VkUWD-+gu!1J$-I4$UGUX`;qXBU|v({1$?~-y9 zweTQk$ixhI4?&W(yi4Sul)_wxMRMXCSa%zBg^-;Ahx=_#MVzsU_hNO~IAbMX0_Sv1 z?mICyQ4&F&fGn+m(3t@@@(p~_fvhCu*GYSZDWBxaSxm*REYplO)M2nLgA{LrFnz?a zq!2Kv=9g>@-k7p7KZICK2x#|+BQZfEzOI3PIpV>6X)s_L6z?~%XNq6}CVMMOvwAy+ zkX=v=A29@_-_-;_Ltd$WG}aeq+#%CB#i*qmMva`dqt=7K=CwR`Sv{WByqw1>Q>n)s zVp*BE5x8ekMBz+82Y?DY2Pos%lT;4&0ddAL(nnw%n9n!{fzCMkIL1-HnzIqsoM-oL z*am<-unQFMU_hfu1~lNE7zZ}ZfW{*d2O-v8h+HzLzP&_#31lx&xEuQ=jjGlFslTLf z3J-&2p_)W`I4q3rvcXF zV_A-VVlZzO6Iga(B63NFL4X-dgAj|~%qgAp>7h8~VJ884g_)BUy>ME&NW|?$;E=r+ zkxrWOLKOx`4xM-?>2-Ypa4E92hU2Y}L;y1Xwag=h;07atrJ8`n8+{vt&`!h;_0%H&{0i7(!$_-MWyeh-UOP%pMq{!)F)gt&fl_bF8RheKgk`ohZ zBwr@Ig1C z)f38Rs&%eDy{Zfj8?WZD<)?F3pDGXK7r6RVi73C!)u%qcU#tp6I^yY^&#Q3Zct!UB z&gEsBg+_<35LEU?@;fNy!+D_~lD@dk6ALYp+B)4`8c}4lym*zP&r+L3ew{&6w%vX6 z2BPkeXCeB|poJ*B3r^8^J}pG$`Q$l8=j{ST>DfC&w4V7CqV}ceJ)KB>b<$NGkTy%A z`V1V>g~Gqz*g~5^c-V&l*YyA( zWz|Vw1*)OI3RD?@p;UVzi22igN2oUNT{NkNg>cI61y1)>BkTuNC0JWYb7Da^Bbfp=mhg2~Yxk_vYKkCZi62>sR{gb00M0|DymU>Fm<>p#lT z9}-Lf)Gk-iJpFhJdcj5l)B!4_ryrU0gf#=y?Se2COa>orMgYxD?`XiBk;K6^wHaE* zo~qFejXTOk-_ArEdQ@3!2n#w$!sT{gol*&9^;0B39@P&qylje(UDZpF;odmiGECGhGOgn68dO&_*02Qf;EhexG7?H@J zD{L^pTmp*;sE$2q5&Fee0$fjE39#KfddIu~*ArL*>@bfBBDNi1v3<7998o9}A(Ah$ zAEW(;zBO_cUt~Yl}>hs`Z34wP$PwAy zl(qQa#_{?-*=dEA**{gFQ17O!F+cc|9s-XIQN|>l_>V2ud#CpIaXv8s$8+8X_D1Je zXP^9>FMgrl&-V=>5WFd4m4SGLB(1CkWotKZ6ABll>oy9#WK@npYD_K+>Q70W;V2A- zBQRlz%7tn587u`GrZ7B+^GxVLfBAv}9BmG>WH!oc7Zxh!mpMH==wWP%s11@N}IV*rc;_)>nfMm6(w&d@gpUC1rd z(}*Vfqvk}1NKY=r1*6Z(L% zA#TWfhs_MLc;`r?qb=J9ltn_(1j?2n<+0}n|Mw)Md?9yoE44fYqabK@P4)$?o(%QX z^K~NL>7D!m>U=?yd`DnZ{D1Yh0DC6KGGEU8iyu9!TBkyJ{^(XE0qE%X(Vva{VBQBc zg0-BkN!2UQz>4s@3Q6Hcpg>;;8?gT=&I zz%*NM7Gx=~9Y{5^9l%Nm{|21^Mkjl`c_#rcqj~W~ZixZ22~+`e;$km+AIv6z#k(GT zsOwgMZUq5z3A6!pC_jjBubB}xKhPU&^PE{8py_(%tR5CX;hD1uP!_Q}6DVGWET7V* zQ;7L$0>jYdwNmJMKQz-1@#*IBNPRY>P`4lI^h3IGNV!!m`Zr#HDg;nSXL}V}s_>V# z$=5GML72QrX4g^dn;7hVV>q-jCh%%hxp1O=5Y~bEqT_`Gd2tU7P+G45+)8`HT3k-A z-%%%P=j3VhoCl=&h$aDi_UeMDVTLe?!6F&F9hTft{ zkij0ew~U3lz1O>3U50}Uq=a_<*$=nM>Qf@KteIbua*9IM=rSD|zn?iJp)wsVu4FG-m>$Tz zj3lTfa9Ys_IDk8;cthq(K*X3Slt0ct%$MBjx#Gr*YdCFWbEU_ONtbxspCNs-+pE2< zGsjfKA)=1AY1}<}C&_$d+N3+dv&QHbV*;CJ-Y6y%U>PtiTY=uOOaS%A5mlbCgG>x? z1Hkp>v=c~-G{6#o%g&fXR-m(divUZ2yV%0H)GTg6z1t+Vn1C0akGK=)f&gN#^s%w(lVn7znyA)7Lz44#N%svDWf;&3D(_~N67x&%HJ#n37sa0_--q3 zr!}P(>6V1R{3C*Tfk!3$jeZlKqL+#vQ7|&_uymp2B^OCKcUtRrV2`}dS~vV$-lHi< z;j|GgJ;Uat^dX~L(s~p-=2&di39CZ%$LgGysH|_*y7Q5B%n!b+dt2THC zKsh^rILbc~xDicgw};fad?Cf_XB zBdd`sq_|=N#uZaLT`^H7ZkD(PJIa-kLV<{kAWSkU9t-+(9^j;tPEAhRwQI(>9<@c4Mf#rAK zDnPi7nB9t|r5Fc}UxEZp!uSeou)rJp@{D~6$3o(0erxgH6zS( z1Ytf{yTNyhLm_N}WI`b(RtSwRG1S7DjY53u zXlcSnlY}APQDuIEY$^=M$0?`;KB=G}m}7|Vi1=~VHv)M~qJ{JU2fbYpAPFHx4Mh{F zFXBaOBC52l5MwD}SjspSFIo0ZDG^ypNR|?lsybkP2ss2AW5j$XK^Pgk}EYoI%OK zW7h=^OH+_VvL(QfW4r|G;)Z>h#=ex}@o04q42%_yC?v!Bl97Bd=MM&>Q_f`8w=7(m z8Xos8P)b8G0f89bNAt&~nHrPWI5 zwNjc*g*K(zN@+J_;F9ng=ePPH_I zUE!j)uYcSl!K@YbWy4yLG+y#pVX?@I4Qze_w0#w%SXeJPx&_u_MD{$@bwi%L$# zgMClOs<)Khk4ulp3RQrAC0d5|x7_YbS=0U$Fh|-4G^`+SBx>$5)_2u>AzoqIx+7wWTf_L!?_~fO>8h{G9OIoE$ihAk{$| z!y(+k@aXJWzt4<|E}#K*0ONu+M}gj$8J22ehoBBnoQsu|oaf3B)`>3B{kd{qt|YB& zFibLe9iseTE>qZLB!d_{T|%dkL2Yn6xrP$mK}j;$$X!5e>Oe{!%H>eYsV+t6=v@u^ z(%<|DmX2I*^)*~%mGX9p-EF(J&$4KEYzzSXnt>oqG_g34`068h-wm=v8|&c<@}bO# zsQH#W1E@{rgSP>dKA|bSEGuq8a5zsgCImU%A(Qhz7Uon8f%Sz#4xJn`= zwMXnY6%J$)vt8RJx)Cm&7blO#i+VKP;OBUw`{Q+|$aMcKWFn)soV1?wpnTa64kycn zcjdy@a^YlIKg?8+E~R=-b%45KZh5$R0qD({q2zOgM8oB?o}U>>{Xhfs3eB?8M>If> z(JZMp8eM<|fE!&7f)%~NDd!a|ysIWuy5GDz3d?t>M&3%kIU(T-tNvi zD^&G@GvH#ZQMsQWM#1)6uoJ{RHZVFZ6j;-8VrN=7ke~(MLnJ78l5>d}Ih&Y~v-E@h z0;lN+n36!5k`LdQnZwg8FU0J~T90ea5BxP#h+!H`I(28$p|3C5;{>@h(42wOLG*=k zx~So_%t9@4uBqpT z+qn;|#P-bA3@ZtNu@oJSVLrx=jYqTyA1ZRjBIYhH2da+huw|N&s^OBg2G5tUIbl$# z>-6J_AU!qfJ+9+(Z%)s_SsCc9EWvp>3!XJ|z03L*c|VptTy1w2_3ETP>Y<`6I;>$P z1OLDj# zLn7L@hm;f`jU!A07%8M(3_^jL?=3>8>xBsLR0NR?R_K=|BE)vy1lc7mA-duH%Hsgk zm_$yC99tVMwJX^`v%;|4#EURfn%nGK0C>~ElmL6aD*6u zSke)yy0|r#%_r}{Ru}v2!*1JG%^GhX;f1L z!Y#Ox5`waF+Fi*urD^A8!XBWUKnf`;kU~leq>uswgqU>+fS*7wn*jPzhGzPqY6{VB zOJH4;Bh=}K+9|}03q#Ls=iUNHDCG#vq!3+s1N@XULf8ADJca1p1uX-#osxM9(ZAZf zBaM(o@Ceb-8pn%}2Wz?Y9*b*2UL576jut7!zC6ytA%*gBDeuUT%W^RBg5@dL)+8rQxDO<()yB4rx zR(4kLkL;|RAG#0YdFZQMYYlKJUF8se4+D3JGnvFKNuPcyt29Sj4|9G)m^hc*@dor; z06tITK&f_bWU?#>F{GMcl-pzY1Uh_{5E50!O&9N{Tf9U=LR8<}tI(f!bDqB^8?13+ zGqVuK+KLUiN&TJ2dJPY8^szQ2D|HqegF3m-(SgD2%Gcd-a9RW5svDC+$~)rCMm}baABrcq8KNm97Kp( zRVl+$+>dYMCxCJ+$y5sJbk4{3P+QMD6;60Qzr8li=ZE^s=H5-NR8;9u zYiI=2tJ~pzg`t>UV#?v}dd{hxXsc9|SD99_rzpx`=piJPq&qsH2qcOh3PE!y1o2MY z0H*_=+tqZeHY!}^xRlx%BY3*+X=;ZfsoN$%_`Fg#QvENrOCLr1a+`(!U&`Jj#;!BV z^LzK+H%7b|IEZ4VNXAPlGpkaSQZiGFnQC+40!Y{k0p67ujETWPi-rIX4H)QFY`rkF z>XjE<8HN`I(eTm+*nk&?SAq=~aQDJQ1BPAYt}10p;t;cc|NlAnzDK3fF7q+&@ZIyB z?+o8?@A-eu`tA97NrWu~iZze07?evSI`WpRtU{?@`de9eTtb8?@T z4r-O-oc#SEb3<_LN80IQz=)&ukVAFOUPt&|tRtNNqjiMHa&6%zvpLu;>KjE@;~Pa+ z7nWJe2kVuEO1o96CcAa&)0f33-27iq{rG@TI31xD#CdJ52V z3>ihs{r-4S9AsJ$$L{7xPXSnD#P^X#ZRc1X$s+p7jx4e;T6LAugTOiu0RPnRh{5a}rkxUkI^d;|vDY_Tw|qn*A1qpZtk$i{w!s;m8~>ggBEPAJyTd^5&}*mRpd z{u*Vxjglnp4}5>ZErcj|;h}cC@KElStmxpDoQ>HGQ&_!|U|X(CA`J>)?=eH@a~1kJgpR1gwhD z#b&3_=G#le^tn~mfK4m~%Qax^t}~|0+AhBPyw148T^Y7w=kHPK)0FukN1l0X2O7pf0lUSr7TS?Zb`B~mWw0)A2=eu`(V<_#8ly9XEWk#3oI|A44* zk;9uX#yty)Tfzz##X}mq{ETOQ)YG$wAOqjiN2lR&6&`TZD=>e?qo7`l`JM&_eKd6Z zA<^;2MVs%9ayO^%k80uww{!X`X@0U)_jBCV>C2`0$x?mKG$xo(stKs4IaKTy~a+M(7SXxYD~Vt!c#hp zC9OYk5>;PGxM>83nD2VUSD3h~EBrG2`aAt|Ri{B^4jYYzBk z<_H(49E?4}1v1~mEc;p^ZpOvh?GD)gFI?4TM06Yqf-~$oi13f9zO!TCUrG4v#8}v|3 zb5RzWisqVW{%g#L9Vq}qTTvFFZF(vftOh^&G(lUqL$`B*t*OEMLL$%tgrWHZp86~& z@6EiSW)lzj?7oPz+p$x#A%i~kS%3KxHe0aKt2Ol=%kh^&_4&|e`~H0B#79LZzct$D zt|Gob%KhgS=I@=I>I0?h^tsZm6rTK)X@1!BYk5<;m{Ok;A-lUg8G-hsGcOm6b%MHc zr9sIE-sM6-eRP%k;#~8mdtz>w^?6p`LVJ1NQ?)E{!=>V_ow(7o#O*^8xD%OupAS^! zAE$F1=1!?~ir(LuzJPFL#4{i$TC%V>I#yN7b-;jAv`L#J9Z!$lo> zH=_&s5^BAR@1k<8xh>_cM|Y>};@hcuZTIiu9i_k3PA>}ik=->ZG#_-A^CRJfUrsU$ zgLfGAPrx^MVF0(QGx-LRxwtEc8{uKTo}{0d&#S0u1otymnW>i|^<1l>i;R(5qxTR0 z90M{~nV982U?*6UeA<0k{>z2p3ggN^H_U!zNWT2?DtFO%A-+8NA$Qq6y}~Vars5k8 z{i4h((Bcp+qro@+!wq7@?&|nHTr;-u$Yly*cQtnL>dofkr+JgkPG4EYBmTn=da(&R zy|m*;cDmOfp2HPA`e~#uqQwpQgqoiOxnX^e#s%Zc5R#<1J19LPS>7Y0qc5zTXXxdI zooCFBnOx%hT&ujoIQ&x%H9-H^AJ$Av@*loa+a{lOG?h_j;p2Q3_^5egz?goN;9kCd z0|*v(5>C*=g-%5keXw z@X0^D&04Pr)w?w{c*i5iY-GBS54WoN0s-Sy9kZDl&pShk)YZPT^Wdo{QZ5Hl=(`w! zvMDX={RnIS=wA%d^#b=F-(yyW%ID>Cf=$0UD{i}*D=OpnbntwlcPP^F`3s)=JRM6ZH?6rUkcDCVpl&)sNT6nyC ztGLY=N~-`q{PDjV65Dve0EuYKx0izo zD%}0FAE4%18tb@gQjS^1El%~gNk{AFEM8fo>jZ*EO3*qWCxB9mVoql=C}%vS<>gE; z1K!TnP&5f3-{!A%MB~eI3@76=m*&fQ7>3^X0u!GbdCoB=jl~6)(8nvRj^)pUvBKw} z=S)w?($;{-^rXdX_vuNizQb79wGG4W?{KX5h=*$s=6c2rd+{z5eQ^(j@JfJ(9iC;& z>(vP1{S*%b%Z1}ntEGiUqxZk;{yXo-sv;_k9-^o)dTeTT5!|B-ptdX=Xj1$&BN10g z;IT}zRZn=w6L5k+TtEJ)RR~s~y6Dl1hWs9Y!a02`RE!xr02SU-O;G}!S-w)+30lbl zJr8Y~Ia*01s)}y*s2ED5qnoeK^u)_G9`vqIOsTp4mvyG)J$e+vYtZVDNrFM?vv^;( zDA7unHSI1KU3CJr!)%2V70FP)P0n+OE8Ac=sLbv#rc@en3 zqN)!{aP2&2?FA0s3;2cFAZlC1Mx`<+!FIc}5Fc2zQ8j~#f~I72zi(U^lwcAnLOO<* zZ85d=+GX(PAtATYpJ3&=UXzd47mm2lTKI(11**Zq2cuK1pBm2v)v-%vr|*Jm#_Ev6 zQRP7IyPOXEY?t2yy+}gO33_ogS>}1Z)T3jB^5!F{6FfDVog2*)B)7IYo#zzRWVqNm zr(`MwZPr?@b>$mxU; zE-K%&EOo86)H^l;P2BsqAGjQoU3+hv{7N9^v~ozVjVMLapJYNB`bcvfTKXIbsb6+) zk3P^Noo0yA*7eA!^mG?+9Oz4SGZ}l>Gb3?9G3KrqMg6GFA zQYtvP`TJ|AUpWOSX&ah4!^1n3K$)ln^BRNc5aJ;|uHUA_;*3XFjTFl8MI?MBAAT(? z=vgFussufMLF+8HmEbbm9Y}o=z7UU3RSz^x%4hpNL#CSkc_f&l9_-Ln^h7M6(8J&< z57J7|OTCc_YiyB#+zJoClmsoLvtA_FUSE??iNczn=k9{DuT`12$uKfTCsA9^pLo?9 zy(cUTr1nfz%CFQ^yYbLTG!t{;80;$rS}jf4xxB zQMwQ?Ef-?VqNSl(94JcW*(wSNc!oNvYH@ce}n6!kqhuk6AD6{K4=rg^g(a*8|0&FoCdv*nMAWd z{c&_2m+8UkU0kO96*+0Q&6m#RNZ)7;3j|Ec!0ux!M)pG)NgU+EM7S49S>a@3i_jn5Z8sTsQDG?yJ>}l^gTq~Rf1gMxB*Gb z&+(n{^?rnmV!|147*(JfNpo({aqHh9DM;eRzpZ#u-tfPpBPZwvnojOIb82QGr^n!C zZsao(ee?bkZie;97kB!TXIj%jda28*e7=D%IP+5llMBZe{COOeeudPbN+OKxLvs2a z{-uX1>I&hcTfq+a??-xNS2u=N= z942szJNbX6`Y-|Qawdc~Ls0V(f)dzE4N-h5B2n)~7YJK5rr`qBK{EolM{orvG8K)UW2y3CuJlg1MJ-A#m zCULT-Rr%&!llV!vy1*zUw1G8#_k;|BK6Glyf^@w8f@(<6f08O6W8bWdMH`&s)fV}dM?qGxOvwHb4cQLU$^t{ZIAq!9eKIO;k)8Vs~+{SErgexSIt`M z1GSnicZ#^t zkomNTcABif?yaC36SFQ7l6uNL0KNTfjXcw5c=86f?z$Vq_k8eVprkF`SL*Io_k}&B zC@dx%jvBz^n68p^KdU5a0JrfSl7d7v;G47d8NR-)TVA1L967qn{>{;;*8pG+on2SZ<~&3FZ*9^++;FR z%Vr*rXUMM(<{Wzhxj*`cxFDyJ`X9QRc+c>c1BJh?s_00- zOB&x9LUl@4q__XXzz(gVV(b(S3wTK|lNqs7q>G(~b-m8*hDJ3Up$p!{st-^PiNR}K zbiuo8@(F`xz9vX3)PE;FKin~f@`{eQqJayS=pNrwVDORzp*~;cuHzlJ%|bLf+B(;~%TOi_u4gjh~K<28O)iYxfwN8u&>A{$`*|35pw@>f#-1}yepj5-S| z?$YZ|q+qm>-XY|-3n|8>fmo;d`%uF~T&=;SkCcQPVpoGpztONER$L5V>9-^Npj3>n z)G@G>?;ui?NQaZal8zazu4xg(bSnmE4J5_FPdT5p;2MKOaY0-$suNZ1l^7({dtE&5 zoDtKb)+@=6a0^vD>Qd)NS?7NgT>32~-uVCg!>DJcFP;N0eSOAy>=#kTZwnpL=;Du@ zZeg(x)usANB`;)UhCWhmlad$MJ?HEr#=Vbp0UJlmhn*rl?7m_58;u=UT9Fs;p2qG4 zyBnI$fV~yx@$ReGDFX9b4G4alk)m6iDagX^IlJF6DEv-kQss5whdVm|SRC>Nmo#W@ zsXMyy1*=Jz>!PJYnmVDcm+3LkAsn%#fBsr!>P2?X8KN|T;2I5&bV*)f(sw?bqeQwS zcxntHY@k76hUIjpqua%8TEw4(mk^s4A?g32yZxZl&JSD6kC>R{;m50AJ1Gy@jat91 zX^o2l9*r4x8C}@p(n*=M!}yrn`Op9{a2G~s={xTS?jKO z@|$MH;*^IfCX(n;+XK{+<1h?rUk?9W=JC)KH@NwqIEy#CQ{KXu;3~P)jZ%;n5>voc zo&W_YaHs{#>WV3fUi{jXEb7NPfzyT2kiOvuJ1v7%hXHqmVJK*XDvpHzj+;s$4Gyg> zQE$E+{-xBI06PEF*|Wex^_4wHa`#o7eaeo~bSKPCi#X9^i<_vEr<&q+!tDNv*0gV> zMq32UtkjpS{~4>UD>Hb(+sF~qzV(VfIw@hY zyaLgmL)6;k9p}PN6lub7~now|^gnGU& z7yR-W)_rKjmV{$zN3(b zDgAi(_buaRBX26i+mptJ^i-kmph4PEP7|83N_=uJ? za<}x6uKI2T`*>-SKGwidSDIrU9^(o7(rtDBRf{^sIK4hP5K2Q`Uvf7T4~M_=G0-aM zzj1q*YJC)KVc7b09Ly0z)^qB4HJ+F#Dr0dNvrDyjKHdV0QM8`E*=aUu{9&Nc0WV>d z2)_KDS*kiEto2hTED*mYGUj9InfE`>5CYXm&&Lww&*Ja{I$525Ku4^-YLMEuj_dAL z2I5)xGz>&MK^IklY$1BBun^toi?cQ2*IV-~o`&?^7A>RI`VHP$@=Pxx(c&E5Yx30X zPm@pFeAWKWc;ARJVkzgtQqNh5u54IJ-;tqO={;QRZpZEhJB-60cPBsBPHW!T?Z@uZ z*xg`Q!B5vfbB&Z8gwiyBl9ALF=>hF?4E~*IwoC?sfXCE*GS2L`(A&(COel7iq0ohfuHsd&4Bl6dl0Ur3gp5%nFm-l(I# z&UJUbo%dICz0FQJtM^yEFW+BdsCJKjiyQDS%N9$@{^i1{p!pMety^p_v(@WRJvoon zGwN~H7x2%ug*EMX{WSpArG<))geFCAt4S94#t&fn4j!G=yb^#-)VbjqB8@&o&&vc! z$#YfDW=!i)wpk^3eX1V4=6F*XiS&zl3Z=LiC0x;JQ%8YybJ10Q`Ce;Y*>nayU8Xv6 z7*8wVvckyvoad00LOvuKa+we_V}koqEju9FKnWQDrXlI|CJ3oA&<*cg;TD7hO+F+6 z@9?%TXXDK8g6Szi+0X{psQ<+^f|sDcH9T&d=#$Y&YeB$zi$ia4$--!Tgp>GFcegf@d%V+|t41UETo~a2 zJ*y#x8jwPh6^zvPbz0{+zUE`pSJV^_ER3Q9R_oEz8m-3^Q*^DtAyzTabQCa^mqv96 za*oruN~6)O7B0|Zph{DtQJ0L-e3^oEfyn? zT>g}?8mWmWKD!2qZw1FqWdDpl_mi`e){8T+=+?fsBeuBW`PsU5Ti&U!Tsy-XPh)qR zH=P_j+uwio{5kzC9?=U?xNFCrP|hnwuYT0C820=$QuG>ZrC=RR>&7+D-M{O-4>2W> zq%GFdiij4Z7-cY|!{<>C2Px7C!>8)^{h-UBgV((DSQ;3jwUBzb+T zUL8Ow)1nzEX1k@4Os_1kTz+W5jiX4|LQp6?$PJ(nFCP4!%87&}`@|SsAStw}+mXO} zHj&`UX9OH^jo*b zt9`pvieK zdxs&)llKHHp6AfR4Dse1p`4Ht8Xcch0{xtB%E{i#sen##);=jnrq}t`1C)|zZ8ZlX0Z-QtBV%q8Q! zENo3`5d&-S`&j?3wCCqhDBH5F#+BSHsZ7Iy#6`)Sb_3WV(!t{MhdV@WOcd zr$NnYaMHxJIiZ1iLl`V^hYD~4gOhqy--y$a-qYZ8B@#4yk%V^`gcw6|Nb>!>CdScV z3~&NcwHQ&1?OkQ~^gO!6{fI$aZFO5yn&GFxvCp6bcb|D!!Y52f;F@p$d#%32a{`2P zd72BURek8;VMz%%B*!EiqOlW)%wN;6r0Ayyt7Yxx@dvX4z2w|aOEe$ms(e{~fIr7+6az%f%+6tNzObPVR@&PJB|?Uv z9E`dxMw1tEpJ(8GgE}O5MxDk!WWa;Ui3gu*D7rxcqYYBy#2kxot3thWa3~o=5q^{? z3_$w~H#`E-q?B1rilOK!(3t1Q?W-+$@WP?qv9*g^)daLkq7wOGBSp_KTIUj9&0aXUw8PQBLewtg8#Lo;nZN zjY!Fz`d*cBO|OEaH|Eh2VZ6dyRal4a(;e!$?i5cdd0(aa=oij$@%=ydMW&l)jORSF zxWvH2-Cu~@p`H(0dP9YZ`pB2PGMYG96Y5c(j<^t!Gu@Zn|D93$*MxdnOg1Led^qSTA)gECeg9k;F_zx8$PrdjF7Gr?dNR!O z3lU%I;itFWMTAY>ZC6E@Ry@;m`A~! zUx*5W#BLnoxeOD%JwrcP$JGc{?};#aLigs(7^Le{A(ux#_x|0{FTKAwQuWC>5Wivs zA>#*5nIHYy`?-7nVZWZmoKH%HGRWG4Cv!_IRqRr{nQPUm_l>bW2A1jgV&(w`zC35{jy$=;g znZ47jT7`GG@U_gPuEslcQk;DnyBq8ZO`hN*xz`BwoP4FXwP|4x>yf{<-Q3|miynuL zcAu{11U&v-@xYKorRZ7p;v40EdIuTEkECqZoPyn$T5g zMbE(f&K3ITLnd_ct{N5eV|ao`eo9qcoZLwU(Q_}b0BO^g|@5 z#qb}0>{_k;{L}I6{L}G&3C#+75x?`7PyX?vy@&t9fB)z|+8h1l&fY)X8vzFKkLZ#A zb=kK0JL9jP$I3X!V|EO&L8IfTiR0;s9d`=BSI7F-<4@)3-$nj(JgXD` zE1vxac~mRWZWYh|!&de0{ZIV;ul)U+x2_k@{<~K3^*?VF-~Lsr?ERxw`N99vD*yfe zqE&AEx2^I&TS%*lfmPIM~@#rdi417zG%wNkD-Bd`pKy-zkdAWu_+%< zKR$i*xOiMVn)=)<-g(l0eEQ^Z_wnmTkK^}wFF3d;(@X`ELWDCSgp#sgKQ5~L{EbR{ z^7-da+E0qdCzh&sTs}Egx!uR#*6fjytZlS8{``qVETl=LBHB;N$46vTDTkte{HT0% z`uI`t$fTL)^Cvy&lL}!JiRI1o<8Q(UE&^fr5980D3_^+v(!B};B;zB?T*zD^D;`S* zL=*q&ar@CxN>M!SJ(B%rAUTYpOO@NhlASP#73@8tI1$cCon1>SC3?RRO-SF zr9OW$`{W>flPdVKrRzUBdiV&EzHC!HX+J)&Z6p|av>%r+JC?#zkB%QcdPHq_X;yfe zUpMrGvV7c8k%;zCrWC1J;#=AL+~X5OpMO+5EFQI$RAy1)u^9$|8Hkr)=Td~^ce_QR|^ZP{?} z_zR=C2!PAc)SNSXY3wN z1?8njmC7z2hK%ip#a{XF1fKJ@`iyG@S)rL$`d+bj`j9H-vYL8kRb)KOYU7~GUXk=i z5BK1gHBwpR(iv%3KI)2bM|wa5?>E{%+*2iPn-V)!k6wqt+4e$}>fw=dSfz)1<(|cf z{zvt`8}>tgIlmKyycB1$>DSq_otjqHw^2(G&OSVqk>L4ouPuS1YK<#O6;k&ez7net z*wo!UX=Vpc!_P*)kUrX*+EXnaSNS5UksL!c3O-@6S=f}1yN?bm{iBC{N!6Cd6jwg1 z_Ku}N5j)Nv?Cm}3$WLm-uwY+3ntpfyk+PI~cEDa&ln?f*y{RyL6#{l2VwWf$a+-kj z?(bC(jv;g1 zU>@|H2bHBpj_HSQf?~q?u(OVP@UHf{57g+~6sS=mi{{6r^5HBNJKcLA8kah&ixO~1 zS?#@7I0^N&?LL@$_&Tm((YDOp3mZY?ADh7gH%m1~ya!!2%e|ReehMp9;(!thYGk(U zQZ*KO3h3`0)+IuRc)R2{-hJ>ut%&O=fXX6$xOZW1M%UX9rYTX{q?HaOwd@Lq;e(Ui z2UI}kEo=Se_D(3Jjipo(AM{j$3MzI7VI*tFMzx@LfPA%%Q_xfoju2>f%=P@b(AMCbwD{6k!cI)5<=)`IfpkfA$_FA-zw>Z!UZxeh8I{bhl8pUbb&!=jN>>mytQ++n1KIqR zZ)W#sXBW!sG>$A7HHR7oQ4yuWv=r0s?&;2Mv3tBjhP0w9Qy57m#Q^;WhaqW+O2gg5 zon4Xl(4^SA5KLhqL5I7=PO;ljg;afPoNHSntko?Z%&JtF?UcLk-#NZ}=kA^1o#JkJ z=k)HK_q3_B8EVtjro3}>_YOo05cPC?H?Q8()eAuvB=b6HN2WTvx&7o$NdZA*rUlIY zA__OX6NgE0t`?^V<`Y6#$|WVwL*(nzI;%LFuCx6_DRZ2i-npw}=g)(FoRPG2=LB7f zyR%9u?!1v9^m7s3%;-u_oAcWAQ@p7-A*D+hCuA{=vshazGmFZmtU}Fm%2kqKpo4en zvtyaFHjT9C1bIgU*3W#MX(leocAY!bU6<9r^IAe%a%IVC?%ZOzVoua zf*jomxk827z^Q^OUQ~8js%RWwC)#j6k}f{$aUjYzGHRcixUVolGL8mqL$}9OBb}K} zOZBR;lahm)?<>h$8@{-E#Mxxcq-y8&e$>sf_M~~JA%sGfEX%FijfHmeNFJR#f7@6s z3iWB$ldz9nDZXlo`g8TJvie$=B2V5}SnMxPHdRbE?8v~r>TbowM?E{wRk!$}R>UpT zr7CA=g9a{1waG4rL!0B@n^V?56_D~orBL@*P*ulfsOmz*$jRlM_T7-1-14&PovKjw z3R1mpVK!hp4DXJgJcVnZDyl?v0ctk2>)P&(q2^eU^fX*|jE-`q*RguI94tyVhB7*Jkzx0` zsn@p7x}0))xH7XW#$8z!5iW4AAd<=YW)HOQ{GGFkyb)=ln^N10hDAP?bW-}+q)R4H7Q9m99HUvlSl-qp^RfkkSqJusOi#914-1lvEMX| zDm^_?Hn~+3vb(5_8eMJ-#4b8a=DH-EzPH|?s&&s6Zu3R!&HD{Rk5;V8lERw+mFoJX z>XL1)qq`~H#g%veRu)Oy)MlkGsJVqQ6D_oQ<@C2OoFEsw+BQWILnlVpiU4FBU3N za(UPJ_&{g;%4F6Padq=>@#f9NMHNBWHy6uAn6^V&$yeSyR;G8&RJxQfFBVU3E`Hpr zb$Sg&@SYXV&dp=-oLc+_h8E42MIpUhKJ-%)wB_P!2?4!~RapN*mZ>#APnj=+#A3=` z@%MX4y{Pgng0hhBy|nvLvOK-H*j+TgG6b+8()4e{IE$80cnS9X#S=IdAAc7*q=x+< zfU3NCU{U0;0}Bz>Tg3Dsdin7odC53LRwM|4%bT4=#3FBh@y(L7hQc}0)u||7Xp3)qth@{W<5@Ab-c-G%lf|W*uDM;+T>U0BYAeGuWN(7`l3JpeT3DM^ z&V@*lntfmFu?eC`q+;n#^J->2k;M(TGt*AvV7hj1i{tDBo zpdRJBo!hY4<~d$k>@5~c7>z%KQAVVwpr*mtYBo(eOSI);1+5+9Yz+EftQ(_w^m8ewXwZVjlKez7g) zkR+&G;NtXj4Au~B|>MZST2_imzS2Q z+UFO)m&L>E;#Hf9)aj*z<)tO)f+59=;HBu(-^jPPgkH-_y`^fIqST9;%GFZj-$5KX zqJoeCt1ja*HaK}%I?`scT9~6PZrhvpB>l0(anohkQR$}bOHzK~SS^#ZOp8TO6>V9o z^w4nWwN(;vv3#mc;k+VCpj2^l-f zhmubv(os`HNd>fYOXrr3Qg%5;5|t9IT(&@MDvvr6H*>7ExHPl$e}!M_EqwhSCD5NH zaTtob#?43u8i?6SYH>a$gSusLmEve9fBS+&gw8S}hV1!WNXk}DoPkdME|$(Mf2*`i zXFspPke6$nWHPn$OyzPF2UE+%3Igd*T26&MWacW&Y+HwA=9UjumX}wSqbtE8R!44;58JZa z(sCbW6@@_;6y?%464UO0z#^Sr{)0G)Xl2FKaMo>({H}O*v5%&fk4051pRjAM9AYj0 zXVs}F`dix~Hf*gd;;$TuH$BSBye`=aRWtq0%Osqs_~n&iW$22fR&T0e>0+AYba|x| zE0l4Wwwh|KtBob>iC5peP^q#t-%zwmG9eWy9QDR&Y}B+dtg}vsES(kAume%>zpcxC zU1={@E7Au^`YTm-I#NZo))qH|z71ruV&z!6S1YY$rcIm)*bHcs-7uiIIYreC(M9~Y zvu9*#Py;|cp+&%IW1T(h=>B_FobJWtDR7vb?G%&SxO-sM{#nv8{+c@L)9RGC2j|t<;cIG zjN(BDVLFr8if{$PKEhW9pb7_;T2KtYcW5R<8F8!tAOeK2?R$uT9s(A=lLC7WAXJ_L zbrVw&elTPGgqB2{KV$R-PB5|*$es*?r2;(?I}`gFqkzWAkVC}-&g}Ic z*a*Y$o5~ehVnY~Gd{Bc8;7hynl22Y}KeR=KpH+L);6W;h;sC`Yj;ZFt^ETlyKqV+T z!Xxd>%210+OlZ(Jj-V?3&l+P&q7WF>mw<*nc6WirOyNx@z%#j_=GYBr%b1Z6u5Z9ftdrE@ zf8uz8eh?ABM_3>1jd2+xqBhB4uFX?HW_6M?-rGG8NMlGU@xwHydD@(XupUu$1P_(F zfbMus_Uyw_u5szcL%R=3>;xbb5{j^I=qK$tCvykRG}wJD%!vQ43RqF#k?e%Av6H~E zVpq7HL8)TrbeF0MSSP>mzrnkT-S1NeD>B@j3TV`F1+0v7445_iINJe3gQ@C&)&*x! z!R??1UIW*vc7{>Ge0i!iMzMSJU>9A6!Kq3QtKBCuoCYz%=8fUC`Q2}Kc0tR~LG>?c z#as;wqUyktLquf#D4UV%9020LrLxZJ) z>-BaJ-_@_dCJ$vo;g}HhAS!l;JJ!-bVcPgWpG8w(q=|Ma7bGPq(2w+1`mZgkenRJ%yzC+Tvw~Xrl~A z+dE{TFBF#TIyRlAt9GY%UTyDincsFcU-7K}u!NAQgHQj38< zRd1tSViQ>b5h%j4Z&%xaxWlk`Ffg1d+F1!(Njun*o&2g(cwVU_;NdV zcD6yKvyZ^OUAW>HRgYO{j-_6)eYmqNF{S|(@}2fb0nJW&UU&9O$sB&6geM7 zlHEe~wwrE3&X3w$Ok+iK%cdNA-IEC?A!!W%u zl-G~wZv*O=2HD2|VjVB;Hc+J^!}@t%z&PFvs*u6oI)Ggy5Ji}`h8riM+KMI%qp8t^ z06i2sH$GwTN5vSp(t%}i$qI-kjAyt;OgJ$1YyHIcTpg?racWG@;d&t^8M1D0js{pu z0jy7QUI<>bvMy}^k3kgNg7BTe(X@D zwXX}bB(`~7QG9u9DJk6md4`asq!j#Xshi+}p@7C*d;)W1|_v0 zP(`rEK{8K#vchmRbS5Cio)h?DC_=uMKWuDUxDvHW!i8xZK`2eF3`|B`qk6g0B&m;M z`bHvOW|WAXxCXq2xH%Q1Tl+!&E$+Syt5|@nrdI85lw#|}R%|6=lvT#OlXQ=*<6QDO zazhDex=JWjC@5Ps4%UhDSAqm<_EAW}kg8d>SpeBlpQGkenyp>WVGxjHJG)^P4MLYK z)n-y_kmbY4Dl;LvXcb}HX&Cif^UN^N;Y1lxOp4n_^&FHMXCL8-i#FaYat%*|UG)}Z+X`Rint}G2Q9CJTJ7hvUE&|&SH>}mem&ao$J_rjTT8Bmq= zRh`__^tvjK8(miW^uEpE>Kd9>f}1(?-ePA>R#G5zDpDw~8aNPaxL=9>$uG6Xv)9YM zDElVKns)4^&flrX_=ATnC9jIjpqb+1N|VAzZ&u#@w@_rMmO3`}W;Ta(cipv16lT(7 zaUpSZfo=iCgo?EqO^Ya)FfpM~^c*VR;5NL(Jm*dXjyiUqs*V+KF|||d*2;z?T@LKT z6fSF}22SVXV|%LsW+85xCoT`IH3Puy4H@Muj=STzC}Ni5##n2Y-$pI@q^^LIhMPQ& z>vFv2HD!Mo?b%+*Nodg=U1=m&-R;#KaL)4yx5+9NG;4@FVbIz>C3mB-+P+O!hDoep z)9^Tx{5aVq+UJwj)A2W9Nh|LS%$r#kHCHto$>Q-aWVC-JW>lQIwu#%g=_-#z%%Rxb zLQIF~scbQOAWcJc4cObYEA9_qi)PKMaFX#^d{~l#f{TY(Hz84{aw@% zxT^*>1*yu&lyau%G(77!o}=ht&uLOEy{HmgjJjzKs>~Rcaf36lrxuuTbW$;THQdG} z-nl!4jJor3?UsF`6A8bLJM8wIo_Y;w1>cwz;nq2Dr4eD>ndT%cQH5F|ojt)OhPS$_ zifJlhTi?BP-8)%U`#XDPS?vF`n=Ay^{U2dux4RwNHpP=Z9uLi>nJ|>LQ!TUWH2Z|y z6SkF8#tv;m*vuVE57&26k~eNjD|MG)N3?Sd5u0eJp?a#I6Zyjeg~D$Ykj61P_i{M{ zMMc+A#grzKGy{y}Eb@6I&EisAB`a*9PHUnK-Q<21q)cmJRa=F8sh6+T+t^rQgLXM@5ZVEQF&mN?EEFba@ap|UT1Ibbq_ z^nhT7N`;fOmkjkL?rjXcTm=6UN3#OE3$SN#2!;mu%g^v=WoR#w5}WKckfV?>&ooI0 zUx;jjz6!ZIA8ZZKoPcvq!(4El;IV+4bsQjmBBO>~j7BamF+byPkR-uNqe!8pB(d;4 zlnaEh&3+(ONM0=dt+Qp$IwSC^P*2dA)UZaX%?cPTk=(WcC{P{$ua-5Pp<<2%tYwu8 zfH-xTMx=`+gN81e(i3H$7CI(qD8NZP*T7^<=_r=Ea5Y43@n&kg>2<(vH`P_23_!Fg8 zVOu&j$0Fy0jp<@fryQ>209A4 zv0LUtG$5i;)C)#3K{}y>l-i{M+p*9CM|U}{07Q9{Eu+BxZ0q}!0a zR3Tm9SBopyIYh2o!qjpXrUOy65#@X9Bc1qfhKcls8xZ%6f#*;XkG;xDj5G$Y1N1f8 zPU+oHQBzY;%Jq5HUcI0TofWsNEX^dY99Ef$6*8qvMb9nr-pb3>6%}X2=L5HvvZ9a{ zvnvN8;1>?B=K-uN4{9tv5$0a#3;7EFi2)K;0BaX`t4lQfGp+Ts>Y{6+2jU%u_`3 zvO!4AzFZ}@80JiaZ(yO{cr&;1ZPKqg7hQx!t5yz!v`bB@$b5F&v21z8jpF1`S*A8hXZ3h(RU)gRgdi!w_vR&j2wzExQk$t&nvE(z7^|DcwY7A; z(5ACmtjUzt=={nXu@EDAfYtBBGPtruy)}7gP4b=(wJBLNqFPyM_ z==qhp1wr0c7~nmu+&8T9gsor3*qR z0r_O)8p7@Dyb)lfA2^iR8)#PsT`}NR?HC@OGKff`E(Z431+O#G3Re32R743BKcK#k%jGt0`g{$T`NW2k5t=tY2&q#4M1P0pFuh`MW z?QLZ`jQri5H@?QE*hU!vlGSz%Njq0bE>gSONPbQz={Em++egAtcM<~xs}%Dx7(lvJ z!@~_d=plgK)&LUVzimyJ;I!E8knejH#D8zP0{XU)0^k(48p8#F_0N)2K~QXiFk+L$ zb&-c(0}rY~NNnfm3%l$>-w~+IAEy<-=Yg_huAM~bw-ZEtEi^NE7J_Jja*cpW=qgZ1 z7j63X_IGcgpT%|`ST&&R%C-`CT5KJMkYL9yw%CN_Y^~4C*6Ah)^{e2d?OddUZZ6ac zmLv;b-J}+ZFPk!C^5vi+AUkdJKuR>odBTPgCOfOS(BoJk9LioxT;jn3k3o>^48zqr#v%QHF;yVyhLxmef;H=al+fXm`)4I2DWYf93xt7NEhn$KaoE zzHwAHR>Wnb&qYST3TP_QDmhYUiWJ(B&_|fF4#sxFQe;SAuL176=&VS4V|4{GJ7G@Q zDbO1i(JYKt=vAgOYG$FDc;s@#Yg$yY(xPkk=1`$i|oWQAv4k2Uw7{IkvHU$VH;>c z*NZ#f1Zx+kJWb80ty^oWhLPAY!Zb2OTkBYssIVo93tOv2rWiZ3M$`nAN{~R;O_dbN zpKftV;EyCCl}u_j;67p%5*BzMIAHq?4ykysgUT8^2id{lMcm4jmR3D z8KaIQN-g>Zjmz2}Ch1Y~1fU=>5)N>E3HOUv+dYlW?O{tG4`-LFxyBBgT)v%#Kzg;t2@BTaR4$;Yw&dU+LaUdk($g`26Wi<+T zR4WGr3B=h8MKauzF&{@a6`m!iW!_WE|JE@DXI5|_#3JBIj;`10m|T%+@+fSlNRQ(h z5f*a%EaEJR=EPbYuXzc1h#*9quT4(Jx+0+Dbw$BwK=7{?->ZWN$5;vEA^0FsWRWr> zc*HRr_9S+J#K;w4v$)(>P>7%p5i>_=v?<4tPA<;C$dONFtBZB;N>_Z4fn$iL9Win^ z34VpeQt+oHTP0{(E~~6C9w8h@FJwplnowRJK0Qamh;4Amkxyh@ML~zUh^9zx7wG_1 zx$2nl#fX|@K*usbs@O6LF~Xu+>10GqY8*MHL={ORIIPM=?EfBtUbJhs4jEiWU)J%NS4J;Z8-Jh}uv%@i7O1 zx~o%BiriJK5Vc#&xF7jh&t+z-=eaZ)LHu5&xomchp21P!BiKfS&j$`e^- z+<;gc@iatWPn@Z}`Z76+uNk&=$q~12Q?)G7(JF$N3TdsbVI3)~VqMy~2#BTD7RVW@ z)o;uWmW|+2xR-KA{4WYr^cDGsDFF&O+=W48AoL^>3bSJEQ1p(~DI{6T3qi5kUOU#s zjK5h}XCYNNZG~aTS`wv0pj%t96BJ`(860;kii0-GuaywDRUh`52LVRbvAjg!<$Sh z;>dyz)(%B0F2(xk+Io9E{6nFZY@m$QT8H8fl|k0y8qv#j>}r8wAQt8Nxu8Aayj*|d zL^fXz_?Ap8Nr^YP4T+Bt(qeT){Z=-|3Kf;&Ep883ro(z4#Vz}>HY68?IC$oTFa^=8 zmx@{Or-doJ!4YchbIFNAf8W-@y$Ip;iEf<`Yf_ZU%gnU);}yA868}37UYk(SNXyp* z@CY}RisHo*t9rqRv}ix@8Y3++aQsgaF@Jy8JS|Iqf@`^Z0`o$PVPY}Q>(s%SLJSE- zjCSe)p<1m*VLClBYi)*B>gbQFUb^}(gkHF%NF;2$nO3PB)$1`F zuJalfM_hS9A!{tKEGweyoSXw+5Le8_6Q|pFq<-UH@!(B_EFbJnQ9i2h)5eiLm~Ruu zvaF8HY9*7_NKDnbW7Mgg*AY$I+15H6tw_n3vp9Dn>_O|qxg zXE?lDXt7c)h{PE>99eC*>s3am=9sl)RyE>Pe<3O{v7PV4T)%CtA1PQ78TJup7xfKiIuPRVV;hd-+S_d<^e#oKC z3i6jyo&U4>mvUS2qi~DsH3YAV7siB#waX# zw1q}2BJ%1EEJ|Ay%b6WQo+5UraWJ{+g#}EGBHKui&eh9UrXq|8JN~Daro_w@rBc{8 zbQ;tl#Acn5+8u;_d1!{E9mGDjE5-f!X@kMo&1yY|t#Yo8i>j@Y5yNF*_^pttqprn7 zEc8^ick7_ii+SBPwh=(__0YFZ*tEmn_YOdsFuD^;aSk?GDx+#qZb$VPs2F};rQ?0H zR?}xw=``VCYKfw#u~5g6$!ZI3wEqh`rkbwTo+#!_aIxINLpH`t#`xynT+i!U}0x7^eAccc>vR$-E!ts(7HM3;!BZSLm8 z`XjU5*`5;LvB9C9hH@5OrA0`M$ANaP9}%(K!r^n2;J9*zlnFa4%IeFGc%p{uqhylN zyKlw5w;g81T@LH+L=~xAu3Ll4Y;RwPpfHhUoc%3anxB?nl}IohPw_zD!+sIVJx+C~Ek#z;N%k5c(!nZc72npvxqXJao_ws~TYAfD@A4Gi1 z%>${$&+;^Q1cC1DtscY*Q=@`7TYN&%Z{aLk-K=cTPbvKDkh83;$omvgbvJh^l>{xQ z9p^*0jA!>9Rz?IVRS3qg4Td7>Y_$n|4>#@N_Vxi+q=kdxj;#~Qm#2|Tk#wTq3U9Lx ztnfN8*S~(C1XRn2pF03f*#3TZ``a)~S_f^x0Fq%}%qqg5aja5`VHxPl?^vP=9bgm18fNK7xw9%#Dq&MHbYX+byh($Wo3Co{U~AJBAo?$! zNZG%CsOqDoZ75K>7D?}{a#*VbJ7{lCi%z-^#}&=2BqEZP+6?czhoJx21l%~V3%540 z$$e~cNNM~Z+&|j5zp()yh^QB?Sb{{V`^9E2lsw&l-|@!%`w5XW0$Hjq0%13Fl~*Ve zeh^{;?56r)7nJuwYfOh=)Ax&wW0g9HQo)`CepE7pgc9B&B&1ULQ}HUq?MiY{DT-=-S>V%9zX8&Pk6h(=9DR7vz~e)hT?A=r%aDvpi%2wCr(T29#4N?#ZCsi^XG#)jccYNpQhTRj^+gb`%uTp62} z$Eq05`vR)pF0C2ai`$Ut|J zJ{{Y;oze8MM$qK)8Oa!49Csn`uKY@0cm+Gj*BBr&WG_@}7nMAU&T1Sjp^pjF3UWD^ zxCG9muFKUrSR_cGE`Ch$`x6SbeND1s^)4d zijZs#c+hnBwY*XyTwydu!;5QbZ6gUSph4Y21GLZQ z1?x&BPaC8Xk8pZztTat#t_RP^m!Luwz&7C=2kx)M9<|h{V*x1VO5&GoI~rwH)9|8ek1KSpa?XOxDlojjGQ*V3$W;l% zuAONw%F3l6#4_)?Il6&Pm0bIY3!bS+DC3vksa;noF(<3F+48Z8ui(sS?=% zwsg}QgooVNn%b+LsDbFlEhLc2=;hrE@>0lAuh2q|w|M5-tjQ{uy@I<+$oa2dhX!4* z$Lk|Ojxjb@ajW*3CXhA zAzokBQ$kh=^%4?0TYP__k59?_mfFIyN$WSGP&S6T79?|-E(=imut;t%DyU|a_hl-- zZiB9sxfC+egFZ`*TU0G@OFu-5>gEl(YS;fEWoorkH&P-s8c{ty%SKTRY_zmMjpgQP zUH!7N)}R4%xokLUgF=8dSxkBP*ay zu7>xySv6yMS9a};f%VCr$QF;=L3^cXOC2g`R3mF8jq1T71`&IXjZtgLmt@)VaNNwP z$(~a6Dt#l<4)}|k2AM3!(u$63qGJtX#n??b8u#2kSx$BHami)EL?txDuFH*0d=&=f z5_hnYm;ae(da_)o8tLn{V+q~RTX$LQrG+S7)&kJly#7)PzQBarK*leP%LX`Gu4oyf z|K}RHnZTpF^+F-=(1foo$#WYUG|JL_$4<-6DZe%Ydij z<(DCY^?@i%oeM4mG5|*g|v05S4+f=#U#!ChfFeU_OAQ19 ziw)RAN>2;ut$rJn&cUX$mX-LxJy$x=8hIkaU~H__wH~;8N)GALQ7{=@YGgW64+?&-@2WG3u8*&ap^w*AZRztDkc`2H^ap1CJ)<_5{ z35s>rqfx$@W=%|2xXR=thMBc;9V?0Q0=zsoWIQjz^B#(I%3q&uri8ePs5rTo|5#{h zVk*Rera~~i!WD&TD7kBnp2*?p6eMdN#w$o=DY$fOb5HhBmP-hRi!>jjSf6p-v=hy5 zHfC(-5*1L>Le^uso=Iri;a*MS@T?Dv=V>J>vV^=`cO|N_hKj!3%wl2A$2#t=u!~hG zm=3b8ex@JRkMIg8OMYEfeVmV>O_RzGP^_~QgQMy^_ znOa5x=3A}Vn~1<=(e>A}hgw~GH*8w0f2*l8o^9iUX-LvjF}=nfn_dgyMAF9o$1>5( zc%scr%`I(*VCDKNGxP>2Z=u!UE%Im8&ACF~S!vjrZje&m!ZiJ8GN@|*cU;?&?)TP($Xez zJPhCxJke-cfV;x}8`z)81}=TtjE#8>4Tu8AGC#yl9 zdOEOe|0*Tl-DTqtyS-(?0sZ>-LWn7(6Xg4&W8*ikmnN;!-xz#Z9v^TF+U z0UQrE-yyAJ9T{+~tx#+py#zmqqw2_( z{jKlpN^SHv<&|SI_utre5DaVw>}8pypiL|&)why>T_@)K$g^Hf0L6ZIIY>Y#>__xKZS+3|D1&OPZGH=^>?4Fb1kN+S%l$ zH(y7Mw1~moz_bi_AL4e1Tx@79q1}rdIIlq3s6ex_1HiY02Fk8Bq)|4iq2_bww|Tz@ zqn9FssWwv^%rB^a{j6GP0V;zTnkVgWqv>Eeb>%(H*#mt;{uF)S94a3nIvcO=ZQO%B z|A(4bVIQ!y(K_k5`y2g@1L!s&)hfvEEodWev2kRcrDg%#-{@|f-rMMH%yunVGij6l>=skJ`ImxYQa~S@NIR`j)uu-B4DF5fJ?g6(+4p9i+V|APOo%W&Dbv{~?;Ruc zz3QIaUyeipf}m zsy)>Gjc;Z4`01#BPfgoXDZ2OnV16bv?+%RHa_PoBXX)Q#CXU2)TaQ^E8||#z-Hju& zrXt*B{@K^!~;WI~Na{OwqsEXr**TvLJ{uRSW_$us527CG9*2-YD8qhMeRlj;pM6GK zak=!D_YTCB|FieHB4G1Z$anl#2+NDn_lqJ+a|QxQNq$xngol{aQ_xl9D9U5jbKE&o}_@Xt*XRXsS^BH{7D&zk=^# z@z;rT)C3J>Y4B76N~ao$uzZeE*HZ{m{U~1Opd#cFLkNy@)0_jExY%Cqw)V1{Ba|{VLWJSDMu`2E<+9tBaYy*=ofSHImo~TljU==9IWs zz1R>JMp&X%B~F(mMth5?3IXO|qO^i_N-+NITnThRYIy|x821kW*p8Qpx?O2{guxdT zQH#+yKM^z47|kq@ZR(Yfma=iJ{f-sXWWysir-`&+oR48g1&ggOQec3HmRV46uHFyB z2ehObk#4S8boHXz32*7-&fP(PsRDchNbCma7Ym0W&?LDut?@tGu*R~~%jAn#m49;i zyen&>*$q#-BC5L0=!N~MvP7P^o^=5kbER`rRqUj?JCKrTh^9&_OTw^D3$3%FMd{gj zSV%VQ@rx1APv?GxeQkABZHpF_H~8tI*{HI(`*h3UVmQKRW)@23w4r64oM=?{RjMEp z^&&v^#QvoaC~1_N{rZF+E-63H zP5fwPa;Qhiu_Gj^r&Ekew)dq%(>}63G+m3|-(i`eq2x=M8w-yY9A_t@y3!aOm74C{ zliXST zku2+C+gX2*+5XBZYmvmzoTpStq?I;fX?edgWi@xtl#uk}9>}(~I2Xbn_4_sCze#sxO^2_#i>xt}NB}1>;25j6g}(&D#L5h{XoI}Qnjk>kh-Uw_{fiqg#o$#H^4NWKMLhg$WwC5yStCkYZk23Y%lpAm zMu=7P)&avvGrHja~P&`#;LXMLtNQVtLQ1u8$pCAHOlh8ZX;8Iv*8Or_5z|^ z$N-ox?NWQzr;XCWK@rcJsDjQng>n$KJ&A!MSNU?SxBfCLW3gt}QM3Wnhp8h1(@8;4 z0h_}Nj~+{j&ib2M>$Na8Q?V*jwk^427MP6xWSseR%%Pu=NgB8kT|YXq#f*5Z-x7Z5 zj<8!3*za<!-H@9_|AP3(tmk&v{*lbE(){Yjctk zHByvI>#t!frsD3o2ZCbtmIA2^Z_v|Qn7~kLb?X=@ZWXs?6E}rM05FB1&Mh{8v2eQ8 zzE!Sw>S}0BvzB3M6?Ci;ySHk646jRUA=_4+_rzgOg|E*J%eN19h^=wE} zD!*S_=mhEl&e~IgFlLxaA5DMIk>!~-L2;{7=j+3rDJI!8;b>92NI|QEm-S+|eyej! zfV4P9uVC6*SZmh4b!74$<=fe9d~xUu>$Ycay)9+Rlyh*aYJhDR*Yf~w(N^Ghiz;Qd z5)sonqmcjPnDw%sb;wpi+}L?8S=Y`y7| z99fp#*S^Faxd5o8n;Z>iG^3G`G?6CBXeO&d?wP1Yb|Lp2sHVQ@PtZsGt&)sJ&C*?k zHTRUx@7()5qS|B;=^5dE-`(DIPxv|aIgnQ|th{uHIMJ-=bRnN)`BOwIH}tY_^Rks% zeyp1L(oDycYlh_Rv(V{u^j03ESoIRs=k%eg`hNN4wT-f=R_-LFSH1Ft1HJE?m!GXG z+_rkv7NIpOw;}sd=Q@LXN*W41ull6@3e2-p0&6u&imjcbWUiGNr?d76OtEX=05eXb zDlXIVEKPXs%NZVaEZ%!rr`C4mp7~wrD~2}e$Ih$7SH5s0eim0~oFuK&qtMY^Ic+Rb+FQk;-muk@+%6vm%OQbM}sy=Rl#SCg8I}h?@!0gWQ__P z#8O|={;@2Y)xR}V4?(6XbLI1#Q}xrGSt^ZdBfbTZtD=R(mx-@SJ6`VFw|`Gy%?$=o2w(Sr3(dR7w;Y@Ca_pVHgWfU=s*s=*i9#gZ9aPXe znV9XIzNyX}dYxr&~mMV1Qjt3N(K7-v8D^|VzVhQW)zx&`g!kRwz6@j@( z5xMY;-t-t(zrDYDE7cAi-{3>vj^7fXn+SraKflmnS|Va?d`!h2(p>lCx;+!4$p|m3WK3tG8D+8OMsp zx%aBRdXEV5yz~|WDOc*Ndk?LzY-$t^U>8%>)wN9Ot)b57Si2tWMRj${ejRKzRMV`V zzSzP>KTmJ3`d14Qt#Qq-D(y5^)w}82N9}8_9yo;0e7=;40aoj`Upzt^j1I4=OXZ+n z91;mzMvbo?FRzpZ^2W}oM0;1Q9B4y&gxX7)c&}gf)k@!94X*B_{qjI)vldmv?s=JG*D`Z};s zdOD89T2?sV|3@H1nxHcqUS7-fI) zf0>BielsMo+P^THds$u#z~v`@dQb-z+rhFJHc`PD25#S(i6p!8Fa$1ce$II>nM61t^ORqkYd~qFom=t~ZII z#OQH{I+{a>!MgpwHQQUK*`VEcHcc{SXTJ^$LystntPH;zzAWr8CY&v!&WWr`dqS=p zOnBW=Gx*SGBH3VqJbizyV7o85JZveUV5>8x_>CR1m!Z7F@4G_%DqOd-9n+!_&Q_i| z3A0zfFJN;5BPx95jE3Qsb^3Zi@+GSP5&Jd->{)X-tvJo*^PC+{V#0(&FiP#*Z)1A?CD?eb&s!q&qmbAu0VEu`YoRf za2c^OydjK6cQJw{454v{mhJ2xe7hERZIY)9SC4caZolJ>DN!5l%?I4~TUJ}&rjB%H`9AkaR&Puv?xY(4E2{*!=r(advTDsn z#9Qty?_b7wd}TkUvX0?~a<6x*?S~$>D~XyK#Q^ zUJfGz{;oN;QGV;Lt8vKR*W7UO@J?BPjYrRl-zzM&@p-$TBRfJ7MqukE5spW zf}wI*Z;$j%KLHtZ(XsK%YDG~quwHRIB-`%z7JDiy_NxUh;BL2C@lEY>4b=Umc5%O1 zt@svxK_9x?XMND^wh)PX50pD``}i4E5nz! zR)bi|>ZU!VniZ!+C<=k(ZMlxth&FP#TKU<&YGW<@QUZy+k}Ra>sRIQj}#8doLo8Fld^tva)k?K0wY^A#J}s<#SzVE=H??A@0+*2Z^2#;)J#pY9%PXHPwX&*T z%D@7q1V~`$Q)pOqhV1@i1tpu-vx-*}1} z;ONI}e(LiqI{N=hr|%QE$S*(rQTMZd%(uQYKk2`PiT>*RZ(Q7^ul8#p0^F8MZQgDh zV9?!cIKqSADm}nWYWEym%=A~8llWwuj{}!ex&zSqq0u(B>%loNnl5Yfc)Z8x% zQ*Zy_;@cCYZ(O!Z!F|kvb6wne=VH?!$He@4L)Ed;0(RqaX~u*yug( zI)QE0y_p*H&d5?7P3azB)Pukin4p0bL3PCQ05)Q06~VX*C4F7+J**x9Xz)tt6o$tN zGQpOGXqHCR(@&biSsVO>RAUY3qgESspae>hnxCVcU8=Af-go-%$cd9OwZZzQ8_D|RmUFkP(t%xbLtP7f37o8JR_+`C zTpIk8&Ak8>fg0$}yUUa7NZAN?GEn($Y$rRW1xGOV?nj?>Y}*&(6NU|j@3^y-Sf;k; z2_O?udE-nQt-Er2B)283O_Xu{#}`H}geDZ^qVHbicd7w|fUe}%2rvb>BpZqi?`VYK z5#6p!E;V{>0q2uKbKiP{<$xNZ?LRRu&w;8AEXzpE!aHu%b+4>WY34jvDR>5Y8HRBd zAQ-*Xs{U3T&ISw=eu7yl;SN^<5bU1JKx?tAO#7D7JUC4K{)~N=p@tP z4K76cxu!uk_mbncaE9JnTG-`?w!<=WlEo3@M4&au-Y1CS(|S=Sp{!53?($ZNKH!}N=_>~Udys%o2>&ujBxs?&%FNoXRxAXX zHHS7iB5w=_2`>V#sjdc2ld&&v2Jb%OYlvR*Gj={a~B(Q{fH#8Al2O~GfXEA{3p zP4N>0?2a%_lDV8XQ9w7%)kh7)2M@_L0|xshKwgHL3|v)L>8jQ_NIbE@>g`P=h?aOm zV>J*GuYL?jq)*EXB7dlXOvr-`&lIRPT8yLBIHz^fb z3V&K)FoRBgu&7#ylh;fryXe!&g4wQIRM7$9$r13r`H@eT5g;X|N&i|?p{Nia2F!I2 zlBJ89>ci#1ufeYYI%loD`UJ)W$fX~h1Y8AN5n2vGnsmlu-oib3Tzi1E<1Ck@ds|4L z?=wy~zi+Q5S9U{%tKWK6m%2bz&d~s2*&1ClFf?0?lCWgKqKrEwq)EH2-}zsX8DyOOS4RE0 zXMg4hp+5QF#u)(gUI0tOU-P|;0pJ?GqH%E^9`k39Ovo=mu4uBJL7$EzE#&H(ggWJg zA+XZTTiSj*;LSs4qoMvo_5 zxK5pZ70fX^nG@$@s(uX*D+J?}rBBpAYbx>F`E%)hG(cy}&2Aaw&1`p#pan$6P50>& zb!o$N;yQyIq2GLlBgPzhB1(AKuu4cYF1sDQ9CK>3`Ep)~6?n>s%SW)~J^p6sI_K22 z6!|K?+r#2BjpYt^5)b}$mV23e)^5#|C8Fz;c;iE}^*ElGRPN$QP6PPgCJG~xv!3As zP=llMDlR^gSGg`hnw$s|2*qn#nM%k}roLJGcpAoi3)tICl=K<1O?`G$n|}UJoN_{M zmx70WovHBXSx%#(JQHpHM}2vL_+1X5LY~Qi?9ujF<6?Hg!b}<}6Yi*Rno1TvoOL}d z|4FC@(Rp3{{%ej=FSApO+OiEiTTCC=2_WC$-drWJuh?9PgU$0eTL0t8yR-8`qbaU` zg+)&%=?s0xDAYaA)mLtxXt4;v^ zZms_wByTN2Q_c;L? zx4~d5R2l5XwbjO5(f?k?{o&tn@ISKoDiiUa7^oT8RVu4p5BVSXrljnug}nOx|Hy~` zJ?&dii9}kP_1Er26>Z>$(9kBwLw4%#LFxhQs0cZ=F&-Pry`0=!x`nzY}3tFz&)bwrv___^HLN!gMK>Tdn-~~8d#O3MB zNA*nhAxz@cbtXz*cCfiq30^?zi@dd>k)QCR`p#W}iu@(u^`~$HPjKUN_+URsP4%7K z7<9mVU!xYjGa(Z_qII;Cs!><*5ENQP$@nwM>zDoS?o*-j@y++yVMjLZb4>eE&F(TD z+)1>~zW5$$K-es5^aeXuciDHMi6p0Y{5&V-eqk3X(CV5EpA^y^Atf7BMK7r061$PmHO{WNA*ZDZf}!iTMv?A;+`@E`GD4>SKI_g?C5G<-gn+2Ejb#mHBB#K zM$<#bE_pEpK*3Te5ff4aVnG?4M)mRzt>nu6i0<>F`cOMouHEKWx)vpw14_G};d8la z&8`-7dXPyGjrb-Za*C5O(Pr@d0}gb?vxCokLQhb3KhlsTeUH0R^P%A7#E)vYs=(x>Y~?|4KIbx3it-P#T3-4vm58V=k5Ln$ey>n;Ztm;4Y~#GS_Z-g}JA2VV z*sA|>&TC&Uu+TM9hH~>Z=&x7CszVj4_>AwV_N)eF-myvG(fmRW#~hktHCZQdvp!35 z@l(3%Un51V+BEAYp>SaQvX&0lnu8Mj@5~7CH(lh@_8!@yHDq-*Yg{H#qN5c~AD>^P z1(Pw0g*PH$DL+}UnCU)=EHHo2U|4RHuv*kdr%a+>&kLjuH)e{JS=H0cusSaDFI~8X zx%y>~Ak0BPs7UPFE`RmQXBsW`WmO567hhpSO|kNVS0nis68J3ymtPdGnHJL~^@=%- zl~t%DDb{A?<&tu#T1q*kyCXoVRaic=bn*ii)6ct5K80F=T~a_R^{NX07*fl*9eiM`fgVsM%xU z2!B~hrA0qM3CSxcAa=T;7vnD^)josB{@mL4fwMfsd2ihuRb&hYEMe^QvD#)%Dt&rDk=LqGstKH(NQyH zi*eXjAr~wBTewm@_k7F!m4($lS4%nN$;uqu$)Mg=`PB5UCswP9U1ikr>Yvx7ZY`DaYt3Y*w7rJN72vB-gzZImFP>}$3y{^Qeh*|;TTuUD~ zWZ>#of`x=C#p7#4SH63KT`^>;O&iFY(MNTn8hjGI49;!fAElOs4$<4#=1}^2Z=)aa z2E(Asf?+#qp?EL`QPT^|PTm??5*`-txLr1d6V0yCKB@r{13LqavQjSak2* zt+ep!km%~|5~lhchd_QnWiBOSH=4UppnM1FO$`p-z4XBdw0;B3J_t}1UGmYU(ay|K0hNNj z%{=yvsR9;{d?qCcqk@sMOcQ;y{LU|OI>G1qBB&cqt2?xJfVM^HD83v8s2yN2g_u}> zb5$nS96@t66*8YV@tuBOLfXWMEl+4HW|EB3H66Goj0Cj zz-Sk#c9SS@`GQ@iTXIVEPjWC77`sgk3M8+IK(>Ej`U|-vQdGlC6o7c87>wX65I}6h z-DVk*Y`_!J*(&?;XxWLckZUfg^Jt--=y*^FmKk0O>{fh2+Qom0 z1grD<;_)to<_DJUi1 z6)`SF=9=wY+**{p57675-<_SG%aw@=>oybQS(Q9ewq7goHR9TwWfarPo*Wr7i)7on zEb(x5j?8$Lj#13FRWXNFEc0hFU!RHGyXZwkN`_O{k^?1-Q|G3nZ*YDqSEXEmG3m@s zb#d?H$(7LCT--%~OXrUgtJaTN!O;n(Ls4w0l8$V8C8@a2_8f;-rwlpEOG0Aed zw?l*T>dYZ%X3jpGYw}9j=2_9RcpcT)p8tZrGr#$8epa95HE|j)6YY&>UK{7x-gr9e z^WIrp@#E6dcM(RQWnP&1`m8#?Pwh{bh|T3iOT90~TuE(K39dijOM_tl?ABT3O6VEl z>=@|m7@mJ571qm#!P&#<8K;k>q$Fx%Oet}^Lfh!<%jwza>6rvM@2m4RtY|U~`8rwrH=T3OZ393SA&Oak&{RCE>PtTrCyHi+PWt69i4+j(#HAro1%mNOd zDZhEenU!oc^Z7O-bS|dpPCO9o_pcNCHVmEIMDiQPtPLR-lCFc-lX@{&J?mN@7KqwV zvEg!q&uPN^LPGhL_y?e4BgVD@xA8x*%V@U2^1-hbAP7kYSf6nL#@GKF_6m|tRYIr} z$o3~2{aZOU|Gb+24eZ%Ay)k#O!Z`QK+q}oQp}!#hj_2>f`YVJjCp3QdwJ`AA=-ziU zZo>a% z|N9uNPmW7uRXD3MGiQ-8so=unV&)EgsTKih+0*gv!{pfAYxr&s`;$9rES^{ea!*wj&#}CoM=~0 zdV`Oqd$2egP%LFY_EqOPx^AS>Z_%;&dnT<kVZG_N#4JbR*`1-sq{vGS>Wa6^*`I~u(86j~ zf;BI^zQz}OqeVe{diMIWzm}aOFq23<=&4^ZA|_UBfEXEYVlY}BKwvb|7^y!CgJQ)x zOEKC)nIyys7HF)^n}nJK$yr&##6nHIHs8>xHwE?+D2gpNowtIDx&ZSpg88b^Twy|&4<&8n~eusTkD<1>i(sor|r1lON=Yxj`{|49853%WC zA39Kw>4caE2?Ppv7bxgY&$ZINgS2p9ca50!GFj zEh`I}%|vhwhk9dxyN!fNUTabejTXQfZX(u!kiucYp9A^(Sz3+7=~ul9an!!N!OuBg zpIBCq$YxK-t>z)hV}`^^q^C6ibrI_eb(AF~O>s3Z4Yy(Fb)0HBCJP_=d{zr*7iHi2IY3LM;_%6^>4>BU%*YXk~3G?;ZLjb2hsCY4ng)5O6 z>}&l76GWvC!CNcgtpa)V+m{x{L=ouKlxYS&Hvn(2cT${4L_BfcGVR8gEeI4XchFs} z1^3Vf_keYPdc*M}q1BcLwnmh3vAD*^y;)xUmy!i%0JZiyCJ2Ti7RSUV$H@*ycyHO> zs(#y>4Es+S;|gFfRK!BnzbY&_N zQ+DO);u^^MH43c6S{DV>lj5wB@N=vYa3uB0vo3~ycq9SY6S%+bK+-d%Xt??wUt$() zJUD>0g|)|ZT$PNj4jn)6fDF_7s6h+pYvhDHTV__INtXZ}sn%|6Q6HxvRIT5yF*i0n zNnt_=RqzgL&%(dEb;+%)E|QIS)vE)JPuHsTo_?%jVKsfxfe}X+II>pD&bq=$r^SGH z>Z2ZU?M3)=EunROM3Yo&Kik{Y%mY@bbOIW#Js?%BD`@>Vfn-KkMGgl^BkO!9!F;v$ zaa~Sy7AV0xl=}2s(<1rdgt$&U% zh(^if8l$&f)#?X-@DBDYu6+)V9Co|@w6Ze-$dhJeH z(&YMR{X@=<Z>(?VfTlBk zG|ahnL_~g@Io4jrYyQ{A>-C1ec<#0N#uMYfba+vRud#18@*L+|^uaQ`vfg~{#`K@x;L)%E+a589I)oq++Z8p{wx9r|a z7j;2lyUNKOMxSv=InkVB?l;4N1ab<&HPO&UL;XB-pAcbl`Bl&| z8bIGSm@5!J^Z>Ms-r#*8&g%Y8hhv@u_$}`AOI>b-~Po^dmbfNNkn*?@xSm|UFhug#&G=9fKluU zCS?h%PKaSgGo;!<0&*O(2B1knk9ee)0X4wPit*sRz zO&)IL{U}TrR0gUiS2GNIA_PtX|I>0#g z4$taSgSi`lRRdjw5H95h1-&UKy$mBlW3Lae6+nrZzM^ z0jhd)r%@hYJQe&@N9xn3v(x%?g7ETL?^M6Y3dY7Vc7rjH+2-_7AIY{+<%y25qdx1O zR_6=))|^Q{lEc#kfTh0){gc?`kt4}gXA24=BLbT}9pJ|B^yx$)dfcOwdFSBt@#OSu z>5Lr}Qd60#P8HqhS$o#7M_!*OhU%mNw$-aSt3xu*bQHNjN*5#F4>Cq(J7*PDe5)FHW8?fp7Kct;5Hi>LisR(>uA* zVf)pdUdy(;(!187(aAOL`e=<`I-(faFmiOVbXuQ0Xs2w*(CFk8JjI>Ee^LKnTv|~g^o!+~z|7SKvvl7SAR|7v5QO7puN+LlzWUxjEb6_sUkkk*I z0ImAZ(H{V!uyW%zh6p<_%GPZzK{Acd|Njz5>t74c0S>fjJ%Wbusd|#y1Uq*KQt0oH zC*zM=pJEk8n)H9?2rR01@1--ff@a?7i{9yq15~TOBm-?Lq9uT@Uw>jauJAMAD&$!{!~_*vYgH^L66- z8YRGoLOrdjn9Zb=nDktB!Ia%mFh%Mj(A}7J{nrZ8kvYwfWYS=#wJpYY3?&|Ex95Pz z%z6heN*i_H-DL)}`YUZvIXIG|I&z?~Yo5zITR^ot$r$Ej%z>3wFVC#36q=z-V)CR= zyv2(Ef+bJYb~$w&=Dh8e3{|^NuXpPJu{|YPCgKS6zt=EcZ>PtnscboqE@vIF;f{3h ztXr69^nV#JK73F-oLD}X6>MoezAKH`PSkzu$;`QIV&3#0nCMW&>FM7$R<2FXKyVl( zJH8&E%139>1W%J#be6MI1TLO4Z$I__GKDA7p*K^V`xT9q{^qqCJAq-`fCt#1n{c5k zf&qGTN(K zowt75+@fsA8xPm5DcFe&0ldk{MmLPj+BA%zqPv~-eVJ1Pj#6$#SA9#?TQd+Nf8yr1 znC!3hwF^KXPzholtl2q3Q2xX&?y^ver{Nek(lY5Ab<_)BGEN0*0bU?jrgI|ll{c`} zI$03xY0tcQw)V4b4p-6Ly?s|V<-QS-InQO3n{IA^dF8EZD`Ug8TlVPP>h@0RX7H3E z@aCJTQi~TV2 zAb>-;F&3pHh0+|qE7Z#n93E7b4@ zx-d4~u5))Ub%We&006M5HXeOTk0TM(QXKefNMXZ{KU=@`oj(KG4RD2tkc=A*H1Hs# zz*=%->P7d{`bM(>L}6=oA00Tfz5!ISQEfPqe(}}N0#@#=yV;n=k$Sx+CBuzn*?Nd@ ztiIiFnAoY-zt|xUOxwbM!bxqttKRq$PUCrBV=BdSM|3zwdN-CbCE;bYamO(X$Zl%s zZ+zynM=`F45HD%mY&^aRWj%si)L#6E*N|P>Y|5ign;RROQe&U$4B8PoKbsrvMza}? z^uvD3z!3vCi~Wt|ja&3+SF`EtYg4a}H-2U>ulTJGzuDx;PKIT?@skJW2&B2vYwH1B zva|A*yLjEkyCF*`fdC!%HkPMC&~kTcu!L?nHwo3z#050aztDfJnH|5NItE?b>9rI+ zgj$7f^}UN1aWFe8fp*+omc{`xE-tP>d%B0MmZq_O*I?yFxt?y}xvy9M#jLhXP#T*1PB2NP2J}faf4tu^furZ?!R?gEqQ*Vc1dazR#}u`!Aq4N z^C~@hU0ptlrwx3a?O1g9MptKb^|c#0U*r*<4a*?Lxy^SHBi#%|$5<_N0c1)2s)*{P zHbl9nXqv=`o~yCwHXsn8Tz3-D+s{4F6e@GkPKLt+(2S5YUJ@Otl3t7yN$)~Q5g^6* z{DqBaKgi7}k)Ruc2s(~y3js#)B!-0xupFZZBj54kNM8;#my3zvaM&OZABgSgOf9<6 zD%W93PJOm*x({kp+OW>gXc?pv7NrKjJo{GJS02*55etwX<$;oNJu782jcTOC2yYs= zjQ|E>h~`XVQQkNc7w6AQ1DbBl>9nLYsSnEx{t{JEli`^<4QX%#_E3MH<}02+VbsqK zs!nNJoSc6G?2xGOm->t;^2A%W&La7WpGzopi<$NqOQN}2$k;*_JqLl55`miUn3H^9 zXc8YWw^VWhW|Pu8V)6QNeMFfU(_jU(IX?4QTAxh_AZG$p76Iv!G9jqP z6nsH++me{jiB`=)W>x~*l|r*ay}Lb z;rOIIxeM*paiIIB3(|4#>R$}&=)m#g!LjmMo!;B9%h@$X#br4UPd+1zxVGctha(li zQi)EpYSemoa#N(H$Aap9|61L=*&6C+R~TLX2lo9Z4;rRf(Hfz?juMX6G(WyYW2j*}`mNEDapYx(zde!&)GlH5D&lwEJZ3ko6gP zPp@rO|4lFvbZH-m(Y;(K2LXNiPID5S$h@+_uE&zrY11?x;KSq6;M$E4_6 zIvc{14sXpCU{9CL6@5c6#xMzdsc|YP2kMyYLVpJS+Fx%9lISlUV7)E_f9hb)(C$2S z{iT5DOC?Y3>wn2Pz<4@CceF9g4CD{?>!oKMLbuT)l*=K@t zd;^(GO2=cwig`?dafV*&-2OiU*s|v?F-aA;NhG*?H&G_dg0kQb8vFv*5w?S zMTRn{gAVas(3hNtoMS1^;Rt6%B);v4+MF-Wma#am6!9+56K3pth+09I< zutToey>^If`h`)mwmkJRll?p+^xySJ60=?IQIzMy{MFKbF$u$IEhkPDe{v&4dzxGp zlFk9i&MQD(H@kC@nQwlTE*H<7hH_>^5;=*uu%jSXqx6*FBBcLFN0yknBxSiYMbVSh z?oU2PgGclv1rfP~)X0l%mIbJFzmwzxGw{Wk^#(dcSU&8~qejp=J?;|fFyWfqR_cCFO^mn-l$-4H zV^BzG=1dm)?#+Z)fg@PW=bMO#gdc<%i`+%WahfL}rNB+w)79recFB&2AGpzIM~;qI zC!Y4_)wQpoaeCtTln|vSV$*)l!i*rB6vhhnMqR1vrc3RP#zd2n-#M^dZ&;u)J zIKph5?^^n0Y&p0jvs{%pmf(QQyatCEE%dS!?bPs)Dk~iC=%OTsYPzB0sWO_ONL2R4 zE~GcXeL?$-*MwSa?~z3X+eZM4I{tIg7LW>bwj8dnR_76Au_{ zeB6Yzls^_0r>*cL+pPaAnQ)XX9~a;~HxYIj;dl?Kn$c2MuRjmVrdl76^OQ`jlPTT6 z<=GVW2^od3vnqKS@f#`#d+DHOcWI;Eyg^WJwFZbQ50A91tWdNzdz^F;w-VIndQ(Y& zpdCeyvf4d&crgfX?Zd`qy-D75VJVcg{Z(@Sc@+z6MjFLBx9rGfwW*jlA4Mozb9h4D z&9uMR_!GgU*Wvqy#<+h#ts+vdmm_eD=9rO=AC#+jG~fx}I18^ypkJQ4iGmY#%>W|3 z$G6S?W)k59XfgZ0yz$wGtz6;{A*-M)gK(Ut+Vhq4>bOe?-B{&+ia46 zJ9OdbJ%i){mk3qJHybzj#=A=I8u?kHQ@lABg-R~+qc6^IZ{r`sO}5s?XkOLEaP#Aq zc18l^&2mh$a>vnY3B}t98*Z{#f(OHhqcue~E{qi%1>ijG#_xe?<0S?oA3fu4Y{;@D z@O8B&M>}yXI)ui0y`hNB!&ERH(v?rtFn%xABCy|Ng{0Whrf#OuB>g+V<=4sFL2Q{q z^iwI&=5FZJCFAfgmAa{eO%Xj5;FuH!S6o4eZhT4T$e{@7_s1y2KnD z6j60HE-Xfs%)nUWP-NcI;yF~CzPxEgtfg@%5)nPog076TYIYZq*Y%krZn|P5<^}(< zvEBqn@+ow{BWIOUvo4wp6_DsS=Qw#amk5pVH>8A2n?!1Yb%AY&?tbE-AzwtsSUgkk z90QWonv{UKz`&``UP(=Zyl{Vh54jq`1a_l3zJ}^Jrk)zrhlqaEPD~d$w9wv)Mforz zMG(j7T>p@c6Jyd|)p2$5=VVY!yPUXUW6^{8rs(sh(A}-yoGzXG3j^$qJc57a)#Xq# zeWJ>>fuY>Fw`_g#s3HC1;B&H0gA40w!90?ft5jVdKb;&m&_FJpu@^Mt?Btj>X|x$N zr$q{~)1;j-zSPMGD(bQPfpU}LMHJ5#Pn1OVgH)0WcriVGJUTw*6wqWiqREN8M1|R| z(Q$n=J$;{5pkJo4GDXjy@P=7r6ps`VGe5U{(XL8fS9sLw!=uj; z)@$H?o+NGXb;OYA8YADx&KKKE0+2ZL9)|ysc{wlT5O~$mql9eziIcr8RIlc> zA6526s{A@WS~$8rJUY}{muE4v;o?Gw$xpuq_*NZ#w&0PrM-o;l`zMPs8S~*-M#|&S zVSV^?bXXlKcs%pQ6F4N1bFccykyl4|hexH}=RsRu&VyO?Aytq24 z#_QvIM`2GKcTes}u34&>^?K@qlM$1#aG zW|3FQvRplo(~k#-Tz9&&wUJX}X(a#m_F>`h=HO5-35uFW5c?BMH*-@vKD<9Tl$?gj zVZ^GV8%HK-PngcI!<&fh=x_nc2h~BN_#zcOB9gzTZ4R%y3@oO7DX$NV9P9t(F!dEH zKERC=Gwv3W2nW`Gmt?3In0b!BFu@0M9BhdIWUDke(h+7F-YwRG!6^h$M?gbHcmbEj z^8}g!HRKz<#10hV z%L??r)@W}xPxeO7lVd(COfqA(yw3}@I!Xgx!8{(`W&*Nd!E37`p&7NDgHK9I*E8<* zGLF<=oi7Jqay_OZry(<&6bc?N_p>^Xb_$D~rjvp`@?OoK)py*t_TqVxNimhd-F`-p z*tM}YGv7@c&Gx~q6dqB{7BR|Zu$*MpoD;H{WT{ylUgk%GEt@X?#bnO{ft~3{oYY>t3)&pbkzx79hZ1O^^sCqZ1rfjV7rrpz~d6^Dfb9?cjppR;}yTjROK%}~%W`H?S| zVQEZgpg4OWV%f7lrCgwrPsJ||UaXqYdf6)P3jcmf< zases(sDmV^%Yl&3>6lyII!qQCH%aH*N<@3>svk!F=k!NR%wE*PpMio1G97)@eUUrm=iv2>Dv%|?fSAw$)&AW%o-QU!9_dV7;o^AQ3l!ta* zM{Y3*u{^6Jne7((6o2LW*^V&Rlft3$Ov=~0ObMxEXt=;{{_zu+@k&=rPRoCB{B|nB zVhCRMq#*u%l==A8#312+)G((MMK*@aTDNimGbeVQr2n-uARB%=oU|9!5JCKs$N6Ue zd;*qGxT5JmlwKVjm6)0RS&M%ISxM>pV5aON(dFqEnIStdmpTW-hHEeW{lO0VuMP8^ zZ7JQq%IeqrP0_oHh#dREM2@VIxyXjk@Cl_+@o9;=PVeUaeZ{|l2v%2&eJYMebo@s4vlY z)BRN`S3T^^b!p)1Rr$Lh8 zTpf12)HJP>P6iYt+nuzg7^H4dD14IQP(%)?EVQ+AwlWC*b^`At(vNO}j~2}w=(`!v zYD3Id%!Itsdn%sS)TeckMMclE!wMIzm8a{Utja;Itv|Pn2}`E{PFNIY5n*MoOl3+t zHcoymZg{3_Z8%4=Ch5Hd?Il*&ioRN}W!IS?ec!;bt*yV1>Av%6=6jA`+)!d%l4V0R z=JH^*7ueBcR9~3#r7~b3y%N~;aGi^PC7cz?Qe0&o;?;~CeE4&lAG6L@VnY+BCi7q} zMYhs%!8B)3qZn=m&vc^Lzj{*-yNe7Zh5yyYmtgwD_^GtYQfZYfM$&!#Hlt`RT=g0p zVgp;N@{(y&w#nN%a~W{{GSS|ef$bG?HO9D@Wv2&!Oi&Q7p_Iba7yI9CQW{X?67uGE zN>I-N$-h>3Q_iZ!sqjpB$+2cs=@f&?i!_Ke9d5?r@%eJfWy&MXc~5JXukppNRwLwb zc1w76Rq&e|1G~^BTWenjh{hGeY_T^MuBB2{)KR;iM8T3{CtB_~+xiX{{SmwPYV&;@ z?rm0E!7OVYsA<_Jus=Dbkn~nVhGNFW*((i_9Bs6l1N{V5ys(UYHB zX~fSda>{-rN#%-UwRMdX_QI_bnbBh1$|s>*`;Q*GWkhOJ@fk4sFsD!i}@p;8sO^)b{& z09);rt`P+3Nc~A^>?W`djn3q~hxE6ewlzxr#KQ+PRan=n+WZ&0p^xznr=}zzlj0f} zZ{Ea!&8;!&M_bjllDMr|h$QBjD=&0yvn#Dnv(x=&e^y{c!7H zduw~E*}C6Gzav~!N?fMB&9Aq5+g&$`%aYkvsCuDK{!O-;?Uv!&+cBIfM`BZRuTB*{ zEOK0Cq!-_oN@-imD70MT2U;|2nmMqa#o9BXv!fD|>g`b$XX7cXx3VIZw!WYUOK9-7V>%ARAI0jYQbLSPs&kT4PWL*KX`5fA90Qq|B7P*Yr7a0$` zP2KhOqg{TKiGlKIZyH~d)Nd4X=fWAvrH^*RBPEWDPun`z!3sxiGS<@q{3g zSoR}`?PbNO87e3$F{~QMYRp>`j~q0wW-43~kjWY%x=%9tVD1gxG-xZhXbq$l!c7(9 zlP?}*`mjEJ0q5x*L47u2#_YJ4M~c)wmc6pF6~@{JX_J6}YYWM({Yrdt z*^4H-%%X{j75^@hQO8Z|i&qs{R+v&~LpeKvrwmp(X|Mj#vl(p$6)4Jk#8K+hgL@qzYic(rKa*&S;^sUfj-)zXKDvi3RJ79BC<>FW3rD{MhiEBnU?PiF5vwBh zf_214k^=uNZWrzq!t*nGc!WM$!Jj2jilPOrq!%tO9S-DgD~)1ZO>7Q= z&s3Nm*TR$^9Zn!b;TdyW1*z!}HBPP^z#AhGTx!z8Lz9#3L3Ma{AYm9u81RYx5DWPL zA6gxJL6fbSgsqN->BB**49Md;_Q*->^bYPdF8Soe!|4HeH4Urm*%tiiL3{A9FTEn1 z8KeyqsU}@iseJCo?rRgW;$#m72ao#)N}L1-QgZ`Q8zDa(9`p_h&srZY96aqG4iCS0 zq(vHKRbf2sYjeGSpcf9*hmFj=IJnpM{o;WsV7%*xI0p~*t9@mc5jC0?4{r7kv|I1m zp+W`^Inq-|+S{hiN*1(tfGXMAZw?0gu)%n!p?4TY`K^ENW0SP_;71hM1~Tn_WlO27 zKDgzO4h;8i_e@70jAEa5*ZcQA*4uwBqfb~Un|l9YZ+}mQ6qmGXHd3}hWU&9VXGiOU zPpKcN{fYMP|7IWfB$g4vszUE}TnO+DixNBF3b_IpgS;DWnJujjdN-fy7id!cpGOI6 zg#bvM5gs6~0{wP76Z`2v^nVT@$=lEg_>=TPr^bkTA?vJuENCbQ28Mz+HHEkiHGv>? zU{eR-%|P;ef~dyhscZ%IZlm4=G-d+E{$k}*;8UPqSdg4i#elE8Gw|I1rv!r>pZ#5* zI{GqFliXBD0DP7tiXcoCK^tMb!vJSAd?9=6je$uZNU*@58NfgdSK}>UoS}1cCp{cU zpm@J<)1EqxUwH=nUa&$GhhS#$UuUaXhqa` zCXwd~bDV5tIA#W6qmhW~okVfcGf`PSz`=~KkTbDfGXpjAr_YIl=d^MHl=`JYx*DGQ z0Crg*=RsryUvf1t6`Q<%NpI{b{)0AG!8Antj)XxNpNmez!vRiM1Jw{`sKILC^SUbi zlg&j|BKR_%^Tb743M6=JTy7Q1jHT-7+JNTZbR5&4i>l10oyy7yTajm<_8P%Vl^NF8 z7)5Y?P-!Z0vdfGXGJs?-vYnMYlm=dc2|MFa-;v3=9X>TY-KAcMBnlCb9NVZ0ZAO+` z&gyhWzcJhqA%1v7%#98uqrm!Xn~YWzAIMqo=URkKOqb7zf6`9uh2hK;%A|vI{LJxu z>6hMd_7EX!S!cZh$xU>sbn4BRc2dzGj4HinUXVKqz_l734;>T1yq7Ac=*r6T?vg7f zo36%jH)bOKYDjH)enMEKXv$xa46!g%g`}}I6yb17BZ1vzd{n6?rEp9o8O}FMSQ7<+ zp?)v}oC-72Ev-UzIr|QT84HR!+;ozPW04+o_^+Q+7mR2ox|{_*Vx?I{_IXA+B_9+Q zxsqpxEx|g^bC2|f?ZvWo3F>9bl-k@`K>D4ljwR(9 zF`Go|_9+ydRJPEMQuMf)s2I?heSO4V{j7f*k7g7&0muW|o=6!04u}PSp)f>4oX-M} zG`Qm(iyN$@5zqu+Qg0dptvZc0FsPLDHoaC0h%S~G#ln}AZ#UkDtpr^FuzDLG7|7ee ziOd5#4Gc#EW%BbmkD=E%Nt?h8$P?niAp*nn(UAw$u}2tGj2;&BNMk~+RkBAW8d;vlGih=HwPdu%@*i#KX9~7p?CmK_PC$O3*sI81ET0a0=ca4H8c`k zz$kr<4?{Wvyel&XL_5-_(1y4d(z1uzwyhHZnPI$@Xw%yk%&TCBLc<0^8-KPg@|8+M zcC`JpBk;A}zKi{W);MlG3>8*a_SCYiD$;=Mh~UdiTMxTa18?%S-M)!bq@wY5z2iiY zzjRTBB7bE{qjm!8^K@$G7!#xI4?D_RzU`7D9B==u{X09`J06V=x#NH}s<(ZkBR*aw zf(RVA=-up>Y-Up`N8A65wD+UYZ|(n9E-BWXTbtk7UcjMh`z}PQ9e*so*V_;5mzkX# zRPeLBea$|<5clwV9oyO-7IE#9FFW@(UrVUkQ53`NFX0ZpR@)0Zq~~dShXh*raOY7+ zau%dgJ2m%=neOmlUKWmNQH!4imk*L-fkI$=tw1f%G0j_Dy zN@6}*TLdu4vM!Lk>ZFY&FMUB>z+HlQVxbnurtwLykLkrK6R8W-PoP?_L)-wccvznC zN*=vu$hA7v3NO$%uOsj#p)suV=Ke2{g;+WPz~)EdO;R)Pl~$PWbh?0Kg;EX;Tq>$u z^&qUy2w_5s0MG2ukH?*duQlA7yY96CB zmgGo%yl9w_byQjk6w8q8MPQ&T2p9(7Wi(Q?S1{@!d13LBCON@LHTnmb7t2iyY6G02 z#p{6NPcAR`5a`+wMXEOdY^@a-S|dW1mcpd8#cBmaz?Jz?LWjp6BH>Px4xOhlj3muO#_5`{HFC@@d& zsiZ?sW2v5 z0k!6O3`H?uxlNoeUUyR+gZQdm8Ins=hG3yu=aG|Uz&V$00P+U13e; z>02Z%0Ix<@kAyd-3*%hBf(I727i)HMxsL%))|!B+ zf?|qJ@NBC>n8$^Lrtx*QFvY;F@LLswz;dslnMMW*zN?uJeUH*B{oSfA&VrsYR>#B> z;j@rU7?tu}h>Ap6pyHZ|kuYtdIXsvgv^uX#Rza1Oe0dvdcw$mXW!9 z6Hgxr>Wz$#0|*wdd!Q?tW5_^s=~VoxcfrVs5047qS}6s&zRQ{=IC9Yui8DVscyA0g zf!6&4#gr?TI4|Wknlo%gz5uoi5}b)t0uv?gN$!r+ka>gLq*J(Uz3-)I&`DX*5(O zRgM%H*!LvDsP=ELjo!ij=RKuI?>w7e0zmJ1>1{w9_`E(?-dD_vkw0={IKF2fU78Z% zUl3ZI%dV2aSUjjTxW+G_Z1Ex0!9du&ID{yvp#gg*EFvB6Kkg+b5S&F44!AT94#BBw z(J8!rZ-0MJS#0*q&NPAhPYymuhNbghe__AcyOWglveu2cfbVhs+6W@31|?+*ei0ADQN_<~#e8Xs7z-)k1 z(J$%y_*P#4vf^MsJaetE0c;iIWv-Kzr2#+->B$TO74Ts!89z#&wm)K{KuEwc#wStG zVa@aHzPK6Kh7F-D(B#gCZhRtSfrAB5iD`e*xWJk?+LV=%K7zjm+U9O^KG$XaS~%$0m|v}tYt(4kovo_@ zGzv)5?v_@j`;!nUl}@XKzp z(YGuVu*y=MR1mYCSHGo}qTSpCcRw}@F8seVGT!s>Bj4T|pk?r9HgJn2@Yl^yM zDIJxSOaRs00m#YXXc)ky^P4Fr1wNwyUiNPYg|fW=D4oP+VhEI3d(?HQ4J z{Q65EJj^D+<*6+-S;fkq&=P}PXo`~@#N?09~?}Aj0V=GXe%kXOT(KI^dDT)_`eF`Aij;l@d&@FNhPK>dr#Xb0`)p zWEpe8oSo8fRXMzXu<%lI;qWSWbQ%8Q{lA{BiqX-dVUQ-zoQ^4<*r8ew}w?%Ue zQXL$6IgmA1sx~LzbrRksS!it?W1`VyEsCbBlX9iw5-cW`Q+J;5nV=+6=1vTI7i|$9 zhl=7)^?L9Z7mPSMw`2ul@{VjU^?aUobwW{+PMbCkoXc7yC=wZGXGeVFlIJe0M41p=rZJ~03A%0~GmGP_u=(p~ zz5CCdKmLGby$I-6yp?ki^Jix%U`;$puz9N9lvE$iEOk1yD!=%X9!YT#Ct$Peyl4n{IBR)rOw>Bs5Wa31O z8fysj&cznPjYe!x5Ov8kxwUvgo30oF@pb%fbY313Y9*B|?e11KTVrO0?(KE4S$-U# zd*x%L0KVu2U1tBh3_zX4>t1fq%cgYJu((-Tvb23KB-4_ey&JhEqS|aW>>zHZ!r|t7 z^C9MF__X1rCmbLADia=Pnr_q)Ct8%DuKw^;ALiMdBSl*xOtT+5e`Tw*B*lD)glV;A zg5+mMd^}bVzjC4{(R+=&X5Qpaw1s;nHPADG*Og}7p=dKn#*a~=f0DTh4=YLLIv8@~ zaG#gdl-_=KT+=5lN9$( zdMP;7aV(sW`_7|TExR- z8h`7s3DO=pG<|~XV|{{p)YF7#+yPcww8onlbRI11UU;qFNwze3RtYV2F-lJHZ~IIY zxgG3fOt{_hX0QdrX~s+iS#87Lc?jw7ni8kawXIJv%Q9p36Q3J%b{f*%Ht zm>f~S+kc8og*k0;jL1|QamGolm}di~<(RQN+1YzG7fNd{pKwl?jj!QRatFK zw`0zr+NEkCXPikTm()sH9B+RVIj1mOn=roc#PRa4jt`Bc4yFa~b_hHo$#9$|W(^`Z zvrxV)%TuP@mE)kxnh$jkcn%yK3p>PRLSstUHDAsWwF2NwQmJr`Nh(%53*EAb;&u`H zMil9zLi^S;L*UEX!AL@$K5XyMd7y;o;up$Wof@W>CpZz*Wi6&v6tv5S%w-BQ8LURJ z==M$p0~)L-jA*$?I2Y~Kup_?5+rPlO##`*DUe(UB>MLTDybOBb2h1t{!mjGn*AI(H zK08d3OqSDO^R3C_CUM(t_jgoBoXrYXKQQQeeXac>b#2zcN816XX9#%0$J>vVfC5&g zaAmwR>=J32#o&!i9(z;m{NIRLxkl?9B^!zf%ys7iA*-T^`#YlcosFG=0`z=K{5gRu za#gCd@M%Y*%``Lh8bz7nFI#@5NLr43-rD;1&XNQbB&RR4FO$RVcIQhRMS8eHvqHR| z&#CA`YTMp$r+QWI{2z!DH0S9q`OLUJI~BZ9XAPE&Bl8;?_)V#53Xq`WhOS za55%F@dHcmABbUsaAbXkD3?PmvJle0IFFu>4!URW$#i?9=dNM7Y@?wb2BA6}nGrBa zDuM@1qACzJvn1aVZif;O(0`PSQb$@W3-+!Lv)etN1t4P1Sl`Uz>L$-9E9kJdPDujiLJxb!k{E#A~{8^@L~1S%|oB zI4TOL7p*KHK|>KI<)L?lK^w$+2|V*M0~0i^<_L2sGHiZkwsxU#D))P2wV%~vr;?I0 zyArb^(&?kAl4L&=jaH5jfL_&M4v0k$cDOk(!=h5&yWYnF($&GI7@|>nXLv0BP-Lch z2K()v*H8p`6aEjBc#%oO$E!cj2{jN&d-dLf95de|x)jc5wgN+i6~zMSQ|;Y~xPkI% z_rBN(2eITDF#nfsw|h^heH1se?DK5XW93X&7DZ01ZV6T2No$*@Y z+^97Usp#3%1kqUf&7MZSdDwgNCOAwncjU#GV{|vMKkdhHxl||0BPPC!**tz|^v15^<{+o|cH7)|k&}0c=|0tcF((FE4o- zXS;$MYe>B>x&1|algQqi_RZ7Yo9c}(E?hpCoWA551%aHSbUOFm4BkBb7?Z5ZWm-Jb z8S}FcU3gS!M-1yDIk8j@CDLKeV z=<>>Q<&ENQG#f67y*Ir#Uw(WOuQ&T6#o%*re{ZyREq(E>&^ml`FReck`j3xqev~XZ ztSGT=mMw_#z5;*K*pDCUAFDSp&y7zFNoO6YqR2k=QN6jt8qWVLZ{qE;lXP$YS((&@ zH;+1o%H~I|Fgi;$o6dS&WNdsWH=o}8*!(Edl0mlGA1i9v;f0qYylkcEfeauoxjv;h zc7@BGaH;ySk(AV>&Z?Xf10v9Dy=jzFr(PO+ZzeywoF5onzp3|@-qg}?6H&eSaq#2) zADEMHNTnlRCi1rppKC1je!Ts|kAL92YrE1@>Yc0}rVy^*eD!1Xhe=n*10|X{>PP17 z?exc|Kge&vZ$O`LTLrO905Y)mf}|Q&G``jD{+|ZD%BBo75GK$w@VMXzg0eyaj2x5> zjM27o6JJ5_l6VQUGrs_@g+xNI2{0xu8<1nH3PBFhfb^1P)*geY0m_0;CR2da9H(lo zhbK8%2Ws#*ok%<}utYC^2~*mZr%lc6NLr(MJxU^_5W}Vgh6&m`?f6qLeC2n>HTlVK zjz*pYd-YEdoxihBN7;fA7nedJpj{4@g&etR4Fd@d2hg1%2AAuFf!3}~a6pjFOq!%^ z57e`xdt3^MCP#L?z9{^%Z_+c1D8eNDq|u0K(j?VuJ*`ZyjL4tLhS)qc!Qc6zm7Qp* z%y{^$c!toSUxmUdpg35#-k|CITw$ZHn!JLkcNBwXL7Vb_{2_$H@o>pVw`F+ZmD6Is z$xmYM2ELu>;D-SIGwU-ll4o~mCw!O}(?!)931^h+E)``0+KzgS=`u?t7XtdW$ALII zt3+y^87FZqxH7&ZNX*d zdKHoQCP$nWZLD$BabBD`d7&vGrLpj}BLZC+PFia!B(41F9FP1+kIeTI-M5RfTADik z(MK6w-qs`u*=3*|^bF`rUQcudB9NGYV9R0;yT>KFkvt|N&lmWO!d?{KmTbd3IusKW zOj$38D?Yj&n51$kna#duUYnk&)nKr*+`9r`(w*zF+>BI2YUf$UkyTiiHgWY=nMY0{ z5&9g3GoP4T#>I>~H=`(R>EOAC1Q(0JNEXx(8e(twK#ojH7F*`HG)%8is6&g)2CNJffc&{1}Fg7eJ5WZKh#m~(yc?vl~)F)yAo?G#E! z-OgzJj;|)k^9kfzUL}^2i?{b>`QEHDW`C24E9Gwj)0!?*ktMq&5sN+n=Lx?|c?f19 z<Sbrvt%a?$#o(#)ny>ca;PJ&yp$wOzO-`mz9N|~3@ z3O9kBVidr-rvjSA@%VX8dft;MfTh5JB?D+$Ru~!YbGEEf!RXH$J@EA z(1B?Tn7f|i#LK#$gZB#e-qClKrddE6(LB-t;O?-z5%&=5omjo3J)7clw3$k*ah?S9 zS3CTO?GkZd?;H!yoQm~fp;eyoL4bci);cN&zK*;*{mEi@8ChG_Q|*W-%4K}O;2pBx zEu3>=Sq{f?GJIqu8Mt^X(gVXTk!)=*%26-K+L7P&PA3Ld?>gQjT3TByzUbxi&_FG9Sz5^ylZ!LO5%nR>cgkRk{IEamQM=UbI zQq$WnViH0N{6Yf%;YCs`-;gTo=3z%U+UW{T%A754v@}t?k!C2OYBZ=vRt9o$fJsaJ z1#5$H$vnrx)>q+myWJ?|q}}63JF~c!aHtoYgd9ic*N~;bP_w!h0h)TjDGR@dI-_Yb3tigVbncs&o`&Q0rG0fL{~dr_B$=@!bi8wC zzm-ds_p8>)g(}l5ByH)so5fe5vrjtY&G6Or4^Epl-)cO0CW6p8ebp^zb+*Rg74uiU zx`}9ZUbTwHj%xG6D{VNjb#=i_o3*%3Dhkfly;+iJBAPorNMpp|xvpM)v6J46P_ER4 zUJ-+@BL6$DdZY%2U%VpGQ%&BZd<#`70pi?wH6ZNCtNI65b+1fascW6zsNv;UG&4Ua zOVtmaTWD8(=w)S5AL*f#T2vwZz)X>VB?pn=>aVGFM!r+_!w;{1&^tD-#E(+3%tlB} z&@+&6nPGYck-MxGmqey~^y(Hpdh4{5uRqw~HspVaS(IXHkMnIBfi*u|r~MyxoXp;i z#Qh3+ZS6)A7G$OR;f^7Bj-(AIi;7-;^=A%7SUAL&`iCi(82tGEx;nSywv8x=3J<<1 zQnuu(R6hKdN+s*C2#5gXs%$75$r@9!ElW1_NKW^?Amj)TM9$o~ui*!~o1paT0;apH zUgk1dH?!=~_srBzXVlJgHrBv^epOusz=4%2YVPAf<{ z#4F@{k1I$ONAxZ%7xwf>bEHyj^OUv>YU(UV9@EL}^O8;+&@3qnVmi z)hdn82lEO|!@5b?uU(?t_D6^6=g1w_D5OO7)Be%P&HH1Q&OPp!hkk>eq`u|YD6{Yg zEu^EUmrjDspwm1=A$Xo!CF#3P%9nHxYbTa!>i!u4rR<)2t))H6>Ac`GE;WNRm@TA-+P_o5J7>h6*p5x6?GrhC~ly6(Rzhwy>Pf|@Kvb^QW6Mz-Ay2 z2OD>a#Co!pYDS?0w{|o6Em66IX@6C zhQKH~hX*FWyn(onN&LU7faqL}^v!c<*7T}xmlBbnk<%01K9UTx188zNe(>MigqdJ* z7bXdkXbMuoUw|g3l1|J?n1aZ>{5f|PitsiaV5W%y-4c`Z#{c-M5Qc&(!BAujD^Jzy zt^}Ts#K(^mwy2@}?xW&M?DBvSb+H^|5y5_oeBRgxd0Wa3J1 zd0|GhFoE$~qYBmxqu?jQu5-YgKGn*>yY3Ids6x3$CKWI*!J+{NXb``+6zsJ0&9J^UL}mON3Tvm<@yBN1!N7_K>92 zH8=Qkdm`Dp=m?8AmiRJ`7k(Cw5$s?y850%+k@45A=DTk~Bw8dA#3lDdUuXhg?kN`z+&fN#K$AS$$QnxVV?=}9L2L`bEhd! z+kz_QxDjMlfL$|@%Z9-tPdMtpbL=S3>gHTeWo6LH5}s7eWH%&R%MAydgiOk2w)^5b zBB(|fUN+Cz0NrCsr4X~oPGB&n$Z!d<5s7fMOD-*5irqiymx(wHHm5QD)RI_%)k^U; z4B}pGGp^jqsA!&BZP8PH9QM81Wv#PD5DaFoH zHSU|XXpizK1Ltw40D7)dYo8R)P07rQ_N8gdmONWJ>pIpygsPj*v0O>(STvagZq%9w zM~EED_L+ceu9vX6@?Nxy8~}F9SZDYwqnyQ16NueYny%U>rJaRW?SqTZ%p`LDbNh literal 0 HcmV?d00001 diff --git a/src/etc/installer/gfx/rust-logo.ico b/src/etc/installer/gfx/rust-logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..a58225d5acb307904e4828b2273a141ccd855d85 GIT binary patch literal 370070 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 literal 0 HcmV?d00001 diff --git a/src/etc/installer/gfx/rust-logo.png b/src/etc/installer/gfx/rust-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2c3de3000879b36b1dc4751ea5db0fa8fce4b5aa GIT binary patch literal 5844 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 + + + + + + + + + + + + + + + + + + README-CARGO.md + + + diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs new file mode 100644 index 0000000000..fb076ccb09 --- /dev/null +++ b/src/etc/installer/msi/rust.wxs @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSTALLDIR_USER + + + NOT INSTALLDIR_USER + NOT INSTALLDIR_MACHINE + + + NOT INSTALLDIR AND NOT ALLUSERS + NOT INSTALLDIR AND ALLUSERS + + NOT ALLUSERS + + + NOT ALLUSERS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ALLUSERS=1 OR (ALLUSERS=2 AND Privileged) + + + + + + ALLUSERS="" OR (ALLUSERS=2 AND (NOT Privileged)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/etc/installer/msi/rustwelcomedlg.wxs b/src/etc/installer/msi/rustwelcomedlg.wxs new file mode 100644 index 0000000000..0ee5415ffb --- /dev/null +++ b/src/etc/installer/msi/rustwelcomedlg.wxs @@ -0,0 +1,57 @@ + + + + +

+ + + + + + + + + 1 + + + + + + 1 + + + + + + + + + NOT Installed + + + diff --git a/src/etc/installer/msi/squash-components.xsl b/src/etc/installer/msi/squash-components.xsl new file mode 100644 index 0000000000..17b4e0388f --- /dev/null +++ b/src/etc/installer/msi/squash-components.xsl @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/etc/installer/msi/ui.wxs b/src/etc/installer/msi/ui.wxs new file mode 100644 index 0000000000..3e2db6051b --- /dev/null +++ b/src/etc/installer/msi/ui.wxs @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + 1 + "1"]]> + + + + 1 + + !(wix.WixUISupportPerUser) AND NOT Privileged + WixAppFolder = "WixPerUserFolder" + WixAppFolder = "WixPerMachineFolder" + WixAppFolder = "WixPerUserFolder" + WixAppFolder = "WixPerMachineFolder" + 1 + + + 1 + NOT WIXUI_DONTVALIDATEPATH + "1"]]> + WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1" + 1 + 1 + + NOT Installed AND WixAppFolder = "WixPerUserFolder" + NOT Installed AND WixAppFolder = "WixPerMachineFolder" + Installed + + 1 + + 1 + 1 + 1 + 1 + + Installed AND NOT PATCH + Installed AND PATCH + + Installed AND PATCH + + + + Installed AND PATCH + + + + + + diff --git a/src/etc/installer/pkg/Distribution.xml b/src/etc/installer/pkg/Distribution.xml new file mode 100644 index 0000000000..79f99818ba --- /dev/null +++ b/src/etc/installer/pkg/Distribution.xml @@ -0,0 +1,71 @@ + + + The Rust Compiler + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rustc.pkg + cargo.pkg + rust-docs.pkg + rust-std.pkg + uninstall.pkg + + diff --git a/src/etc/installer/pkg/postinstall b/src/etc/installer/pkg/postinstall new file mode 100755 index 0000000000..fb035a4869 --- /dev/null +++ b/src/etc/installer/pkg/postinstall @@ -0,0 +1,26 @@ +#!/bin/sh + +source_dir="$(dirname "$0")" +dest_dir="$2" +package_id="$INSTALL_PKG_SESSION_ID" + +if [ -z "$source_dir" ]; then + exit 1 +fi +if [ -z "$dest_dir" ]; then + exit 1 +fi +if [ -z "$package_id" ]; then + exit 1 +fi + +if [ "$package_id" = "org.rust-lang.uninstall" ]; then + if [ ! -e "$dest_dir/lib/rustlib/uninstall.sh" ]; then + exit 1 + fi + sh "$dest_dir/lib/rustlib/uninstall.sh" +else + sh "$source_dir/install.sh" --prefix="$dest_dir" +fi + +exit 0 diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py index 335acae5fb..4427313f9e 100644 --- a/src/etc/lldb_rust_formatters.py +++ b/src/etc/lldb_rust_formatters.py @@ -90,6 +90,7 @@ def print_val(lldb_val, internal_dict): type_kind = val.type.get_type_kind() if (type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT or + type_kind == rustpp.TYPE_KIND_REGULAR_UNION or type_kind == rustpp.TYPE_KIND_EMPTY): return print_struct_val(val, internal_dict, @@ -175,7 +176,8 @@ def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tu Prints a struct, tuple, or tuple struct value with Rust syntax. Ignores any fields before field_start_index. """ - assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT + assert (val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT or + val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_UNION) if omit_type_name: type_name = "" diff --git a/src/etc/platform-intrinsics/nvptx/cuda.json b/src/etc/platform-intrinsics/nvptx/cuda.json new file mode 100644 index 0000000000..1beaaeb5d8 --- /dev/null +++ b/src/etc/platform-intrinsics/nvptx/cuda.json @@ -0,0 +1,13 @@ +{ + "intrinsic_prefix": "_", + "llvm_prefix": "llvm.cuda.", + "intrinsics": [ + { + "intrinsic": "syncthreads", + "width": ["0"], + "llvm": "syncthreads", + "ret": "V", + "args": [] + } + ] +} diff --git a/src/etc/platform-intrinsics/nvptx/info.json b/src/etc/platform-intrinsics/nvptx/info.json new file mode 100644 index 0000000000..80332c54e0 --- /dev/null +++ b/src/etc/platform-intrinsics/nvptx/info.json @@ -0,0 +1,7 @@ +{ + "platform": "nvptx", + "number_info": { + "signed": {} + }, + "width_info": {} +} diff --git a/src/etc/platform-intrinsics/nvptx/sreg.json b/src/etc/platform-intrinsics/nvptx/sreg.json new file mode 100644 index 0000000000..33d97f2694 --- /dev/null +++ b/src/etc/platform-intrinsics/nvptx/sreg.json @@ -0,0 +1,90 @@ +{ + "intrinsic_prefix": "_", + "llvm_prefix": "llvm.nvvm.read.ptx.sreg.", + "intrinsics": [ + { + "intrinsic": "block_dim_x", + "width": ["0"], + "llvm": "ntid.x", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_dim_y", + "width": ["0"], + "llvm": "ntid.y", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_dim_z", + "width": ["0"], + "llvm": "ntid.z", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_idx_x", + "width": ["0"], + "llvm": "ctaid.x", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_idx_y", + "width": ["0"], + "llvm": "ctaid.y", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "block_idx_z", + "width": ["0"], + "llvm": "ctaid.z", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "grid_dim_x", + "width": ["0"], + "llvm": "nctaid.x", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "grid_dim_y", + "width": ["0"], + "llvm": "nctaid.y", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "grid_dim_z", + "width": ["0"], + "llvm": "nctaid.z", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "thread_idx_x", + "width": ["0"], + "llvm": "tid.x", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "thread_idx_y", + "width": ["0"], + "llvm": "tid.y", + "ret": "S32", + "args": [] + }, + { + "intrinsic": "thread_idx_z", + "width": ["0"], + "llvm": "tid.z", + "ret": "S32", + "args": [] + } + ] +} diff --git a/src/etc/unicode.py b/src/etc/unicode.py index bddc83f63d..e5389c112e 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -23,10 +23,7 @@ # Since this should not require frequent updates, we just store this # out-of-line and check the unicode.rs file into git. -import fileinput, re, os, sys, operator - -bytes_old = 0 -bytes_new = 0 +import fileinput, re, os, sys, operator, math preamble = '''// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at @@ -362,7 +359,23 @@ fn trie_lookup_range_table(c: char, r: &'static BoolTrie) -> bool { let leaf = r.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)]; trie_range_leaf(c, r.r6[leaf as usize]) } -}\n +} + +pub struct SmallBoolTrie { + r1: &'static [u8], // first level + r2: &'static [u64], // leaves +} + +impl SmallBoolTrie { + fn lookup(&self, c: char) -> bool { + let c = c as usize; + match self.r1.get(c >> 6) { + Some(&child) => trie_range_leaf(c, self.r2[child as usize]), + None => false, + } + } +} + """) def compute_trie(rawdata, chunksize): @@ -379,8 +392,6 @@ def compute_trie(rawdata, chunksize): return (root, child_data) def emit_bool_trie(f, name, t_data, is_pub=True): - global bytes_old, bytes_new - bytes_old += 8 * len(t_data) CHUNK = 64 rawdata = [False] * 0x110000 for (lo, hi) in t_data: @@ -433,15 +444,50 @@ def emit_bool_trie(f, name, t_data, is_pub=True): f.write("\n ],\n") f.write(" };\n\n") - bytes_new += 256 + 992 + 256 + 8 * len(r3) + len(r5) + 8 * len(r6) + +def emit_small_bool_trie(f, name, t_data, is_pub=True): + last_chunk = max(int(hi / 64) for (lo, hi) in t_data) + n_chunks = last_chunk + 1 + chunks = [0] * n_chunks + for (lo, hi) in t_data: + for cp in range(lo, hi + 1): + if int(cp / 64) >= len(chunks): + print(cp, int(cp / 64), len(chunks), lo, hi) + chunks[int(cp / 64)] |= 1 << (cp & 63) + + pub_string = "" + if is_pub: + pub_string = "pub " + f.write(" %sconst %s: &'static super::SmallBoolTrie = &super::SmallBoolTrie {\n" + % (pub_string, name)) + + (r1, r2) = compute_trie(chunks, 1) + + f.write(" r1: &[\n") + data = ','.join(str(node) for node in r1) + format_table_content(f, data, 12) + f.write("\n ],\n") + + f.write(" r2: &[\n") + data = ','.join('0x%016x' % node for node in r2) + format_table_content(f, data, 12) + f.write("\n ],\n") + + f.write(" };\n\n") def emit_property_module(f, mod, tbl, emit): f.write("pub mod %s {\n" % mod) for cat in sorted(emit): - emit_bool_trie(f, "%s_table" % cat, tbl[cat]) - f.write(" pub fn %s(c: char) -> bool {\n" % cat) - f.write(" super::trie_lookup_range_table(c, %s_table)\n" % cat) - f.write(" }\n\n") + if cat in ["Cc", "White_Space", "Pattern_White_Space"]: + emit_small_bool_trie(f, "%s_table" % cat, tbl[cat]) + f.write(" pub fn %s(c: char) -> bool {\n" % cat) + f.write(" %s_table.lookup(c)\n" % cat) + f.write(" }\n\n") + else: + emit_bool_trie(f, "%s_table" % cat, tbl[cat]) + f.write(" pub fn %s(c: char) -> bool {\n" % cat) + f.write(" super::trie_lookup_range_table(c, %s_table)\n" % cat) + f.write(" }\n\n") f.write("}\n\n") def emit_conversions_module(f, to_upper, to_lower, to_title): @@ -543,4 +589,3 @@ pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s); # normalizations and conversions module emit_norm_module(rf, canon_decomp, compat_decomp, combines, norm_props) emit_conversions_module(rf, to_upper, to_lower, to_title) - #print 'bytes before = %d, bytes after = %d' % (bytes_old, bytes_new) diff --git a/src/jemalloc/configure.ac b/src/jemalloc/configure.ac index eb387ed957..829e43f1f7 100644 --- a/src/jemalloc/configure.ac +++ b/src/jemalloc/configure.ac @@ -1532,37 +1532,6 @@ if test "x${enable_zone_allocator}" = "x1" ; then AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin]) fi AC_DEFINE([JEMALLOC_ZONE], [ ]) - - dnl The szone version jumped from 3 to 6 between the OS X 10.5.x and 10.6 - dnl releases. malloc_zone_t and malloc_introspection_t have new fields in - dnl 10.6, which is the only source-level indication of the change. - AC_MSG_CHECKING([malloc zone version]) - AC_DEFUN([JE_ZONE_PROGRAM], - [AC_LANG_PROGRAM( - [#include ], - [static int foo[[sizeof($1) $2 sizeof(void *) * $3 ? 1 : -1]]] - )]) - - AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,14)],[JEMALLOC_ZONE_VERSION=3],[ - AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,15)],[JEMALLOC_ZONE_VERSION=5],[ - AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,16)],[ - AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,9)],[JEMALLOC_ZONE_VERSION=6],[ - AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_introspection_t,==,13)],[JEMALLOC_ZONE_VERSION=7],[JEMALLOC_ZONE_VERSION=] - )])],[ - AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,==,17)],[JEMALLOC_ZONE_VERSION=8],[ - AC_COMPILE_IFELSE([JE_ZONE_PROGRAM(malloc_zone_t,>,17)],[JEMALLOC_ZONE_VERSION=9],[JEMALLOC_ZONE_VERSION=] - )])])])]) - if test "x${JEMALLOC_ZONE_VERSION}" = "x"; then - AC_MSG_RESULT([unsupported]) - AC_MSG_ERROR([Unsupported malloc zone version]) - fi - if test "${JEMALLOC_ZONE_VERSION}" = 9; then - JEMALLOC_ZONE_VERSION=8 - AC_MSG_RESULT([> 8]) - else - AC_MSG_RESULT([$JEMALLOC_ZONE_VERSION]) - fi - AC_DEFINE_UNQUOTED(JEMALLOC_ZONE_VERSION, [$JEMALLOC_ZONE_VERSION]) fi dnl ============================================================================ diff --git a/src/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in b/src/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in index 3f54391f05..19c8dd6c16 100644 --- a/src/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in +++ b/src/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in @@ -158,7 +158,6 @@ static const bool config_cache_oblivious = #include #include #include -#include #endif #define RB_COMPACT diff --git a/src/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in b/src/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in index 2c75371981..5378d14034 100644 --- a/src/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/src/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -212,7 +212,6 @@ * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings. */ #undef JEMALLOC_ZONE -#undef JEMALLOC_ZONE_VERSION /* * Methods for purging unused pages differ between operating systems. diff --git a/src/jemalloc/include/jemalloc/internal/private_symbols.txt b/src/jemalloc/include/jemalloc/internal/private_symbols.txt index 5880996adf..467e748cea 100644 --- a/src/jemalloc/include/jemalloc/internal/private_symbols.txt +++ b/src/jemalloc/include/jemalloc/internal/private_symbols.txt @@ -433,7 +433,6 @@ quarantine quarantine_alloc_hook quarantine_alloc_hook_work quarantine_cleanup -register_zone rtree_child_read rtree_child_read_hard rtree_child_tryread @@ -541,3 +540,4 @@ valgrind_freelike_block valgrind_make_mem_defined valgrind_make_mem_noaccess valgrind_make_mem_undefined +zone_register diff --git a/src/jemalloc/src/zone.c b/src/jemalloc/src/zone.c index e9b86afcfd..2c6a4f3146 100644 --- a/src/jemalloc/src/zone.c +++ b/src/jemalloc/src/zone.c @@ -3,8 +3,77 @@ # error "This source file is for zones on Darwin (OS X)." #endif +/* Definitions of the following structs in malloc/malloc.h might be too old + * for the built binary to run on newer versions of OSX. So use the newest + * possible version of those structs. + */ +typedef struct _malloc_zone_t { + void *reserved1; + void *reserved2; + size_t (*size)(struct _malloc_zone_t *, const void *); + void *(*malloc)(struct _malloc_zone_t *, size_t); + void *(*calloc)(struct _malloc_zone_t *, size_t, size_t); + void *(*valloc)(struct _malloc_zone_t *, size_t); + void (*free)(struct _malloc_zone_t *, void *); + void *(*realloc)(struct _malloc_zone_t *, void *, size_t); + void (*destroy)(struct _malloc_zone_t *); + const char *zone_name; + unsigned (*batch_malloc)(struct _malloc_zone_t *, size_t, void **, unsigned); + void (*batch_free)(struct _malloc_zone_t *, void **, unsigned); + struct malloc_introspection_t *introspect; + unsigned version; + void *(*memalign)(struct _malloc_zone_t *, size_t, size_t); + void (*free_definite_size)(struct _malloc_zone_t *, void *, size_t); + size_t (*pressure_relief)(struct _malloc_zone_t *, size_t); +} malloc_zone_t; + +typedef struct { + vm_address_t address; + vm_size_t size; +} vm_range_t; + +typedef struct malloc_statistics_t { + unsigned blocks_in_use; + size_t size_in_use; + size_t max_size_in_use; + size_t size_allocated; +} malloc_statistics_t; + +typedef kern_return_t memory_reader_t(task_t, vm_address_t, vm_size_t, void **); + +typedef void vm_range_recorder_t(task_t, void *, unsigned type, vm_range_t *, unsigned); + +typedef struct malloc_introspection_t { + kern_return_t (*enumerator)(task_t, void *, unsigned, vm_address_t, memory_reader_t, vm_range_recorder_t); + size_t (*good_size)(malloc_zone_t *, size_t); + boolean_t (*check)(malloc_zone_t *); + void (*print)(malloc_zone_t *, boolean_t); + void (*log)(malloc_zone_t *, void *); + void (*force_lock)(malloc_zone_t *); + void (*force_unlock)(malloc_zone_t *); + void (*statistics)(malloc_zone_t *, malloc_statistics_t *); + boolean_t (*zone_locked)(malloc_zone_t *); + boolean_t (*enable_discharge_checking)(malloc_zone_t *); + boolean_t (*disable_discharge_checking)(malloc_zone_t *); + void (*discharge)(malloc_zone_t *, void *); +#ifdef __BLOCKS__ + void (*enumerate_discharged_pointers)(malloc_zone_t *, void (^)(void *, void *)); +#else + void *enumerate_unavailable_without_blocks; +#endif + void (*reinit_lock)(malloc_zone_t *); +} malloc_introspection_t; + +extern kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *); + +extern malloc_zone_t *malloc_default_zone(void); + +extern void malloc_zone_register(malloc_zone_t *zone); + +extern void malloc_zone_unregister(malloc_zone_t *zone); + /* - * The malloc_default_purgeable_zone function is only available on >= 10.6. + * The malloc_default_purgeable_zone() function is only available on >= 10.6. * We need to check whether it is present at runtime, thus the weak_import. */ extern malloc_zone_t *malloc_default_purgeable_zone(void) @@ -13,30 +82,42 @@ JEMALLOC_ATTR(weak_import); /******************************************************************************/ /* Data. */ -static malloc_zone_t zone; -static struct malloc_introspection_t zone_introspect; +static malloc_zone_t *default_zone, *purgeable_zone; +static malloc_zone_t jemalloc_zone; +static struct malloc_introspection_t jemalloc_zone_introspect; /******************************************************************************/ /* Function prototypes for non-inline static functions. */ -static size_t zone_size(malloc_zone_t *zone, void *ptr); +static size_t zone_size(malloc_zone_t *zone, const void *ptr); static void *zone_malloc(malloc_zone_t *zone, size_t size); static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size); static void *zone_valloc(malloc_zone_t *zone, size_t size); static void zone_free(malloc_zone_t *zone, void *ptr); static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size); -#if (JEMALLOC_ZONE_VERSION >= 5) static void *zone_memalign(malloc_zone_t *zone, size_t alignment, -#endif -#if (JEMALLOC_ZONE_VERSION >= 6) size_t size); static void zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size); -#endif -static void *zone_destroy(malloc_zone_t *zone); +static void zone_destroy(malloc_zone_t *zone); +static unsigned zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, + void **results, unsigned num_requested); +static void zone_batch_free(struct _malloc_zone_t *zone, + void **to_be_freed, unsigned num_to_be_freed); +static size_t zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal); static size_t zone_good_size(malloc_zone_t *zone, size_t size); +static kern_return_t zone_enumerator(task_t task, void *data, unsigned type_mask, + vm_address_t zone_address, memory_reader_t reader, + vm_range_recorder_t recorder); +static boolean_t zone_check(malloc_zone_t *zone); +static void zone_print(malloc_zone_t *zone, boolean_t verbose); +static void zone_log(malloc_zone_t *zone, void *address); static void zone_force_lock(malloc_zone_t *zone); static void zone_force_unlock(malloc_zone_t *zone); +static void zone_statistics(malloc_zone_t *zone, + malloc_statistics_t *stats); +static boolean_t zone_locked(malloc_zone_t *zone); +static void zone_reinit_lock(malloc_zone_t *zone); /******************************************************************************/ /* @@ -44,7 +125,7 @@ static void zone_force_unlock(malloc_zone_t *zone); */ static size_t -zone_size(malloc_zone_t *zone, void *ptr) +zone_size(malloc_zone_t *zone, const void *ptr) { /* @@ -105,7 +186,6 @@ zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) return (realloc(ptr, size)); } -#if (JEMALLOC_ZONE_VERSION >= 5) static void * zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) { @@ -115,9 +195,7 @@ zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) return (ret); } -#endif -#if (JEMALLOC_ZONE_VERSION >= 6) static void zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size) { @@ -132,15 +210,46 @@ zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size) free(ptr); } -#endif -static void * +static void zone_destroy(malloc_zone_t *zone) { /* This function should never be called. */ not_reached(); - return (NULL); +} + +static unsigned +zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, void **results, + unsigned num_requested) +{ + unsigned i; + + for (i = 0; i < num_requested; i++) { + results[i] = je_malloc(size); + if (!results[i]) + break; + } + + return i; +} + +static void +zone_batch_free(struct _malloc_zone_t *zone, void **to_be_freed, + unsigned num_to_be_freed) +{ + unsigned i; + + for (i = 0; i < num_to_be_freed; i++) { + zone_free(zone, to_be_freed[i]); + to_be_freed[i] = NULL; + } +} + +static size_t +zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal) +{ + return 0; } static size_t @@ -152,6 +261,30 @@ zone_good_size(malloc_zone_t *zone, size_t size) return (s2u(size)); } +static kern_return_t +zone_enumerator(task_t task, void *data, unsigned type_mask, + vm_address_t zone_address, memory_reader_t reader, + vm_range_recorder_t recorder) +{ + return KERN_SUCCESS; +} + +static boolean_t +zone_check(malloc_zone_t *zone) +{ + return true; +} + +static void +zone_print(malloc_zone_t *zone, boolean_t verbose) +{ +} + +static void +zone_log(malloc_zone_t *zone, void *address) +{ +} + static void zone_force_lock(malloc_zone_t *zone) { @@ -164,11 +297,84 @@ static void zone_force_unlock(malloc_zone_t *zone) { + /* + * Call jemalloc_postfork_child() rather than + * jemalloc_postfork_parent(), because this function is executed by both + * parent and child. The parent can tolerate having state + * reinitialized, but the child cannot unlock mutexes that were locked + * by the parent. + */ if (isthreaded) - jemalloc_postfork_parent(); + jemalloc_postfork_child(); +} + +static void +zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) +{ + /* We make no effort to actually fill the values */ + stats->blocks_in_use = 0; + stats->size_in_use = 0; + stats->max_size_in_use = 0; + stats->size_allocated = 0; +} + +static boolean_t +zone_locked(malloc_zone_t *zone) +{ + /* Pretend no lock is being held */ + return false; +} + +static void +zone_reinit_lock(malloc_zone_t *zone) +{ + /* As of OSX 10.12, this function is only used when force_unlock would + * be used if the zone version were < 9. So just use force_unlock. */ + zone_force_unlock(zone); } -static malloc_zone_t *get_default_zone() +static void +zone_init(void) +{ + + jemalloc_zone.size = zone_size; + jemalloc_zone.malloc = zone_malloc; + jemalloc_zone.calloc = zone_calloc; + jemalloc_zone.valloc = zone_valloc; + jemalloc_zone.free = zone_free; + jemalloc_zone.realloc = zone_realloc; + jemalloc_zone.destroy = zone_destroy; + jemalloc_zone.zone_name = "jemalloc_zone"; + jemalloc_zone.batch_malloc = zone_batch_malloc; + jemalloc_zone.batch_free = zone_batch_free; + jemalloc_zone.introspect = &jemalloc_zone_introspect; + jemalloc_zone.version = 9; + jemalloc_zone.memalign = zone_memalign; + jemalloc_zone.free_definite_size = zone_free_definite_size; + jemalloc_zone.pressure_relief = zone_pressure_relief; + + jemalloc_zone_introspect.enumerator = zone_enumerator; + jemalloc_zone_introspect.good_size = zone_good_size; + jemalloc_zone_introspect.check = zone_check; + jemalloc_zone_introspect.print = zone_print; + jemalloc_zone_introspect.log = zone_log; + jemalloc_zone_introspect.force_lock = zone_force_lock; + jemalloc_zone_introspect.force_unlock = zone_force_unlock; + jemalloc_zone_introspect.statistics = zone_statistics; + jemalloc_zone_introspect.zone_locked = zone_locked; + jemalloc_zone_introspect.enable_discharge_checking = NULL; + jemalloc_zone_introspect.disable_discharge_checking = NULL; + jemalloc_zone_introspect.discharge = NULL; +#ifdef __BLOCKS__ + jemalloc_zone_introspect.enumerate_discharged_pointers = NULL; +#else + jemalloc_zone_introspect.enumerate_unavailable_without_blocks = NULL; +#endif + jemalloc_zone_introspect.reinit_lock = zone_reinit_lock; +} + +static malloc_zone_t * +zone_default_get(void) { malloc_zone_t **zones = NULL; unsigned int num_zones = 0; @@ -179,98 +385,29 @@ static malloc_zone_t *get_default_zone() * if one is present (apparently enabled when malloc stack logging is * enabled), or the first registered zone otherwise. In practice this * means unless malloc stack logging is enabled, the first registered - * zone is the default. - * So get the list of zones to get the first one, instead of relying on - * malloc_default_zone. + * zone is the default. So get the list of zones to get the first one, + * instead of relying on malloc_default_zone. */ - if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, (vm_address_t**) &zones, - &num_zones)) { - /* Reset the value in case the failure happened after it was set. */ + if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, + (vm_address_t**)&zones, &num_zones)) { + /* + * Reset the value in case the failure happened after it was + * set. + */ num_zones = 0; } if (num_zones) - return zones[0]; + return (zones[0]); - return malloc_default_zone(); + return (malloc_default_zone()); } -JEMALLOC_ATTR(constructor) -void -register_zone(void) +/* As written, this function can only promote jemalloc_zone. */ +static void +zone_promote(void) { - - /* - * If something else replaced the system default zone allocator, don't - * register jemalloc's. - */ - malloc_zone_t *default_zone = get_default_zone(); - malloc_zone_t *purgeable_zone = NULL; - if (!default_zone->zone_name || - strcmp(default_zone->zone_name, "DefaultMallocZone") != 0) { - return; - } - - zone.size = (void *)zone_size; - zone.malloc = (void *)zone_malloc; - zone.calloc = (void *)zone_calloc; - zone.valloc = (void *)zone_valloc; - zone.free = (void *)zone_free; - zone.realloc = (void *)zone_realloc; - zone.destroy = (void *)zone_destroy; - zone.zone_name = "jemalloc_zone"; - zone.batch_malloc = NULL; - zone.batch_free = NULL; - zone.introspect = &zone_introspect; - zone.version = JEMALLOC_ZONE_VERSION; -#if (JEMALLOC_ZONE_VERSION >= 5) - zone.memalign = zone_memalign; -#endif -#if (JEMALLOC_ZONE_VERSION >= 6) - zone.free_definite_size = zone_free_definite_size; -#endif -#if (JEMALLOC_ZONE_VERSION >= 8) - zone.pressure_relief = NULL; -#endif - - zone_introspect.enumerator = NULL; - zone_introspect.good_size = (void *)zone_good_size; - zone_introspect.check = NULL; - zone_introspect.print = NULL; - zone_introspect.log = NULL; - zone_introspect.force_lock = (void *)zone_force_lock; - zone_introspect.force_unlock = (void *)zone_force_unlock; - zone_introspect.statistics = NULL; -#if (JEMALLOC_ZONE_VERSION >= 6) - zone_introspect.zone_locked = NULL; -#endif -#if (JEMALLOC_ZONE_VERSION >= 7) - zone_introspect.enable_discharge_checking = NULL; - zone_introspect.disable_discharge_checking = NULL; - zone_introspect.discharge = NULL; -#ifdef __BLOCKS__ - zone_introspect.enumerate_discharged_pointers = NULL; -#else - zone_introspect.enumerate_unavailable_without_blocks = NULL; -#endif -#endif - - /* - * The default purgeable zone is created lazily by OSX's libc. It uses - * the default zone when it is created for "small" allocations - * (< 15 KiB), but assumes the default zone is a scalable_zone. This - * obviously fails when the default zone is the jemalloc zone, so - * malloc_default_purgeable_zone is called beforehand so that the - * default purgeable zone is created when the default zone is still - * a scalable_zone. As purgeable zones only exist on >= 10.6, we need - * to check for the existence of malloc_default_purgeable_zone() at - * run time. - */ - if (malloc_default_purgeable_zone != NULL) - purgeable_zone = malloc_default_purgeable_zone(); - - /* Register the custom zone. At this point it won't be the default. */ - malloc_zone_register(&zone); + malloc_zone_t *zone; do { /* @@ -283,6 +420,7 @@ register_zone(void) */ malloc_zone_unregister(default_zone); malloc_zone_register(default_zone); + /* * On OSX 10.6, having the default purgeable zone appear before * the default zone makes some things crash because it thinks it @@ -294,11 +432,47 @@ register_zone(void) * above, i.e. the default zone. Registering it again then puts * it at the end, obviously after the default zone. */ - if (purgeable_zone) { + if (purgeable_zone != NULL) { malloc_zone_unregister(purgeable_zone); malloc_zone_register(purgeable_zone); } - default_zone = get_default_zone(); - } while (default_zone != &zone); + zone = zone_default_get(); + } while (zone != &jemalloc_zone); +} + +JEMALLOC_ATTR(constructor) +void +zone_register(void) +{ + + /* + * If something else replaced the system default zone allocator, don't + * register jemalloc's. + */ + default_zone = zone_default_get(); + if (!default_zone->zone_name || strcmp(default_zone->zone_name, + "DefaultMallocZone") != 0) + return; + + /* + * The default purgeable zone is created lazily by OSX's libc. It uses + * the default zone when it is created for "small" allocations + * (< 15 KiB), but assumes the default zone is a scalable_zone. This + * obviously fails when the default zone is the jemalloc zone, so + * malloc_default_purgeable_zone() is called beforehand so that the + * default purgeable zone is created when the default zone is still + * a scalable_zone. As purgeable zones only exist on >= 10.6, we need + * to check for the existence of malloc_default_purgeable_zone() at + * run time. + */ + purgeable_zone = (malloc_default_purgeable_zone == NULL) ? NULL : + malloc_default_purgeable_zone(); + + /* Register the custom zone. At this point it won't be the default. */ + zone_init(); + malloc_zone_register(&jemalloc_zone); + + /* Promote the custom zone to be default. */ + zone_promote(); } diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 1cad8f7f40..38d843263f 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -55,24 +55,24 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. /// /// `Arc` uses atomic operations for reference counting, so `Arc`s can be -/// sent between threads. In other words, `Arc` implements [`Send`][send] -/// as long as `T` implements `Send` and [`Sync`][sync]. The disadvantage is +/// sent between threads. In other words, `Arc` implements [`Send`] +/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is /// that atomic operations are more expensive than ordinary memory accesses. /// If you are not sharing reference-counted values between threads, consider -/// using [`rc::Rc`][rc] for lower overhead. `Rc` is a safe default, because -/// the compiler will catch any attempt to send an `Rc` between threads. +/// using [`rc::Rc`][`Rc`] for lower overhead. [`Rc`] is a safe default, because +/// the compiler will catch any attempt to send an [`Rc`] between threads. /// However, a library might choose `Arc` in order to give library consumers /// more flexibility. /// /// The [`downgrade`][downgrade] method can be used to create a non-owning -/// [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d -/// to an `Arc`, but this will return [`None`][option] if the value has -/// already been dropped. +/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d +/// to an `Arc`, but this will return [`None`] if the value has already been +/// dropped. /// /// A cycle between `Arc` pointers will never be deallocated. For this reason, -/// `Weak` is used to break cycles. For example, a tree could have strong -/// `Arc` pointers from parent nodes to children, and `Weak` pointers from -/// children back to their parents. +/// [`Weak`][weak] is used to break cycles. For example, a tree could have +/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak] +/// pointers from children back to their parents. /// /// `Arc` automatically dereferences to `T` (via the [`Deref`][deref] trait), /// so you can call `T`'s methods on a value of type `Arc`. To avoid name @@ -86,22 +86,22 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// Arc::downgrade(&my_arc); /// ``` /// -/// `Weak` does not auto-dereference to `T`, because the value may have +/// [`Weak`][weak] does not auto-dereference to `T`, because the value may have /// already been destroyed. /// /// [arc]: struct.Arc.html /// [weak]: struct.Weak.html -/// [rc]: ../../std/rc/struct.Rc.html +/// [`Rc`]: ../../std/rc/struct.Rc.html /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone /// [mutex]: ../../std/sync/struct.Mutex.html /// [rwlock]: ../../std/sync/struct.RwLock.html /// [atomic]: ../../std/sync/atomic/index.html -/// [send]: ../../std/marker/trait.Send.html +/// [`Send`]: ../../std/marker/trait.Send.html /// [sync]: ../../std/marker/trait.Sync.html /// [deref]: ../../std/ops/trait.Deref.html /// [downgrade]: struct.Arc.html#method.downgrade /// [upgrade]: struct.Weak.html#method.upgrade -/// [option]: ../../std/option/enum.Option.html +/// [`None`]: ../../std/option/enum.Option.html#variant.None /// [assoc]: ../../book/method-syntax.html#associated-functions /// /// # Examples @@ -127,7 +127,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// } /// ``` /// -/// Sharing a mutable `AtomicUsize`: +/// Sharing a mutable [`AtomicUsize`]: +/// +/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html /// /// ```no_run /// use std::sync::Arc; @@ -706,7 +708,7 @@ impl Arc { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Arc { +unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { /// Drops the `Arc`. /// /// This will decrement the strong reference count. If the strong reference @@ -734,7 +736,6 @@ impl Drop for Arc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` - #[unsafe_destructor_blind_to_params] #[inline] fn drop(&mut self) { // Because `fetch_sub` is already atomic, we do not need to synchronize diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index addb056f53..b6f490e09c 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -103,6 +103,7 @@ pub struct ExchangeHeapSingleton { /// /// See the [module-level documentation](../../std/boxed/index.html) for more. #[lang = "owned_box"] +#[fundamental] #[stable(feature = "rust1", since = "1.0.0")] pub struct Box(Unique); @@ -292,6 +293,14 @@ impl Box { } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized> Drop for Box { + fn drop(&mut self) { + // FIXME: Do nothing, drop is currently performed by compiler. + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Default for Box { /// Creates a `Box`, with the `Default` value for T. @@ -587,7 +596,7 @@ impl FusedIterator for Box {} /// ``` #[rustc_paren_sugar] #[unstable(feature = "fnbox", - reason = "will be deprecated if and when Box becomes usable", issue = "28796")] + reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] pub trait FnBox
{ type Output; @@ -595,7 +604,7 @@ pub trait FnBox { } #[unstable(feature = "fnbox", - reason = "will be deprecated if and when Box becomes usable", issue = "28796")] + reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] impl FnBox for F where F: FnOnce { @@ -607,7 +616,7 @@ impl FnBox for F } #[unstable(feature = "fnbox", - reason = "will be deprecated if and when Box becomes usable", issue = "28796")] + reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + 'a> { type Output = R; @@ -617,7 +626,7 @@ impl<'a, A, R> FnOnce for Box + 'a> { } #[unstable(feature = "fnbox", - reason = "will be deprecated if and when Box becomes usable", issue = "28796")] + reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + Send + 'a> { type Output = R; diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 12809171b7..81ed4be776 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -127,6 +127,7 @@ pub fn usable_size(size: usize, align: usize) -> usize { pub const EMPTY: *mut () = 0x1 as *mut (); /// The allocator for unique pointers. +// This function must not unwind. If it does, MIR trans will fail. #[cfg(not(test))] #[lang = "exchange_malloc"] #[inline] @@ -143,6 +144,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } #[cfg(not(test))] +#[cfg(stage0)] #[lang = "exchange_free"] #[inline] unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index f9dfdc0e07..0c01eabd59 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -47,7 +47,7 @@ //! that the contained type `T` is shareable. Additionally, `Arc` is itself //! sendable while `Rc` is not. //! -//! This types allows for shared access to the contained data, and is often +//! This type allows for shared access to the contained data, and is often //! paired with synchronization primitives such as mutexes to allow mutation of //! shared resources. //! @@ -70,7 +70,7 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_std] #![needs_allocator] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(allocator)] #![feature(box_syntax)] @@ -79,9 +79,10 @@ #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(custom_attribute)] -#![feature(dropck_parametricity)] +#![feature(dropck_eyepatch)] #![cfg_attr(not(test), feature(exact_size_is_empty))] #![feature(fundamental)] +#![feature(generic_param_attrs)] #![feature(lang_items)] #![feature(needs_allocator)] #![feature(optin_builtin_traits)] diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index f23ea0ea8b..357a2724e0 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -539,8 +539,7 @@ impl RawVec { } } -impl Drop for RawVec { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for RawVec { /// Frees the memory owned by the RawVec *without* trying to Drop its contents. fn drop(&mut self) { let elem_size = mem::size_of::(); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 86f8c74664..010e378ef2 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -644,7 +644,7 @@ impl Deref for Rc { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Rc { +unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { /// Drops the `Rc`. /// /// This will decrement the strong reference count. If the strong reference @@ -672,7 +672,6 @@ impl Drop for Rc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` - #[unsafe_destructor_blind_to_params] fn drop(&mut self) { unsafe { let ptr = *self.ptr; diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 60b7875a97..1143df0c63 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -36,7 +36,8 @@ fn main() { // targets, which means we have to build the alloc_jemalloc crate // for targets like emscripten, even if we don't use it. if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") || - target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") { + target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") || + target.contains("redox") { println!("cargo:rustc-cfg=dummy_jemalloc"); return; } @@ -150,6 +151,12 @@ fn main() { cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); + // for some reason, jemalloc configure doesn't detect this value + // automatically for this target + if target == "sparc64-unknown-linux-gnu" { + cmd.arg("--with-lg-quantum=4"); + } + run(&mut cmd); let mut make = Command::new(build_helper::make(&host)); make.current_dir(&build_dir) @@ -174,4 +181,15 @@ fn main() { } else if !target.contains("windows") && !target.contains("musl") { println!("cargo:rustc-link-lib=pthread"); } + + // The pthread_atfork symbols is used by jemalloc on android but the really + // old android we're building on doesn't have them defined, so just make + // sure the symbols are available. + if target.contains("androideabi") { + println!("cargo:rerun-if-changed=pthread_atfork_dummy.c"); + gcc::Config::new() + .flag("-fvisibility=hidden") + .file("pthread_atfork_dummy.c") + .compile("libpthread_atfork_dummy.a"); + } } diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index 21e45f9c4b..fc8a5455d1 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -16,7 +16,7 @@ reason = "this library is unlikely to be stabilized in its current \ form or name", issue = "27783")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(allocator)] #![feature(libc)] #![feature(staged_api)] @@ -84,7 +84,8 @@ mod imp { target_arch = "aarch64", target_arch = "powerpc64", target_arch = "mips64", - target_arch = "s390x")))] + target_arch = "s390x", + target_arch = "sparc64")))] const MIN_ALIGN: usize = 16; // MALLOCX_ALIGN(a) macro @@ -142,7 +143,7 @@ mod imp { // we're building on doesn't have them defined, so just make sure the symbols // are available. #[no_mangle] - #[cfg(target_os = "android")] + #[cfg(all(target_os = "android", not(cargobuild)))] pub extern "C" fn pthread_atfork(_prefork: *mut u8, _postfork_parent: *mut u8, _postfork_child: *mut u8) diff --git a/src/liballoc_jemalloc/pthread_atfork_dummy.c b/src/liballoc_jemalloc/pthread_atfork_dummy.c new file mode 100644 index 0000000000..4e3df0ab26 --- /dev/null +++ b/src/liballoc_jemalloc/pthread_atfork_dummy.c @@ -0,0 +1,16 @@ +// 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. + +// See comments in build.rs for why this exists +int pthread_atfork(void* prefork, + void* postfork_parent, + void* postfork_child) { + return 0; +} diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index a4fabb5a2c..de2b75f62b 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -12,14 +12,14 @@ #![crate_type = "rlib"] #![no_std] #![allocator] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![unstable(feature = "alloc_system", reason = "this library is unlikely to be stabilized in its current \ form or name", issue = "27783")] #![feature(allocator)] #![feature(staged_api)] -#![cfg_attr(unix, feature(libc))] +#![cfg_attr(any(unix, target_os = "redox"), feature(libc))] // The minimum alignment guaranteed by the architecture. This value is used to // add fast paths for low alignment values. In practice, the alignment is a @@ -35,7 +35,8 @@ const MIN_ALIGN: usize = 8; #[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", - target_arch = "s390x")))] + target_arch = "s390x", + target_arch = "sparc64")))] const MIN_ALIGN: usize = 16; #[no_mangle] @@ -71,7 +72,7 @@ pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { imp::usable_size(size, align) } -#[cfg(unix)] +#[cfg(any(unix, target_os = "redox"))] mod imp { extern crate libc; @@ -87,7 +88,7 @@ mod imp { } } - #[cfg(target_os = "android")] + #[cfg(any(target_os = "android", target_os = "redox"))] unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { // On android we currently target API level 9 which unfortunately // doesn't have the `posix_memalign` API used below. Instead we use @@ -109,7 +110,7 @@ mod imp { libc::memalign(align as libc::size_t, size as libc::size_t) as *mut u8 } - #[cfg(not(target_os = "android"))] + #[cfg(not(any(target_os = "android", target_os = "redox")))] unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { let mut out = ptr::null_mut(); let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t); diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 6044bec2c5..a3cfc15895 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -26,14 +26,14 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(no_crate_inject, attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(alloc)] #![feature(core_intrinsics)] +#![feature(dropck_eyepatch)] #![feature(heap_api)] -#![feature(heap_api)] +#![feature(generic_param_attrs)] #![feature(staged_api)] -#![feature(dropck_parametricity)] #![cfg_attr(test, feature(test))] #![allow(deprecated)] @@ -196,9 +196,9 @@ impl TypedArena { self.end.set(last_chunk.end()); return; } else { - let prev_capacity = last_chunk.storage.cap(); + new_capacity = last_chunk.storage.cap(); loop { - new_capacity = prev_capacity.checked_mul(2).unwrap(); + new_capacity = new_capacity.checked_mul(2).unwrap(); if new_capacity >= currently_used_cap + n { break; } @@ -258,8 +258,7 @@ impl TypedArena { } } -impl Drop for TypedArena { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for TypedArena { fn drop(&mut self) { unsafe { // Determine how much was filled. @@ -280,6 +279,133 @@ impl Drop for TypedArena { unsafe impl Send for TypedArena {} +pub struct DroplessArena { + /// A pointer to the next object to be allocated. + ptr: Cell<*mut u8>, + + /// A pointer to the end of the allocated area. When this pointer is + /// reached, a new chunk is allocated. + end: Cell<*mut u8>, + + /// A vector of arena chunks. + chunks: RefCell>>, +} + +impl DroplessArena { + pub fn new() -> DroplessArena { + DroplessArena { + ptr: Cell::new(0 as *mut u8), + end: Cell::new(0 as *mut u8), + chunks: RefCell::new(vec![]), + } + } + + pub fn in_arena(&self, ptr: *const T) -> bool { + let ptr = ptr as *const u8 as *mut u8; + for chunk in &*self.chunks.borrow() { + if chunk.start() <= ptr && ptr < chunk.end() { + return true; + } + } + + false + } + + fn align_for(&self) { + let align = mem::align_of::(); + let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1); + self.ptr.set(final_address as *mut u8); + assert!(self.ptr <= self.end); + } + + #[inline(never)] + #[cold] + fn grow(&self, n: usize) { + let needed_bytes = n * mem::size_of::(); + unsafe { + let mut chunks = self.chunks.borrow_mut(); + let (chunk, mut new_capacity); + if let Some(last_chunk) = chunks.last_mut() { + let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize; + if last_chunk.storage.reserve_in_place(used_bytes, needed_bytes) { + self.end.set(last_chunk.end()); + return; + } else { + new_capacity = last_chunk.storage.cap(); + loop { + new_capacity = new_capacity.checked_mul(2).unwrap(); + if new_capacity >= used_bytes + needed_bytes { + break; + } + } + } + } else { + new_capacity = cmp::max(needed_bytes, PAGE); + } + chunk = TypedArenaChunk::::new(new_capacity); + self.ptr.set(chunk.start()); + self.end.set(chunk.end()); + chunks.push(chunk); + } + } + + #[inline] + pub fn alloc(&self, object: T) -> &mut T { + unsafe { + assert!(!intrinsics::needs_drop::()); + assert!(mem::size_of::() != 0); + + self.align_for::(); + let future_end = intrinsics::arith_offset(self.ptr.get(), mem::size_of::() as isize); + if (future_end as *mut u8) >= self.end.get() { + self.grow::(1) + } + + let ptr = self.ptr.get(); + // Set the pointer past ourselves + self.ptr.set(intrinsics::arith_offset( + self.ptr.get(), mem::size_of::() as isize + ) as *mut u8); + // Write into uninitialized memory. + ptr::write(ptr as *mut T, object); + &mut *(ptr as *mut T) + } + } + + /// Allocates a slice of objects that are copied into the `DroplessArena`, returning a mutable + /// reference to it. Will panic if passed a zero-sized type. + /// + /// Panics: + /// - Zero-sized types + /// - Zero-length slices + #[inline] + pub fn alloc_slice(&self, slice: &[T]) -> &mut [T] + where T: Copy { + unsafe { + assert!(!intrinsics::needs_drop::()); + } + assert!(mem::size_of::() != 0); + assert!(slice.len() != 0); + self.align_for::(); + + let future_end = unsafe { + intrinsics::arith_offset(self.ptr.get(), (slice.len() * mem::size_of::()) as isize) + }; + if (future_end as *mut u8) >= self.end.get() { + self.grow::(slice.len()); + } + + unsafe { + let arena_slice = slice::from_raw_parts_mut(self.ptr.get() as *mut T, slice.len()); + self.ptr.set(intrinsics::arith_offset( + self.ptr.get(), (slice.len() * mem::size_of::()) as isize + ) as *mut u8); + arena_slice.copy_from_slice(slice); + arena_slice + } + } +} + #[cfg(test)] mod tests { extern crate test; diff --git a/src/libbacktrace/pecoff.c b/src/libbacktrace/pecoff.c index 04e0bafb14..2d6a987721 100644 --- a/src/libbacktrace/pecoff.c +++ b/src/libbacktrace/pecoff.c @@ -607,7 +607,9 @@ coff_add (struct backtrace_state *state, int descriptor, // against the upstream libbacktrace, that's what's going on. uint32_t str_size; off_t str_off; - struct backtrace_view syms_view; + // NOTE: upstream doesn't have `{0}`, this is a fix for Rust issue #39468. + // If syms_view is not initialized, then `free(syms_view.base)` may segfault later. + struct backtrace_view syms_view = {0}; off_t syms_off; size_t syms_size; int syms_view_valid; diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml index ab882fde9c..186ba6e8f2 100644 --- a/src/libcollections/Cargo.toml +++ b/src/libcollections/Cargo.toml @@ -16,6 +16,7 @@ std_unicode = { path = "../libstd_unicode" } name = "collectionstest" path = "../libcollectionstest/lib.rs" -[[bench]] -name = "collectionstest" -path = "../libcollectionstest/lib.rs" +# FIXME: need to extract benchmarks to separate crate +#[[bench]] +#name = "collectionstest" +#path = "../libcollectionstest/lib.rs" diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 8d0c76c364..b7c2a708ba 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -151,10 +151,9 @@ #![allow(missing_docs)] #![stable(feature = "rust1", since = "1.0.0")] -use core::ops::{Deref, DerefMut}; +use core::ops::{Deref, DerefMut, Place, Placer, InPlace}; use core::iter::{FromIterator, FusedIterator}; -use core::mem::swap; -use core::mem::size_of; +use core::mem::{swap, size_of}; use core::ptr; use core::fmt; @@ -225,13 +224,16 @@ pub struct BinaryHeap { /// [`peek_mut()`]: struct.BinaryHeap.html#method.peek_mut #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub struct PeekMut<'a, T: 'a + Ord> { - heap: &'a mut BinaryHeap + heap: &'a mut BinaryHeap, + sift: bool, } #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl<'a, T: Ord> Drop for PeekMut<'a, T> { fn drop(&mut self) { - self.heap.sift_down(0); + if self.sift { + self.heap.sift_down(0); + } } } @@ -250,6 +252,16 @@ impl<'a, T: Ord> DerefMut for PeekMut<'a, T> { } } +impl<'a, T: Ord> PeekMut<'a, T> { + /// Removes the peeked value from the heap and returns it. + #[unstable(feature = "binary_heap_peek_mut_pop", issue = "38863")] + pub fn pop(mut this: PeekMut<'a, T>) -> T { + let value = this.heap.pop().unwrap(); + this.sift = false; + value + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for BinaryHeap { fn clone(&self) -> Self { @@ -386,7 +398,8 @@ impl BinaryHeap { None } else { Some(PeekMut { - heap: self + heap: self, + sift: true, }) } } @@ -660,7 +673,7 @@ impl BinaryHeap { // the hole is filled back at the end of its scope, even on panic. // Using a hole reduces the constant factor compared to using swaps, // which involves twice as many moves. - fn sift_up(&mut self, start: usize, pos: usize) { + fn sift_up(&mut self, start: usize, pos: usize) -> usize { unsafe { // Take out the value at `pos` and create a hole. let mut hole = Hole::new(&mut self.data, pos); @@ -672,6 +685,7 @@ impl BinaryHeap { } hole.move_to(parent); } + hole.pos() } } @@ -1126,7 +1140,9 @@ impl IntoIterator for BinaryHeap { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a BinaryHeap where T: Ord { +impl<'a, T> IntoIterator for &'a BinaryHeap + where T: Ord +{ type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1174,3 +1190,56 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap { self.extend(iter.into_iter().cloned()); } } + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +pub struct BinaryHeapPlace<'a, T: 'a> +where T: Clone + Ord { + heap: *mut BinaryHeap, + place: vec::PlaceBack<'a, T>, +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T: 'a> Placer for &'a mut BinaryHeap +where T: Clone + Ord { + type Place = BinaryHeapPlace<'a, T>; + + fn make_place(self) -> Self::Place { + let ptr = self as *mut BinaryHeap; + let place = Placer::make_place(self.data.place_back()); + BinaryHeapPlace { + heap: ptr, + place: place, + } + } +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> Place for BinaryHeapPlace<'a, T> +where T: Clone + Ord { + fn pointer(&mut self) -> *mut T { + self.place.pointer() + } +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> InPlace for BinaryHeapPlace<'a, T> +where T: Clone + Ord { + type Owner = &'a T; + + unsafe fn finalize(self) -> &'a T { + self.place.finalize(); + + let heap: &mut BinaryHeap = &mut *self.heap; + let len = heap.len(); + let i = heap.sift_up(0, len - 1); + heap.data.get_unchecked(i) + } +} diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 37618b7600..e5bcf0d8e8 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -63,7 +63,9 @@ pub trait ToOwned { } #[stable(feature = "rust1", since = "1.0.0")] -impl ToOwned for T where T: Clone { +impl ToOwned for T + where T: Clone +{ type Owned = T; fn to_owned(&self) -> T { self.clone() @@ -117,17 +119,19 @@ pub enum Cow<'a, B: ?Sized + 'a> { /// Borrowed data. #[stable(feature = "rust1", since = "1.0.0")] - Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B), + Borrowed(#[stable(feature = "rust1", since = "1.0.0")] + &'a B), /// Owned data. #[stable(feature = "rust1", since = "1.0.0")] - Owned( - #[stable(feature = "rust1", since = "1.0.0")] ::Owned - ), + Owned(#[stable(feature = "rust1", since = "1.0.0")] + ::Owned), } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned { +impl<'a, B: ?Sized> Clone for Cow<'a, B> + where B: ToOwned +{ fn clone(&self) -> Cow<'a, B> { match *self { Borrowed(b) => Borrowed(b), @@ -139,7 +143,9 @@ impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned { } } -impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { +impl<'a, B: ?Sized> Cow<'a, B> + where B: ToOwned +{ /// Acquires a mutable reference to the owned form of the data. /// /// Clones the data if it is not already owned. @@ -194,7 +200,9 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned { +impl<'a, B: ?Sized> Deref for Cow<'a, B> + where B: ToOwned +{ type Target = B; fn deref(&self) -> &B { @@ -209,7 +217,9 @@ impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned { impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {} #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned { +impl<'a, B: ?Sized> Ord for Cow<'a, B> + where B: Ord + ToOwned +{ #[inline] fn cmp(&self, other: &Cow<'a, B>) -> Ordering { Ord::cmp(&**self, &**other) @@ -228,7 +238,9 @@ impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned { +impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> + where B: PartialOrd + ToOwned +{ #[inline] fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { PartialOrd::partial_cmp(&**self, &**other) @@ -273,7 +285,9 @@ impl<'a, B: ?Sized> Default for Cow<'a, B> } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned { +impl<'a, B: ?Sized> Hash for Cow<'a, B> + where B: Hash + ToOwned +{ #[inline] fn hash(&self, state: &mut H) { Hash::hash(&**self, state) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 788236c24d..4755f8a4c5 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -17,7 +17,8 @@ use core::ops::Index; use core::{fmt, intrinsics, mem, ptr}; use borrow::Borrow; -use Bound::{self, Excluded, Included, Unbounded}; +use Bound::{Excluded, Included, Unbounded}; +use range::RangeArgument; use super::node::{self, Handle, NodeRef, marker}; use super::search; @@ -137,8 +138,7 @@ pub struct BTreeMap { } #[stable(feature = "btree_drop", since = "1.7.0")] -impl Drop for BTreeMap { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap { fn drop(&mut self) { unsafe { for _ in ptr::read(self).into_iter() { @@ -655,10 +655,12 @@ impl BTreeMap { self.fix_right_edge(); } - /// Constructs a double-ended iterator over a sub-range of elements in the map, starting - /// at min, and ending at max. If min is `Unbounded`, then it will be treated as "negative - /// infinity", and if max is `Unbounded`, then it will be treated as "positive infinity". - /// Thus range(Unbounded, Unbounded) will yield the whole collection. + /// Constructs a double-ended iterator over a sub-range of elements in the map. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. /// /// # Examples /// @@ -668,26 +670,25 @@ impl BTreeMap { /// #![feature(btree_range, collections_bound)] /// /// use std::collections::BTreeMap; - /// use std::collections::Bound::{Included, Unbounded}; + /// use std::collections::Bound::Included; /// /// let mut map = BTreeMap::new(); /// map.insert(3, "a"); /// map.insert(5, "b"); /// map.insert(8, "c"); - /// for (&key, &value) in map.range(Included(&4), Included(&8)) { + /// for (&key, &value) in map.range((Included(&4), Included(&8))) { /// println!("{}: {}", key, value); /// } - /// assert_eq!(Some((&5, &"b")), map.range(Included(&4), Unbounded).next()); + /// assert_eq!(Some((&5, &"b")), map.range(4..).next()); /// ``` #[unstable(feature = "btree_range", reason = "matches collection reform specification, waiting for dust to settle", issue = "27787")] - pub fn range(&self, - min: Bound<&Min>, - max: Bound<&Max>) - -> Range - where K: Borrow + Borrow + pub fn range(&self, range: R) -> Range + where T: Ord, K: Borrow, R: RangeArgument { + let min = range.start(); + let max = range.end(); let front = match min { Included(key) => { match search::search_tree(self.root.as_ref(), key) { @@ -746,25 +747,26 @@ impl BTreeMap { } } - /// Constructs a mutable double-ended iterator over a sub-range of elements in the map, starting - /// at min, and ending at max. If min is `Unbounded`, then it will be treated as "negative - /// infinity", and if max is `Unbounded`, then it will be treated as "positive infinity". - /// Thus range(Unbounded, Unbounded) will yield the whole collection. + /// Constructs a mutable double-ended iterator over a sub-range of elements in the map. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. /// /// # Examples /// /// Basic usage: /// /// ``` - /// #![feature(btree_range, collections_bound)] + /// #![feature(btree_range)] /// /// use std::collections::BTreeMap; - /// use std::collections::Bound::{Included, Excluded}; /// /// let mut map: BTreeMap<&str, i32> = ["Alice", "Bob", "Carol", "Cheryl"].iter() /// .map(|&s| (s, 0)) /// .collect(); - /// for (_, balance) in map.range_mut(Included("B"), Excluded("Cheryl")) { + /// for (_, balance) in map.range_mut("B".."Cheryl") { /// *balance += 100; /// } /// for (name, balance) in &map { @@ -774,12 +776,11 @@ impl BTreeMap { #[unstable(feature = "btree_range", reason = "matches collection reform specification, waiting for dust to settle", issue = "27787")] - pub fn range_mut(&mut self, - min: Bound<&Min>, - max: Bound<&Max>) - -> RangeMut - where K: Borrow + Borrow + pub fn range_mut(&mut self, range: R) -> RangeMut + where T: Ord, K: Borrow, R: RangeArgument { + let min = range.start(); + let max = range.end(); let root1 = self.root.as_mut(); let root2 = unsafe { ptr::read(&root1) }; @@ -1991,11 +1992,11 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { /// use std::collections::BTreeMap; /// /// let mut map: BTreeMap<&str, String> = BTreeMap::new(); - /// let s = "hoho".to_owned(); + /// let s = "hoho".to_string(); /// /// map.entry("poneyland").or_insert_with(|| s); /// - /// assert_eq!(map["poneyland"], "hoho".to_owned()); + /// assert_eq!(map["poneyland"], "hoho".to_string()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index c57266d9e3..f006ba9537 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -21,7 +21,7 @@ use core::ops::{BitOr, BitAnd, BitXor, Sub}; use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use super::Recover; -use Bound; +use range::RangeArgument; // FIXME(conventions): implement bounded iterators @@ -74,24 +74,44 @@ pub struct BTreeSet { map: BTreeMap, } -/// An iterator over a BTreeSet's items. +/// An iterator over a `BTreeSet`'s items. +/// +/// This structure is created by the [`iter`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`iter`]: struct.BTreeSet.html#method.iter #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { iter: Keys<'a, T, ()>, } -/// An owning iterator over a BTreeSet's items. +/// An owning iterator over a `BTreeSet`'s items. +/// +/// This structure is created by the `into_iter` method on [`BTreeSet`] +/// [`BTreeSet`] (provided by the `IntoIterator` trait). +/// +/// [`BTreeSet`]: struct.BTreeSet.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { iter: ::btree_map::IntoIter, } -/// An iterator over a sub-range of BTreeSet's items. +/// An iterator over a sub-range of `BTreeSet`'s items. +/// +/// This structure is created by the [`range`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`range`]: struct.BTreeSet.html#method.range pub struct Range<'a, T: 'a> { iter: ::btree_map::Range<'a, T, ()>, } /// A lazy iterator producing elements in the set difference (in-order). +/// +/// This structure is created by the [`difference`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`difference`]: struct.BTreeSet.html#method.difference #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference<'a, T: 'a> { a: Peekable>, @@ -99,6 +119,12 @@ pub struct Difference<'a, T: 'a> { } /// A lazy iterator producing elements in the set symmetric difference (in-order). +/// +/// This structure is created by the [`symmetric_difference`] method on +/// [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference #[stable(feature = "rust1", since = "1.0.0")] pub struct SymmetricDifference<'a, T: 'a> { a: Peekable>, @@ -106,6 +132,11 @@ pub struct SymmetricDifference<'a, T: 'a> { } /// A lazy iterator producing elements in the set intersection (in-order). +/// +/// This structure is created by the [`intersection`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`intersection`]: struct.BTreeSet.html#method.intersection #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection<'a, T: 'a> { a: Peekable>, @@ -113,6 +144,11 @@ pub struct Intersection<'a, T: 'a> { } /// A lazy iterator producing elements in the set union (in-order). +/// +/// This structure is created by the [`union`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`union`]: struct.BTreeSet.html#method.union #[stable(feature = "rust1", since = "1.0.0")] pub struct Union<'a, T: 'a> { a: Peekable>, @@ -120,7 +156,7 @@ pub struct Union<'a, T: 'a> { } impl BTreeSet { - /// Makes a new BTreeSet with a reasonable choice of B. + /// Makes a new `BTreeSet` with a reasonable choice of B. /// /// # Examples /// @@ -137,21 +173,32 @@ impl BTreeSet { } impl BTreeSet { - /// Gets an iterator over the BTreeSet's contents. + /// Gets an iterator that visits the values in the `BTreeSet` in ascending order. /// /// # Examples /// /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); + /// let set: BTreeSet = [1, 2, 3].iter().cloned().collect(); + /// let mut set_iter = set.iter(); + /// assert_eq!(set_iter.next(), Some(&1)); + /// assert_eq!(set_iter.next(), Some(&2)); + /// assert_eq!(set_iter.next(), Some(&3)); + /// assert_eq!(set_iter.next(), None); + /// ``` /// - /// for x in set.iter() { - /// println!("{}", x); - /// } + /// Values returned by the iterator are returned in ascending order: /// - /// let v: Vec<_> = set.iter().cloned().collect(); - /// assert_eq!(v, [1, 2, 3, 4]); + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet = [3, 1, 2].iter().cloned().collect(); + /// let mut set_iter = set.iter(); + /// assert_eq!(set_iter.next(), Some(&1)); + /// assert_eq!(set_iter.next(), Some(&2)); + /// assert_eq!(set_iter.next(), Some(&3)); + /// assert_eq!(set_iter.next(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { @@ -160,10 +207,12 @@ impl BTreeSet { } impl BTreeSet { - /// Constructs a double-ended iterator over a sub-range of elements in the set, starting - /// at min, and ending at max. If min is `Unbounded`, then it will be treated as "negative - /// infinity", and if max is `Unbounded`, then it will be treated as "positive infinity". - /// Thus range(Unbounded, Unbounded) will yield the whole collection. + /// Constructs a double-ended iterator over a sub-range of elements in the set. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. /// /// # Examples /// @@ -171,27 +220,24 @@ impl BTreeSet { /// #![feature(btree_range, collections_bound)] /// /// use std::collections::BTreeSet; - /// use std::collections::Bound::{Included, Unbounded}; + /// use std::collections::Bound::Included; /// /// let mut set = BTreeSet::new(); /// set.insert(3); /// set.insert(5); /// set.insert(8); - /// for &elem in set.range(Included(&4), Included(&8)) { + /// for &elem in set.range((Included(&4), Included(&8))) { /// println!("{}", elem); /// } - /// assert_eq!(Some(&5), set.range(Included(&4), Unbounded).next()); + /// assert_eq!(Some(&5), set.range(4..).next()); /// ``` #[unstable(feature = "btree_range", reason = "matches collection reform specification, waiting for dust to settle", issue = "27787")] - pub fn range<'a, Min: ?Sized + Ord, Max: ?Sized + Ord>(&'a self, - min: Bound<&Min>, - max: Bound<&Max>) - -> Range<'a, T> - where T: Borrow + Borrow + pub fn range(&self, range: R) -> Range + where K: Ord, T: Borrow, R: RangeArgument { - Range { iter: self.map.range(min, max) } + Range { iter: self.map.range(range) } } } diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 79e0021b14..78b6107977 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -17,6 +17,8 @@ reason = "matches collection reform specification, \ waiting for dust to settle", issue = "37966")] +#![rustc_deprecated(since = "1.16.0", reason = "long since replaced")] +#![allow(deprecated)] use core::marker; use core::fmt; @@ -276,7 +278,8 @@ impl FromIterator for EnumSet { } } -impl<'a, E> IntoIterator for &'a EnumSet where E: CLike +impl<'a, E> IntoIterator for &'a EnumSet + where E: CLike { type Item = E; type IntoIter = Iter; diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 68b067012d..39de87c084 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -27,7 +27,7 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![cfg_attr(test, allow(deprecated))] // rand -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(alloc)] #![feature(allow_internal_unstable)] @@ -35,16 +35,18 @@ #![feature(box_syntax)] #![cfg_attr(not(test), feature(char_escape_debug))] #![feature(core_intrinsics)] -#![feature(dropck_parametricity)] +#![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] #![feature(fused)] +#![feature(generic_param_attrs)] #![feature(heap_api)] #![feature(inclusive_range)] #![feature(lang_items)] #![feature(nonzero)] #![feature(pattern)] #![feature(placement_in)] +#![feature(placement_in_syntax)] #![feature(placement_new_protocol)] #![feature(shared)] #![feature(slice_get_slice)] @@ -77,6 +79,7 @@ pub use btree_set::BTreeSet; #[doc(no_inline)] pub use linked_list::LinkedList; #[doc(no_inline)] +#[allow(deprecated)] pub use enum_set::EnumSet; #[doc(no_inline)] pub use vec_deque::VecDeque; diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 67f3708a62..7f913d4afe 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -10,8 +10,15 @@ //! A doubly-linked list with owned nodes. //! -//! The `LinkedList` allows pushing and popping elements at either end and is thus -//! efficiently usable as a double-ended queue. +//! The `LinkedList` allows pushing and popping elements at either end +//! in constant time. +//! +//! Almost always it is better to use `Vec` or [`VecDeque`] instead of +//! [`LinkedList`]. In general, array-based containers are faster, +//! more memory efficient and make better use of CPU cache. +//! +//! [`LinkedList`]: ../linked_list/struct.LinkedList.html +//! [`VecDeque`]: ../vec_deque/struct.VecDeque.html #![stable(feature = "rust1", since = "1.0.0")] @@ -27,7 +34,14 @@ use core::ptr::{self, Shared}; use super::SpecExtend; -/// A doubly-linked list. +/// A doubly-linked list with owned nodes. +/// +/// The `LinkedList` allows pushing and popping elements at either end +/// in constant time. +/// +/// Almost always it is better to use `Vec` or `VecDeque` instead of +/// `LinkedList`. In general, array-based containers are faster, +/// more memory efficient and make better use of CPU cache. #[stable(feature = "rust1", since = "1.0.0")] pub struct LinkedList { head: Option>>, @@ -225,15 +239,17 @@ impl LinkedList { pub fn append(&mut self, other: &mut Self) { match self.tail { None => mem::swap(self, other), - Some(tail) => if let Some(other_head) = other.head.take() { - unsafe { - (**tail).next = Some(other_head); - (**other_head).prev = Some(tail); - } + Some(tail) => { + if let Some(other_head) = other.head.take() { + unsafe { + (**tail).next = Some(other_head); + (**other_head).prev = Some(tail); + } - self.tail = other.tail.take(); - self.len += mem::replace(&mut other.len, 0); - }, + self.tail = other.tail.take(); + self.len += mem::replace(&mut other.len, 0); + } + } } } @@ -674,7 +690,10 @@ impl LinkedList { reason = "method name and placement protocol are subject to change", issue = "30172")] pub fn front_place(&mut self) -> FrontPlace { - FrontPlace { list: self, node: IntermediateBox::make_place() } + FrontPlace { + list: self, + node: IntermediateBox::make_place(), + } } /// Returns a place for insertion at the back of the list. @@ -699,13 +718,15 @@ impl LinkedList { reason = "method name and placement protocol are subject to change", issue = "30172")] pub fn back_place(&mut self) -> BackPlace { - BackPlace { list: self, node: IntermediateBox::make_place() } + BackPlace { + list: self, + node: IntermediateBox::make_place(), + } } } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for LinkedList { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for LinkedList { fn drop(&mut self) { while let Some(_) = self.pop_front_node() {} } @@ -852,7 +873,7 @@ impl<'a, T> IterMut<'a, T> { (**head).prev = node; self.list.len += 1; - } + }, } } @@ -1135,9 +1156,15 @@ impl<'a, T> InPlace for BackPlace<'a, T> { // Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters. #[allow(dead_code)] fn assert_covariance() { - fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> { x } - fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> { x } - fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> { x } + fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> { + x + } + fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> { + x + } + fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> { + x + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1298,10 +1325,10 @@ mod tests { fn test_send() { let n = list_from(&[1, 2, 3]); thread::spawn(move || { - check_links(&n); - let a: &[_] = &[&1, &2, &3]; - assert_eq!(a, &n.iter().collect::>()[..]); - }) + check_links(&n); + let a: &[_] = &[&1, &2, &3]; + assert_eq!(a, &n.iter().collect::>()[..]); + }) .join() .ok() .unwrap(); diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs index d331ead2c5..1df4ace377 100644 --- a/src/libcollections/range.rs +++ b/src/libcollections/range.rs @@ -15,78 +15,120 @@ //! Range syntax. use core::ops::{RangeFull, Range, RangeTo, RangeFrom}; +use Bound::{self, Excluded, Included, Unbounded}; /// **RangeArgument** is implemented by Rust's built-in range types, produced /// by range syntax like `..`, `a..`, `..b` or `c..d`. -pub trait RangeArgument { - /// Start index (inclusive) +pub trait RangeArgument { + /// Start index bound /// - /// Return start value if present, else `None`. + /// Return start value as a `Bound` /// /// # Examples /// /// ``` /// #![feature(collections)] /// #![feature(collections_range)] + /// #![feature(collections_bound)] /// /// extern crate collections; /// /// # fn main() { /// use collections::range::RangeArgument; + /// use collections::Bound::*; /// - /// assert_eq!((..10).start(), None); - /// assert_eq!((3..10).start(), Some(&3)); + /// assert_eq!((..10).start(), Unbounded); + /// assert_eq!((3..10).start(), Included(&3)); /// # } /// ``` - fn start(&self) -> Option<&T> { - None - } + fn start(&self) -> Bound<&T>; - /// End index (exclusive) + /// End index bound /// - /// Return end value if present, else `None`. + /// Return end value as a `Bound` /// /// # Examples /// /// ``` /// #![feature(collections)] /// #![feature(collections_range)] + /// #![feature(collections_bound)] /// /// extern crate collections; /// /// # fn main() { /// use collections::range::RangeArgument; + /// use collections::Bound::*; /// - /// assert_eq!((3..).end(), None); - /// assert_eq!((3..10).end(), Some(&10)); + /// assert_eq!((3..).end(), Unbounded); + /// assert_eq!((3..10).end(), Excluded(&10)); /// # } /// ``` - fn end(&self) -> Option<&T> { - None - } + fn end(&self) -> Bound<&T>; } // FIXME add inclusive ranges to RangeArgument -impl RangeArgument for RangeFull {} +impl RangeArgument for RangeFull { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} impl RangeArgument for RangeFrom { - fn start(&self) -> Option<&T> { - Some(&self.start) + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Unbounded } } impl RangeArgument for RangeTo { - fn end(&self) -> Option<&T> { - Some(&self.end) + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) } } impl RangeArgument for Range { - fn start(&self) -> Option<&T> { - Some(&self.start) + fn start(&self) -> Bound<&T> { + Included(&self.start) } - fn end(&self) -> Option<&T> { - Some(&self.end) + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +impl RangeArgument for (Bound, Bound) { + fn start(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } + + fn end(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } +} + +impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { + fn start(&self) -> Bound<&T> { + self.0 + } + + fn end(&self) -> Bound<&T> { + self.1 } } diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 5fb8cd6e1e..11f513ed79 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -181,7 +181,7 @@ impl [T] { core_slice::SliceExt::len(self) } - /// Returns true if the slice has a length of 0. + /// Returns `true` if the slice has a length of 0. /// /// # Example /// @@ -342,15 +342,22 @@ impl [T] { core_slice::SliceExt::last_mut(self) } - /// Returns the element of a slice at the given index, or `None` if the - /// index is out of bounds. + /// Returns a reference to an element or subslice depending on the type of + /// index. + /// + /// - If given a position, returns a reference to the element at that + /// position or `None` if out of bounds. + /// - If given a range, returns the subslice corresponding to that range, + /// or `None` if out of bounds. /// /// # Examples /// /// ``` /// let v = [10, 40, 30]; /// assert_eq!(Some(&40), v.get(1)); + /// assert_eq!(Some(&[10, 40][..]), v.get(0..2)); /// assert_eq!(None, v.get(3)); + /// assert_eq!(None, v.get(0..4)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -360,7 +367,10 @@ impl [T] { core_slice::SliceExt::get(self, index) } - /// Returns a mutable reference to the element at the given index. + /// Returns a mutable reference to an element or subslice depending on the + /// type of index (see [`get()`]) or `None` if the index is out of bounds. + /// + /// [`get()`]: #method.get /// /// # Examples /// @@ -372,7 +382,6 @@ impl [T] { /// } /// assert_eq!(x, &[0, 42, 2]); /// ``` - /// or `None` if the index is out of bounds #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn get_mut(&mut self, index: I) -> Option<&mut I::Output> @@ -381,8 +390,8 @@ impl [T] { core_slice::SliceExt::get_mut(self, index) } - /// Returns a pointer to the element at the given index, without doing - /// bounds checking. So use it very carefully! + /// Returns a reference to an element or subslice, without doing bounds + /// checking. So use it very carefully! /// /// # Examples /// @@ -401,8 +410,8 @@ impl [T] { core_slice::SliceExt::get_unchecked(self, index) } - /// Returns an unsafe mutable pointer to the element in index. So use it - /// very carefully! + /// Returns a mutable reference to an element or subslice, without doing + /// bounds checking. So use it very carefully! /// /// # Examples /// @@ -423,7 +432,7 @@ impl [T] { core_slice::SliceExt::get_unchecked_mut(self, index) } - /// Returns an raw pointer to the slice's buffer. + /// Returns a raw pointer to the slice's buffer. /// /// The caller must ensure that the slice outlives the pointer this /// function returns, or else it will end up pointing to garbage. @@ -500,7 +509,7 @@ impl [T] { core_slice::SliceExt::swap(self, a, b) } - /// Reverse the order of elements in a slice, in place. + /// Reverses the order of elements in a slice, in place. /// /// # Example /// @@ -540,12 +549,8 @@ impl [T] { /// /// ``` /// let x = &mut [1, 2, 4]; - /// { - /// let iterator = x.iter_mut(); - /// - /// for elem in iterator { - /// *elem += 2; - /// } + /// for elem in x.iter_mut() { + /// *elem += 2; /// } /// assert_eq!(x, &[3, 4, 6]); /// ``` @@ -880,7 +885,7 @@ impl [T] { core_slice::SliceExt::rsplitn_mut(self, n, pred) } - /// Returns true if the slice contains an element with the given value. + /// Returns `true` if the slice contains an element with the given value. /// /// # Examples /// @@ -896,7 +901,7 @@ impl [T] { core_slice::SliceExt::contains(self, x) } - /// Returns true if `needle` is a prefix of the slice. + /// Returns `true` if `needle` is a prefix of the slice. /// /// # Examples /// @@ -907,6 +912,15 @@ impl [T] { /// assert!(!v.starts_with(&[50])); /// assert!(!v.starts_with(&[10, 50])); /// ``` + /// + /// Always returns `true` if `needle` is an empty slice: + /// + /// ``` + /// let v = &[10, 40, 30]; + /// assert!(v.starts_with(&[])); + /// let v: &[u8] = &[]; + /// assert!(v.starts_with(&[])); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq @@ -914,7 +928,7 @@ impl [T] { core_slice::SliceExt::starts_with(self, needle) } - /// Returns true if `needle` is a suffix of the slice. + /// Returns `true` if `needle` is a suffix of the slice. /// /// # Examples /// @@ -925,6 +939,15 @@ impl [T] { /// assert!(!v.ends_with(&[50])); /// assert!(!v.ends_with(&[50, 30])); /// ``` + /// + /// Always returns `true` if `needle` is an empty slice: + /// + /// ``` + /// let v = &[10, 40, 30]; + /// assert!(v.ends_with(&[])); + /// let v: &[u8] = &[]; + /// assert!(v.ends_with(&[])); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq @@ -1039,10 +1062,19 @@ impl [T] { core_slice::SliceExt::binary_search_by_key(self, b, f) } - /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. + /// Sorts the slice. + /// + /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. + /// + /// # Current implementation + /// + /// The current algorithm is an adaptive, iterative merge sort inspired by + /// [timsort](https://en.wikipedia.org/wiki/Timsort). + /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of + /// two or more sorted sequences concatenated one after another. /// - /// This sort is stable and `O(n log n)` worst-case, but allocates - /// temporary storage half the size of `self`. + /// Also, it allocates temporary storage half the size of `self`, but for short slices a + /// non-allocating insertion sort is used instead. /// /// # Examples /// @@ -1060,11 +1092,19 @@ impl [T] { self.sort_by(|a, b| a.cmp(b)) } - /// Sorts the slice, in place, using `f` to extract a key by which to - /// order the sort by. + /// Sorts the slice using `f` to extract a key to compare elements by. /// - /// This sort is stable and `O(n log n)` worst-case, but allocates - /// temporary storage half the size of `self`. + /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. + /// + /// # Current implementation + /// + /// The current algorithm is an adaptive, iterative merge sort inspired by + /// [timsort](https://en.wikipedia.org/wiki/Timsort). + /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of + /// two or more sorted sequences concatenated one after another. + /// + /// Also, it allocates temporary storage half the size of `self`, but for short slices a + /// non-allocating insertion sort is used instead. /// /// # Examples /// @@ -1082,11 +1122,19 @@ impl [T] { self.sort_by(|a, b| f(a).cmp(&f(b))) } - /// Sorts the slice, in place, using `compare` to compare - /// elements. + /// Sorts the slice using `compare` to compare elements. + /// + /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. + /// + /// # Current implementation + /// + /// The current algorithm is an adaptive, iterative merge sort inspired by + /// [timsort](https://en.wikipedia.org/wiki/Timsort). + /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of + /// two or more sorted sequences concatenated one after another. /// - /// This sort is stable and `O(n log n)` worst-case, but allocates - /// temporary storage half the size of `self`. + /// Also, it allocates temporary storage half the size of `self`, but for short slices a + /// non-allocating insertion sort is used instead. /// /// # Examples /// @@ -1496,10 +1544,10 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F) /// The algorithm identifies strictly descending and non-descending subsequences, which are called /// natural runs. There is a stack of pending runs yet to be merged. Each newly found run is pushed /// onto the stack, and then some pairs of adjacent runs are merged until these two invariants are -/// satisfied, for every `i` in `0 .. runs.len() - 2`: +/// satisfied: /// -/// 1. `runs[i].len > runs[i + 1].len` -/// 2. `runs[i].len > runs[i + 1].len + runs[i + 2].len` +/// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len` +/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len` /// /// The invariants ensure that the total running time is `O(n log n)` worst-case. fn merge_sort(v: &mut [T], mut compare: F) @@ -1512,7 +1560,7 @@ fn merge_sort(v: &mut [T], mut compare: F) // FIXME #12092: These numbers are platform-specific and need more extensive testing/tuning. // - // If `v` has length up to `insertion_len`, simply switch to insertion sort because it is going + // If `v` has length up to `max_insertion`, simply switch to insertion sort because it is going // to perform better than merge sort. For bigger types `T`, the threshold is smaller. // // Short runs are extended using insertion sort to span at least `min_run` elements, in order diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index d4be0914f1..458d511482 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1607,7 +1607,6 @@ impl str { /// Basic usage: /// /// ``` - /// # #![feature(str_replacen)] /// let s = "foo foo 123 foo"; /// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2)); /// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3)); @@ -1617,13 +1616,10 @@ impl str { /// When the pattern doesn't match: /// /// ``` - /// # #![feature(str_replacen)] /// let s = "this is old"; /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); /// ``` - #[unstable(feature = "str_replacen", - issue = "36436", - reason = "only need to replace first N matches")] + #[stable(feature = "str_replacen", since = "1.16.0")] pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String { // Hope to reduce the times of re-allocation let mut result = String::with_capacity(32); @@ -1697,11 +1693,7 @@ impl str { debug_assert!('Σ'.len_utf8() == 2); let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) && !case_ignoreable_then_cased(from[i + 2..].chars()); - to.push_str(if is_word_final { - "ς" - } else { - "σ" - }); + to.push_str(if is_word_final { "ς" } else { "σ" }); } fn case_ignoreable_then_cased>(iter: I) -> bool { @@ -1799,11 +1791,9 @@ impl str { /// Basic usage: /// /// ``` - /// #![feature(repeat_str)] - /// /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); /// ``` - #[unstable(feature = "repeat_str", issue = "37079")] + #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { let mut s = String::with_capacity(self.len() * n); s.extend((0..n).map(|_| self)); diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index b4c41a99a6..b184a8603e 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -68,6 +68,7 @@ use std_unicode::str as unicode_str; use borrow::{Cow, ToOwned}; use range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; use str::{self, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; @@ -542,11 +543,7 @@ impl String { unsafe { *xs.get_unchecked(i) } } fn safe_get(xs: &[u8], i: usize, total: usize) -> u8 { - if i >= total { - 0 - } else { - unsafe_get(xs, i) - } + if i >= total { 0 } else { unsafe_get(xs, i) } } let mut res = String::with_capacity(total); @@ -976,7 +973,7 @@ impl String { pub fn push(&mut self, ch: char) { match ch.len_utf8() { 1 => self.vec.push(ch as u8), - _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0;4]).as_bytes()), + _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()), } } @@ -1169,8 +1166,6 @@ impl String { /// Basic usage: /// /// ``` - /// #![feature(insert_str)] - /// /// let mut s = String::from("bar"); /// /// s.insert_str(0, "foo"); @@ -1178,9 +1173,7 @@ impl String { /// assert_eq!("foobar", s); /// ``` #[inline] - #[unstable(feature = "insert_str", - reason = "recent addition", - issue = "35553")] + #[stable(feature = "insert_str", since = "1.16.0")] pub fn insert_str(&mut self, idx: usize, string: &str) { assert!(self.is_char_boundary(idx)); @@ -1273,7 +1266,6 @@ impl String { /// # Examples /// /// ``` - /// # #![feature(string_split_off)] /// # fn main() { /// let mut hello = String::from("Hello, World!"); /// let world = hello.split_off(7); @@ -1282,7 +1274,7 @@ impl String { /// # } /// ``` #[inline] - #[unstable(feature = "string_split_off", issue = "38080")] + #[stable(feature = "string_split_off", since = "1.16.0")] pub fn split_off(&mut self, mid: usize) -> String { assert!(self.is_char_boundary(mid)); let other = self.vec.split_off(mid); @@ -1354,8 +1346,16 @@ impl String { // Because the range removal happens in Drop, if the Drain iterator is leaked, // the removal will not happen. let len = self.len(); - let start = *range.start().unwrap_or(&0); - let end = *range.end().unwrap_or(&len); + let start = match range.start() { + Included(&n) => n, + Excluded(&n) => n + 1, + Unbounded => 0, + }; + let end = match range.end() { + Included(&n) => n + 1, + Excluded(&n) => n, + Unbounded => len, + }; // Take out two simultaneous borrows. The &mut String won't be accessed // until iteration is over, in Drop. @@ -1935,7 +1935,7 @@ impl<'a> FromIterator for Cow<'a, str> { #[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] impl From for Vec { - fn from(string : String) -> Vec { + fn from(string: String) -> Vec { string.into_bytes() } } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index e212592eda..c45518438b 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -77,13 +77,14 @@ use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::mem; -use core::ops::{Index, IndexMut}; +use core::ops::{InPlace, Index, IndexMut, Place, Placer}; use core::ops; use core::ptr; use core::ptr::Shared; use core::slice; use super::range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// @@ -370,7 +371,8 @@ impl Vec { /// * `capacity` needs to be the capacity that the pointer was allocated with. /// /// Violating these may cause problems like corrupting the allocator's - /// internal datastructures. + /// internal datastructures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array and a `size_t`. /// /// The ownership of `ptr` is effectively transferred to the /// `Vec` which may then deallocate, reallocate or change the @@ -818,15 +820,13 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(dedup_by)] - /// /// let mut vec = vec![10, 20, 21, 30, 20]; /// /// vec.dedup_by_key(|i| *i / 10); /// /// assert_eq!(vec, [10, 20, 30, 20]); /// ``` - #[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")] + #[stable(feature = "dedup_by", since = "1.16.0")] #[inline] pub fn dedup_by_key(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq { self.dedup_by(|a, b| key(a) == key(b)) @@ -839,7 +839,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(dedup_by)] /// use std::ascii::AsciiExt; /// /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; @@ -848,7 +847,7 @@ impl Vec { /// /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); /// ``` - #[unstable(feature = "dedup_by", reason = "recently added", issue = "37087")] + #[stable(feature = "dedup_by", since = "1.16.0")] pub fn dedup_by(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool { unsafe { // Although we have a mutable reference to `self`, we cannot make @@ -1021,8 +1020,8 @@ impl Vec { /// Create a draining iterator that removes the specified range in the vector /// and yields the removed items. /// - /// Note 1: The element range is removed even if the iterator is not - /// consumed until the end. + /// Note 1: The element range is removed even if the iterator is only + /// partially consumed or not consumed at all. /// /// Note 2: It is unspecified how many elements are removed from the vector, /// if the `Drain` value is leaked. @@ -1059,8 +1058,16 @@ impl Vec { // the hole, and the vector length is restored to the new length. // let len = self.len(); - let start = *range.start().unwrap_or(&0); - let end = *range.end().unwrap_or(&len); + let start = match range.start() { + Included(&n) => n, + Excluded(&n) => n + 1, + Unbounded => 0, + }; + let end = match range.end() { + Included(&n) => n + 1, + Excluded(&n) => n, + Unbounded => len, + }; assert!(start <= end); assert!(end <= len); @@ -1246,6 +1253,29 @@ impl Vec { pub fn extend_from_slice(&mut self, other: &[T]) { self.spec_extend(other.iter()) } + + /// Returns a place for insertion at the back of the `Vec`. + /// + /// Using this method with placement syntax is equivalent to [`push`](#method.push), + /// but may be more efficient. + /// + /// # Examples + /// + /// ``` + /// #![feature(collection_placement)] + /// #![feature(placement_in_syntax)] + /// + /// let mut vec = vec![1, 2]; + /// vec.place_back() <- 3; + /// vec.place_back() <- 4; + /// assert_eq!(&vec, &[1, 2, 3, 4]); + /// ``` + #[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] + pub fn place_back(&mut self) -> PlaceBack { + PlaceBack { vec: self } + } } // Set the length of the vec when the `SetLenOnDrop` value goes out of scope. @@ -1763,8 +1793,7 @@ impl Ord for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Vec { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for Vec { fn drop(&mut self) { unsafe { // use drop for [T] @@ -2033,8 +2062,7 @@ impl Clone for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for IntoIter { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for IntoIter { fn drop(&mut self) { // destroy the remaining elements for _x in self.by_ref() {} @@ -2119,3 +2147,52 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> { #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for Drain<'a, T> {} + +/// A place for insertion at the back of a `Vec`. +/// +/// See [`Vec::place_back`](struct.Vec.html#method.place_back) for details. +#[must_use = "places do nothing unless written to with `<-` syntax"] +#[unstable(feature = "collection_placement", + reason = "struct name and placement protocol are subject to change", + issue = "30172")] +pub struct PlaceBack<'a, T: 'a> { + vec: &'a mut Vec, +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> Placer for PlaceBack<'a, T> { + type Place = PlaceBack<'a, T>; + + fn make_place(self) -> Self { + // This will panic or abort if we would allocate > isize::MAX bytes + // or if the length increment would overflow for zero-sized types. + if self.vec.len == self.vec.buf.cap() { + self.vec.buf.double(); + } + self + } +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> Place for PlaceBack<'a, T> { + fn pointer(&mut self) -> *mut T { + unsafe { self.vec.as_mut_ptr().offset(self.vec.len as isize) } + } +} + +#[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] +impl<'a, T> InPlace for PlaceBack<'a, T> { + type Owner = &'a mut T; + + unsafe fn finalize(mut self) -> &'a mut T { + let ptr = self.pointer(); + self.vec.len += 1; + &mut *ptr + } +} diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index dbe3fec205..5b1bc3a3ae 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -33,6 +33,7 @@ use core::cmp; use alloc::raw_vec::RawVec; use super::range::RangeArgument; +use Bound::{Excluded, Included, Unbounded}; use super::vec::Vec; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 @@ -69,8 +70,7 @@ impl Clone for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for VecDeque { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for VecDeque { fn drop(&mut self) { let (front, back) = self.as_mut_slices(); unsafe { @@ -206,11 +206,7 @@ impl VecDeque { unsafe fn wrap_copy(&self, dst: usize, src: usize, len: usize) { #[allow(dead_code)] fn diff(a: usize, b: usize) -> usize { - if a <= b { - b - a - } else { - a - b - } + if a <= b { b - a } else { a - b } } debug_assert!(cmp::min(diff(dst, src), self.cap() - diff(dst, src)) + len <= self.cap(), "wrc dst={} src={} len={} cap={}", @@ -552,8 +548,8 @@ impl VecDeque { let old_cap = self.cap(); let used_cap = self.len() + 1; let new_cap = used_cap.checked_add(additional) - .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) - .expect("capacity overflow"); + .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) + .expect("capacity overflow"); if new_cap > self.capacity() { self.buf.reserve_exact(used_cap, new_cap - used_cap); @@ -647,8 +643,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(deque_extras)] - /// /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -659,9 +653,7 @@ impl VecDeque { /// assert_eq!(buf.len(), 1); /// assert_eq!(Some(&5), buf.get(0)); /// ``` - #[unstable(feature = "deque_extras", - reason = "matches collection reform specification; waiting on panic semantics", - issue = "27788")] + #[stable(feature = "deque_extras", since = "1.16.0")] pub fn truncate(&mut self, len: usize) { for _ in len..self.len() { self.pop_back(); @@ -857,8 +849,16 @@ impl VecDeque { // and the head/tail values will be restored correctly. // let len = self.len(); - let start = *range.start().unwrap_or(&0); - let end = *range.end().unwrap_or(&len); + let start = match range.start() { + Included(&n) => n, + Excluded(&n) => n + 1, + Unbounded => 0, + }; + let end = match range.end() { + Included(&n) => n + 1, + Excluded(&n) => n, + Unbounded => len, + }; assert!(start <= end, "drain lower bound was too large"); assert!(end <= len, "drain upper bound was too large"); @@ -1232,9 +1232,8 @@ impl VecDeque { self.pop_front() } - /// Inserts an element at `index` within the `VecDeque`. Whichever - /// end is closer to the insertion point will be moved to make room, - /// and all the affected elements will be moved to new positions. + /// Inserts an element at `index` within the `VecDeque`, shifting all elements with indices + /// greater than or equal to `index` towards the back. /// /// Element at index 0 is the front of the queue. /// @@ -1243,14 +1242,19 @@ impl VecDeque { /// Panics if `index` is greater than `VecDeque`'s length /// /// # Examples + /// /// ``` /// use std::collections::VecDeque; /// - /// let mut buf = VecDeque::new(); - /// buf.push_back(10); - /// buf.push_back(12); - /// buf.insert(1, 11); - /// assert_eq!(Some(&11), buf.get(1)); + /// let mut vec_deque = VecDeque::new(); + /// vec_deque.push_back('a'); + /// vec_deque.push_back('b'); + /// vec_deque.push_back('c'); + /// + /// vec_deque.insert(1, 'd'); + /// + /// let vec = vec_deque.into_iter().collect::>(); + /// assert_eq!(vec, ['a', 'd', 'b', 'c']); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn insert(&mut self, index: usize, value: T) { @@ -1293,9 +1297,7 @@ impl VecDeque { let contiguous = self.is_contiguous(); - match (contiguous, - distance_to_tail <= distance_to_head, - idx >= self.tail) { + match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) { (true, true, _) if index == 0 => { // push_front // @@ -1513,9 +1515,7 @@ impl VecDeque { let contiguous = self.is_contiguous(); - match (contiguous, - distance_to_tail <= distance_to_head, - idx >= self.tail) { + match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) { (true, true, _) => { unsafe { // contiguous, remove closer to tail: @@ -1775,8 +1775,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(deque_extras)] - /// /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -1789,9 +1787,7 @@ impl VecDeque { /// assert_eq!(a, b); /// } /// ``` - #[unstable(feature = "deque_extras", - reason = "matches collection reform specification; waiting on panic semantics", - issue = "27788")] + #[stable(feature = "deque_extras", since = "1.16.0")] pub fn resize(&mut self, new_len: usize, value: T) { let len = self.len(); @@ -1812,7 +1808,7 @@ fn wrap_index(index: usize, size: usize) -> usize { } /// Returns the two slices that cover the VecDeque's valid range -trait RingSlices : Sized { +trait RingSlices: Sized { fn slice(self, from: usize, to: usize) -> Self; fn split_at(self, i: usize) -> (Self, Self); @@ -1895,7 +1891,7 @@ impl<'a, T> Iterator for Iter<'a, T> { } fn fold(self, mut accum: Acc, mut f: F) -> Acc - where F: FnMut(Acc, Self::Item) -> Acc, + where F: FnMut(Acc, Self::Item) -> Acc { let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); accum = front.iter().fold(accum, &mut f); @@ -1959,7 +1955,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { } fn fold(self, mut accum: Acc, mut f: F) -> Acc - where F: FnMut(Acc, Self::Item) -> Acc, + where F: FnMut(Acc, Self::Item) -> Acc { let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); accum = front.iter_mut().fold(accum, &mut f); @@ -2082,17 +2078,15 @@ impl<'a, T: 'a> Drop for Drain<'a, T> { (_, 0) => { source_deque.head = drain_tail; } - _ => { - unsafe { - if tail_len <= head_len { - source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); - source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); - } else { - source_deque.head = source_deque.wrap_add(drain_tail, head_len); - source_deque.wrap_copy(drain_tail, drain_head, head_len); - } + _ => unsafe { + if tail_len <= head_len { + source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); + source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); + } else { + source_deque.head = source_deque.wrap_add(drain_tail, head_len); + source_deque.wrap_copy(drain_tail, drain_head, head_len); } - } + }, } } } @@ -2288,10 +2282,8 @@ impl From> for VecDeque { // We need to extend the buf if it's not a power of two, too small // or doesn't have at least one free space - if !buf.cap().is_power_of_two() - || (buf.cap() < (MINIMUM_CAPACITY + 1)) - || (buf.cap() == len) - { + if !buf.cap().is_power_of_two() || (buf.cap() < (MINIMUM_CAPACITY + 1)) || + (buf.cap() == len) { let cap = cmp::max(buf.cap() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); buf.reserve_exact(len, cap - len); } @@ -2299,7 +2291,7 @@ impl From> for VecDeque { VecDeque { tail: 0, head: len, - buf: buf + buf: buf, } } } @@ -2324,18 +2316,17 @@ impl From> for Vec { // 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), - cap - tail); + ptr::copy(buf.offset(tail as isize), + buf.offset((tail - head) as isize), + cap - tail); // copy left in the end ptr::copy(buf, buf.offset((cap - head) as isize), head); // shift the new thing to the start - ptr::copy(buf.offset((tail-head) as isize), buf, len); + ptr::copy(buf.offset((tail - head) as isize), 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.offset((cap - tail) as isize), head); + ptr::copy(buf.offset(tail as isize), buf, cap - tail); } } else { // Need to use N swaps to move the ring @@ -2576,8 +2567,8 @@ mod tests { // We should see the correct values in the VecDeque let expected: VecDeque<_> = (0..drain_start) - .chain(drain_end..len) - .collect(); + .chain(drain_end..len) + .collect(); assert_eq!(expected, tester); } } @@ -2693,19 +2684,19 @@ mod tests { let cap = (2i32.pow(cap_pwr) - 1) as usize; // In these cases there is enough free space to solve it with copies - for len in 0..((cap+1)/2) { + for len in 0..((cap + 1) / 2) { // Test contiguous cases - for offset in 0..(cap-len) { + for offset in 0..(cap - len) { create_vec_and_test_convert(cap, offset, len) } // Test cases where block at end of buffer is bigger than block at start - for offset in (cap-len)..(cap-(len/2)) { + for offset in (cap - len)..(cap - (len / 2)) { create_vec_and_test_convert(cap, offset, len) } // Test cases where block at start of buffer is bigger than block at end - for offset in (cap-(len/2))..cap { + for offset in (cap - (len / 2))..cap { create_vec_and_test_convert(cap, offset, len) } } @@ -2714,19 +2705,19 @@ mod tests { // the ring will use swapping when: // (cap + 1 - offset) > (cap + 1 - len) && (len - (cap + 1 - offset)) > (cap + 1 - len)) // right block size > free space && left block size > free space - for len in ((cap+1)/2)..cap { + for len in ((cap + 1) / 2)..cap { // Test contiguous cases - for offset in 0..(cap-len) { + for offset in 0..(cap - len) { create_vec_and_test_convert(cap, offset, len) } // Test cases where block at end of buffer is bigger than block at start - for offset in (cap-len)..(cap-(len/2)) { + for offset in (cap - len)..(cap - (len / 2)) { create_vec_and_test_convert(cap, offset, len) } // Test cases where block at start of buffer is bigger than block at end - for offset in (cap-(len/2))..cap { + for offset in (cap - (len / 2))..cap { create_vec_and_test_convert(cap, offset, len) } } diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs index 9cd63d8793..d284937a9e 100644 --- a/src/libcollectionstest/binary_heap.rs +++ b/src/libcollectionstest/binary_heap.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::panic; use std::collections::BinaryHeap; -use std::collections::binary_heap::Drain; +use std::collections::binary_heap::{Drain, PeekMut}; #[test] fn test_iterator() { @@ -94,6 +95,19 @@ fn test_peek_mut() { assert_eq!(heap.peek(), Some(&9)); } +#[test] +fn test_peek_mut_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut heap = BinaryHeap::from(data); + assert_eq!(heap.peek(), Some(&10)); + { + let mut top = heap.peek_mut().unwrap(); + *top -= 2; + assert_eq!(PeekMut::pop(top), 8); + } + assert_eq!(heap.peek(), Some(&9)); +} + #[test] fn test_push() { let mut heap = BinaryHeap::from(vec![2, 4, 9]); @@ -297,6 +311,26 @@ fn test_extend_specialization() { assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); } +#[test] +fn test_placement() { + let mut a = BinaryHeap::new(); + &mut a <- 2; + &mut a <- 4; + &mut a <- 3; + assert_eq!(a.peek(), Some(&4)); + assert_eq!(a.len(), 3); + &mut a <- 1; + assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]); +} + +#[test] +fn test_placement_panic() { + let mut heap = BinaryHeap::from(vec![1, 2, 3]); + fn mkpanic() -> usize { panic!() } + let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); })); + assert_eq!(heap.len(), 3); +} + #[allow(dead_code)] fn assert_covariance() { fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs index 8222da105c..c84753415a 100644 --- a/src/libcollectionstest/btree/map.rs +++ b/src/libcollectionstest/btree/map.rs @@ -170,7 +170,7 @@ fn test_range_small() { let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); let mut j = 0; - for ((&k, &v), i) in map.range(Included(&2), Unbounded).zip(2..size) { + for ((&k, &v), i) in map.range(2..).zip(2..size) { assert_eq!(k, i); assert_eq!(v, i); j += 1; @@ -184,7 +184,7 @@ fn test_range_1000() { let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { - let mut kvs = map.range(min, max).map(|(&k, &v)| (k, v)); + let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v)); let mut pairs = (0..size).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { @@ -201,6 +201,20 @@ fn test_range_1000() { test(&map, size, Unbounded, Unbounded); } +#[test] +fn test_range_borrowed_key() { + let mut map = BTreeMap::new(); + map.insert("aardvark".to_string(), 1); + map.insert("baboon".to_string(), 2); + map.insert("coyote".to_string(), 3); + map.insert("dingo".to_string(), 4); + // NOTE: would like to use simply "b".."d" here... + let mut iter = map.range::((Included("b"),Excluded("d"))); + assert_eq!(iter.next(), Some((&"baboon".to_string(), &2))); + assert_eq!(iter.next(), Some((&"coyote".to_string(), &3))); + assert_eq!(iter.next(), None); +} + #[test] fn test_range() { let size = 200; @@ -208,7 +222,26 @@ fn test_range() { for i in 0..size { for j in i..size { - let mut kvs = map.range(Included(&i), Included(&j)).map(|(&k, &v)| (k, v)); + let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v)); + let mut pairs = (i..j + 1).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + } +} + +#[test] +fn test_range_mut() { + let size = 200; + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + for i in 0..size { + for j in i..size { + let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v)); let mut pairs = (i..j + 1).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs deleted file mode 100644 index 972361326d..0000000000 --- a/src/libcollectionstest/enum_set.rs +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2012 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::mem; - -use collections::enum_set::{CLike, EnumSet}; - -use self::Foo::*; - -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(usize)] -enum Foo { - A, - B, - C, -} - -impl CLike for Foo { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Foo { - unsafe { mem::transmute(v) } - } -} - -#[test] -fn test_new() { - let e: EnumSet = EnumSet::new(); - assert!(e.is_empty()); -} - -#[test] -fn test_show() { - let mut e = EnumSet::new(); - assert!(format!("{:?}", e) == "{}"); - e.insert(A); - assert!(format!("{:?}", e) == "{A}"); - e.insert(C); - assert!(format!("{:?}", e) == "{A, C}"); -} - -#[test] -fn test_len() { - let mut e = EnumSet::new(); - assert_eq!(e.len(), 0); - e.insert(A); - e.insert(B); - e.insert(C); - assert_eq!(e.len(), 3); - e.remove(&A); - assert_eq!(e.len(), 2); - e.clear(); - assert_eq!(e.len(), 0); -} - -/////////////////////////////////////////////////////////////////////////// -// intersect - -#[test] -fn test_two_empties_do_not_intersect() { - let e1: EnumSet = EnumSet::new(); - let e2: EnumSet = EnumSet::new(); - assert!(e1.is_disjoint(&e2)); -} - -#[test] -fn test_empty_does_not_intersect_with_full() { - let e1: EnumSet = EnumSet::new(); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - e2.insert(C); - - assert!(e1.is_disjoint(&e2)); -} - -#[test] -fn test_disjoint_intersects() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(B); - - assert!(e1.is_disjoint(&e2)); -} - -#[test] -fn test_overlapping_intersects() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - assert!(!e1.is_disjoint(&e2)); -} - -/////////////////////////////////////////////////////////////////////////// -// contains and contains_elem - -#[test] -fn test_superset() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - let mut e3: EnumSet = EnumSet::new(); - e3.insert(C); - - assert!(e1.is_subset(&e2)); - assert!(e2.is_superset(&e1)); - assert!(!e3.is_superset(&e2)); - assert!(!e2.is_superset(&e3)) -} - -#[test] -fn test_contains() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - assert!(e1.contains(&A)); - assert!(!e1.contains(&B)); - assert!(!e1.contains(&C)); - - e1.insert(A); - e1.insert(B); - assert!(e1.contains(&A)); - assert!(e1.contains(&B)); - assert!(!e1.contains(&C)); -} - -/////////////////////////////////////////////////////////////////////////// -// iter - -#[test] -fn test_iterator() { - let mut e1: EnumSet = EnumSet::new(); - - let elems: Vec = e1.iter().collect(); - assert!(elems.is_empty()); - - e1.insert(A); - let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A]); - - e1.insert(C); - let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A, C]); - - e1.insert(C); - let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A, C]); - - e1.insert(B); - let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A, B, C]); -} - -/////////////////////////////////////////////////////////////////////////// -// operators - -#[test] -fn test_operators() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - e1.insert(C); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(B); - e2.insert(C); - - let e_union = e1 | e2; - let elems: Vec<_> = e_union.iter().collect(); - assert_eq!(elems, [A, B, C]); - - let e_intersection = e1 & e2; - let elems: Vec<_> = e_intersection.iter().collect(); - assert_eq!(elems, [C]); - - // Another way to express intersection - let e_intersection = e1 - (e1 - e2); - let elems: Vec<_> = e_intersection.iter().collect(); - assert_eq!(elems, [C]); - - let e_subtract = e1 - e2; - let elems: Vec<_> = e_subtract.iter().collect(); - assert_eq!(elems, [A]); - - // Bitwise XOR of two sets, aka symmetric difference - let e_symmetric_diff = e1 ^ e2; - let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A, B]); - - // Another way to express symmetric difference - let e_symmetric_diff = (e1 - e2) | (e2 - e1); - let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A, B]); - - // Yet another way to express symmetric difference - let e_symmetric_diff = (e1 | e2) - (e1 & e2); - let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A, B]); -} - -#[test] -#[should_panic] -fn test_overflow() { - #[allow(dead_code)] - #[derive(Copy, Clone)] - #[repr(usize)] - enum Bar { - V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, - V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, - V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, - V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, - V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, - V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, - V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, - } - - impl CLike for Bar { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Bar { - unsafe { mem::transmute(v) } - } - } - let mut set = EnumSet::new(); - set.insert(Bar::V64); -} - -#[test] -fn test_extend_ref() { - let mut a = EnumSet::new(); - a.insert(A); - - a.extend(&[A, C]); - - assert_eq!(a.len(), 2); - assert!(a.contains(&A)); - assert!(a.contains(&C)); - - let mut b = EnumSet::new(); - b.insert(B); - - a.extend(&b); - - assert_eq!(a.len(), 3); - assert!(a.contains(&A)); - assert!(a.contains(&B)); - assert!(a.contains(&C)); -} diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index d4fb5ea03a..b146672893 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -11,21 +11,19 @@ #![deny(warnings)] #![feature(binary_heap_extras)] +#![feature(binary_heap_peek_mut_pop)] #![feature(box_syntax)] #![feature(btree_range)] +#![feature(collection_placement)] #![feature(collections)] #![feature(collections_bound)] #![feature(const_fn)] -#![feature(dedup_by)] -#![feature(enumset)] #![feature(exact_size_is_empty)] #![feature(pattern)] +#![feature(placement_in_syntax)] #![feature(rand)] -#![feature(repeat_str)] #![feature(step_by)] #![feature(str_escape)] -#![feature(str_replacen)] -#![feature(string_split_off)] #![feature(test)] #![feature(unboxed_closures)] #![feature(unicode)] @@ -44,7 +42,6 @@ mod bench; mod binary_heap; mod btree; mod cow_str; -mod enum_set; mod fmt; mod linked_list; mod slice; diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 384579ce6b..5e685847e3 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -383,17 +383,29 @@ tempus vel, gravida nec quam."; // check the panic includes the prefix of the sliced string #[test] -#[should_panic(expected="Lorem ipsum dolor sit amet")] +#[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")] fn test_slice_fail_truncated_1() { &LOREM_PARAGRAPH[..1024]; } // check the truncation in the panic message #[test] -#[should_panic(expected="luctus, im`[...] do not lie on character boundary")] +#[should_panic(expected="luctus, im`[...]")] fn test_slice_fail_truncated_2() { &LOREM_PARAGRAPH[..1024]; } +#[test] +#[should_panic(expected="byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of")] +fn test_slice_fail_boundary_1() { + &"abcαβγ"[4..]; +} + +#[test] +#[should_panic(expected="byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of")] +fn test_slice_fail_boundary_2() { + &"abcαβγ"[2..6]; +} + #[test] fn test_slice_from() { assert_eq!(&"abcd"[0..], "abcd"); diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index 3bc1321d75..6d0f1eaffa 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -12,6 +12,7 @@ use std::ascii::AsciiExt; use std::borrow::Cow; use std::iter::{FromIterator, repeat}; use std::mem::size_of; +use std::panic; use std::vec::{Drain, IntoIter}; use test::Bencher; @@ -615,6 +616,24 @@ fn assert_covariance() { } } +#[test] +fn test_placement() { + let mut vec = vec![1]; + assert_eq!(vec.place_back() <- 2, &2); + assert_eq!(vec.len(), 2); + assert_eq!(vec.place_back() <- 3, &3); + assert_eq!(vec.len(), 3); + assert_eq!(&vec, &[1, 2, 3]); +} + +#[test] +fn test_placement_panic() { + let mut vec = vec![1, 2, 3]; + fn mkpanic() -> usize { panic!() } + let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); })); + assert_eq!(vec.len(), 3); +} + #[bench] fn bench_new(b: &mut Bencher) { b.iter(|| { diff --git a/src/libcompiler_builtins/build.rs b/src/libcompiler_builtins/build.rs index f61e2281a5..b9421d779b 100644 --- a/src/libcompiler_builtins/build.rs +++ b/src/libcompiler_builtins/build.rs @@ -107,7 +107,6 @@ fn main() { "apple_versioning.c", "ashldi3.c", "ashrdi3.c", - "clear_cache.c", "clzdi2.c", "clzsi2.c", "cmpdi2.c", @@ -192,14 +191,12 @@ fn main() { if !target.contains("ios") { sources.extend(&["absvti2.c", - "addtf3.c", "addvti3.c", "ashlti3.c", "ashrti3.c", "clzti2.c", "cmpti2.c", "ctzti2.c", - "divtf3.c", "divti3.c", "ffsti2.c", "fixdfti.c", @@ -216,17 +213,13 @@ fn main() { "floatuntixf.c", "lshrti3.c", "modti3.c", - "multf3.c", "multi3.c", "mulvti3.c", "negti2.c", "negvti2.c", "parityti2.c", "popcountti2.c", - "powitf2.c", - "subtf3.c", "subvti3.c", - "trampoline_setup.c", "ucmpti2.c", "udivmodti4.c", "udivti3.c", @@ -242,10 +235,6 @@ fn main() { "atomic_thread_fence.c"]); } - if !target.contains("windows") { - sources.extend(&["emutls.c"]); - } - if target.contains("msvc") { if target.contains("x86_64") { sources.extend(&["x86_64/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]); diff --git a/src/libcompiler_builtins/lib.rs b/src/libcompiler_builtins/lib.rs index 4a703b3da6..69ec99bb83 100644 --- a/src/libcompiler_builtins/lib.rs +++ b/src/libcompiler_builtins/lib.rs @@ -16,4 +16,790 @@ issue = "0")] #![crate_name = "compiler_builtins"] #![crate_type = "rlib"] -#![feature(staged_api)] +#![allow(unused_features)] +#![feature(staged_api, core_intrinsics, repr_simd, + i128_type, core_float, abi_unadjusted, associated_consts)] +#![allow(non_camel_case_types, unused_variables, unused_imports)] +#![cfg_attr(stage0, allow(dead_code))] + +#[cfg(any(target_pointer_width="32", target_pointer_width="16", target_os="windows", + target_arch="mips64"))] +pub mod reimpls { + + #![allow(unused_comparisons)] + + use core::intrinsics::unchecked_div; + use core::intrinsics::unchecked_rem; + use core::ptr; + + // C API is expected to tolerate some amount of size mismatch in ABI. Hopefully the amount of + // handling is sufficient for bootstrapping. + #[cfg(stage0)] + type u128_ = u64; + #[cfg(stage0)] + type i128_ = i64; + #[cfg(not(stage0))] + type u128_ = u128; + #[cfg(not(stage0))] + type i128_ = i128; + + macro_rules! ashl { + ($a:expr, $b:expr, $ty:ty) => {{ + let (a, b) = ($a, $b); + let bits = (::core::mem::size_of::<$ty>() * 8) as $ty; + let half_bits = bits >> 1; + if b & half_bits != 0 { + <$ty>::from_parts(0, a.low().wrapping_shl( + b.wrapping_sub(half_bits) as u32)) + } else if b == 0 { + a + } else { + <$ty>::from_parts(a.low().wrapping_shl(b as u32), + a.high().wrapping_shl(b as u32) + | a.low() + .wrapping_shr(half_bits.wrapping_sub(b) as u32)) + } + }} + } + + #[export_name="__ashlti3"] + pub extern "C" fn shl(a: u128_, b: u128_) -> u128_ { + ashl!(a, b, u128_) + } + + macro_rules! ashr { + ($a: expr, $b: expr, $ty:ty) => {{ + let (a, b) = ($a, $b); + let bits = (::core::mem::size_of::<$ty>() * 8) as $ty; + let half_bits = bits >> 1; + if b & half_bits != 0 { + <$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32) + as <$ty as LargeInt>::LowHalf, + a.high().wrapping_shr(half_bits.wrapping_sub(1) as u32)) + } else if b == 0 { + a + } else { + let high_unsigned = a.high() as <$ty as LargeInt>::LowHalf; + <$ty>::from_parts(high_unsigned.wrapping_shl(half_bits.wrapping_sub(b) as u32) + | a.low().wrapping_shr(b as u32), + a.high().wrapping_shr(b as u32)) + } + }} + } + + #[export_name="__ashrti3"] + pub extern "C" fn shr(a: i128_, b: i128_) -> i128_ { + ashr!(a, b, i128_) + } + + macro_rules! lshr { + ($a: expr, $b: expr, $ty:ty) => {{ + let (a, b) = ($a, $b); + let bits = (::core::mem::size_of::<$ty>() * 8) as $ty; + let half_bits = bits >> 1; + if b & half_bits != 0 { + <$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32), 0) + } else if b == 0 { + a + } else { + <$ty>::from_parts(a.high().wrapping_shl(half_bits.wrapping_sub(b) as u32) + | a.low().wrapping_shr(b as u32), + a.high().wrapping_shr(b as u32)) + } + }} + } + + + #[export_name="__lshrti3"] + pub extern "C" fn lshr(a: u128_, b: u128_) -> u128_ { + lshr!(a, b, u128_) + } + + #[cfg(stage0)] + pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ { + unsafe { + if !rem.is_null() { + *rem = unchecked_rem(n, d); + } + unchecked_div(n, d) + } + } + + #[cfg(not(stage0))] + pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ { + // Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide + unsafe { + // special cases, X is unknown, K != 0 + if n.high() == 0 { + if d.high() == 0 { + // 0 X + // --- + // 0 X + if !rem.is_null() { + *rem = u128::from(unchecked_rem(n.low(), d.low())); + } + return u128::from(unchecked_div(n.low(), d.low())); + } else { + // 0 X + // --- + // K X + if !rem.is_null() { + *rem = n; + } + return 0; + }; + } + + let mut sr; + let mut q; + let mut r; + + if d.low() == 0 { + if d.high() == 0 { + // K X + // --- + // 0 0 + if !rem.is_null() { + *rem = u128::from(unchecked_rem(n.high(), d.low())); + } + return u128::from(unchecked_div(n.high(), d.low())); + } + + if n.low() == 0 { + // K 0 + // --- + // K 0 + if !rem.is_null() { + *rem = u128::from_parts(0, unchecked_rem(n.high(), d.high())); + } + return u128::from(unchecked_div(n.high(), d.high())); + } + + // K K + // --- + // K 0 + + if d.high().is_power_of_two() { + if !rem.is_null() { + *rem = u128::from_parts(n.low(), + n.high() & (d.high().wrapping_sub(1))); + } + return u128::from(n.high().wrapping_shr(d.high().trailing_zeros())); + } + + // K K + // --- + // K 0 + sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros()); + + // D > N + if sr > 64 - 2 { + if !rem.is_null() { + *rem = n; + } + return 0; + } + + sr = sr.wrapping_add(1); + + // 1 <= sr <= u64::bits() - 1 + q = n.wrapping_shl(64u32.wrapping_sub(sr)); + r = n.wrapping_shr(sr); + } else { + if d.high() == 0 { + // K X + // --- + // 0 K + if d.low().is_power_of_two() { + if !rem.is_null() { + *rem = u128::from(n.low() & (d.low().wrapping_sub(1))); + } + + if d.low() == 1 { + return n; + } else { + let sr = d.low().trailing_zeros(); + return n.wrapping_shr(sr); + }; + } + + sr = (1 + 64u32) + .wrapping_add(d.low().leading_zeros()) + .wrapping_sub(n.high().leading_zeros()); + + // 2 <= sr <= u64::bits() - 1 + q = n.wrapping_shl(128u32.wrapping_sub(sr)); + r = n.wrapping_shr(sr); + // FIXME the C compiler-rt implementation has something here + // that looks like a speed optimisation. + // It would be worth a try to port it to Rust too and + // compare the speed. + } else { + // K X + // --- + // K K + sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros()); + + // D > N + if sr > 64 - 1 { + if !rem.is_null() { + *rem = n; + } + return 0; + } + + sr = sr.wrapping_add(1); + + // 1 <= sr <= u32::bits() + q = n.wrapping_shl(128u32.wrapping_sub(sr)); + r = n.wrapping_shr(sr); + } + } + + // Not a special case + // q and r are initialized with + // q = n << (u64::bits() - sr) + // r = n >> sr + // 1 <= sr <= u64::bits() - 1 + let mut carry = 0; + + // FIXME: replace this with a for loop + // (atm not doable as this generates call to + // eh_personality when optimisations are turned off, + // which in turn gives a linker error in later + // compilation steps) + while sr > 0 { + // r:q = ((r:q) << 1) | carry + r = r.wrapping_shl(1) | q.wrapping_shr(128 - 1); + q = q.wrapping_shl(1) | carry as u128; + + // carry = 0 + // if r >= d { + // r -= d; + // carry = 1; + // } + let s = ((d.wrapping_sub(r).wrapping_sub(1)) as i128).wrapping_shr(128 - 1); + carry = (s & 1) as u64; + r = r.wrapping_sub(d & s as u128); + sr = sr.wrapping_sub(1); + } + + if !rem.is_null() { + *rem = r; + } + (q.wrapping_shl(1)) | carry as u128 + } + } + + fn i128_mod(a: i128_, b: i128_) -> i128_ { + let b = b.uabs(); + let sa = a.signum(); + let a = a.uabs(); + unsafe { + let mut r = ::core::mem::zeroed(); + u128_div_mod(a, b, &mut r); + if sa == -1 { (r as i128_).unchecked_neg() } else { r as i128_ } + } + } + + fn i128_div(a: i128_, b: i128_) -> i128_ { + let sa = a.signum(); + let sb = b.signum(); + let a = a.uabs(); + let b = b.uabs(); + let sr = sa.wrapping_mul(sb); // sign of quotient + (if sr == -1 { + (u128_div_mod(a, b, ptr::null_mut()) as i128_).unchecked_neg() + } else { + u128_div_mod(a, b, ptr::null_mut()) as i128_ + }) + } + + #[cfg(stage0)] + #[export_name="__udivti3"] + pub extern "C" fn u128_div(a: u128_, b: u128_) -> u128_ { + (a / b) + } + + macro_rules! mulo { + ($a:expr, $b:expr, $o: expr, $ty: ty) => {{ + let (a, b, overflow) = ($a, $b, $o); + *overflow = 0; + let result = a.wrapping_mul(b); + if a == <$ty>::min_value() { + if b != 0 && b != 1 { + *overflow = 1; + } + return result; + } + if b == <$ty>::min_value() { + if a != 0 && a != 1 { + *overflow = 1; + } + return result; + } + + let sa = a.signum(); + let abs_a = a.iabs(); + let sb = b.signum(); + let abs_b = b.iabs(); + if abs_a < 2 || abs_b < 2 { + return result; + } + if sa == sb { + if abs_a > unchecked_div(<$ty>::max_value(), abs_b) { + *overflow = 1; + } + } else { + if abs_a > unchecked_div(<$ty>::min_value(), abs_b.unchecked_neg()) { + *overflow = 1; + } + } + result + }} + } + + pub trait LargeInt { + type LowHalf; + type HighHalf; + + fn low(self) -> Self::LowHalf; + fn high(self) -> Self::HighHalf; + fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self; + } + impl LargeInt for u64 { + type LowHalf = u32; + type HighHalf = u32; + + fn low(self) -> u32 { + self as u32 + } + fn high(self) -> u32 { + (self.wrapping_shr(32)) as u32 + } + fn from_parts(low: u32, high: u32) -> u64 { + low as u64 | (high as u64).wrapping_shl(32) + } + } + impl LargeInt for i64 { + type LowHalf = u32; + type HighHalf = i32; + + fn low(self) -> u32 { + self as u32 + } + fn high(self) -> i32 { + self.wrapping_shr(32) as i32 + } + fn from_parts(low: u32, high: i32) -> i64 { + u64::from_parts(low, high as u32) as i64 + } + } + #[cfg(not(stage0))] + impl LargeInt for u128 { + type LowHalf = u64; + type HighHalf = u64; + + fn low(self) -> u64 { + self as u64 + } + fn high(self) -> u64 { + self.wrapping_shr(64) as u64 + } + fn from_parts(low: u64, high: u64) -> u128 { + (high as u128).wrapping_shl(64) | low as u128 + } + } + #[cfg(not(stage0))] + impl LargeInt for i128 { + type LowHalf = u64; + type HighHalf = i64; + + fn low(self) -> u64 { + self as u64 + } + fn high(self) -> i64 { + self.wrapping_shr(64) as i64 + } + fn from_parts(low: u64, high: i64) -> i128 { + u128::from_parts(low, high as u64) as i128 + } + } + + macro_rules! mul { + ($a:expr, $b:expr, $ty: ty, $tyh: ty) => {{ + let (a, b) = ($a, $b); + let half_bits = ((::core::mem::size_of::<$tyh>() * 8) / 2) as u32; + let lower_mask = (!0u64).wrapping_shr(half_bits); + let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask); + let mut t = low.wrapping_shr(half_bits); + low &= lower_mask; + t = t.wrapping_add(a.low().wrapping_shr(half_bits) + .wrapping_mul(b.low() & lower_mask)); + low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits)); + let mut high = t.wrapping_shr(half_bits) as $tyh; + t = low.wrapping_shr(half_bits); + low &= lower_mask; + t = t.wrapping_add(b.low().wrapping_shr(half_bits) + .wrapping_mul(a.low() & lower_mask)); + low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits)); + high = high.wrapping_add(t.wrapping_shr(half_bits) as $tyh); + high = high.wrapping_add(a.low().wrapping_shr(half_bits) + .wrapping_mul(b.low().wrapping_shr(half_bits)) as $tyh); + high = high + .wrapping_add(a.high() + .wrapping_mul(b.low() as $tyh)) + .wrapping_add((a.low() as $tyh) + .wrapping_mul(b.high())); + <$ty>::from_parts(low, high) + }} + } + + #[cfg(stage0)] + #[export_name="__multi3"] + pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ { + ((a as i64).wrapping_mul(b as i64) as i128_) + } + + #[cfg(not(stage0))] + #[export_name="__multi3"] + pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ { + mul!(a, b, i128_, i64) + } + + trait AbsExt: Sized { + fn uabs(self) -> u128_; + fn iabs(self) -> i128_; + } + + #[cfg(stage0)] + impl AbsExt for i128_ { + fn uabs(self) -> u128_ { + self.iabs() as u128_ + } + fn iabs(self) -> i128_ { + let s = self >> 63; + ((self ^ s).wrapping_sub(s)) + } + } + + #[cfg(not(stage0))] + impl AbsExt for i128_ { + fn uabs(self) -> u128_ { + self.iabs() as u128_ + } + fn iabs(self) -> i128_ { + let s = self >> 127; + ((self ^ s).wrapping_sub(s)) + } + } + + trait NegExt: Sized { + fn unchecked_neg(self) -> i128_; + } + + impl NegExt for i128_ { + fn unchecked_neg(self) -> i128_ { + (!self).wrapping_add(1) + } + } + + trait FloatStuff: Sized { + type ToBytes; + + const MANTISSA_BITS: u32; + const MAX_EXP: i32; + const EXP_MASK: Self::ToBytes; + const MANTISSA_MASK: Self::ToBytes; + const MANTISSA_LEAD_BIT: Self::ToBytes; + + fn to_bytes(self) -> Self::ToBytes; + fn get_exponent(self) -> i32; + } + + impl FloatStuff for f32 { + type ToBytes = u32; + const MANTISSA_BITS: u32 = 23; + const MAX_EXP: i32 = 127; + const EXP_MASK: u32 = 0x7F80_0000; + const MANTISSA_MASK: u32 = 0x007F_FFFF; + const MANTISSA_LEAD_BIT: u32 = 0x0080_0000; + + fn to_bytes(self) -> u32 { unsafe { ::core::mem::transmute(self) } } + fn get_exponent(self) -> i32 { + ((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32) + .wrapping_sub(Self::MAX_EXP) + } + } + + impl FloatStuff for f64 { + type ToBytes = u64; + const MANTISSA_BITS: u32 = 52; + const MAX_EXP: i32 = 1023; + const EXP_MASK: u64 = 0x7FF0_0000_0000_0000; + const MANTISSA_MASK: u64 = 0x000F_FFFF_FFFF_FFFF; + const MANTISSA_LEAD_BIT: u64 = 0x0010_0000_0000_0000; + + fn to_bytes(self) -> u64 { unsafe { ::core::mem::transmute(self) } } + fn get_exponent(self) -> i32 { + ((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32) + .wrapping_sub(Self::MAX_EXP) + } + } + + macro_rules! float_as_unsigned { + ($from: expr, $fromty: ty, $outty: ty) => { { + use core::num::Float; + let repr = $from.to_bytes(); + let sign = $from.signum(); + let exponent = $from.get_exponent(); + let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK; + let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT; + if sign == -1.0 || exponent < 0 { return 0 as u128_; } + if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 { + return !(0 as u128_); + } + (if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 { + (mantissa as $outty) + .wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32) + .wrapping_sub(exponent) as u32) + } else { + (mantissa as $outty) + .wrapping_shl(exponent.wrapping_sub( + <$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32) + }) + } } + } + + macro_rules! float_as_signed { + ($from: expr, $fromty: ty, $outty: ty) => {{ + use core::num::Float; + let repr = $from.to_bytes(); + let sign = $from.signum(); + let exponent = $from.get_exponent(); + let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK; + let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT; + + if exponent < 0 { return 0 as i128_; } + if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 { + let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() }; + return ret + } + let r = if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 { + (mantissa as $outty) + .wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32) + .wrapping_sub(exponent) as u32) + } else { + (mantissa as $outty) + .wrapping_shl(exponent.wrapping_sub( + <$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32) + }; + (if sign >= 0.0 { r } else { r.unchecked_neg() }) + }} + } + + + fn i128_as_f64(a: i128_) -> f64 { + match a.signum() { + 1 => u128_as_f64(a.uabs()), + 0 => 0.0, + _ => -u128_as_f64(a.uabs()), + } + } + + fn i128_as_f32(a: i128_) -> f32 { + match a.signum() { + 1 => u128_as_f32(a.uabs()), + 0 => 0.0, + _ => -u128_as_f32(a.uabs()), + } + } + + fn u128_as_f64(mut a: u128_) -> f64 { + use ::core::f64::MANTISSA_DIGITS; + if a == 0 { return 0.0; } + let sd = 128u32.wrapping_sub(a.leading_zeros()); + let mut e = sd.wrapping_sub(1); + const MD1 : u32 = MANTISSA_DIGITS + 1; + const MD2 : u32 = MANTISSA_DIGITS + 2; + + // SNAP: replace this with !0u128 + let negn :u128_ = !0; + + if sd > MANTISSA_DIGITS { + a = match sd { + MD1 => a.wrapping_shl(1), + MD2 => a, + _ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) | + (if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2) + .wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 }) + }; + a |= if (a & 4) == 0 { 0 } else { 1 }; + a = a.wrapping_add(1); + a = a.wrapping_shr(2); + if a & (1 << MANTISSA_DIGITS) != 0 { + a = a.wrapping_shr(1); + e = e.wrapping_add(1); + } + } else { + a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd)); + } + unsafe { + ::core::mem::transmute((e as u64).wrapping_add(1023).wrapping_shl(52) + | (a as u64 & 0x000f_ffff_ffff_ffff)) + } + } + + fn u128_as_f32(mut a: u128_) -> f32 { + use ::core::f32::MANTISSA_DIGITS; + if a == 0 { return 0.0; } + let sd = 128u32.wrapping_sub(a.leading_zeros()); + let mut e = sd.wrapping_sub(1); + const MD1 : u32 = MANTISSA_DIGITS + 1; + const MD2 : u32 = MANTISSA_DIGITS + 2; + + // SNAP: replace this with !0u128 + let negn :u128_ = !0; + + if sd > MANTISSA_DIGITS { + a = match sd { + MD1 => a.wrapping_shl(1), + MD2 => a, + _ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) | + (if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2) + .wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 }) + }; + a |= if (a & 4) == 0 { 0 } else { 1 }; + a = a.wrapping_add(1); + a = a.wrapping_shr(2); + if a & (1 << MANTISSA_DIGITS) != 0 { + a = a.wrapping_shr(1); + e = e.wrapping_add(1); + } + } else { + a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd)); + } + unsafe { + ::core::mem::transmute((e as u32).wrapping_add(127).wrapping_shl(23) + | (a as u32 & 0x007f_ffff)) + } + } + + + macro_rules! why_are_abi_strings_checked_by_parser { ($cret:ty, $conv:expr, $unadj:tt) => { + mod imp { + use super::{i128_, u128_, LargeInt, FloatStuff, NegExt, AbsExt}; + use super::{i128_as_f64, i128_as_f32, u128_as_f64, u128_as_f32, + i128_div, i128_mod, u128_div_mod, unchecked_div, ptr}; + // For x64 + // rdx:rcx, r9:r8, stack -> rdx:rax + // aka. + // define i128 @__muloti4(i128, i128, i32*) + #[export_name="__muloti4"] + pub unsafe extern $unadj fn i128_mul_oflow(a: i128_, b: i128_, o: *mut i32) -> i128_ { + mulo!(a, b, o, i128_) + } + + // For x64 + // rdx:rax -> xmm0 + // aka. + // define double @__muloti4(i128) + #[export_name="__floattidf"] + pub extern $unadj fn i128_as_f64_(a: i128_) -> f64 { + i128_as_f64(a) + } + #[export_name="__floattisf"] + pub extern $unadj fn i128_as_f32_(a: i128_) -> f32 { + i128_as_f32(a) + } + #[export_name="__floatuntidf"] + pub extern $unadj fn u128_as_f64_(a: u128_) -> f64 { + u128_as_f64(a) + } + #[export_name="__floatuntisf"] + pub extern $unadj fn u128_as_f32_(a: u128_) -> f32 { + u128_as_f32(a) + } + + // For x64 + // xmm0 -> rdx:rax + // aka. + // define i128 @stuff(double) + #[export_name="__fixunsdfti"] + pub extern $unadj fn f64_as_u128(a: f64) -> u128_ { + float_as_unsigned!(a, f64, u128_) + } + + #[export_name="__fixunssfti"] + pub extern "unadjusted" fn f32_as_u128(a: f32) -> u128_ { + float_as_unsigned!(a, f32, u128_) + } + + #[export_name="__fixdfti"] + pub extern "unadjusted" fn f64_as_i128(a: f64) -> i128_ { + float_as_signed!(a, f64, i128_) + } + + #[export_name="__fixsfti"] + pub extern "unadjusted" fn f32_as_i128(a: f32) -> i128_ { + float_as_signed!(a, f32, i128_) + } + + #[repr(simd)] + pub struct u64x2(u64, u64); + + // For x64 + // pointers -> xmm0 + // aka. + // define <2 x u64> @stuff(i128*, i128*, i128*) + // + // That almost matches the C ABI, so we simply use the C ABI + #[export_name="__udivmodti4"] + pub extern "C" fn u128_div_mod_(n: u128_, d: u128_, rem: *mut u128_) -> $cret { + let x = u128_div_mod(n, d, rem); + ($conv)(x) + } + + #[export_name="__udivti3"] + pub extern "C" fn u128_div_(a: u128_, b: u128_) -> $cret { + let x = u128_div_mod(a, b, ptr::null_mut()); + ($conv)(x) + } + + #[export_name="__umodti3"] + pub extern "C" fn u128_mod_(a: u128_, b: u128_) -> $cret { + unsafe { + let mut r = ::core::mem::zeroed(); + u128_div_mod(a, b, &mut r); + ($conv)(r) + } + } + + #[export_name="__divti3"] + pub extern "C" fn i128_div_(a: i128_, b: i128_) -> $cret { + let x = i128_div(a, b); + ($conv)(x as u128_) + } + + #[export_name="__modti3"] + pub extern "C" fn i128_mod_(a: i128_, b: i128_) -> $cret { + let x = i128_mod(a, b); + ($conv)(x as u128_) + } + } + } } + + // LLVM expectations for ABI on windows x64 are pure madness. + #[cfg(not(stage0))] + #[cfg(all(windows, target_pointer_width="64"))] + why_are_abi_strings_checked_by_parser!(u64x2, + |i: u128_| u64x2(i.low(), i.high()), + "unadjusted"); + + #[cfg(not(stage0))] + #[cfg(not(all(windows, target_pointer_width="64")))] + why_are_abi_strings_checked_by_parser!(u128_, |i|{ i }, "C"); + + #[cfg(not(stage0))] + pub use self::imp::*; +} diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index a72c712ad1..e0dbc096cd 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -13,6 +13,7 @@ bench = false name = "coretest" path = "../libcoretest/lib.rs" -[[bench]] -name = "coretest" -path = "../libcoretest/lib.rs" +# FIXME: need to extract benchmarks to a separate crate +#[[bench]] +#name = "coretest" +#path = "../libcoretest/lib.rs" diff --git a/src/libcore/any.rs b/src/libcore/any.rs index eb0636e857..78f3cd5576 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -101,7 +101,7 @@ pub trait Any: 'static { /// /// fn main() { /// assert_eq!(is_string(&0), false); - /// assert_eq!(is_string(&"cookie monster".to_owned()), true); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); /// } /// ``` #[unstable(feature = "get_type_id", @@ -154,7 +154,7 @@ impl Any { /// /// fn main() { /// is_string(&0); - /// is_string(&"cookie monster".to_owned()); + /// is_string(&"cookie monster".to_string()); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -188,7 +188,7 @@ impl Any { /// /// fn main() { /// print_if_string(&0); - /// print_if_string(&"cookie monster".to_owned()); + /// print_if_string(&"cookie monster".to_string()); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -219,7 +219,7 @@ impl Any { /// /// fn main() { /// let mut x = 10u32; - /// let mut s = "starlord".to_owned(); + /// let mut s = "starlord".to_string(); /// /// modify_if_u32(&mut x); /// modify_if_u32(&mut s); @@ -259,7 +259,7 @@ impl Any+Send { /// /// fn main() { /// is_string(&0); - /// is_string(&"cookie monster".to_owned()); + /// is_string(&"cookie monster".to_string()); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -285,7 +285,7 @@ impl Any+Send { /// /// fn main() { /// print_if_string(&0); - /// print_if_string(&"cookie monster".to_owned()); + /// print_if_string(&"cookie monster".to_string()); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -309,7 +309,7 @@ impl Any+Send { /// /// fn main() { /// let mut x = 10u32; - /// let mut s = "starlord".to_owned(); + /// let mut s = "starlord".to_string(); /// /// modify_if_u32(&mut x); /// modify_if_u32(&mut s); @@ -359,7 +359,7 @@ impl TypeId { /// /// fn main() { /// assert_eq!(is_string(&0), false); - /// assert_eq!(is_string(&"cookie monster".to_owned()), true); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/char.rs b/src/libcore/char.rs index c14ae6e089..367422f553 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -17,7 +17,7 @@ use char_private::is_printable; use convert::TryFrom; -use fmt; +use fmt::{self, Write}; use slice; use iter::FusedIterator; use mem::transmute; @@ -588,6 +588,16 @@ impl ExactSizeIterator for EscapeUnicode { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeUnicode {} +#[stable(feature = "char_struct_display", since = "1.17.0")] +impl fmt::Display for EscapeUnicode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for c in self.clone() { + f.write_char(c)?; + } + Ok(()) + } +} + /// An iterator that yields the literal escape code of a `char`. /// /// This `struct` is created by the [`escape_default()`] method on [`char`]. See @@ -691,6 +701,16 @@ impl ExactSizeIterator for EscapeDefault { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDefault {} +#[stable(feature = "char_struct_display", since = "1.17.0")] +impl fmt::Display for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for c in self.clone() { + f.write_char(c)?; + } + Ok(()) + } +} + /// An iterator that yields the literal escape code of a `char`. /// /// This `struct` is created by the [`escape_debug()`] method on [`char`]. See its @@ -715,6 +735,13 @@ impl ExactSizeIterator for EscapeDebug { } #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDebug {} +#[stable(feature = "char_struct_display", since = "1.17.0")] +impl fmt::Display for EscapeDebug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + /// An iterator over an iterator of bytes of the characters the bytes represent diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index d72b18ae34..cd2e8f1018 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -153,12 +153,16 @@ clone_impl! { i8 } clone_impl! { i16 } clone_impl! { i32 } clone_impl! { i64 } +#[cfg(not(stage0))] +clone_impl! { i128 } clone_impl! { usize } clone_impl! { u8 } clone_impl! { u16 } clone_impl! { u32 } clone_impl! { u64 } +#[cfg(not(stage0))] +clone_impl! { u128 } clone_impl! { f32 } clone_impl! { f64 } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 0daf658a0f..a78d27ea3a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -429,7 +429,7 @@ impl PartialOrd for Ordering { /// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic /// ordering based on the top-to-bottom declaration order of the struct's members. /// -/// ## How can I implement `Ord`? +/// ## How can I implement `PartialOrd`? /// /// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated /// from default implementations. @@ -681,6 +681,8 @@ mod impls { partial_eq_impl! { bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } + #[cfg(not(stage0))] + partial_eq_impl! { u128 i128 } macro_rules! eq_impl { ($($t:ty)*) => ($( @@ -690,6 +692,8 @@ mod impls { } eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 } + #[cfg(not(stage0))] + eq_impl! { u128 i128 } macro_rules! partial_ord_impl { ($($t:ty)*) => ($( @@ -779,6 +783,8 @@ mod impls { } ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 } + #[cfg(not(stage0))] + ord_impl! { u128 i128 } #[unstable(feature = "never_type_impls", issue = "35121")] impl PartialEq for ! { diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 830bbc079a..abd686b15e 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -18,25 +18,33 @@ //! support arguments of multiple types. //! //! - Impl the `As*` traits for reference-to-reference conversions -//! - Impl the `Into` trait when you want to consume the value in the conversion -//! - The `From` trait is the most flexible, useful for value _and_ reference conversions -//! - The `TryFrom` and `TryInto` traits behave like `From` and `Into`, but allow for the +//! - Impl the [`Into`] trait when you want to consume the value in the conversion +//! - The [`From`] trait is the most flexible, useful for value _and_ reference conversions +//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`], but allow for the //! conversion to fail //! -//! As a library author, you should prefer implementing `From` or `TryFrom` rather than -//! `Into` or `TryInto`, as `From` and `TryFrom` provide greater flexibility and offer -//! equivalent `Into` or `TryInto` implementations for free, thanks to a blanket implementation +//! As a library author, you should prefer implementing [`From`][`From`] or +//! [`TryFrom`][`TryFrom`] rather than [`Into`][`Into`] or [`TryInto`][`TryInto`], +//! as [`From`] and [`TryFrom`] provide greater flexibility and offer +//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a blanket implementation //! in the standard library. //! //! # Generic impl //! -//! - `AsRef` and `AsMut` auto-dereference if the inner type is a reference -//! - `From for T` implies `Into for U` -//! - `TryFrom for T` implies `TryInto for U` -//! - `From` and `Into` are reflexive, which means that all types can `into()` +//! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference +//! - [`From`]` for T` implies [`Into`]` for U` +//! - [`TryFrom`]` for T` implies [`TryInto`]` for U` +//! - [`From`] and [`Into`] are reflexive, which means that all types can `into()` //! themselves and `from()` themselves //! //! See each trait for usage examples. +//! +//! [`Into`]: trait.Into.html +//! [`From`]: trait.From.html +//! [`TryFrom`]: trait.TryFrom.html +//! [`TryInto`]: trait.TryInto.html +//! [`AsRef`]: trait.AsRef.html +//! [`AsMut`]: trait.AsMut.html #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 85e4b2a006..ccd4343336 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -144,12 +144,16 @@ default_impl! { u8, 0 } default_impl! { u16, 0 } default_impl! { u32, 0 } default_impl! { u64, 0 } +#[cfg(not(stage0))] +default_impl! { u128, 0 } default_impl! { isize, 0 } default_impl! { i8, 0 } default_impl! { i16, 0 } default_impl! { i32, 0 } default_impl! { i64, 0 } +#[cfg(not(stage0))] +default_impl! { i128, 0 } default_impl! { f32, 0.0f32 } default_impl! { f64, 0.0f64 } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 0145897d8f..cd725392b6 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -30,6 +30,8 @@ trait Int: Zero + PartialEq + PartialOrd + Div + Rem + fn to_u16(&self) -> u16; fn to_u32(&self) -> u32; fn to_u64(&self) -> u64; + #[cfg(not(stage0))] + fn to_u128(&self) -> u128; } macro_rules! doit { @@ -39,9 +41,13 @@ macro_rules! doit { fn to_u16(&self) -> u16 { *self as u16 } fn to_u32(&self) -> u32 { *self as u32 } fn to_u64(&self) -> u64 { *self as u64 } + #[cfg(not(stage0))] + fn to_u128(&self) -> u128 { *self as u128 } })*) } doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } +#[cfg(not(stage0))] +doit! { i128 u128 } /// A type that represents a specific radix #[doc(hidden)] @@ -59,11 +65,11 @@ trait GenericRadix { /// Format an integer using the radix using a formatter. fn fmt_int(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result { - // The radix can be as low as 2, so we need a buffer of at least 64 + // The radix can be as low as 2, so we need a buffer of at least 128 // characters for a base 2 number. let zero = T::zero(); let is_nonnegative = x >= zero; - let mut buf = [0; 64]; + let mut buf = [0; 128]; let mut curr = buf.len(); let base = T::from_u8(self.base()); if is_nonnegative { @@ -182,6 +188,8 @@ integer! { i8, u8 } integer! { i16, u16 } integer! { i32, u32 } integer! { i64, u64 } +#[cfg(not(stage0))] +integer! { i128, u128 } const DEC_DIGITS_LUT: &'static[u8] = b"0001020304050607080910111213141516171819\ @@ -203,14 +211,15 @@ macro_rules! impl_Display { // convert the negative num to positive by summing 1 to it's 2 complement (!self.$conv_fn()).wrapping_add(1) }; - let mut buf: [u8; 20] = unsafe { mem::uninitialized() }; + let mut buf: [u8; 39] = unsafe { mem::uninitialized() }; let mut curr = buf.len() as isize; let buf_ptr = buf.as_mut_ptr(); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); unsafe { - // eagerly decode 4 characters at a time - if <$t>::max_value() as u64 >= 10000 { + // need at least 16 bits for the 4-characters-at-a-time to work. + if ::mem::size_of::<$t>() >= 2 { + // eagerly decode 4 characters at a time while n >= 10000 { let rem = (n % 10000) as isize; n /= 10000; @@ -256,6 +265,8 @@ macro_rules! impl_Display { impl_Display!(i8, u8, i16, u16, i32, u32: to_u32); impl_Display!(i64, u64: to_u64); +#[cfg(not(stage0))] +impl_Display!(i128, u128: to_u128); #[cfg(target_pointer_width = "16")] impl_Display!(isize, usize: to_u16); #[cfg(target_pointer_width = "32")] diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 18b465d85a..dd6edc7d39 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -186,6 +186,13 @@ pub trait Hasher { fn write_u64(&mut self, i: u64) { self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) }) } + #[cfg(not(stage0))] + /// Writes a single `u128` into this hasher. + #[inline] + #[unstable(feature = "i128", issue = "35118")] + fn write_u128(&mut self, i: u128) { + self.write(&unsafe { mem::transmute::<_, [u8; 16]>(i) }) + } /// Writes a single `usize` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] @@ -220,6 +227,13 @@ pub trait Hasher { fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) } + #[cfg(not(stage0))] + /// Writes a single `i128` into this hasher. + #[inline] + #[unstable(feature = "i128", issue = "35118")] + fn write_i128(&mut self, i: i128) { + self.write_u128(i as u128) + } /// Writes a single `isize` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] @@ -293,6 +307,7 @@ pub trait BuildHasher { /// [`BuildHasher`]: trait.BuildHasher.html /// [`Default`]: ../default/trait.Default.html /// [`Hasher`]: trait.Hasher.html +/// [`HashMap`]: ../../std/collections/struct.HashMap.html #[stable(since = "1.7.0", feature = "build_hasher")] pub struct BuildHasherDefault(marker::PhantomData); @@ -362,6 +377,11 @@ mod impls { (i64, write_i64), (isize, write_isize), } + #[cfg(not(stage0))] + impl_write! { + (u128, write_u128), + (i128, write_i128), + } #[stable(feature = "rust1", since = "1.0.0")] impl Hash for bool { diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 3726eee9a9..31a0cc6884 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1156,10 +1156,58 @@ extern "rust-intrinsic" { /// Returns the number of bits set in an integer type `T` pub fn ctpop(x: T) -> T; - /// Returns the number of leading bits unset in an integer type `T` + /// Returns the number of leading unset bits (zeroes) in an integer type `T`. + /// + /// # Examples + /// + /// ``` + /// #![feature(core_intrinsics)] + /// + /// use std::intrinsics::ctlz; + /// + /// let x = 0b0001_1100_u8; + /// let num_leading = unsafe { ctlz(x) }; + /// assert_eq!(num_leading, 3); + /// ``` + /// + /// An `x` with value `0` will return the bit width of `T`. + /// + /// ``` + /// #![feature(core_intrinsics)] + /// + /// use std::intrinsics::ctlz; + /// + /// let x = 0u16; + /// let num_leading = unsafe { ctlz(x) }; + /// assert_eq!(num_leading, 16); + /// ``` pub fn ctlz(x: T) -> T; - /// Returns the number of trailing bits unset in an integer type `T` + /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. + /// + /// # Examples + /// + /// ``` + /// #![feature(core_intrinsics)] + /// + /// use std::intrinsics::cttz; + /// + /// let x = 0b0011_1000_u8; + /// let num_trailing = unsafe { cttz(x) }; + /// assert_eq!(num_trailing, 3); + /// ``` + /// + /// An `x` with value `0` will return the bit width of `T`: + /// + /// ``` + /// #![feature(core_intrinsics)] + /// + /// use std::intrinsics::cttz; + /// + /// let x = 0u16; + /// let num_trailing = unsafe { cttz(x) }; + /// assert_eq!(num_trailing, 16); + /// ``` pub fn cttz(x: T) -> T; /// Reverses the bytes in an integer type `T`. diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index ec590d2bd0..3b406873d4 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1108,9 +1108,9 @@ pub trait Iterator { /// /// One of the keys to `collect()`'s power is that many things you might /// not think of as 'collections' actually are. For example, a [`String`] - /// is a collection of [`char`]s. And a collection of [`Result`] can - /// be thought of as single [`Result`]`, E>`. See the examples - /// below for more. + /// is a collection of [`char`]s. And a collection of + /// [`Result`][`Result`] can be thought of as single + /// [`Result`]`, E>`. See the examples below for more. /// /// Because `collect()` is so general, it can cause problems with type /// inference. As such, `collect()` is one of the few times you'll see @@ -1612,7 +1612,7 @@ pub trait Iterator { /// Returns the maximum element of an iterator. /// - /// If the two elements are equally maximum, the latest element is + /// If several elements are equally maximum, the last element is /// returned. /// /// # Examples @@ -1638,7 +1638,7 @@ pub trait Iterator { /// Returns the minimum element of an iterator. /// - /// If the two elements are equally minimum, the first element is + /// If several elements are equally minimum, the first element is /// returned. /// /// # Examples @@ -1665,8 +1665,8 @@ pub trait Iterator { /// Returns the element that gives the maximum value from the /// specified function. /// - /// Returns the rightmost element if the comparison determines two elements - /// to be equally maximum. + /// If several elements are equally maximum, the last element is + /// returned. /// /// # Examples /// @@ -1690,8 +1690,8 @@ pub trait Iterator { /// Returns the element that gives the maximum value with respect to the /// specified comparison function. /// - /// Returns the rightmost element if the comparison determines two elements - /// to be equally maximum. + /// If several elements are equally maximum, the last element is + /// returned. /// /// # Examples /// @@ -1715,8 +1715,8 @@ pub trait Iterator { /// Returns the element that gives the minimum value from the /// specified function. /// - /// Returns the latest element if the comparison determines two elements - /// to be equally minimum. + /// If several elements are equally minimum, the first element is + /// returned. /// /// # Examples /// @@ -1739,8 +1739,8 @@ pub trait Iterator { /// Returns the element that gives the minimum value with respect to the /// specified comparison function. /// - /// Returns the latest element if the comparison determines two elements - /// to be equally minimum. + /// If several elements are equally minimum, the first element is + /// returned. /// /// # Examples /// diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index e6f21d6c17..9d22037882 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -242,6 +242,8 @@ step_impl_signed!(i64); // assume here that it is less than 64-bits. #[cfg(not(target_pointer_width = "64"))] step_impl_no_between!(u64 i64); +#[cfg(not(stage0))] +step_impl_no_between!(u128 i128); /// An adapter for stepping range iterators by a custom amount. /// diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index da346eaf1d..b988ce73bd 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -12,7 +12,7 @@ use fmt; use marker; use usize; -use super::FusedIterator; +use super::{FusedIterator, TrustedLen}; /// An iterator that repeats an element endlessly. /// @@ -138,6 +138,9 @@ impl ExactSizeIterator for Empty { } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Empty {} + #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Empty {} @@ -216,6 +219,9 @@ impl ExactSizeIterator for Once { } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Once {} + #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Once {} diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index c5465549ad..1e12714830 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -260,7 +260,10 @@ impl IntoIterator for I { /// /// Iterators produce a series of values, and collections can also be thought /// of as a series of values. The `Extend` trait bridges this gap, allowing you -/// to extend a collection by including the contents of that iterator. +/// to extend a collection by including the contents of that iterator. When +/// extending a collection with an already existing key, that entry is updated +/// or, in the case of collections that permit multiple entries with equal +/// keys, that entry is inserted. /// /// # Examples /// @@ -670,6 +673,87 @@ macro_rules! float_sum_product { integer_sum_product! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } float_sum_product! { f32 f64 } +/// An iterator adapter that produces output as long as the underlying +/// iterator produces `Result::Ok` values. +/// +/// If an error is encountered, the iterator stops and the error is +/// stored. The error may be recovered later via `reconstruct`. +struct ResultShunt { + iter: I, + error: Option, +} + +impl ResultShunt + where I: Iterator> +{ + /// Process the given iterator as if it yielded a `T` instead of a + /// `Result`. Any errors will stop the inner iterator and + /// the overall result will be an error. + pub fn process(iter: I, mut f: F) -> Result + where F: FnMut(&mut Self) -> U + { + let mut shunt = ResultShunt::new(iter); + let value = f(shunt.by_ref()); + shunt.reconstruct(value) + } + + fn new(iter: I) -> Self { + ResultShunt { + iter: iter, + error: None, + } + } + + /// Consume the adapter and rebuild a `Result` value. This should + /// *always* be called, otherwise any potential error would be + /// lost. + fn reconstruct(self, val: U) -> Result { + match self.error { + None => Ok(val), + Some(e) => Err(e), + } + } +} + +impl Iterator for ResultShunt + where I: Iterator> +{ + type Item = T; + + fn next(&mut self) -> Option { + match self.iter.next() { + Some(Ok(v)) => Some(v), + Some(Err(e)) => { + self.error = Some(e); + None + } + None => None, + } + } +} + +#[stable(feature = "iter_arith_traits_result", since="1.16.0")] +impl Sum> for Result + where T: Sum, +{ + fn sum(iter: I) -> Result + where I: Iterator>, + { + ResultShunt::process(iter, |i| i.sum()) + } +} + +#[stable(feature = "iter_arith_traits_result", since="1.16.0")] +impl Product> for Result + where T: Product, +{ + fn product(iter: I) -> Result + where I: Iterator>, + { + ResultShunt::process(iter, |i| i.product()) + } +} + /// An iterator that always continues to yield `None` when exhausted. /// /// Calling next on a fused iterator that has returned `None` once is guaranteed diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 9834fca5fd..98871bd084 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -65,7 +65,7 @@ #![no_core] #![deny(missing_docs)] #![deny(missing_debug_implementations)] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(allow_internal_unstable)] #![feature(asm)] @@ -82,7 +82,6 @@ #![feature(no_core)] #![feature(on_unimplemented)] #![feature(optin_builtin_traits)] -#![feature(reflect)] #![feature(unwind_attributes)] #![feature(repr_simd, platform_intrinsics)] #![feature(rustc_attrs)] @@ -90,6 +89,7 @@ #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(never_type)] +#![cfg_attr(not(stage0), feature(i128_type))] #![feature(prelude_import)] #[prelude_import] @@ -120,12 +120,20 @@ mod uint_macros; #[path = "num/i32.rs"] pub mod i32; #[path = "num/i64.rs"] pub mod i64; +// SNAP +#[cfg(not(stage0))] +#[path = "num/i128.rs"] pub mod i128; + #[path = "num/usize.rs"] pub mod usize; #[path = "num/u8.rs"] pub mod u8; #[path = "num/u16.rs"] pub mod u16; #[path = "num/u32.rs"] pub mod u32; #[path = "num/u64.rs"] pub mod u64; +// SNAP +#[cfg(not(stage0))] +#[path = "num/u128.rs"] pub mod u128; + #[path = "num/f32.rs"] pub mod f32; #[path = "num/f64.rs"] pub mod f64; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index b3f5363f5b..bc5392f6b8 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -45,7 +45,8 @@ macro_rules! panic { /// Other use-cases of `assert!` include [testing] and enforcing run-time /// invariants in safe code (whose violation cannot result in unsafety). /// -/// This macro has a second version, where a custom panic message can be provided. +/// This macro has a second version, where a custom panic message can +/// be provided with or without arguments for formatting. /// /// [testing]: ../book/testing.html /// @@ -87,12 +88,17 @@ macro_rules! assert { /// On panic, this macro will print the values of the expressions with their /// debug representations. /// +/// Like `assert!()`, this macro has a second version, where a custom +/// panic message can be provided. +/// /// # Examples /// /// ``` /// let a = 3; /// let b = 1 + 2; /// assert_eq!(a, b); +/// +/// assert_eq!(a, b, "we are testing addition with {} and {}", a, b); /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] @@ -125,12 +131,17 @@ macro_rules! assert_eq { /// On panic, this macro will print the values of the expressions with their /// debug representations. /// +/// Like `assert!()`, this macro has a second version, where a custom +/// panic message can be provided. +/// /// # Examples /// /// ``` /// let a = 3; /// let b = 2; /// assert_ne!(a, b); +/// +/// assert_ne!(a, b, "we are testing that the values are not equal"); /// ``` #[macro_export] #[stable(feature = "assert_ne", since = "1.12.0")] @@ -404,10 +415,11 @@ macro_rules! write { /// use std::io::Write; /// /// let mut w = Vec::new(); +/// writeln!(&mut w).unwrap(); /// writeln!(&mut w, "test").unwrap(); /// writeln!(&mut w, "formatted {}", "arguments").unwrap(); /// -/// assert_eq!(&w[..], "test\nformatted arguments\n".as_bytes()); +/// assert_eq!(&w[..], "\ntest\nformatted arguments\n".as_bytes()); /// ``` /// /// A module can import both `std::fmt::Write` and `std::io::Write` and call `write!` on objects @@ -427,6 +439,9 @@ macro_rules! write { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! writeln { + ($dst:expr) => ( + write!($dst, "\n") + ); ($dst:expr, $fmt:expr) => ( write!($dst, concat!($fmt, "\n")) ); diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 9af10966ed..ede22ccddc 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -100,13 +100,26 @@ pub trait Sized { /// /// All implementations of `Unsize` are provided automatically by the compiler. /// +/// `Unsize` is implemented for: +/// +/// - `[T; N]` is `Unsize<[T]>` +/// - `T` is `Unsize` when `T: Trait` +/// - `Foo<..., T, ...>` is `Unsize>` if: +/// - `T: Unsize` +/// - Foo is a struct +/// - Only the last field of `Foo` has a type involving `T` +/// - `T` is not part of the type of any other fields +/// - `Bar: Unsize>`, if the last field of `Foo` has type `Bar` +/// /// `Unsize` is used along with [`ops::CoerceUnsized`][coerceunsized] to allow /// "user-defined" containers such as [`rc::Rc`][rc] to contain dynamically-sized -/// types. See the [DST coercion RFC][RFC982] for more details. +/// types. See the [DST coercion RFC][RFC982] and [the nomicon entry on coercion][nomicon-coerce] +/// for more details. /// /// [coerceunsized]: ../ops/trait.CoerceUnsized.html /// [rc]: ../../std/rc/struct.Rc.html /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md + #[unstable(feature = "unsize", issue = "27732")] #[lang="unsize"] pub trait Unsize { @@ -234,12 +247,10 @@ pub trait Unsize { /// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's /// managing some resource besides its own [`size_of::()`] bytes. /// -/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get a -/// compile-time error. Specifically, with structs you'll get [E0204] and with enums you'll get -/// [E0205]. +/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get +/// the error [E0204]. /// /// [E0204]: ../../error-index.html#E0204 -/// [E0205]: ../../error-index.html#E0205 /// /// ## When *should* my type be `Copy`? /// @@ -542,59 +553,3 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {} } - -/// Types that can be reflected over. -/// -/// By "reflection" we mean use of the [`Any`][any] trait, or related -/// machinery such as [`TypeId`][typeid]. -/// -/// `Reflect` is implemented for all types. Its purpose is to ensure -/// that when you write a generic function that will employ reflection, -/// that must be reflected (no pun intended) in the generic bounds of -/// that function. -/// -/// ``` -/// #![feature(reflect_marker)] -/// use std::marker::Reflect; -/// use std::any::Any; -/// -/// # #[allow(dead_code)] -/// fn foo(x: &T) { -/// let any: &Any = x; -/// if any.is::() { println!("u32"); } -/// } -/// ``` -/// -/// Without the bound `T: Reflect`, `foo` would not typecheck. (As -/// a matter of style, it would be preferable to write `T: Any`, -/// because `T: Any` implies `T: Reflect` and `T: 'static`, but we -/// use `Reflect` here for illustrative purposes.) -/// -/// The `Reflect` bound serves to alert `foo`'s caller to the -/// fact that `foo` may behave differently depending on whether -/// `T` is `u32` or not. The ability for a caller to reason about what -/// a function may do based solely on what generic bounds are declared -/// is often called the "[parametricity property][param]". Despite the -/// use of `Reflect`, Rust lacks true parametricity because a generic -/// function can, at the very least, call [`mem::size_of`][size_of] -/// without employing any trait bounds whatsoever. -/// -/// [any]: ../any/trait.Any.html -/// [typeid]: ../any/struct.TypeId.html -/// [param]: http://en.wikipedia.org/wiki/Parametricity -/// [size_of]: ../mem/fn.size_of.html -#[rustc_reflect_like] -#[unstable(feature = "reflect_marker", - reason = "requires RFC and more experience", - issue = "27749")] -#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")] -#[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \ - ensure all type parameters are bounded by `Any`"] -pub trait Reflect {} - -#[unstable(feature = "reflect_marker", - reason = "requires RFC and more experience", - issue = "27749")] -#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")] -#[allow(deprecated)] -impl Reflect for .. { } diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 47afaf7735..539ad00bd3 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -30,6 +30,10 @@ unsafe impl Zeroable for i32 {} unsafe impl Zeroable for u32 {} unsafe impl Zeroable for i64 {} unsafe impl Zeroable for u64 {} +#[cfg(not(stage0))] +unsafe impl Zeroable for i128 {} +#[cfg(not(stage0))] +unsafe impl Zeroable for u128 {} /// A wrapper type for raw pointers and integers that will never be /// NULL or 0 that might allow certain optimizations. diff --git a/src/libcore/num/i128.rs b/src/libcore/num/i128.rs new file mode 100644 index 0000000000..04354e2e33 --- /dev/null +++ b/src/libcore/num/i128.rs @@ -0,0 +1,17 @@ +// 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. + +//! The 128-bit signed integer type. +//! +//! *[See also the `i128` primitive type](../../std/primitive.i128.html).* + +#![unstable(feature = "i128", issue="35118")] + +int_module! { i128, #[unstable(feature = "i128", issue="35118")] } diff --git a/src/libcore/num/i16.rs b/src/libcore/num/i16.rs index 1dd820980f..0f3a5baa2d 100644 --- a/src/libcore/num/i16.rs +++ b/src/libcore/num/i16.rs @@ -14,4 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -int_module! { i16, 16 } +int_module! { i16 } diff --git a/src/libcore/num/i32.rs b/src/libcore/num/i32.rs index 8a2168933d..ea8b3a9145 100644 --- a/src/libcore/num/i32.rs +++ b/src/libcore/num/i32.rs @@ -14,4 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -int_module! { i32, 32 } +int_module! { i32 } diff --git a/src/libcore/num/i64.rs b/src/libcore/num/i64.rs index 2ce9eb1193..aa21b1190a 100644 --- a/src/libcore/num/i64.rs +++ b/src/libcore/num/i64.rs @@ -14,4 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -int_module! { i64, 64 } +int_module! { i64 } diff --git a/src/libcore/num/i8.rs b/src/libcore/num/i8.rs index 8b5a7f1910..1bed486159 100644 --- a/src/libcore/num/i8.rs +++ b/src/libcore/num/i8.rs @@ -14,4 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -int_module! { i8, 8 } +int_module! { i8 } diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index e74c30d5e5..04311d687e 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,13 +10,14 @@ #![doc(hidden)] -macro_rules! int_module { ($T:ident, $bits:expr) => ( - -/// The smallest value that can be represented by this integer type. -#[stable(feature = "rust1", since = "1.0.0")] -pub const MIN: $T = $T::min_value(); -/// The largest value that can be represented by this integer type. -#[stable(feature = "rust1", since = "1.0.0")] -pub const MAX: $T = $T::max_value(); - -) } +macro_rules! int_module { + ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); + ($T:ident, $($attr: tt)*) => ( + /// The smallest value that can be represented by this integer type. + $($attr)* + pub const MIN: $T = $T::min_value(); + /// The largest value that can be represented by this integer type. + $($attr)* + pub const MAX: $T = $T::max_value(); + ) +} diff --git a/src/libcore/num/isize.rs b/src/libcore/num/isize.rs index 86bcef4011..e0917f79c4 100644 --- a/src/libcore/num/isize.rs +++ b/src/libcore/num/isize.rs @@ -14,9 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[cfg(target_pointer_width = "16")] -int_module! { isize, 16 } -#[cfg(target_pointer_width = "32")] -int_module! { isize, 32 } -#[cfg(target_pointer_width = "64")] -int_module! { isize, 64 } +int_module! { isize } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a4529909e8..61c687313d 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -145,6 +145,8 @@ macro_rules! zero_one_impl { )*) } zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } +#[cfg(not(stage0))] +zero_one_impl! { u128 i128 } macro_rules! zero_one_impl_float { ($($t:ty)*) => ($( @@ -191,7 +193,7 @@ macro_rules! int_impl { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub const fn min_value() -> Self { - (-1 as Self) << ($BITS - 1) + !0 ^ ((!0 as $UnsignedT) >> 1) as Self } /// Returns the largest value that can be represented by this integer type. @@ -1298,6 +1300,16 @@ impl i64 { intrinsics::mul_with_overflow } } +// SNAP +#[cfg(not(stage0))] +#[lang = "i128"] +impl i128 { + int_impl! { i128, u128, 128, + intrinsics::add_with_overflow, + intrinsics::sub_with_overflow, + intrinsics::mul_with_overflow } +} + #[cfg(target_pointer_width = "16")] #[lang = "isize"] impl isize { @@ -2330,6 +2342,20 @@ impl u64 { intrinsics::mul_with_overflow } } +// SNAP +#[cfg(not(stage0))] +#[lang = "u128"] +impl u128 { + uint_impl! { u128, 128, + intrinsics::ctpop, + intrinsics::ctlz, + intrinsics::cttz, + intrinsics::bswap, + intrinsics::add_with_overflow, + intrinsics::sub_with_overflow, + intrinsics::mul_with_overflow } +} + #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { @@ -2543,6 +2569,8 @@ macro_rules! from_str_radix_int_impl { )*} } from_str_radix_int_impl! { isize i8 i16 i32 i64 usize u8 u16 u32 u64 } +#[cfg(not(stage0))] +from_str_radix_int_impl! { u128 i128 } /// The error type returned when a checked integral type conversion fails. #[unstable(feature = "try_from", issue = "33417")] @@ -2567,7 +2595,7 @@ impl fmt::Display for TryFromIntError { } } -macro_rules! same_sign_from_int_impl { +macro_rules! same_sign_try_from_int_impl { ($storage:ty, $target:ty, $($source:ty),*) => {$( #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$source> for $target { @@ -2586,16 +2614,51 @@ macro_rules! same_sign_from_int_impl { )*} } -same_sign_from_int_impl!(u64, u8, u8, u16, u32, u64, usize); -same_sign_from_int_impl!(i64, i8, i8, i16, i32, i64, isize); -same_sign_from_int_impl!(u64, u16, u8, u16, u32, u64, usize); -same_sign_from_int_impl!(i64, i16, i8, i16, i32, i64, isize); -same_sign_from_int_impl!(u64, u32, u8, u16, u32, u64, usize); -same_sign_from_int_impl!(i64, i32, i8, i16, i32, i64, isize); -same_sign_from_int_impl!(u64, u64, u8, u16, u32, u64, usize); -same_sign_from_int_impl!(i64, i64, i8, i16, i32, i64, isize); -same_sign_from_int_impl!(u64, usize, u8, u16, u32, u64, usize); -same_sign_from_int_impl!(i64, isize, i8, i16, i32, i64, isize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(u64, u8, u8, u16, u32, u64, usize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(i64, i8, i8, i16, i32, i64, isize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(u64, u16, u8, u16, u32, u64, usize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(i64, i16, i8, i16, i32, i64, isize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(u64, u32, u8, u16, u32, u64, usize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(i64, i32, i8, i16, i32, i64, isize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(u64, u64, u8, u16, u32, u64, usize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(i64, i64, i8, i16, i32, i64, isize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(u64, usize, u8, u16, u32, u64, usize); +#[cfg(stage0)] +same_sign_try_from_int_impl!(i64, isize, i8, i16, i32, i64, isize); + +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(u128, u8, u8, u16, u32, u64, u128, usize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(i128, i8, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(u128, u16, u8, u16, u32, u64, u128, usize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(i128, i16, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(u128, u32, u8, u16, u32, u64, u128, usize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(i128, i32, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(u128, u64, u8, u16, u32, u64, u128, usize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(i128, i64, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(u128, u128, u8, u16, u32, u64, u128, usize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(i128, i128, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(u128, usize, u8, u16, u32, u64, u128, usize); +#[cfg(not(stage0))] +same_sign_try_from_int_impl!(i128, isize, i8, i16, i32, i64, i128, isize); macro_rules! cross_sign_from_int_impl { ($unsigned:ty, $($signed:ty),*) => {$( @@ -2629,12 +2692,30 @@ macro_rules! cross_sign_from_int_impl { )*} } +#[cfg(stage0)] cross_sign_from_int_impl!(u8, i8, i16, i32, i64, isize); +#[cfg(stage0)] cross_sign_from_int_impl!(u16, i8, i16, i32, i64, isize); +#[cfg(stage0)] cross_sign_from_int_impl!(u32, i8, i16, i32, i64, isize); +#[cfg(stage0)] cross_sign_from_int_impl!(u64, i8, i16, i32, i64, isize); +#[cfg(stage0)] cross_sign_from_int_impl!(usize, i8, i16, i32, i64, isize); +#[cfg(not(stage0))] +cross_sign_from_int_impl!(u8, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +cross_sign_from_int_impl!(u16, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +cross_sign_from_int_impl!(u32, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +cross_sign_from_int_impl!(u64, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +cross_sign_from_int_impl!(u128, i8, i16, i32, i64, i128, isize); +#[cfg(not(stage0))] +cross_sign_from_int_impl!(usize, i8, i16, i32, i64, i128, isize); + #[doc(hidden)] trait FromStrRadixHelper: PartialOrd + Copy { fn min_value() -> Self; @@ -2662,6 +2743,8 @@ macro_rules! doit { })*) } doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } +#[cfg(not(stage0))] +doit! { i128 u128 } fn from_str_radix(src: &str, radix: u32) -> Result { use self::IntErrorKind::*; @@ -2795,27 +2878,51 @@ macro_rules! impl_from { impl_from! { u8, u16 } impl_from! { u8, u32 } impl_from! { u8, u64 } +#[cfg(not(stage0))] +impl_from! { u8, u128 } impl_from! { u8, usize } impl_from! { u16, u32 } impl_from! { u16, u64 } +#[cfg(not(stage0))] +impl_from! { u16, u128 } impl_from! { u32, u64 } +#[cfg(not(stage0))] +impl_from! { u32, u128 } +#[cfg(not(stage0))] +impl_from! { u64, u128 } // Signed -> Signed impl_from! { i8, i16 } impl_from! { i8, i32 } impl_from! { i8, i64 } +#[cfg(not(stage0))] +impl_from! { i8, i128 } impl_from! { i8, isize } impl_from! { i16, i32 } impl_from! { i16, i64 } +#[cfg(not(stage0))] +impl_from! { i16, i128 } impl_from! { i32, i64 } +#[cfg(not(stage0))] +impl_from! { i32, i128 } +#[cfg(not(stage0))] +impl_from! { i64, i128 } // Unsigned -> Signed impl_from! { u8, i16 } impl_from! { u8, i32 } impl_from! { u8, i64 } +#[cfg(not(stage0))] +impl_from! { u8, i128 } impl_from! { u16, i32 } impl_from! { u16, i64 } +#[cfg(not(stage0))] +impl_from! { u16, i128 } impl_from! { u32, i64 } +#[cfg(not(stage0))] +impl_from! { u32, i128 } +#[cfg(not(stage0))] +impl_from! { u64, i128 } // Note: integers can only be represented with full precision in a float if // they fit in the significand, which is 24 bits in f32 and 53 bits in f64. diff --git a/src/libcore/num/u128.rs b/src/libcore/num/u128.rs new file mode 100644 index 0000000000..987ac3e000 --- /dev/null +++ b/src/libcore/num/u128.rs @@ -0,0 +1,16 @@ +// 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. + +//! The 128-bit unsigned integer type. +//! +//! *[See also the `u128` primitive type](../../std/primitive.u128.html).* + +#![unstable(feature = "i128", issue="35118")] +uint_module! { u128, #[unstable(feature = "i128", issue="35118")] } diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs index d34d87caa5..9c318216f1 100644 --- a/src/libcore/num/u16.rs +++ b/src/libcore/num/u16.rs @@ -14,4 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { u16, 16 } +uint_module! { u16 } diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs index f9c9099e47..84367c2073 100644 --- a/src/libcore/num/u32.rs +++ b/src/libcore/num/u32.rs @@ -14,4 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { u32, 32 } +uint_module! { u32 } diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs index 8dfe4335a3..cc48a28b22 100644 --- a/src/libcore/num/u64.rs +++ b/src/libcore/num/u64.rs @@ -14,4 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { u64, 64 } +uint_module! { u64 } diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs index 0106ee8e40..6c0daa7763 100644 --- a/src/libcore/num/u8.rs +++ b/src/libcore/num/u8.rs @@ -14,4 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { u8, 8 } +uint_module! { u8 } diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index cc9256ab6b..2e59b39278 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,13 +10,14 @@ #![doc(hidden)] -macro_rules! uint_module { ($T:ident, $bits:expr) => ( - -/// The smallest value that can be represented by this integer type. -#[stable(feature = "rust1", since = "1.0.0")] -pub const MIN: $T = $T::min_value(); -/// The largest value that can be represented by this integer type. -#[stable(feature = "rust1", since = "1.0.0")] -pub const MAX: $T = $T::max_value(); - -) } +macro_rules! uint_module { + ($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); + ($T:ident, $($attr: tt)*) => ( + /// The smallest value that can be represented by this integer type. + $($attr)* + pub const MIN: $T = $T::min_value(); + /// The largest value that can be represented by this integer type. + $($attr)* + pub const MAX: $T = $T::max_value(); + ) +} diff --git a/src/libcore/num/usize.rs b/src/libcore/num/usize.rs index 685c52e271..0b6f1c73c5 100644 --- a/src/libcore/num/usize.rs +++ b/src/libcore/num/usize.rs @@ -14,9 +14,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[cfg(target_pointer_width = "16")] -uint_module! { usize, 16 } -#[cfg(target_pointer_width = "32")] -uint_module! { usize, 32 } -#[cfg(target_pointer_width = "64")] -uint_module! { usize, 64 } +uint_module! { usize } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 50d64838a5..b3c2c25551 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -298,6 +298,8 @@ macro_rules! wrapping_impl { } wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +wrapping_impl! { u128 i128 } mod shift_max { #![allow(non_upper_case_globals)] diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 07ae5b920b..9ff4725c9b 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -268,6 +268,8 @@ macro_rules! add_impl { } add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +add_impl! { u128 i128 } /// The `Sub` trait is used to specify the functionality of `-`. /// @@ -341,6 +343,8 @@ macro_rules! sub_impl { } sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +sub_impl! { u128 i128 } /// The `Mul` trait is used to specify the functionality of `*`. /// @@ -463,6 +467,8 @@ macro_rules! mul_impl { } mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +mul_impl! { u128 i128 } /// The `Div` trait is used to specify the functionality of `/`. /// @@ -592,6 +598,8 @@ macro_rules! div_impl_integer { } div_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +div_impl_integer! { u128 i128 } macro_rules! div_impl_float { ($($t:ty)*) => ($( @@ -671,6 +679,9 @@ macro_rules! rem_impl_integer { } rem_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +rem_impl_integer! { u128 i128 } + macro_rules! rem_impl_float { ($($t:ty)*) => ($( @@ -766,6 +777,8 @@ macro_rules! neg_impl_unsigned { // neg_impl_unsigned! { usize u8 u16 u32 u64 } neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +neg_impl_numeric! { i128 } /// The `Not` trait is used to specify the functionality of unary `!`. /// @@ -824,6 +837,8 @@ macro_rules! not_impl { } not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +not_impl! { u128 i128 } /// The `BitAnd` trait is used to specify the functionality of `&`. /// @@ -907,6 +922,8 @@ macro_rules! bitand_impl { } bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +bitand_impl! { u128 i128 } /// The `BitOr` trait is used to specify the functionality of `|`. /// @@ -990,6 +1007,8 @@ macro_rules! bitor_impl { } bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +bitor_impl! { u128 i128 } /// The `BitXor` trait is used to specify the functionality of `^`. /// @@ -1076,6 +1095,8 @@ macro_rules! bitxor_impl { } bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +bitxor_impl! { u128 i128 } /// The `Shl` trait is used to specify the functionality of `<<`. /// @@ -1166,17 +1187,23 @@ macro_rules! shl_impl_all { shl_impl! { $t, u16 } shl_impl! { $t, u32 } shl_impl! { $t, u64 } + #[cfg(not(stage0))] + shl_impl! { $t, u128 } shl_impl! { $t, usize } shl_impl! { $t, i8 } shl_impl! { $t, i16 } shl_impl! { $t, i32 } shl_impl! { $t, i64 } + #[cfg(not(stage0))] + shl_impl! { $t, i128 } shl_impl! { $t, isize } )*) } shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } +#[cfg(not(stage0))] +shl_impl_all! { u128 i128 } /// The `Shr` trait is used to specify the functionality of `>>`. /// @@ -1267,17 +1294,23 @@ macro_rules! shr_impl_all { shr_impl! { $t, u16 } shr_impl! { $t, u32 } shr_impl! { $t, u64 } + #[cfg(not(stage0))] + shr_impl! { $t, u128 } shr_impl! { $t, usize } shr_impl! { $t, i8 } shr_impl! { $t, i16 } shr_impl! { $t, i32 } shr_impl! { $t, i64 } + #[cfg(not(stage0))] + shr_impl! { $t, i128 } shr_impl! { $t, isize } )*) } shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } +#[cfg(not(stage0))] +shr_impl_all! { u128 i128 } /// The `AddAssign` trait is used to specify the functionality of `+=`. /// @@ -1334,6 +1367,8 @@ macro_rules! add_assign_impl { } add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +add_assign_impl! { u128 i128 } /// The `SubAssign` trait is used to specify the functionality of `-=`. /// @@ -1390,6 +1425,8 @@ macro_rules! sub_assign_impl { } sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +sub_assign_impl! { u128 i128 } /// The `MulAssign` trait is used to specify the functionality of `*=`. /// @@ -1435,6 +1472,8 @@ macro_rules! mul_assign_impl { } mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +mul_assign_impl! { u128 i128 } /// The `DivAssign` trait is used to specify the functionality of `/=`. /// @@ -1479,6 +1518,8 @@ macro_rules! div_assign_impl { } div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +div_assign_impl! { u128 i128 } /// The `RemAssign` trait is used to specify the functionality of `%=`. /// @@ -1523,6 +1564,8 @@ macro_rules! rem_assign_impl { } rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } +#[cfg(not(stage0))] +rem_assign_impl! { u128 i128 } /// The `BitAndAssign` trait is used to specify the functionality of `&=`. /// @@ -1609,6 +1652,8 @@ macro_rules! bitand_assign_impl { } bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +bitand_assign_impl! { u128 i128 } /// The `BitOrAssign` trait is used to specify the functionality of `|=`. /// @@ -1653,6 +1698,8 @@ macro_rules! bitor_assign_impl { } bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +bitor_assign_impl! { u128 i128 } /// The `BitXorAssign` trait is used to specify the functionality of `^=`. /// @@ -1697,6 +1744,8 @@ macro_rules! bitxor_assign_impl { } bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } +#[cfg(not(stage0))] +bitxor_assign_impl! { u128 i128 } /// The `ShlAssign` trait is used to specify the functionality of `<<=`. /// @@ -1749,17 +1798,23 @@ macro_rules! shl_assign_impl_all { shl_assign_impl! { $t, u16 } shl_assign_impl! { $t, u32 } shl_assign_impl! { $t, u64 } + #[cfg(not(stage0))] + shl_assign_impl! { $t, u128 } shl_assign_impl! { $t, usize } shl_assign_impl! { $t, i8 } shl_assign_impl! { $t, i16 } shl_assign_impl! { $t, i32 } shl_assign_impl! { $t, i64 } + #[cfg(not(stage0))] + shl_assign_impl! { $t, i128 } shl_assign_impl! { $t, isize } )*) } shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } +#[cfg(not(stage0))] +shl_assign_impl_all! { u128 i128 } /// The `ShrAssign` trait is used to specify the functionality of `>>=`. /// @@ -1812,17 +1867,23 @@ macro_rules! shr_assign_impl_all { shr_assign_impl! { $t, u16 } shr_assign_impl! { $t, u32 } shr_assign_impl! { $t, u64 } + #[cfg(not(stage0))] + shr_assign_impl! { $t, u128 } shr_assign_impl! { $t, usize } shr_assign_impl! { $t, i8 } shr_assign_impl! { $t, i16 } shr_assign_impl! { $t, i32 } shr_assign_impl! { $t, i64 } + #[cfg(not(stage0))] + shr_assign_impl! { $t, i128 } shr_assign_impl! { $t, isize } )*) } shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } +#[cfg(not(stage0))] +shr_assign_impl_all! { u128 i128 } /// The `Index` trait is used to specify the functionality of indexing operations /// like `container[index]` when used in an immutable context. @@ -2649,6 +2710,35 @@ mod impls { /// 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] +/// for more details. +/// +/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize` +/// by converting from a thin pointer to a fat pointer. +/// +/// For custom types, the coercion here works by coercing `Foo` to `Foo` +/// provided an impl of `CoerceUnsized> for Foo` exists. +/// Such an impl can only be written if `Foo` has only a single non-phantomdata +/// field involving `T`. If the type of that field is `Bar`, an implementation +/// of `CoerceUnsized> for Bar` must exist. The coercion will work by +/// by coercing the `Bar` field into `Bar` and filling in the rest of the fields +/// from `Foo` to create a `Foo`. This will effectively drill down to a pointer +/// field and coerce that. +/// +/// Generally, for smart pointers you will implement +/// `CoerceUnsized> for Ptr where T: Unsize, U: ?Sized`, with an +/// optional `?Sized` bound on `T` itself. For wrapper types that directly embed `T` +/// like `Cell` and `RefCell`, you +/// can directly implement `CoerceUnsized> for Wrap where T: CoerceUnsized`. +/// This will let coercions of types like `Cell>` work. +/// +/// [`Unsize`][unsize] is used to mark types which can be coerced to DSTs if behind +/// pointers. It is implemented automatically by the compiler. +/// +/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md +/// [unsize]: ../marker/trait.Unsize.html +/// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "27732")] #[lang="coerce_unsized"] pub trait CoerceUnsized { @@ -2686,7 +2776,7 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -/// Both `in (PLACE) EXPR` and `box EXPR` desugar into expressions +/// Both `PLACE <- EXPR` and `box EXPR` desugar into expressions /// that allocate an intermediate "place" that holds uninitialized /// state. The desugaring evaluates EXPR, and writes the result at /// the address returned by the `pointer` method of this trait. @@ -2701,7 +2791,7 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// converting the agent to an instance of the owning pointer, via the /// appropriate `finalize` method (see the `InPlace`. /// -/// If evaluating EXPR fails, then the destructor for the +/// If evaluating EXPR fails, then it is up to the destructor for the /// implementation of Place to clean up any intermediate state /// (e.g. deallocate box storage, pop a stack, etc). #[unstable(feature = "placement_new_protocol", issue = "27779")] @@ -2712,9 +2802,9 @@ pub trait Place { fn pointer(&mut self) -> *mut Data; } -/// Interface to implementations of `in (PLACE) EXPR`. +/// Interface to implementations of `PLACE <- EXPR`. /// -/// `in (PLACE) EXPR` effectively desugars into: +/// `PLACE <- EXPR` effectively desugars into: /// /// ```rust,ignore /// let p = PLACE; @@ -2727,7 +2817,7 @@ pub trait Place { /// } /// ``` /// -/// The type of `in (PLACE) EXPR` is derived from the type of `PLACE`; +/// The type of `PLACE <- EXPR` is derived from the type of `PLACE`; /// if the type of `PLACE` is `P`, then the final type of the whole /// expression is `P::Place::Owner` (see the `InPlace` and `Boxed` /// traits). @@ -2745,12 +2835,12 @@ pub trait Placer { fn make_place(self) -> Self::Place; } -/// Specialization of `Place` trait supporting `in (PLACE) EXPR`. +/// Specialization of `Place` trait supporting `PLACE <- EXPR`. #[unstable(feature = "placement_new_protocol", issue = "27779")] pub trait InPlace: Place { - /// `Owner` is the type of the end value of `in (PLACE) EXPR` + /// `Owner` is the type of the end value of `PLACE <- EXPR` /// - /// Note that when `in (PLACE) EXPR` is solely used for + /// Note that when `PLACE <- EXPR` is solely used for /// side-effecting an existing data-structure, /// e.g. `Vec::emplace_back`, then `Owner` need not carry any /// information at all (e.g. it can be the unit type `()` in that diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 8871e1fa84..c4d7b2dcf9 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -60,7 +60,7 @@ //! the optional owned box, [`Option`]`<`[`Box`]`>`. //! //! The following example uses [`Option`] to create an optional box of -//! [`i32`]. Notice that in order to use the inner [`i32`] value first the +//! [`i32`]. Notice that in order to use the inner [`i32`] value first, the //! `check_optional` function needs to use pattern matching to //! determine whether the box has a value (i.e. it is [`Some(...)`][`Some`]) or //! not ([`None`]). @@ -74,8 +74,8 @@ //! //! fn check_optional(optional: &Option>) { //! match *optional { -//! Some(ref p) => println!("have value {}", p), -//! None => println!("have no value"), +//! Some(ref p) => println!("has value {}", p), +//! None => println!("has no value"), //! } //! } //! ``` diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index e3ca8eca76..02851c224e 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -74,7 +74,10 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } /// /// # Safety /// -/// This is only unsafe because it accepts a raw pointer. +/// This function copies the memory through the raw pointers passed to it +/// as arguments. +/// +/// Ensure that these pointers are valid before calling `swap`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn swap(x: *mut T, y: *mut T) { @@ -445,7 +448,6 @@ impl *const T { /// Basic usage: /// /// ``` - /// #![feature(ptr_wrapping_offset)] /// // Iterate using a raw pointer in increments of two elements /// let data = [1u8, 2, 3, 4, 5]; /// let mut ptr: *const u8 = data.as_ptr(); @@ -460,7 +462,7 @@ impl *const T { /// ptr = ptr.wrapping_offset(step); /// } /// ``` - #[unstable(feature = "ptr_wrapping_offset", issue = "37570")] + #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[inline] pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized { unsafe { @@ -569,7 +571,6 @@ impl *mut T { /// Basic usage: /// /// ``` - /// #![feature(ptr_wrapping_offset)] /// // Iterate using a raw pointer in increments of two elements /// let mut data = [1u8, 2, 3, 4, 5]; /// let mut ptr: *mut u8 = data.as_mut_ptr(); @@ -584,7 +585,7 @@ impl *mut T { /// } /// assert_eq!(&data, &[0, 2, 0, 4, 0]); /// ``` - #[unstable(feature = "ptr_wrapping_offset", issue = "37570")] + #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[inline] pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized { unsafe { diff --git a/src/libcore/result.rs b/src/libcore/result.rs index afed99d265..0a2e363965 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -501,6 +501,8 @@ impl Result { /// Returns an iterator over the possibly contained value. /// + /// The iterator yields one value if the result is [`Ok`], otherwise none. + /// /// # Examples /// /// Basic usage: @@ -512,6 +514,8 @@ 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 { @@ -520,6 +524,8 @@ impl Result { /// Returns a mutable iterator over the possibly contained value. /// + /// The iterator yields one value if the result is [`Ok`], otherwise none. + /// /// # Examples /// /// Basic usage: @@ -535,6 +541,8 @@ 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 { @@ -790,6 +798,31 @@ impl Result { Err(e) => e, } } + + /// Unwraps a result, yielding the content of an `Err`. + /// + /// # Panics + /// + /// Panics if the value is an `Ok`, with a panic message including the + /// passed message, and the content of the `Ok`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```{.should_panic} + /// # #![feature(result_expect_err)] + /// let x: Result = Ok(10); + /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10` + /// ``` + #[inline] + #[unstable(feature = "result_expect_err", issue = "39041")] + pub fn expect_err(self, msg: &str) -> E { + match self { + Ok(t) => unwrap_failed(msg, t), + Err(e) => e, + } + } } impl Result { @@ -807,8 +840,6 @@ impl Result { /// `Err` on error. /// /// ``` - /// #![feature(result_unwrap_or_default)] - /// /// let good_year_from_input = "1909"; /// let bad_year_from_input = "190blarg"; /// let good_year = good_year_from_input.parse().unwrap_or_default(); @@ -821,7 +852,7 @@ impl Result { /// [`FromStr`]: ../../std/str/trait.FromStr.html /// ``` #[inline] - #[unstable(feature = "result_unwrap_or_default", issue = "37516")] + #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] pub fn unwrap_or_default(self) -> T { match self { Ok(x) => x, @@ -848,6 +879,8 @@ 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. + /// /// # Examples /// /// Basic usage: @@ -861,6 +894,8 @@ 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() } @@ -893,8 +928,13 @@ impl<'a, T, E> IntoIterator for &'a mut Result { /// An iterator over a reference to the [`Ok`] variant of a [`Result`]. /// +/// The iterator yields one value if the result is [`Ok`], otherwise none. +/// +/// Created by [`Result::iter`]. +/// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Result`]: enum.Result.html +/// [`Result::iter`]: enum.Result.html#method.iter #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { inner: Option<&'a T> } @@ -934,8 +974,11 @@ impl<'a, T> Clone for Iter<'a, T> { /// An iterator over a mutable reference to the [`Ok`] variant of a [`Result`]. /// +/// Created by [`Result::iter_mut`]. +/// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Result`]: enum.Result.html +/// [`Result::iter_mut`]: enum.Result.html#method.iter_mut #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> } @@ -968,9 +1011,12 @@ impl<'a, T> FusedIterator for IterMut<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} -/// An iterator over the value in a [`Ok`] variant of a [`Result`]. This struct is -/// created by the [`into_iter`] method on [`Result`][`Result`] (provided by -/// the [`IntoIterator`] trait). +/// An iterator over the value in a [`Ok`] variant of a [`Result`]. +/// +/// The iterator yields one value if the result is [`Ok`], otherwise none. +/// +/// This struct is created by the [`into_iter`] method on +/// [`Result`][`Result`] (provided by the [`IntoIterator`] trait). /// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Result`]: enum.Result.html diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index a4a90e7a9d..b942d85f98 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -33,6 +33,7 @@ // * The `raw` and `bytes` submodules. // * Boilerplate trait implementations. +use borrow::Borrow; use cmp::Ordering::{self, Less, Equal, Greater}; use cmp; use fmt; @@ -100,15 +101,17 @@ pub trait SliceExt { #[stable(feature = "core", since = "1.6.0")] fn as_ptr(&self) -> *const Self::Item; #[stable(feature = "core", since = "1.6.0")] - fn binary_search(&self, x: &Self::Item) -> Result - where Self::Item: Ord; + fn binary_search(&self, x: &Q) -> Result + where Self::Item: Borrow, + Q: Ord; #[stable(feature = "core", since = "1.6.0")] fn binary_search_by<'a, F>(&'a self, f: F) -> Result where F: FnMut(&'a Self::Item) -> Ordering; #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] - fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result + fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, f: F) -> Result where F: FnMut(&'a Self::Item) -> B, - B: Ord; + B: Borrow, + Q: Ord; #[stable(feature = "core", since = "1.6.0")] fn len(&self) -> usize; #[stable(feature = "core", since = "1.6.0")] @@ -169,21 +172,35 @@ macro_rules! slice_offset { ($ptr:expr, $by:expr) => {{ let ptr = $ptr; if size_from_ptr(ptr) == 0 { - ::intrinsics::arith_offset(ptr as *mut i8, $by) as *mut _ + (ptr as *mut i8).wrapping_offset($by) as _ } else { ptr.offset($by) } }}; } -macro_rules! slice_ref { +// 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 { - mem::transmute(ptr) + &mut *ptr } }}; } @@ -493,8 +510,8 @@ impl SliceExt for [T] { m >= n && needle == &self[m-n..] } - fn binary_search(&self, x: &T) -> Result where T: Ord { - self.binary_search_by(|p| p.cmp(x)) + fn binary_search(&self, x: &Q) -> Result where T: Borrow, Q: Ord { + self.binary_search_by(|p| p.borrow().cmp(x)) } #[inline] @@ -522,11 +539,12 @@ impl SliceExt for [T] { } #[inline] - fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result + fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result where F: FnMut(&'a Self::Item) -> B, - B: Ord + B: Borrow, + Q: Ord { - self.binary_search_by(|k| f(k).cmp(b)) + self.binary_search_by(|k| f(k).borrow().cmp(b)) } } @@ -959,7 +977,7 @@ fn size_from_ptr(_: *const T) -> usize { // The shared definition of the `Iter` and `IterMut` iterators macro_rules! iterator { - (struct $name:ident -> $ptr:ty, $elem:ty) => { + (struct $name:ident -> $ptr:ty, $elem:ty, $mkref:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for $name<'a, T> { type Item = $elem; @@ -975,18 +993,14 @@ macro_rules! iterator { if self.ptr == self.end { None } else { - let old = self.ptr; - self.ptr = slice_offset!(self.ptr, 1); - Some(slice_ref!(old)) + Some($mkref!(self.ptr.post_inc())) } } } #[inline] fn size_hint(&self) -> (usize, Option) { - let diff = (self.end as usize).wrapping_sub(self.ptr as usize); - let size = mem::size_of::(); - let exact = diff / (if size == 0 {1} else {size}); + let exact = ptrdistance(self.ptr, self.end); (exact, Some(exact)) } @@ -1005,6 +1019,64 @@ macro_rules! iterator { fn last(mut self) -> Option<$elem> { self.next_back() } + + fn all(&mut self, mut predicate: F) -> bool + where F: FnMut(Self::Item) -> bool, + { + self.search_while(true, move |elt| { + if predicate(elt) { + SearchWhile::Continue + } else { + SearchWhile::Done(false) + } + }) + } + + fn any(&mut self, mut predicate: F) -> bool + where F: FnMut(Self::Item) -> bool, + { + !self.all(move |elt| !predicate(elt)) + } + + fn find(&mut self, mut predicate: F) -> Option + where F: FnMut(&Self::Item) -> bool, + { + self.search_while(None, move |elt| { + if predicate(&elt) { + SearchWhile::Done(Some(elt)) + } else { + SearchWhile::Continue + } + }) + } + + fn position(&mut self, mut predicate: F) -> Option + where F: FnMut(Self::Item) -> bool, + { + let mut index = 0; + self.search_while(None, move |elt| { + if predicate(elt) { + SearchWhile::Done(Some(index)) + } else { + index += 1; + SearchWhile::Continue + } + }) + } + + fn rposition(&mut self, mut predicate: F) -> Option + where F: FnMut(Self::Item) -> bool, + { + let mut index = self.len(); + self.rsearch_while(None, move |elt| { + index -= 1; + if predicate(elt) { + SearchWhile::Done(Some(index)) + } else { + SearchWhile::Continue + } + }) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1020,10 +1092,51 @@ macro_rules! iterator { if self.end == self.ptr { None } else { - self.end = slice_offset!(self.end, -1); - Some(slice_ref!(self.end)) + Some($mkref!(self.end.pre_dec())) + } + } + } + } + + // search_while is a generalization of the internal iteration methods. + impl<'a, T> $name<'a, T> { + // search through the iterator's element using the closure `g`. + // if no element was found, return `default`. + fn search_while(&mut self, default: Acc, mut g: G) -> Acc + where Self: Sized, + G: FnMut($elem) -> SearchWhile + { + // manual unrolling is needed when there are conditional exits from the loop + unsafe { + while ptrdistance(self.ptr, self.end) >= 4 { + search_while!(g($mkref!(self.ptr.post_inc()))); + search_while!(g($mkref!(self.ptr.post_inc()))); + search_while!(g($mkref!(self.ptr.post_inc()))); + search_while!(g($mkref!(self.ptr.post_inc()))); + } + while self.ptr != self.end { + search_while!(g($mkref!(self.ptr.post_inc()))); } } + default + } + + fn rsearch_while(&mut self, default: Acc, mut g: G) -> Acc + where Self: Sized, + G: FnMut($elem) -> SearchWhile + { + unsafe { + while ptrdistance(self.ptr, self.end) >= 4 { + search_while!(g($mkref!(self.end.pre_dec()))); + search_while!(g($mkref!(self.end.pre_dec()))); + search_while!(g($mkref!(self.end.pre_dec()))); + search_while!(g($mkref!(self.end.pre_dec()))); + } + while self.ptr != self.end { + search_while!(g($mkref!(self.end.pre_dec()))); + } + } + default } } } @@ -1057,6 +1170,24 @@ macro_rules! make_mut_slice { }} } +// An enum used for controlling the execution of `.search_while()`. +enum SearchWhile { + // Continue searching + Continue, + // Fold is complete and will return this value + Done(T), +} + +// helper macro for search while's control flow +macro_rules! search_while { + ($e:expr) => { + match $e { + SearchWhile::Continue => { } + SearchWhile::Done(done) => return done, + } + } +} + /// Immutable slice iterator /// /// This struct is created by the [`iter`] method on [slices]. @@ -1143,7 +1274,7 @@ impl<'a, T> Iter<'a, T> { } } -iterator!{struct Iter -> *const T, &'a T} +iterator!{struct Iter -> *const T, &'a T, make_ref} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> { @@ -1271,7 +1402,7 @@ impl<'a, T> IterMut<'a, T> { } } -iterator!{struct IterMut -> *mut T, &'a mut T} +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> { @@ -1286,6 +1417,50 @@ impl<'a, T> FusedIterator for IterMut<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {} + +// Return the number of elements of `T` from `start` to `end`. +// Return the arithmetic difference if `T` is zero size. +#[inline(always)] +fn ptrdistance(start: *const T, end: *const T) -> usize { + let diff = (end as usize).wrapping_sub(start as usize); + let size = mem::size_of::(); + diff / (if size == 0 { 1 } else { size }) +} + +// Extension methods for raw pointers, used by the iterators +trait PointerExt : Copy { + unsafe fn slice_offset(self, i: isize) -> Self; + + /// Increment self by 1, but return the old value + #[inline(always)] + unsafe fn post_inc(&mut self) -> Self { + let current = *self; + *self = self.slice_offset(1); + current + } + + /// Decrement self by 1, and return the new value + #[inline(always)] + unsafe fn pre_dec(&mut self) -> Self { + *self = self.slice_offset(-1); + *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) + } +} + /// An internal abstraction over the splitting iterators, so that /// splitn, splitn_mut etc can be implemented once. #[doc(hidden)] @@ -1297,6 +1472,11 @@ trait SplitIter: DoubleEndedIterator { /// An iterator over subslices separated by elements that match a predicate /// function. +/// +/// This struct is created by the [`split`] method on [slices]. +/// +/// [`split`]: ../../std/primitive.slice.html#method.split +/// [slices]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool { v: &'a [T], @@ -1383,6 +1563,11 @@ impl<'a, T, P> FusedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {} /// An iterator over the subslices of the vector which are separated /// by elements that match `pred`. +/// +/// This struct is created by the [`split_mut`] method on [slices]. +/// +/// [`split_mut`]: ../../std/primitive.slice.html#method.split_mut +/// [slices]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] pub struct SplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool { v: &'a mut [T], @@ -1508,6 +1693,11 @@ impl> Iterator for GenericSplitN { /// An iterator over subslices separated by elements that match a predicate /// function, limited to a given number of splits. +/// +/// This struct is created by the [`splitn`] method on [slices]. +/// +/// [`splitn`]: ../../std/primitive.slice.html#method.splitn +/// [slices]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool { inner: GenericSplitN> @@ -1525,6 +1715,11 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitN<'a, T, P> where P: FnMut(& /// An iterator over subslices separated by elements that match a /// predicate function, limited to a given number of splits, starting /// from the end of the slice. +/// +/// This struct is created by the [`rsplitn`] method on [slices]. +/// +/// [`rsplitn`]: ../../std/primitive.slice.html#method.rsplitn +/// [slices]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool { inner: GenericSplitN> @@ -1541,6 +1736,11 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitN<'a, T, P> where P: FnMut( /// An iterator over subslices separated by elements that match a predicate /// function, limited to a given number of splits. +/// +/// This struct is created by the [`splitn_mut`] method on [slices]. +/// +/// [`splitn_mut`]: ../../std/primitive.slice.html#method.splitn_mut +/// [slices]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { inner: GenericSplitN> @@ -1558,6 +1758,11 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitNMut<'a, T, P> where P: FnMu /// An iterator over subslices separated by elements that match a /// predicate function, limited to a given number of splits, starting /// from the end of the slice. +/// +/// This struct is created by the [`rsplitn_mut`] method on [slices]. +/// +/// [`rsplitn_mut`]: ../../std/primitive.slice.html#method.rsplitn_mut +/// [slices]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { inner: GenericSplitN> @@ -1603,6 +1808,11 @@ forward_iterator! { SplitNMut: T, &'a mut [T] } forward_iterator! { RSplitNMut: T, &'a mut [T] } /// An iterator over overlapping subslices of length `size`. +/// +/// This struct is created by the [`windows`] method on [slices]. +/// +/// [`windows`]: ../../std/primitive.slice.html#method.windows +/// [slices]: ../../std/primitive.slice.html #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Windows<'a, T:'a> { @@ -1700,6 +1910,11 @@ impl<'a, T> FusedIterator for Windows<'a, T> {} /// /// When the slice len is not evenly divided by the chunk size, the last slice /// of the iteration will be the remainder. +/// +/// This struct is created by the [`chunks`] method on [slices]. +/// +/// [`chunks`]: ../../std/primitive.slice.html#method.chunks +/// [slices]: ../../std/primitive.slice.html #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Chunks<'a, T:'a> { @@ -1804,6 +2019,11 @@ impl<'a, T> FusedIterator for Chunks<'a, T> {} /// An iterator over a slice in (non-overlapping) mutable chunks (`size` /// elements at a time). When the slice len is not evenly divided by the chunk /// size, the last slice of the iteration will be the remainder. +/// +/// This struct is created by the [`chunks_mut`] method on [slices]. +/// +/// [`chunks_mut`]: ../../std/primitive.slice.html#method.chunks_mut +/// [slices]: ../../std/primitive.slice.html #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct ChunksMut<'a, T:'a> { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index de418b831c..49a6b1b5fc 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1232,10 +1232,15 @@ fn contains_nonascii(x: usize) -> bool { /// invalid sequence. #[inline(always)] fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { - let mut offset = 0; + let mut index = 0; let len = v.len(); - while offset < len { - let old_offset = offset; + + let usize_bytes = mem::size_of::(); + let ascii_block_size = 2 * usize_bytes; + let blocks_end = if len >= ascii_block_size { len - ascii_block_size + 1 } else { 0 }; + + while index < len { + let old_offset = index; macro_rules! err { () => {{ return Err(Utf8Error { valid_up_to: old_offset @@ -1243,15 +1248,15 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { }}} macro_rules! next { () => {{ - offset += 1; + index += 1; // we needed data, but there was none: error! - if offset >= len { + if index >= len { err!() } - v[offset] + v[index] }}} - let first = v[offset]; + let first = v[index]; if first >= 128 { let w = UTF8_CHAR_WIDTH[first as usize]; let second = next!(); @@ -1294,38 +1299,32 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { } _ => err!() } - offset += 1; + index += 1; } else { // Ascii case, try to skip forward quickly. // When the pointer is aligned, read 2 words of data per iteration // until we find a word containing a non-ascii byte. - let usize_bytes = mem::size_of::(); - let bytes_per_iteration = 2 * usize_bytes; let ptr = v.as_ptr(); - let align = (ptr as usize + offset) & (usize_bytes - 1); + let align = (ptr as usize + index) & (usize_bytes - 1); if align == 0 { - if len >= bytes_per_iteration { - while offset <= len - bytes_per_iteration { - unsafe { - let u = *(ptr.offset(offset as isize) as *const usize); - let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize); - - // break if there is a nonascii byte - let zu = contains_nonascii(u); - let zv = contains_nonascii(v); - if zu || zv { - break; - } + while index < blocks_end { + unsafe { + let block = ptr.offset(index as isize) as *const usize; + // break if there is a nonascii byte + let zu = contains_nonascii(*block); + let zv = contains_nonascii(*block.offset(1)); + if zu | zv { + break; } - offset += bytes_per_iteration; } + index += ascii_block_size; } // step from the point where the wordwise loop stopped - while offset < len && v[offset] < 128 { - offset += 1; + while index < len && v[index] < 128 { + index += 1; } } else { - offset += 1; + index += 1; } } } @@ -1746,13 +1745,31 @@ fn truncate_to_char_boundary(s: &str, mut max: usize) -> (bool, &str) { #[cold] fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { const MAX_DISPLAY_LENGTH: usize = 256; - let (truncated, s) = truncate_to_char_boundary(s, MAX_DISPLAY_LENGTH); + let (truncated, s_trunc) = truncate_to_char_boundary(s, MAX_DISPLAY_LENGTH); let ellipsis = if truncated { "[...]" } else { "" }; + // 1. out of bounds + if begin > s.len() || end > s.len() { + let oob_index = if begin > s.len() { begin } else { end }; + panic!("byte index {} is out of bounds of `{}`{}", oob_index, s_trunc, ellipsis); + } + + // 2. begin <= end assert!(begin <= end, "begin <= end ({} <= {}) when slicing `{}`{}", - begin, end, s, ellipsis); - panic!("index {} and/or {} in `{}`{} do not lie on character boundary", - begin, end, s, ellipsis); + begin, end, s_trunc, ellipsis); + + // 3. character boundary + let index = if !s.is_char_boundary(begin) { begin } else { end }; + // find the character + let mut char_start = index; + while !s.is_char_boundary(char_start) { + char_start -= 1; + } + // `char_start` must be less than len and a char boundary + let ch = s[char_start..].chars().next().unwrap(); + let char_range = char_start .. char_start + ch.len_utf8(); + panic!("byte index {} is not a char boundary; it is inside {:?} (bytes {:?}) of `{}`{}", + index, ch, char_range, s_trunc, ellipsis); } #[stable(feature = "core", since = "1.6.0")] diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 198db0e7c0..743e3c4117 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -21,9 +21,10 @@ //! //! Each method takes an `Ordering` which represents the strength of //! the memory barrier for that operation. These orderings are the -//! same as [LLVM atomic orderings][1]. +//! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2]. //! //! [1]: http://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`) //! but they do not themselves provide the mechanism for sharing and follow the @@ -141,6 +142,9 @@ unsafe impl Sync for AtomicPtr {} /// /// Rust's memory orderings are [the same as /// LLVM's](http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations). +/// +/// For more information see the [nomicon][1]. +/// [1]: ../../../nomicon/atomics.html #[stable(feature = "rust1", since = "1.0.0")] #[derive(Copy, Clone, Debug)] pub enum Ordering { @@ -237,11 +241,16 @@ impl AtomicBool { /// Loads a value from the bool. /// - /// `load` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `load` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. /// /// # Panics /// - /// Panics if `order` is `Release` or `AcqRel`. + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.Release /// /// # Examples /// @@ -260,7 +269,10 @@ impl AtomicBool { /// Stores a value into the bool. /// - /// `store` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `store` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -286,7 +298,10 @@ impl AtomicBool { /// Stores a value into the bool, returning the old 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. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -309,8 +324,10 @@ impl AtomicBool { /// The return value is always the previous value. If it is equal to `current`, then the value /// was updated. /// - /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of - /// this operation. + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -339,10 +356,15 @@ impl AtomicBool { /// The return value is a result indicating whether the new value was written and containing /// 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. + /// `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`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.Release /// /// # Examples /// @@ -387,11 +409,15 @@ impl AtomicBool { /// return value is a result indicating whether the new value was written and containing the /// previous value. /// - /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory + /// `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. + /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or + /// weaker than the success ordering. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.Release /// /// # Examples /// @@ -619,11 +645,16 @@ impl AtomicPtr { /// Loads a value from the pointer. /// - /// `load` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `load` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. /// /// # Panics /// - /// Panics if `order` is `Release` or `AcqRel`. + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -643,7 +674,10 @@ impl AtomicPtr { /// Stores a value into the pointer. /// - /// `store` takes an `Ordering` argument which describes the memory ordering of this operation. + /// `store` takes an [`Ordering`] argument which describes the memory ordering + /// of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -671,7 +705,10 @@ impl AtomicPtr { /// Stores a value into the pointer, returning the old 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. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -696,8 +733,10 @@ impl AtomicPtr { /// The return value is always the previous value. If it is equal to `current`, then the value /// was updated. /// - /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of - /// this operation. + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory + /// ordering of this operation. + /// + /// [`Ordering`]: enum.Ordering.html /// /// # Examples /// @@ -726,10 +765,15 @@ impl AtomicPtr { /// The return value is a result indicating whether the new value was written and containing /// 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. + /// `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`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -768,16 +812,21 @@ impl AtomicPtr { /// Stores a value into the pointer if the current value is the same as the `current` value. /// - /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the + /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the /// comparison succeeds, which can result in more efficient code on some platforms. The /// return value is a result indicating whether the new value was written and containing the /// previous value. /// - /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory + /// `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. + /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or + /// weaker than the success ordering. + /// + /// [`compare_exchange`]: #method.compare_exchange + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -913,12 +962,16 @@ macro_rules! atomic_int { /// Loads a value from the atomic integer. /// - /// `load` takes an `Ordering` argument which describes the memory ordering of this + /// `load` takes an [`Ordering`] argument which describes the memory ordering of this /// operation. /// /// # Panics /// - /// Panics if `order` is `Release` or `AcqRel`. + /// Panics if `order` is [`Release`] or [`AcqRel`]. + /// + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -937,9 +990,11 @@ macro_rules! atomic_int { /// Stores a value into the atomic integer. /// - /// `store` takes an `Ordering` argument which describes the memory ordering of this + /// `store` takes an [`Ordering`] argument which describes the memory ordering of this /// operation. /// + /// [`Ordering`]: enum.Ordering.html + /// /// # Examples /// /// ``` @@ -962,9 +1017,11 @@ macro_rules! atomic_int { /// Stores a value into the atomic integer, returning the old value. /// - /// `swap` takes an `Ordering` argument which describes the memory ordering of this + /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this /// operation. /// + /// [`Ordering`]: enum.Ordering.html + /// /// # Examples /// /// ``` @@ -986,9 +1043,11 @@ macro_rules! atomic_int { /// The return value is always the previous value. If it is equal to `current`, then the /// value was updated. /// - /// `compare_and_swap` also takes an `Ordering` argument which describes the memory + /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory /// ordering of this operation. /// + /// [`Ordering`]: enum.Ordering.html + /// /// # Examples /// /// ``` @@ -1024,11 +1083,15 @@ macro_rules! atomic_int { /// containing 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. + /// `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`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -1062,16 +1125,21 @@ macro_rules! atomic_int { /// Stores a value into the atomic integer if the current value is the same as the /// `current` value. /// - /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the - /// comparison succeeds, which can result in more efficient code on some platforms. The - /// return value is a result indicating whether the new value was written and containing - /// the previous value. + /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even + /// when the comparison succeeds, which can result in more efficient code on some + /// platforms. The return value is a result indicating whether the new value was + /// written and containing the previous value. /// - /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory + /// `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. The failure ordering can't be [`Release`] or [`AcqRel`] and + /// must be equivalent or weaker than the success ordering. + /// + /// [`compare_exchange`]: #method.compare_exchange + /// [`Ordering`]: enum.Ordering.html + /// [`Release`]: enum.Ordering.html#variant.Release + /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel /// /// # Examples /// @@ -1431,24 +1499,31 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { /// An atomic fence. /// -/// A fence 'A' which has `Release` ordering semantics, synchronizes with a -/// fence 'B' with (at least) `Acquire` semantics, if and only if there exists +/// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a +/// fence 'B' with (at least) [`Acquire`] semantics, if and only if there exists /// atomic operations X and Y, both operating on some atomic object 'M' such /// that A is sequenced before X, Y is synchronized before B and Y observes /// the change to M. This provides a happens-before dependence between A and B. /// -/// Atomic operations with `Release` or `Acquire` semantics can also synchronize +/// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize /// with a fence. /// -/// A fence which has `SeqCst` ordering, in addition to having both `Acquire` -/// and `Release` semantics, participates in the global program order of the -/// other `SeqCst` operations and/or fences. +/// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`] +/// and [`Release`] semantics, participates in the global program order of the +/// other [`SeqCst`] operations and/or fences. /// -/// Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings. +/// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings. /// /// # Panics /// -/// Panics if `order` is `Relaxed`. +/// Panics if `order` is [`Relaxed`]. +/// +/// [`Ordering`]: enum.Ordering.html +/// [`Acquire`]: enum.Ordering.html#variant.Acquire +/// [`SeqCst`]: enum.Ordering.html#variant.SeqCst +/// [`Release`]: enum.Ordering.html#variant.Release +/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel +/// [`Relaxed`]: enum.Ordering.html#variant.Relaxed #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn fence(order: Ordering) { diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs index b4088ffbf8..e4012ec91e 100644 --- a/src/libcoretest/char.rs +++ b/src/libcoretest/char.rs @@ -75,47 +75,53 @@ fn test_to_digit() { #[test] fn test_to_lowercase() { - fn lower(c: char) -> Vec { - c.to_lowercase().collect() + fn lower(c: char) -> String { + let iter: String = c.to_lowercase().collect(); + let disp: String = c.to_lowercase().to_string(); + assert_eq!(iter, disp); + iter } - assert_eq!(lower('A'), ['a']); - assert_eq!(lower('Ö'), ['ö']); - assert_eq!(lower('ß'), ['ß']); - assert_eq!(lower('Ü'), ['ü']); - assert_eq!(lower('💩'), ['💩']); - assert_eq!(lower('Σ'), ['σ']); - assert_eq!(lower('Τ'), ['τ']); - assert_eq!(lower('Ι'), ['ι']); - assert_eq!(lower('Γ'), ['γ']); - assert_eq!(lower('Μ'), ['μ']); - assert_eq!(lower('Α'), ['α']); - assert_eq!(lower('Σ'), ['σ']); - assert_eq!(lower('Dž'), ['dž']); - assert_eq!(lower('fi'), ['fi']); - assert_eq!(lower('Ä°'), ['i', '\u{307}']); + assert_eq!(lower('A'), "a"); + assert_eq!(lower('Ö'), "ö"); + assert_eq!(lower('ß'), "ß"); + assert_eq!(lower('Ü'), "ü"); + assert_eq!(lower('💩'), "💩"); + assert_eq!(lower('Σ'), "σ"); + assert_eq!(lower('Τ'), "τ"); + assert_eq!(lower('Ι'), "ι"); + assert_eq!(lower('Γ'), "γ"); + assert_eq!(lower('Μ'), "μ"); + assert_eq!(lower('Α'), "α"); + assert_eq!(lower('Σ'), "σ"); + assert_eq!(lower('Dž'), "dž"); + assert_eq!(lower('fi'), "fi"); + assert_eq!(lower('Ä°'), "i\u{307}"); } #[test] fn test_to_uppercase() { - fn upper(c: char) -> Vec { - c.to_uppercase().collect() + fn upper(c: char) -> String { + let iter: String = c.to_uppercase().collect(); + let disp: String = c.to_uppercase().to_string(); + assert_eq!(iter, disp); + iter } - assert_eq!(upper('a'), ['A']); - assert_eq!(upper('ö'), ['Ö']); - assert_eq!(upper('ß'), ['S', 'S']); // not ẞ: Latin capital letter sharp s - assert_eq!(upper('ü'), ['Ü']); - assert_eq!(upper('💩'), ['💩']); - - assert_eq!(upper('σ'), ['Σ']); - assert_eq!(upper('τ'), ['Τ']); - assert_eq!(upper('ι'), ['Ι']); - assert_eq!(upper('γ'), ['Γ']); - assert_eq!(upper('μ'), ['Μ']); - assert_eq!(upper('α'), ['Α']); - assert_eq!(upper('ς'), ['Σ']); - assert_eq!(upper('Dž'), ['DŽ']); - assert_eq!(upper('fi'), ['F', 'I']); - assert_eq!(upper('ᾀ'), ['Ἀ', 'Ι']); + assert_eq!(upper('a'), "A"); + assert_eq!(upper('ö'), "Ö"); + assert_eq!(upper('ß'), "SS"); // not ẞ: Latin capital letter sharp s + assert_eq!(upper('ü'), "Ü"); + assert_eq!(upper('💩'), "💩"); + + assert_eq!(upper('σ'), "Σ"); + assert_eq!(upper('τ'), "Τ"); + assert_eq!(upper('ι'), "Ι"); + assert_eq!(upper('γ'), "Γ"); + assert_eq!(upper('μ'), "Μ"); + assert_eq!(upper('α'), "Α"); + assert_eq!(upper('ς'), "Σ"); + assert_eq!(upper('Dž'), "DŽ"); + assert_eq!(upper('fi'), "FI"); + assert_eq!(upper('ᾀ'), "ἈΙ"); } #[test] @@ -144,107 +150,75 @@ fn test_is_digit() { #[test] fn test_escape_debug() { fn string(c: char) -> String { - c.escape_debug().collect() + let iter: String = c.escape_debug().collect(); + let disp: String = c.escape_debug().to_string(); + assert_eq!(iter, disp); + iter } - let s = string('\n'); - assert_eq!(s, "\\n"); - let s = string('\r'); - assert_eq!(s, "\\r"); - let s = string('\''); - assert_eq!(s, "\\'"); - let s = string('"'); - assert_eq!(s, "\\\""); - let s = string(' '); - assert_eq!(s, " "); - let s = string('a'); - assert_eq!(s, "a"); - let s = string('~'); - assert_eq!(s, "~"); - let s = string('é'); - assert_eq!(s, "é"); - let s = string('文'); - assert_eq!(s, "文"); - let s = string('\x00'); - assert_eq!(s, "\\u{0}"); - let s = string('\x1f'); - assert_eq!(s, "\\u{1f}"); - let s = string('\x7f'); - assert_eq!(s, "\\u{7f}"); - let s = string('\u{80}'); - assert_eq!(s, "\\u{80}"); - let s = string('\u{ff}'); - assert_eq!(s, "\u{ff}"); - let s = string('\u{11b}'); - assert_eq!(s, "\u{11b}"); - let s = string('\u{1d4b6}'); - assert_eq!(s, "\u{1d4b6}"); - let s = string('\u{200b}'); // zero width space - assert_eq!(s, "\\u{200b}"); - let s = string('\u{e000}'); // private use 1 - assert_eq!(s, "\\u{e000}"); - let s = string('\u{100000}'); // private use 2 - assert_eq!(s, "\\u{100000}"); + assert_eq!(string('\n'), "\\n"); + assert_eq!(string('\r'), "\\r"); + assert_eq!(string('\''), "\\'"); + assert_eq!(string('"'), "\\\""); + assert_eq!(string(' '), " "); + assert_eq!(string('a'), "a"); + assert_eq!(string('~'), "~"); + assert_eq!(string('é'), "é"); + assert_eq!(string('文'), "文"); + assert_eq!(string('\x00'), "\\u{0}"); + assert_eq!(string('\x1f'), "\\u{1f}"); + assert_eq!(string('\x7f'), "\\u{7f}"); + assert_eq!(string('\u{80}'), "\\u{80}"); + assert_eq!(string('\u{ff}'), "\u{ff}"); + assert_eq!(string('\u{11b}'), "\u{11b}"); + assert_eq!(string('\u{1d4b6}'), "\u{1d4b6}"); + assert_eq!(string('\u{200b}'),"\\u{200b}"); // zero width space + assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1 + assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2 } #[test] fn test_escape_default() { fn string(c: char) -> String { - c.escape_default().collect() + let iter: String = c.escape_default().collect(); + let disp: String = c.escape_default().to_string(); + assert_eq!(iter, disp); + iter } - let s = string('\n'); - assert_eq!(s, "\\n"); - let s = string('\r'); - assert_eq!(s, "\\r"); - let s = string('\''); - assert_eq!(s, "\\'"); - let s = string('"'); - assert_eq!(s, "\\\""); - let s = string(' '); - assert_eq!(s, " "); - let s = string('a'); - assert_eq!(s, "a"); - let s = string('~'); - assert_eq!(s, "~"); - let s = string('é'); - assert_eq!(s, "\\u{e9}"); - let s = string('\x00'); - assert_eq!(s, "\\u{0}"); - let s = string('\x1f'); - assert_eq!(s, "\\u{1f}"); - let s = string('\x7f'); - assert_eq!(s, "\\u{7f}"); - let s = string('\u{80}'); - assert_eq!(s, "\\u{80}"); - let s = string('\u{ff}'); - assert_eq!(s, "\\u{ff}"); - let s = string('\u{11b}'); - assert_eq!(s, "\\u{11b}"); - let s = string('\u{1d4b6}'); - assert_eq!(s, "\\u{1d4b6}"); - let s = string('\u{200b}'); // zero width space - assert_eq!(s, "\\u{200b}"); - let s = string('\u{e000}'); // private use 1 - assert_eq!(s, "\\u{e000}"); - let s = string('\u{100000}'); // private use 2 - assert_eq!(s, "\\u{100000}"); + assert_eq!(string('\n'), "\\n"); + assert_eq!(string('\r'), "\\r"); + assert_eq!(string('\''), "\\'"); + assert_eq!(string('"'), "\\\""); + assert_eq!(string(' '), " "); + assert_eq!(string('a'), "a"); + assert_eq!(string('~'), "~"); + assert_eq!(string('é'), "\\u{e9}"); + assert_eq!(string('\x00'), "\\u{0}"); + assert_eq!(string('\x1f'), "\\u{1f}"); + assert_eq!(string('\x7f'), "\\u{7f}"); + assert_eq!(string('\u{80}'), "\\u{80}"); + assert_eq!(string('\u{ff}'), "\\u{ff}"); + assert_eq!(string('\u{11b}'), "\\u{11b}"); + assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}"); + assert_eq!(string('\u{200b}'), "\\u{200b}"); // zero width space + assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1 + assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2 } #[test] fn test_escape_unicode() { - fn string(c: char) -> String { c.escape_unicode().collect() } - - let s = string('\x00'); - assert_eq!(s, "\\u{0}"); - let s = string('\n'); - assert_eq!(s, "\\u{a}"); - let s = string(' '); - assert_eq!(s, "\\u{20}"); - let s = string('a'); - assert_eq!(s, "\\u{61}"); - let s = string('\u{11b}'); - assert_eq!(s, "\\u{11b}"); - let s = string('\u{1d4b6}'); - assert_eq!(s, "\\u{1d4b6}"); + fn string(c: char) -> String { + let iter: String = c.escape_unicode().collect(); + let disp: String = c.escape_unicode().to_string(); + assert_eq!(iter, disp); + iter + } + + assert_eq!(string('\x00'), "\\u{0}"); + assert_eq!(string('\n'), "\\u{a}"); + assert_eq!(string(' '), "\\u{20}"); + assert_eq!(string('a'), "\\u{61}"); + assert_eq!(string('\u{11b}'), "\\u{11b}"); + assert_eq!(string('\u{1d4b6}'), "\\u{1d4b6}"); } #[test] diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs index 4ea42644ec..0d12433813 100644 --- a/src/libcoretest/hash/mod.rs +++ b/src/libcoretest/hash/mod.rs @@ -62,9 +62,8 @@ fn test_writer_hasher() { let s: &str = "a"; assert_eq!(hash(& s), 97 + 0xFF); - // FIXME (#18283) Enable test - //let s: Box = box "a"; - //assert_eq!(hasher.hash(& s), 97 + 0xFF); + let s: Box = String::from("a").into_boxed_str(); + assert_eq!(hash(& s), 97 + 0xFF); let cs: &[u8] = &[1, 2, 3]; assert_eq!(hash(& cs), 9); // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 274539dfa6..99d3129305 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -614,6 +614,14 @@ fn test_iterator_sum() { assert_eq!(v[..0].iter().cloned().sum::(), 0); } +#[test] +fn test_iterator_sum_result() { + let v: &[Result] = &[Ok(1), Ok(2), Ok(3), Ok(4)]; + assert_eq!(v.iter().cloned().sum::>(), Ok(10)); + let v: &[Result] = &[Ok(1), Err(()), Ok(3), Ok(4)]; + assert_eq!(v.iter().cloned().sum::>(), Err(())); +} + #[test] fn test_iterator_product() { let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; @@ -622,6 +630,14 @@ fn test_iterator_product() { assert_eq!(v[..0].iter().cloned().product::(), 1); } +#[test] +fn test_iterator_product_result() { + let v: &[Result] = &[Ok(1), Ok(2), Ok(3), Ok(4)]; + assert_eq!(v.iter().cloned().product::>(), Ok(24)); + let v: &[Result] = &[Ok(1), Err(()), Ok(3), Ok(4)]; + assert_eq!(v.iter().cloned().product::>(), Err(())); +} + #[test] fn test_iterator_max() { let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index d12616a97a..8e5893b5ec 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -23,6 +23,7 @@ #![feature(nonzero)] #![feature(rand)] #![feature(raw)] +#![feature(result_expect_err)] #![feature(sip_hash_13)] #![feature(slice_patterns)] #![feature(step_by)] @@ -31,7 +32,6 @@ #![feature(unicode)] #![feature(unique)] #![feature(ordering_chaining)] -#![feature(result_unwrap_or_default)] #![feature(ptr_unaligned)] extern crate core; diff --git a/src/libcoretest/result.rs b/src/libcoretest/result.rs index bc2cd8bbfc..4c5f19dee1 100644 --- a/src/libcoretest/result.rs +++ b/src/libcoretest/result.rs @@ -151,6 +151,19 @@ pub fn test_expect_err() { err.expect("Got expected error"); } + +#[test] +pub fn test_expect_err_err() { + let ok: Result<&'static str, isize> = Err(100); + assert_eq!(ok.expect_err("Unexpected ok"), 100); +} +#[test] +#[should_panic(expected="Got expected ok: \"All good\"")] +pub fn test_expect_err_ok() { + let err: Result<&'static str, isize> = Ok("All good"); + err.expect_err("Got expected ok"); +} + #[test] pub fn test_iter() { let ok: Result = Ok(100); diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 3c608ef9c9..8365e9db2a 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -22,7 +22,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(libc)] #![feature(staged_api)] diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index b179a16e55..f5a687de64 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -23,7 +23,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] #![feature(unicode)] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 4d2f1b999a..a5cd9fab2c 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -90,6 +90,7 @@ test(attr(deny(warnings))))] #![deny(missing_docs)] +#![deny(warnings)] #![feature(staged_api)] use self::Name::*; @@ -968,7 +969,6 @@ fn test_split_within() { #[cfg(test)] mod tests { use super::*; - use super::Fail::*; use std::result::Result::{Err, Ok}; use std::result; diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 220051c9d3..8e587ad211 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -292,7 +292,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(allow(unused_variables), deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(str_escape)] diff --git a/src/liblibc/.travis.yml b/src/liblibc/.travis.yml index 71c771d2b7..fa07ffc7c7 100644 --- a/src/liblibc/.travis.yml +++ b/src/liblibc/.travis.yml @@ -33,7 +33,7 @@ matrix: # build documentation - os: linux env: TARGET=x86_64-unknown-linux-gnu - rust: nightly-2016-11-26 + rust: nightly script: sh ci/dox.sh # stable compat @@ -103,10 +103,10 @@ matrix: # nightly - os: linux env: TARGET=x86_64-unknown-linux-gnu - rust: nightly-2016-11-26 + rust: nightly - os: osx env: TARGET=x86_64-apple-darwin - rust: nightly-2016-11-26 + rust: nightly # QEMU based targets that compile in an emulator - os: linux diff --git a/src/liblibc/ci/docker/mipsel-unknown-linux-musl/Dockerfile b/src/liblibc/ci/docker/mipsel-unknown-linux-musl/Dockerfile index 36c4d90ef6..4c7ee8bcff 100644 --- a/src/liblibc/ci/docker/mipsel-unknown-linux-musl/Dockerfile +++ b/src/liblibc/ci/docker/mipsel-unknown-linux-musl/Dockerfile @@ -6,7 +6,10 @@ RUN apt-get install -y --no-install-recommends \ bzip2 RUN mkdir /toolchain -RUN curl -L https://downloads.openwrt.org/snapshots/trunk/malta/generic/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \ + +# Note that this originally came from: +# https://downloads.openwrt.org/snapshots/trunk/malta/generic/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 +RUN curl -L https://s3.amazonaws.com/rust-lang-ci/libc/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \ tar xjf - -C /toolchain --strip-components=2 ENV PATH=$PATH:/rust/bin:/toolchain/bin \ diff --git a/src/liblibc/ci/dox.sh b/src/liblibc/ci/dox.sh index 88d882dcac..85e9243948 100644 --- a/src/liblibc/ci/dox.sh +++ b/src/liblibc/ci/dox.sh @@ -27,7 +27,7 @@ cat ci/landing-page-footer.html >> target/doc/index.html # If we're on travis, not a PR, and on the right branch, publish! if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then - pip install ghp-import --user $USER + pip install ghp_import --install-option="--prefix=$HOME/.local" $HOME/.local/bin/ghp-import -n target/doc git push -qf https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages fi diff --git a/src/liblibc/libc-test/build.rs b/src/liblibc/libc-test/build.rs index 7b241dcb73..a48590462e 100644 --- a/src/liblibc/libc-test/build.rs +++ b/src/liblibc/libc-test/build.rs @@ -216,7 +216,7 @@ fn main() { cfg.header("sys/ioctl_compat.h"); } - if linux || freebsd || netbsd || apple { + if linux || freebsd || dragonfly || netbsd || apple { cfg.header("aio.h"); } @@ -315,7 +315,7 @@ fn main() { "uuid_t" if dragonfly => true, n if n.starts_with("pthread") => true, // sem_t is a struct or pointer - "sem_t" if openbsd || freebsd || rumprun => true, + "sem_t" if openbsd || freebsd || dragonfly || rumprun => true, // windows-isms n if n.starts_with("P") => true, diff --git a/src/liblibc/src/dox.rs b/src/liblibc/src/dox.rs index c7d3dc9c2d..fbec3f2d4e 100644 --- a/src/liblibc/src/dox.rs +++ b/src/liblibc/src/dox.rs @@ -40,6 +40,12 @@ mod imp { $mac!(u32); $mac!(u64); $mac!(usize); + each_signed_int!($mac); + ) + } + + macro_rules! each_signed_int { + ($mac:ident) => ( $mac!(i8); $mac!(i16); $mac!(i32); @@ -128,6 +134,38 @@ mod imp { } each_int!(impl_bitor); + #[lang = "neg"] + pub trait Neg { + type Output; + fn neg(self) -> Self::Output; + } + + macro_rules! impl_neg { + ($($i:ident)*) => ($( + impl Neg for $i { + type Output = $i; + fn neg(self) -> $i { -self } + } + )*) + } + each_signed_int!(impl_neg); + + #[lang = "not"] + pub trait Not { + type Output; + fn not(self) -> Self::Output; + } + + macro_rules! impl_not { + ($($i:ident)*) => ($( + impl Not for $i { + type Output = $i; + fn not(self) -> $i { !self } + } + )*) + } + each_int!(impl_not); + pub mod mem { pub fn size_of_val(_: &T) -> usize { 4 } } diff --git a/src/liblibc/src/redox.rs b/src/liblibc/src/redox.rs index 7a05a3957b..eb1ce0d9a4 100644 --- a/src/liblibc/src/redox.rs +++ b/src/liblibc/src/redox.rs @@ -47,3 +47,7 @@ s! { pub sin6_scope_id: u32, } } + +extern { + pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; +} diff --git a/src/liblibc/src/unix/bsd/apple/mod.rs b/src/liblibc/src/unix/bsd/apple/mod.rs index 919d12680a..0eaaced03e 100644 --- a/src/liblibc/src/unix/bsd/apple/mod.rs +++ b/src/liblibc/src/unix/bsd/apple/mod.rs @@ -1530,6 +1530,8 @@ extern { linkpath: *const ::c_char) -> ::c_int; pub fn unlinkat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int) -> ::c_int; + + pub fn initgroups(user: *const ::c_char, basegroup: ::c_int) -> ::c_int; } cfg_if! { diff --git a/src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs index 3a91bca008..ddb7150292 100644 --- a/src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs +++ b/src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs @@ -14,7 +14,34 @@ pub type uuid_t = ::uuid; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; +pub type sem_t = *mut sem; + +pub enum sem {} + s! { + + pub struct exit_status { + pub e_termination: u16, + pub e_exit: u16 + } + + pub struct utmpx { + pub ut_name: [::c_char; 32], + pub ut_id: [::c_char; 4], + + pub ut_line: [::c_char; 32], + pub ut_host: [::c_char; 256], + + pub ut_unused: [u8; 16], + pub ut_session: u16, + pub ut_type: u16, + pub ut_pid: ::pid_t, + ut_exit: exit_status, + ut_ss: ::sockaddr_storage, + pub ut_tv: ::timeval, + pub ut_unused2: [u8; 16], + } + pub struct aiocb { pub aio_fildes: ::c_int, pub aio_offset: ::off_t, @@ -47,11 +74,15 @@ s! { pub struct sigevent { pub sigev_notify: ::c_int, - pub sigev_signo: ::c_int, //actually a union + // The union is 8-byte in size, so it is aligned at a 8-byte offset. #[cfg(target_pointer_width = "64")] __unused1: ::c_int, + pub sigev_signo: ::c_int, //actually a union + // pad the union + #[cfg(target_pointer_width = "64")] + __unused2: ::c_int, pub sigev_value: ::sigval, - __unused2: *mut ::c_void //actually a function pointer + __unused3: *mut ::c_void //actually a function pointer } pub struct statvfs { @@ -271,7 +302,6 @@ pub const EVFILT_VNODE: ::int16_t = -4; pub const EVFILT_PROC: ::int16_t = -5; pub const EVFILT_SIGNAL: ::int16_t = -6; pub const EVFILT_TIMER: ::int16_t = -7; -pub const EVFILT_PROCDESC: ::int16_t = -8; pub const EVFILT_USER: ::int16_t = -9; pub const EVFILT_FS: ::int16_t = -10; @@ -314,11 +344,42 @@ pub const NOTE_TRACK: ::uint32_t = 0x00000001; pub const NOTE_TRACKERR: ::uint32_t = 0x00000002; pub const NOTE_CHILD: ::uint32_t = 0x00000004; -pub const MSG_NOSIGNAL: ::uint32_t = 0x400; +pub const MSG_NOSIGNAL: ::c_int = 0x400; + +pub const EMPTY: ::c_short = 0; +pub const RUN_LVL: ::c_short = 1; +pub const BOOT_TIME: ::c_short = 2; +pub const OLD_TIME: ::c_short = 3; +pub const NEW_TIME: ::c_short = 4; +pub const INIT_PROCESS: ::c_short = 5; +pub const LOGIN_PROCESS: ::c_short = 6; +pub const USER_PROCESS: ::c_short = 7; +pub const DEAD_PROCESS: ::c_short = 8; + +pub const LC_COLLATE_MASK: ::c_int = (1 << 0); +pub const LC_CTYPE_MASK: ::c_int = (1 << 1); +pub const LC_MONETARY_MASK: ::c_int = (1 << 2); +pub const LC_NUMERIC_MASK: ::c_int = (1 << 3); +pub const LC_TIME_MASK: ::c_int = (1 << 4); +pub const LC_MESSAGES_MASK: ::c_int = (1 << 5); +pub const LC_ALL_MASK: ::c_int = LC_COLLATE_MASK + | LC_CTYPE_MASK + | LC_MESSAGES_MASK + | LC_MONETARY_MASK + | LC_NUMERIC_MASK + | LC_TIME_MASK; extern { pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn clock_getres(clk_id: clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: clockid_t, tp: *mut ::timespec) -> ::c_int; + pub fn clock_settime(clk_id: clockid_t, tp: *const ::timespec) -> ::c_int; + + pub fn setutxdb(_type: ::c_uint, file: *mut ::c_char) -> ::c_int; + + pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, + timeout: *mut ::timespec) -> ::c_int; + + pub fn freelocale(loc: ::locale_t); } diff --git a/src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs b/src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs index 9cd0a34ba2..ba56d1e13e 100644 --- a/src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs +++ b/src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs @@ -5,11 +5,23 @@ pub type lwpid_t = i32; pub type nlink_t = u16; pub type blksize_t = u32; pub type clockid_t = ::c_int; +pub type sem_t = _sem; pub type fsblkcnt_t = ::uint64_t; pub type fsfilcnt_t = ::uint64_t; s! { + pub struct utmpx { + pub ut_type: ::c_short, + pub ut_tv: ::timeval, + pub ut_id: [::c_char; 8], + pub ut_pid: ::pid_t, + pub ut_user: [::c_char; 32], + pub ut_line: [::c_char; 16], + pub ut_host: [::c_char; 128], + pub __ut_spare: [::c_char; 64], + } + pub struct aiocb { pub aio_fildes: ::c_int, pub aio_offset: ::off_t, @@ -59,12 +71,18 @@ s! { pub f_fsid: ::c_ulong, pub f_namemax: ::c_ulong, } + + // internal structure has changed over time + pub struct _sem { + data: [u32; 4], + } } pub const SIGEV_THREAD_ID: ::c_int = 4; pub const RAND_MAX: ::c_int = 0x7fff_fffd; pub const PTHREAD_STACK_MIN: ::size_t = 2048; +pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 4; pub const SIGSTKSZ: ::size_t = 34816; pub const SF_NODISKIO: ::c_int = 0x00000001; pub const SF_MNOWAIT: ::c_int = 0x00000002; @@ -315,6 +333,29 @@ pub const CTL_P1003_1B_MAXID: ::c_int = 26; pub const MSG_NOSIGNAL: ::c_int = 0x20000; +pub const EMPTY: ::c_short = 0; +pub const BOOT_TIME: ::c_short = 1; +pub const OLD_TIME: ::c_short = 2; +pub const NEW_TIME: ::c_short = 3; +pub const USER_PROCESS: ::c_short = 4; +pub const INIT_PROCESS: ::c_short = 5; +pub const LOGIN_PROCESS: ::c_short = 6; +pub const DEAD_PROCESS: ::c_short = 7; +pub const SHUTDOWN_TIME: ::c_short = 8; + +pub const LC_COLLATE_MASK: ::c_int = (1 << 0); +pub const LC_CTYPE_MASK: ::c_int = (1 << 1); +pub const LC_MESSAGES_MASK: ::c_int = (1 << 2); +pub const LC_MONETARY_MASK: ::c_int = (1 << 3); +pub const LC_NUMERIC_MASK: ::c_int = (1 << 4); +pub const LC_TIME_MASK: ::c_int = (1 << 5); +pub const LC_ALL_MASK: ::c_int = LC_COLLATE_MASK + | LC_CTYPE_MASK + | LC_MESSAGES_MASK + | LC_MONETARY_MASK + | LC_NUMERIC_MASK + | LC_TIME_MASK; + extern { pub fn __error() -> *mut ::c_int; @@ -323,6 +364,7 @@ extern { pub fn clock_getres(clk_id: clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: clockid_t, tp: *mut ::timespec) -> ::c_int; + pub fn clock_settime(clk_id: clockid_t, tp: *const ::timespec) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; @@ -332,6 +374,14 @@ extern { pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; + + pub fn getutxuser(user: *const ::c_char) -> *mut utmpx; + pub fn setutxdb(_type: ::c_int, file: *const ::c_char) -> ::c_int; + + pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, + timeout: *mut ::timespec) -> ::ssize_t; + + pub fn freelocale(loc: ::locale_t) -> ::c_int; } cfg_if! { diff --git a/src/liblibc/src/unix/bsd/freebsdlike/mod.rs b/src/liblibc/src/unix/bsd/freebsdlike/mod.rs index 0e8d69adb8..9fa9ebad04 100644 --- a/src/liblibc/src/unix/bsd/freebsdlike/mod.rs +++ b/src/liblibc/src/unix/bsd/freebsdlike/mod.rs @@ -12,22 +12,10 @@ pub type tcflag_t = ::c_uint; pub type speed_t = ::c_uint; pub type nl_item = ::c_int; pub type id_t = i64; -pub type sem_t = _sem; pub enum timezone {} s! { - pub struct utmpx { - pub ut_type: ::c_short, - pub ut_tv: ::timeval, - pub ut_id: [::c_char; 8], - pub ut_pid: ::pid_t, - pub ut_user: [::c_char; 32], - pub ut_line: [::c_char; 16], - pub ut_host: [::c_char; 128], - pub __ut_spare: [::c_char; 64], - } - pub struct glob_t { pub gl_pathc: ::size_t, pub gl_matchc: ::size_t, @@ -170,11 +158,6 @@ s! { pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } - - // internal structure has changed over time - pub struct _sem { - data: [u32; 4], - } } pub const AIO_LISTIO_MAX: ::c_int = 16; @@ -192,29 +175,6 @@ pub const SIGEV_SIGNAL: ::c_int = 1; pub const SIGEV_THREAD: ::c_int = 2; pub const SIGEV_KEVENT: ::c_int = 3; -pub const EMPTY: ::c_short = 0; -pub const BOOT_TIME: ::c_short = 1; -pub const OLD_TIME: ::c_short = 2; -pub const NEW_TIME: ::c_short = 3; -pub const USER_PROCESS: ::c_short = 4; -pub const INIT_PROCESS: ::c_short = 5; -pub const LOGIN_PROCESS: ::c_short = 6; -pub const DEAD_PROCESS: ::c_short = 7; -pub const SHUTDOWN_TIME: ::c_short = 8; - -pub const LC_COLLATE_MASK: ::c_int = (1 << 0); -pub const LC_CTYPE_MASK: ::c_int = (1 << 1); -pub const LC_MESSAGES_MASK: ::c_int = (1 << 2); -pub const LC_MONETARY_MASK: ::c_int = (1 << 3); -pub const LC_NUMERIC_MASK: ::c_int = (1 << 4); -pub const LC_TIME_MASK: ::c_int = (1 << 5); -pub const LC_ALL_MASK: ::c_int = LC_COLLATE_MASK - | LC_CTYPE_MASK - | LC_MESSAGES_MASK - | LC_MONETARY_MASK - | LC_NUMERIC_MASK - | LC_TIME_MASK; - pub const CODESET: ::nl_item = 0; pub const D_T_FMT: ::nl_item = 1; pub const D_FMT: ::nl_item = 2; @@ -706,7 +666,6 @@ pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = 0 as *mut _; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 3; -pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 4; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_ERRORCHECK; pub const SCHED_FIFO: ::c_int = 1; @@ -756,8 +715,6 @@ extern { pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); - pub fn getutxuser(user: *const ::c_char) -> *mut utmpx; - pub fn setutxdb(_type: ::c_int, file: *const ::c_char) -> ::c_int; } #[link(name = "util")] @@ -772,9 +729,6 @@ extern { pub fn aio_cancel(fd: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn lio_listio(mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent) -> ::c_int; - pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, - timeout: *mut ::timespec) -> ::ssize_t; - pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, @@ -839,7 +793,6 @@ extern { winp: *mut ::winsize) -> ::pid_t; pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn duplocale(base: ::locale_t) -> ::locale_t; - pub fn freelocale(loc: ::locale_t) -> ::c_int; pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; diff --git a/src/liblibc/src/unix/bsd/mod.rs b/src/liblibc/src/unix/bsd/mod.rs index 0616cd3518..c7997ef5e9 100644 --- a/src/liblibc/src/unix/bsd/mod.rs +++ b/src/liblibc/src/unix/bsd/mod.rs @@ -117,6 +117,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::socklen_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct fsid_t { __fsid_val: [::int32_t; 2], } diff --git a/src/liblibc/src/unix/bsd/netbsdlike/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/mod.rs index 6604ec03b2..5fb527d44b 100644 --- a/src/liblibc/src/unix/bsd/netbsdlike/mod.rs +++ b/src/liblibc/src/unix/bsd/netbsdlike/mod.rs @@ -472,6 +472,8 @@ extern { pub fn clock_getres(clk_id: clockid_t, tp: *mut ::timespec) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_gettime50")] pub fn clock_gettime(clk_id: clockid_t, tp: *mut ::timespec) -> ::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__clock_settime50")] + pub fn clock_settime(clk_id: clockid_t, tp: *const ::timespec) -> ::c_int; pub fn __errno() -> *mut ::c_int; pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; diff --git a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/mod.rs b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/mod.rs index f4e7cc4061..3a9bf0866c 100644 --- a/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/mod.rs +++ b/src/liblibc/src/unix/bsd/netbsdlike/netbsd/other/mod.rs @@ -1,5 +1,6 @@ cfg_if! { - if #[cfg(target_arch = "x86_64")] { + if #[cfg(any(target_arch = "sparc64", + target_arch = "x86_64"))] { mod b64; pub use self::b64::*; } else if #[cfg(any(target_arch = "arm", diff --git a/src/liblibc/src/unix/haiku/mod.rs b/src/liblibc/src/unix/haiku/mod.rs index a241a02054..ab53e6c788 100644 --- a/src/liblibc/src/unix/haiku/mod.rs +++ b/src/liblibc/src/unix/haiku/mod.rs @@ -143,6 +143,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::size_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, @@ -706,6 +712,7 @@ f! { extern { pub fn clock_gettime(clk_id: ::c_int, tp: *mut ::timespec) -> ::c_int; + pub fn clock_settime(clk_id: ::c_int, tp: *const ::timespec) -> ::c_int; pub fn pthread_attr_getguardsize(attr: *const ::pthread_attr_t, guardsize: *mut ::size_t) -> ::c_int; pub fn pthread_attr_getstack(attr: *const ::pthread_attr_t, diff --git a/src/liblibc/src/unix/mod.rs b/src/liblibc/src/unix/mod.rs index cf3a87ab48..f88ed6dcc2 100644 --- a/src/liblibc/src/unix/mod.rs +++ b/src/liblibc/src/unix/mod.rs @@ -377,6 +377,12 @@ extern { pub fn close(fd: ::c_int) -> ::c_int; pub fn dup(fd: ::c_int) -> ::c_int; pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int; + pub fn execl(path: *const c_char, + arg0: *const c_char, ...) -> ::c_int; + pub fn execle(path: *const ::c_char, + arg0: *const ::c_char, ...) -> ::c_int; + pub fn execlp(file: *const ::c_char, + arg0: *const ::c_char, ...) -> ::c_int; pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::c_int; pub fn execve(prog: *const c_char, argv: *const *const c_char, diff --git a/src/liblibc/src/unix/notbsd/android/mod.rs b/src/liblibc/src/unix/notbsd/android/mod.rs index a88f8ef7da..8a1b565d62 100644 --- a/src/liblibc/src/unix/notbsd/android/mod.rs +++ b/src/liblibc/src/unix/notbsd/android/mod.rs @@ -75,6 +75,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::size_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, @@ -131,6 +137,34 @@ s! { } } +pub const O_TRUNC: ::c_int = 512; + +pub const O_CLOEXEC: ::c_int = 0x80000; + +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 EDOTDOT: ::c_int = 73; + +pub const SA_NODEFER: ::c_int = 0x40000000; +pub const SA_RESETHAND: ::c_int = 0x80000000; +pub const SA_RESTART: ::c_int = 0x10000000; +pub const SA_NOCLDSTOP: ::c_int = 0x00000001; + +pub const EPOLL_CLOEXEC: ::c_int = 0x80000; + +pub const EFD_CLOEXEC: ::c_int = 0x80000; + pub const USER_PROCESS: ::c_short = 7; pub const BUFSIZ: ::c_uint = 1024; @@ -221,7 +255,6 @@ pub const FIOCLEX: ::c_int = 0x5451; pub const SA_ONSTACK: ::c_ulong = 0x08000000; pub const SA_SIGINFO: ::c_ulong = 0x00000004; pub const SA_NOCLDWAIT: ::c_ulong = 0x00000002; - pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs b/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs index 8b9c5ca767..22bb33b723 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mips32.rs @@ -197,6 +197,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::size_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs b/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs index 71dfb71d49..947859998d 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mips64.rs @@ -171,6 +171,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::size_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, diff --git a/src/liblibc/src/unix/notbsd/linux/mips/mod.rs b/src/liblibc/src/unix/notbsd/linux/mips/mod.rs index 7952e3a40d..48e773088e 100644 --- a/src/liblibc/src/unix/notbsd/linux/mips/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/mips/mod.rs @@ -1,3 +1,37 @@ +pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; + +pub const SFD_CLOEXEC: ::c_int = 0x080000; + +pub const NCCS: usize = 32; + +pub const O_TRUNC: ::c_int = 512; + +pub const O_CLOEXEC: ::c_int = 0x80000; + +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 EDOTDOT: ::c_int = 73; + +pub const SA_NODEFER: ::c_int = 0x40000000; +pub const SA_RESETHAND: ::c_int = 0x80000000; +pub const SA_RESTART: ::c_int = 0x10000000; +pub const SA_NOCLDSTOP: ::c_int = 0x00000001; + +pub const EPOLL_CLOEXEC: ::c_int = 0x80000; + +pub const EFD_CLOEXEC: ::c_int = 0x80000; + pub const BUFSIZ: ::c_uint = 8192; pub const TMP_MAX: ::c_uint = 238328; pub const FOPEN_MAX: ::c_uint = 16; diff --git a/src/liblibc/src/unix/notbsd/linux/mod.rs b/src/liblibc/src/unix/notbsd/linux/mod.rs index 08efed2ea0..f822a2faa2 100644 --- a/src/liblibc/src/unix/notbsd/linux/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/mod.rs @@ -87,10 +87,12 @@ s! { pub struct pthread_mutexattr_t { #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", - target_arch = "mips64", target_arch = "s390x"))] + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64"))] __align: [::c_int; 0], #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", - target_arch = "mips64", target_arch = "s390x")))] + target_arch = "mips64", target_arch = "s390x", + target_arch = "sparc64")))] __align: [::c_long; 0], size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } @@ -248,8 +250,6 @@ pub const ABMON_10: ::nl_item = 0x20017; pub const ABMON_11: ::nl_item = 0x20018; pub const ABMON_12: ::nl_item = 0x20019; -pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; - pub const MON_1: ::nl_item = 0x2001A; pub const MON_2: ::nl_item = 0x2001B; pub const MON_3: ::nl_item = 0x2001C; @@ -500,12 +500,8 @@ pub const EPOLLONESHOT: ::c_int = 0x40000000; pub const QFMT_VFS_OLD: ::c_int = 1; pub const QFMT_VFS_V0: ::c_int = 2; -pub const SFD_CLOEXEC: ::c_int = 0x080000; - pub const EFD_SEMAPHORE: ::c_int = 0x1; -pub const NCCS: usize = 32; - pub const LOG_NFACILITIES: ::c_int = 24; pub const SEM_FAILED: *mut ::sem_t = 0 as *mut sem_t; @@ -518,6 +514,31 @@ pub const RB_POWER_OFF: ::c_int = 0x4321fedcu32 as i32; pub const RB_SW_SUSPEND: ::c_int = 0xd000fce2u32 as i32; pub const RB_KEXEC: ::c_int = 0x45584543u32 as i32; +pub const AI_PASSIVE: ::c_int = 0x0001; +pub const AI_CANONNAME: ::c_int = 0x0002; +pub const AI_NUMERICHOST: ::c_int = 0x0004; +pub const AI_V4MAPPED: ::c_int = 0x0008; +pub const AI_ALL: ::c_int = 0x0010; +pub const AI_ADDRCONFIG: ::c_int = 0x0020; + +pub const AI_NUMERICSERV: ::c_int = 0x0400; + +pub const EAI_BADFLAGS: ::c_int = -1; +pub const EAI_NONAME: ::c_int = -2; +pub const EAI_AGAIN: ::c_int = -3; +pub const EAI_FAIL: ::c_int = -4; +pub const EAI_FAMILY: ::c_int = -6; +pub const EAI_SOCKTYPE: ::c_int = -7; +pub const EAI_SERVICE: ::c_int = -8; +pub const EAI_MEMORY: ::c_int = -10; +pub const EAI_OVERFLOW: ::c_int = -12; + +pub const NI_NUMERICHOST: ::c_int = 1; +pub const NI_NUMERICSERV: ::c_int = 2; +pub const NI_NOFQDN: ::c_int = 4; +pub const NI_NAMEREQD: ::c_int = 8; +pub const NI_DGRAM: ::c_int = 16; + pub const SYNC_FILE_RANGE_WAIT_BEFORE: ::c_uint = 1; pub const SYNC_FILE_RANGE_WRITE: ::c_uint = 2; pub const SYNC_FILE_RANGE_WAIT_AFTER: ::c_uint = 4; @@ -533,6 +554,129 @@ pub const LIO_NOP: ::c_int = 2; pub const LIO_WAIT: ::c_int = 0; pub const LIO_NOWAIT: ::c_int = 1; +pub const MREMAP_MAYMOVE: ::c_int = 1; +pub const MREMAP_FIXED: ::c_int = 2; + +pub const PR_SET_PDEATHSIG: ::c_int = 1; +pub const PR_GET_PDEATHSIG: ::c_int = 2; + +pub const PR_GET_DUMPABLE: ::c_int = 3; +pub const PR_SET_DUMPABLE: ::c_int = 4; + +pub const PR_GET_UNALIGN: ::c_int = 5; +pub const PR_SET_UNALIGN: ::c_int = 6; +pub const PR_UNALIGN_NOPRINT: ::c_int = 1; +pub const PR_UNALIGN_SIGBUS: ::c_int = 2; + +pub const PR_GET_KEEPCAPS: ::c_int = 7; +pub const PR_SET_KEEPCAPS: ::c_int = 8; + +pub const PR_GET_FPEMU: ::c_int = 9; +pub const PR_SET_FPEMU: ::c_int = 10; +pub const PR_FPEMU_NOPRINT: ::c_int = 1; +pub const PR_FPEMU_SIGFPE: ::c_int = 2; + +pub const PR_GET_FPEXC: ::c_int = 11; +pub const PR_SET_FPEXC: ::c_int = 12; +pub const PR_FP_EXC_SW_ENABLE: ::c_int = 0x80; +pub const PR_FP_EXC_DIV: ::c_int = 0x010000; +pub const PR_FP_EXC_OVF: ::c_int = 0x020000; +pub const PR_FP_EXC_UND: ::c_int = 0x040000; +pub const PR_FP_EXC_RES: ::c_int = 0x080000; +pub const PR_FP_EXC_INV: ::c_int = 0x100000; +pub const PR_FP_EXC_DISABLED: ::c_int = 0; +pub const PR_FP_EXC_NONRECOV: ::c_int = 1; +pub const PR_FP_EXC_ASYNC: ::c_int = 2; +pub const PR_FP_EXC_PRECISE: ::c_int = 3; + +pub const PR_GET_TIMING: ::c_int = 13; +pub const PR_SET_TIMING: ::c_int = 14; +pub const PR_TIMING_STATISTICAL: ::c_int = 0; +pub const PR_TIMING_TIMESTAMP: ::c_int = 1; + +pub const PR_SET_NAME: ::c_int = 15; +pub const PR_GET_NAME: ::c_int = 16; + +pub const PR_GET_ENDIAN: ::c_int = 19; +pub const PR_SET_ENDIAN: ::c_int = 20; +pub const PR_ENDIAN_BIG: ::c_int = 0; +pub const PR_ENDIAN_LITTLE: ::c_int = 1; +pub const PR_ENDIAN_PPC_LITTLE: ::c_int = 2; + +pub const PR_GET_SECCOMP: ::c_int = 21; +pub const PR_SET_SECCOMP: ::c_int = 22; + +pub const PR_CAPBSET_READ: ::c_int = 23; +pub const PR_CAPBSET_DROP: ::c_int = 24; + +pub const PR_GET_TSC: ::c_int = 25; +pub const PR_SET_TSC: ::c_int = 26; +pub const PR_TSC_ENABLE: ::c_int = 1; +pub const PR_TSC_SIGSEGV: ::c_int = 2; + +pub const PR_GET_SECUREBITS: ::c_int = 27; +pub const PR_SET_SECUREBITS: ::c_int = 28; + +pub const PR_SET_TIMERSLACK: ::c_int = 29; +pub const PR_GET_TIMERSLACK: ::c_int = 30; + +pub const PR_TASK_PERF_EVENTS_DISABLE: ::c_int = 31; +pub const PR_TASK_PERF_EVENTS_ENABLE: ::c_int = 32; + +pub const PR_MCE_KILL: ::c_int = 33; +pub const PR_MCE_KILL_CLEAR: ::c_int = 0; +pub const PR_MCE_KILL_SET: ::c_int = 1; + +pub const PR_MCE_KILL_LATE: ::c_int = 0; +pub const PR_MCE_KILL_EARLY: ::c_int = 1; +pub const PR_MCE_KILL_DEFAULT: ::c_int = 2; + +pub const PR_MCE_KILL_GET: ::c_int = 34; + +pub const PR_SET_MM: ::c_int = 35; +pub const PR_SET_MM_START_CODE: ::c_int = 1; +pub const PR_SET_MM_END_CODE: ::c_int = 2; +pub const PR_SET_MM_START_DATA: ::c_int = 3; +pub const PR_SET_MM_END_DATA: ::c_int = 4; +pub const PR_SET_MM_START_STACK: ::c_int = 5; +pub const PR_SET_MM_START_BRK: ::c_int = 6; +pub const PR_SET_MM_BRK: ::c_int = 7; +pub const PR_SET_MM_ARG_START: ::c_int = 8; +pub const PR_SET_MM_ARG_END: ::c_int = 9; +pub const PR_SET_MM_ENV_START: ::c_int = 10; +pub const PR_SET_MM_ENV_END: ::c_int = 11; +pub const PR_SET_MM_AUXV: ::c_int = 12; +pub const PR_SET_MM_EXE_FILE: ::c_int = 13; +pub const PR_SET_MM_MAP: ::c_int = 14; +pub const PR_SET_MM_MAP_SIZE: ::c_int = 15; + +pub const PR_SET_PTRACER: ::c_int = 0x59616d61; + +pub const PR_SET_CHILD_SUBREAPER: ::c_int = 36; +pub const PR_GET_CHILD_SUBREAPER: ::c_int = 37; + +pub const PR_SET_NO_NEW_PRIVS: ::c_int = 38; +pub const PR_GET_NO_NEW_PRIVS: ::c_int = 39; + +pub const PR_GET_TID_ADDRESS: ::c_int = 40; + +pub const PR_SET_THP_DISABLE: ::c_int = 41; +pub const PR_GET_THP_DISABLE: ::c_int = 42; + +pub const PR_MPX_ENABLE_MANAGEMENT: ::c_int = 43; +pub const PR_MPX_DISABLE_MANAGEMENT: ::c_int = 44; + +pub const PR_SET_FP_MODE: ::c_int = 45; +pub const PR_GET_FP_MODE: ::c_int = 46; +pub const PR_FP_MODE_FR: ::c_int = 1 << 0; +pub const PR_FP_MODE_FRE: ::c_int = 1 << 1; + +pub const PR_CAP_AMBIENT: ::c_int = 47; +pub const PR_CAP_AMBIENT_IS_SET: ::c_int = 1; +pub const PR_CAP_AMBIENT_RAISE: ::c_int = 2; +pub const PR_CAP_AMBIENT_LOWER: ::c_int = 3; +pub const PR_CAP_AMBIENT_CLEAR_ALL: ::c_int = 4; + f! { pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { @@ -748,6 +892,12 @@ extern { nbytes: ::off64_t, flags: ::c_uint) -> ::c_int; pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); + + pub fn mremap(addr: *mut ::c_void, + len: ::size_t, + new_len: ::size_t, + flags: ::c_int, + ...) -> *mut ::c_void; } cfg_if! { 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 899bc69310..61eb6dba17 100644 --- a/src/liblibc/src/unix/notbsd/linux/musl/b32/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/musl/b32/mod.rs @@ -21,6 +21,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::socklen_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct sem_t { __val: [::c_int; 4], } diff --git a/src/liblibc/src/unix/notbsd/linux/musl/b64/mod.rs b/src/liblibc/src/unix/notbsd/linux/musl/b64/mod.rs index 9c5d43419d..2de34133fc 100644 --- a/src/liblibc/src/unix/notbsd/linux/musl/b64/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/musl/b64/mod.rs @@ -114,6 +114,13 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::socklen_t, + pub __pad1: ::c_int, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct sem_t { __val: [::c_int; 8], } diff --git a/src/liblibc/src/unix/notbsd/linux/musl/mod.rs b/src/liblibc/src/unix/notbsd/linux/musl/mod.rs index e80850608e..ff8e59b08a 100644 --- a/src/liblibc/src/unix/notbsd/linux/musl/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/musl/mod.rs @@ -87,6 +87,40 @@ s! { } } +pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; + +pub const SFD_CLOEXEC: ::c_int = 0x080000; + +pub const NCCS: usize = 32; + +pub const O_TRUNC: ::c_int = 512; + +pub const O_CLOEXEC: ::c_int = 0x80000; + +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 EDOTDOT: ::c_int = 73; + +pub const SA_NODEFER: ::c_int = 0x40000000; +pub const SA_RESETHAND: ::c_int = 0x80000000; +pub const SA_RESTART: ::c_int = 0x10000000; +pub const SA_NOCLDSTOP: ::c_int = 0x00000001; + +pub const EPOLL_CLOEXEC: ::c_int = 0x80000; + +pub const EFD_CLOEXEC: ::c_int = 0x80000; + pub const BUFSIZ: ::c_uint = 1024; pub const TMP_MAX: ::c_uint = 10000; pub const FOPEN_MAX: ::c_uint = 1000; 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 48c3502ada..0f936c7e24 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b32/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b32/mod.rs @@ -63,6 +63,201 @@ s! { } } +pub const TIOCGSOFTCAR: ::c_ulong = 0x5419; +pub const TIOCSSOFTCAR: ::c_ulong = 0x541A; + +pub const RLIMIT_NOFILE: ::c_int = 7; +pub const RLIMIT_NPROC: ::c_int = 6; + +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 O_FSYNC: ::c_int = 0x101000; + +pub const MAP_GROWSDOWN: ::c_int = 0x0100; + +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 EMULTIHOP: ::c_int = 72; +pub const EOVERFLOW: ::c_int = 75; +pub const ENOTUNIQ: ::c_int = 76; +pub const EBADFD: ::c_int = 77; +pub const EBADMSG: ::c_int = 74; +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 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 EHWPOISON: ::c_int = 133; +pub const ERFKILL: ::c_int = 132; + +pub const SOL_SOCKET: ::c_int = 1; + +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_LINGER: ::c_int = 13; +pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_ACCEPTCONN: ::c_int = 30; + +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 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 SIGUNUSED: ::c_int = 31; +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 POLLWRNORM: ::c_short = 0x100; +pub const POLLWRBAND: ::c_short = 0x200; + +pub const O_ASYNC: ::c_int = 0x2000; +pub const O_NDELAY: ::c_int = 0x800; + +pub const PTRACE_DETACH: ::c_uint = 17; + +pub const EFD_NONBLOCK: ::c_int = 0x800; + +pub const F_GETLK: ::c_int = 5; +pub const F_GETOWN: ::c_int = 9; +pub const F_SETOWN: ::c_int = 8; +pub const F_SETLK: ::c_int = 6; +pub const F_SETLKW: ::c_int = 7; + +pub const SFD_NONBLOCK: ::c_int = 0x0800; + +pub const TIOCEXCL: ::c_ulong = 0x540C; +pub const TIOCNXCL: ::c_ulong = 0x540D; +pub const TIOCSCTTY: ::c_ulong = 0x540E; +pub const TIOCSTI: ::c_ulong = 0x5412; +pub const TIOCMGET: ::c_ulong = 0x5415; +pub const TIOCMBIS: ::c_ulong = 0x5416; +pub const TIOCMBIC: ::c_ulong = 0x5417; +pub const TIOCMSET: ::c_ulong = 0x5418; +pub const TIOCCONS: ::c_ulong = 0x541D; +pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; + +pub const SFD_CLOEXEC: ::c_int = 0x080000; + +pub const NCCS: usize = 32; + +pub const O_TRUNC: ::c_int = 512; + +pub const O_CLOEXEC: ::c_int = 0x80000; + +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 EDOTDOT: ::c_int = 73; + +pub const SA_NODEFER: ::c_int = 0x40000000; +pub const SA_RESETHAND: ::c_int = 0x80000000; +pub const SA_RESTART: ::c_int = 0x10000000; +pub const SA_NOCLDSTOP: ::c_int = 0x00000001; + +pub const EPOLL_CLOEXEC: ::c_int = 0x80000; + +pub const EFD_CLOEXEC: ::c_int = 0x80000; + pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; 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 1da95b1020..cb0e1a6979 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/aarch64.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/aarch64.rs @@ -4,6 +4,7 @@ pub type c_char = u8; pub type wchar_t = u32; pub type nlink_t = u32; pub type blksize_t = i32; +pub type suseconds_t = i64; s! { pub struct stat { @@ -81,6 +82,202 @@ s! { } } +pub const TIOCGSOFTCAR: ::c_ulong = 0x5419; +pub const TIOCSSOFTCAR: ::c_ulong = 0x541A; + +pub const RLIMIT_NOFILE: ::c_int = 7; +pub const RLIMIT_NPROC: ::c_int = 6; + +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 O_FSYNC: ::c_int = 0x101000; + +pub const MAP_GROWSDOWN: ::c_int = 0x0100; + +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 EMULTIHOP: ::c_int = 72; +pub const EOVERFLOW: ::c_int = 75; +pub const ENOTUNIQ: ::c_int = 76; +pub const EBADFD: ::c_int = 77; +pub const EBADMSG: ::c_int = 74; +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 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 EHWPOISON: ::c_int = 133; +pub const ERFKILL: ::c_int = 132; + +pub const SOL_SOCKET: ::c_int = 1; + +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_LINGER: ::c_int = 13; +pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_ACCEPTCONN: ::c_int = 30; + +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 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 SIGUNUSED: ::c_int = 31; +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 POLLWRNORM: ::c_short = 0x100; +pub const POLLWRBAND: ::c_short = 0x200; + +pub const O_ASYNC: ::c_int = 0x2000; +pub const O_NDELAY: ::c_int = 0x800; + +pub const PTRACE_DETACH: ::c_uint = 17; + +pub const EFD_NONBLOCK: ::c_int = 0x800; + +pub const F_GETLK: ::c_int = 5; +pub const F_GETOWN: ::c_int = 9; +pub const F_SETOWN: ::c_int = 8; +pub const F_SETLK: ::c_int = 6; +pub const F_SETLKW: ::c_int = 7; + +pub const SFD_NONBLOCK: ::c_int = 0x0800; + +pub const TIOCEXCL: ::c_ulong = 0x540C; +pub const TIOCNXCL: ::c_ulong = 0x540D; +pub const TIOCSCTTY: ::c_ulong = 0x540E; +pub const TIOCSTI: ::c_ulong = 0x5412; +pub const TIOCMGET: ::c_ulong = 0x5415; +pub const TIOCMBIS: ::c_ulong = 0x5416; +pub const TIOCMBIC: ::c_ulong = 0x5417; +pub const TIOCMSET: ::c_ulong = 0x5418; +pub const TIOCCONS: ::c_ulong = 0x541D; + +pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; + +pub const SFD_CLOEXEC: ::c_int = 0x080000; + +pub const NCCS: usize = 32; + +pub const O_TRUNC: ::c_int = 512; + +pub const O_CLOEXEC: ::c_int = 0x80000; + +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 EDOTDOT: ::c_int = 73; + +pub const SA_NODEFER: ::c_int = 0x40000000; +pub const SA_RESETHAND: ::c_int = 0x80000000; +pub const SA_RESTART: ::c_int = 0x10000000; +pub const SA_NOCLDSTOP: ::c_int = 0x00000001; + +pub const EPOLL_CLOEXEC: ::c_int = 0x80000; + +pub const EFD_CLOEXEC: ::c_int = 0x80000; + pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 48; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 8; diff --git a/src/liblibc/src/unix/notbsd/linux/other/b64/mod.rs b/src/liblibc/src/unix/notbsd/linux/other/b64/mod.rs index 352dba843d..2fcec73a89 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/mod.rs @@ -4,7 +4,6 @@ pub type c_long = i64; pub type c_ulong = u64; pub type clock_t = i64; pub type time_t = i64; -pub type suseconds_t = i64; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i64; @@ -56,6 +55,9 @@ cfg_if! { } else if #[cfg(any(target_arch = "powerpc64"))] { mod powerpc64; pub use self::powerpc64::*; + } else if #[cfg(any(target_arch = "sparc64"))] { + mod sparc64; + pub use self::sparc64::*; } else if #[cfg(any(target_arch = "x86_64"))] { mod x86_64; pub use self::x86_64::*; 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 c5ce962e39..a5fad66dd1 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/powerpc64.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/powerpc64.rs @@ -4,6 +4,7 @@ pub type c_char = u8; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = i64; +pub type suseconds_t = i64; s! { pub struct stat { @@ -79,6 +80,202 @@ s! { } } +pub const TIOCGSOFTCAR: ::c_ulong = 0x5419; +pub const TIOCSSOFTCAR: ::c_ulong = 0x541A; + +pub const RLIMIT_NOFILE: ::c_int = 7; +pub const RLIMIT_NPROC: ::c_int = 6; + +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 O_FSYNC: ::c_int = 0x101000; + +pub const MAP_GROWSDOWN: ::c_int = 0x0100; + +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 EMULTIHOP: ::c_int = 72; +pub const EOVERFLOW: ::c_int = 75; +pub const ENOTUNIQ: ::c_int = 76; +pub const EBADFD: ::c_int = 77; +pub const EBADMSG: ::c_int = 74; +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 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 EHWPOISON: ::c_int = 133; +pub const ERFKILL: ::c_int = 132; + +pub const SOL_SOCKET: ::c_int = 1; + +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_LINGER: ::c_int = 13; +pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_ACCEPTCONN: ::c_int = 30; + +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 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 SIGUNUSED: ::c_int = 31; +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 POLLWRNORM: ::c_short = 0x100; +pub const POLLWRBAND: ::c_short = 0x200; + +pub const O_ASYNC: ::c_int = 0x2000; +pub const O_NDELAY: ::c_int = 0x800; + +pub const PTRACE_DETACH: ::c_uint = 17; + +pub const EFD_NONBLOCK: ::c_int = 0x800; + +pub const F_GETLK: ::c_int = 5; +pub const F_GETOWN: ::c_int = 9; +pub const F_SETOWN: ::c_int = 8; +pub const F_SETLK: ::c_int = 6; +pub const F_SETLKW: ::c_int = 7; + +pub const SFD_NONBLOCK: ::c_int = 0x0800; + +pub const TIOCEXCL: ::c_ulong = 0x540C; +pub const TIOCNXCL: ::c_ulong = 0x540D; +pub const TIOCSCTTY: ::c_ulong = 0x540E; +pub const TIOCSTI: ::c_ulong = 0x5412; +pub const TIOCMGET: ::c_ulong = 0x5415; +pub const TIOCMBIS: ::c_ulong = 0x5416; +pub const TIOCMBIC: ::c_ulong = 0x5417; +pub const TIOCMSET: ::c_ulong = 0x5418; +pub const TIOCCONS: ::c_ulong = 0x541D; + +pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; + +pub const SFD_CLOEXEC: ::c_int = 0x080000; + +pub const NCCS: usize = 32; + +pub const O_TRUNC: ::c_int = 512; + +pub const O_CLOEXEC: ::c_int = 0x80000; + +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 EDOTDOT: ::c_int = 73; + +pub const SA_NODEFER: ::c_int = 0x40000000; +pub const SA_RESETHAND: ::c_int = 0x80000000; +pub const SA_RESTART: ::c_int = 0x10000000; +pub const SA_NOCLDSTOP: ::c_int = 0x00000001; + +pub const EPOLL_CLOEXEC: ::c_int = 0x80000; + +pub const EFD_CLOEXEC: ::c_int = 0x80000; + pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; diff --git a/src/liblibc/src/unix/notbsd/linux/other/b64/sparc64.rs b/src/liblibc/src/unix/notbsd/linux/other/b64/sparc64.rs new file mode 100644 index 0000000000..a1ac4f5389 --- /dev/null +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/sparc64.rs @@ -0,0 +1,369 @@ +//! SPARC64-specific definitions for 64-bit linux-like values + +pub type c_char = i8; +pub type wchar_t = i32; +pub type nlink_t = u32; +pub type blksize_t = i64; +pub type suseconds_t = i32; + +s! { + pub struct stat { + pub st_dev: ::dev_t, + __pad0: u64, + 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, + __pad1: u64, + 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, + __pad0: u64, + pub st_ino: ::ino64_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, + __pad2: ::c_int, + pub st_size: ::off64_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; 2], + } + + pub struct pthread_attr_t { + __size: [u64; 7] + } + + pub struct ipc_perm { + pub __key: ::key_t, + pub uid: ::uid_t, + pub gid: ::gid_t, + pub cuid: ::uid_t, + pub cgid: ::gid_t, + pub mode: ::mode_t, + __pad0: u16, + pub __seq: ::c_ushort, + __unused1: ::c_ulonglong, + __unused2: ::c_ulonglong, + } + + pub struct shmid_ds { + pub shm_perm: ::ipc_perm, + pub shm_atime: ::time_t, + pub shm_dtime: ::time_t, + pub shm_ctime: ::time_t, + pub shm_segsz: ::size_t, + pub shm_cpid: ::pid_t, + pub shm_lpid: ::pid_t, + pub shm_nattch: ::shmatt_t, + __reserved1: ::c_ulong, + __reserved2: ::c_ulong + } +} + +pub const TIOCGSOFTCAR: ::c_ulong = 0x40047464; +pub const TIOCSSOFTCAR: ::c_ulong = 0x80047465; + +pub const RLIMIT_NOFILE: ::c_int = 6; +pub const RLIMIT_NPROC: ::c_int = 7; + +pub const O_APPEND: ::c_int = 0x8; +pub const O_CREAT: ::c_int = 0x200; +pub const O_EXCL: ::c_int = 0x800; +pub const O_NOCTTY: ::c_int = 0x8000; +pub const O_NONBLOCK: ::c_int = 0x4000; +pub const O_SYNC: ::c_int = 0x802000; +pub const O_RSYNC: ::c_int = 0x802000; +pub const O_DSYNC: ::c_int = 0x2000; +pub const O_FSYNC: ::c_int = 0x802000; + +pub const MAP_GROWSDOWN: ::c_int = 0x0200; + +pub const EDEADLK: ::c_int = 78; +pub const ENAMETOOLONG: ::c_int = 63; +pub const ENOLCK: ::c_int = 79; +pub const ENOSYS: ::c_int = 90; +pub const ENOTEMPTY: ::c_int = 66; +pub const ELOOP: ::c_int = 62; +pub const ENOMSG: ::c_int = 75; +pub const EIDRM: ::c_int = 77; +pub const ECHRNG: ::c_int = 94; +pub const EL2NSYNC: ::c_int = 95; +pub const EL3HLT: ::c_int = 96; +pub const EL3RST: ::c_int = 97; +pub const ELNRNG: ::c_int = 98; +pub const EUNATCH: ::c_int = 99; +pub const ENOCSI: ::c_int = 100; +pub const EL2HLT: ::c_int = 101; +pub const EBADE: ::c_int = 102; +pub const EBADR: ::c_int = 103; +pub const EXFULL: ::c_int = 104; +pub const ENOANO: ::c_int = 105; +pub const EBADRQC: ::c_int = 106; +pub const EBADSLT: ::c_int = 107; +pub const EMULTIHOP: ::c_int = 87; +pub const EOVERFLOW: ::c_int = 92; +pub const ENOTUNIQ: ::c_int = 115; +pub const EBADFD: ::c_int = 93; +pub const EBADMSG: ::c_int = 76; +pub const EREMCHG: ::c_int = 89; +pub const ELIBACC: ::c_int = 114; +pub const ELIBBAD: ::c_int = 112; +pub const ELIBSCN: ::c_int = 124; +pub const ELIBMAX: ::c_int = 123; +pub const ELIBEXEC: ::c_int = 110; +pub const EILSEQ: ::c_int = 122; +pub const ERESTART: ::c_int = 116; +pub const ESTRPIPE: ::c_int = 91; +pub const EUSERS: ::c_int = 68; +pub const ENOTSOCK: ::c_int = 38; +pub const EDESTADDRREQ: ::c_int = 39; +pub const EMSGSIZE: ::c_int = 40; +pub const EPROTOTYPE: ::c_int = 41; +pub const ENOPROTOOPT: ::c_int = 42; +pub const EPROTONOSUPPORT: ::c_int = 43; +pub const ESOCKTNOSUPPORT: ::c_int = 44; +pub const EOPNOTSUPP: ::c_int = 45; +pub const EPFNOSUPPORT: ::c_int = 46; +pub const EAFNOSUPPORT: ::c_int = 47; +pub const EADDRINUSE: ::c_int = 48; +pub const EADDRNOTAVAIL: ::c_int = 49; +pub const ENETDOWN: ::c_int = 50; +pub const ENETUNREACH: ::c_int = 51; +pub const ENETRESET: ::c_int = 52; +pub const ECONNABORTED: ::c_int = 53; +pub const ECONNRESET: ::c_int = 54; +pub const ENOBUFS: ::c_int = 55; +pub const EISCONN: ::c_int = 56; +pub const ENOTCONN: ::c_int = 57; +pub const ESHUTDOWN: ::c_int = 58; +pub const ETOOMANYREFS: ::c_int = 59; +pub const ETIMEDOUT: ::c_int = 60; +pub const ECONNREFUSED: ::c_int = 61; +pub const EHOSTDOWN: ::c_int = 64; +pub const EHOSTUNREACH: ::c_int = 65; +pub const EALREADY: ::c_int = 37; +pub const EINPROGRESS: ::c_int = 36; +pub const ESTALE: ::c_int = 70; +pub const EDQUOT: ::c_int = 69; +pub const ENOMEDIUM: ::c_int = 125; +pub const EMEDIUMTYPE: ::c_int = 126; +pub const ECANCELED: ::c_int = 127; +pub const ENOKEY: ::c_int = 128; +pub const EKEYEXPIRED: ::c_int = 129; +pub const EKEYREVOKED: ::c_int = 130; +pub const EKEYREJECTED: ::c_int = 131; +pub const EOWNERDEAD: ::c_int = 132; +pub const ENOTRECOVERABLE: ::c_int = 133; +pub const EHWPOISON: ::c_int = 135; +pub const ERFKILL: ::c_int = 134; + +pub const SOL_SOCKET: ::c_int = 0xffff; + +pub const SO_REUSEADDR: ::c_int = 4; +pub const SO_TYPE: ::c_int = 0x1008; +pub const SO_ERROR: ::c_int = 0x1007; +pub const SO_DONTROUTE: ::c_int = 16; +pub const SO_BROADCAST: ::c_int = 32; +pub const SO_SNDBUF: ::c_int = 0x1001; +pub const SO_RCVBUF: ::c_int = 0x1002; +pub const SO_KEEPALIVE: ::c_int = 8; +pub const SO_OOBINLINE: ::c_int = 0x100; +pub const SO_LINGER: ::c_int = 128; +pub const SO_REUSEPORT: ::c_int = 0x200; +pub const SO_ACCEPTCONN: ::c_int = 0x8000; + +pub const SA_ONSTACK: ::c_int = 1; +pub const SA_SIGINFO: ::c_int = 0x200; +pub const SA_NOCLDWAIT: ::c_int = 0x100; + +pub const SIGCHLD: ::c_int = 20; +pub const SIGBUS: ::c_int = 10; +pub const SIGUSR1: ::c_int = 30; +pub const SIGUSR2: ::c_int = 31; +pub const SIGCONT: ::c_int = 19; +pub const SIGSTOP: ::c_int = 17; +pub const SIGTSTP: ::c_int = 18; +pub const SIGURG: ::c_int = 16; +pub const SIGIO: ::c_int = 23; +pub const SIGSYS: ::c_int = 12; +pub const SIGPOLL: ::c_int = 23; +pub const SIGPWR: ::c_int = 29; +pub const SIG_SETMASK: ::c_int = 4; +pub const SIG_BLOCK: ::c_int = 1; +pub const SIG_UNBLOCK: ::c_int = 2; + +pub const POLLWRNORM: ::c_short = 4; +pub const POLLWRBAND: ::c_short = 0x100; + +pub const O_ASYNC: ::c_int = 0x40; +pub const O_NDELAY: ::c_int = 0x4004; + +pub const PTRACE_DETACH: ::c_uint = 11; + +pub const EFD_NONBLOCK: ::c_int = 0x4000; + +pub const F_GETLK: ::c_int = 7; +pub const F_GETOWN: ::c_int = 5; +pub const F_SETOWN: ::c_int = 6; +pub const F_SETLK: ::c_int = 8; +pub const F_SETLKW: ::c_int = 9; + +pub const SFD_NONBLOCK: ::c_int = 0x4000; + +pub const TIOCEXCL: ::c_ulong = 0x2000740d; +pub const TIOCNXCL: ::c_ulong = 0x2000740e; +pub const TIOCSCTTY: ::c_ulong = 0x20007484; +pub const TIOCSTI: ::c_ulong = 0x80017472; +pub const TIOCMGET: ::c_ulong = 0x4004746a; +pub const TIOCMBIS: ::c_ulong = 0x8004746c; +pub const TIOCMBIC: ::c_ulong = 0x8004746b; +pub const TIOCMSET: ::c_ulong = 0x8004746d; +pub const TIOCCONS: ::c_ulong = 0x20007424; + +pub const SFD_CLOEXEC: ::c_int = 0x400000; + +pub const NCCS: usize = 17; +pub const O_TRUNC: ::c_int = 0x400; + +pub const O_CLOEXEC: ::c_int = 0x400000; + +pub const EBFONT: ::c_int = 109; +pub const ENOSTR: ::c_int = 72; +pub const ENODATA: ::c_int = 111; +pub const ETIME: ::c_int = 73; +pub const ENOSR: ::c_int = 74; +pub const ENONET: ::c_int = 80; +pub const ENOPKG: ::c_int = 113; +pub const EREMOTE: ::c_int = 71; +pub const ENOLINK: ::c_int = 82; +pub const EADV: ::c_int = 83; +pub const ESRMNT: ::c_int = 84; +pub const ECOMM: ::c_int = 85; +pub const EPROTO: ::c_int = 86; +pub const EDOTDOT: ::c_int = 88; + +pub const SA_NODEFER: ::c_int = 0x20; +pub const SA_RESETHAND: ::c_int = 0x4; +pub const SA_RESTART: ::c_int = 0x2; +pub const SA_NOCLDSTOP: ::c_int = 0x00000008; + +pub const EPOLL_CLOEXEC: ::c_int = 0x400000; + +pub const EFD_CLOEXEC: ::c_int = 0x400000; +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 O_DIRECTORY: ::c_int = 0o200000; +pub const O_NOFOLLOW: ::c_int = 0o400000; +pub const O_DIRECT: ::c_int = 0x100000; + +pub const MAP_LOCKED: ::c_int = 0x0100; +pub const MAP_NORESERVE: ::c_int = 0x00040; + +pub const EDEADLOCK: ::c_int = 108; + +pub const SO_PEERCRED: ::c_int = 0x40; +pub const SO_RCVLOWAT: ::c_int = 0x800; +pub const SO_SNDLOWAT: ::c_int = 0x1000; +pub const SO_RCVTIMEO: ::c_int = 0x2000; +pub const SO_SNDTIMEO: ::c_int = 0x4000; + +pub const FIOCLEX: ::c_ulong = 0x20006601; +pub const FIONBIO: ::c_ulong = 0x8004667e; + +pub const SYS_gettid: ::c_long = 143; +pub const SYS_perf_event_open: ::c_long = 327; + +pub const MCL_CURRENT: ::c_int = 0x2000; +pub const MCL_FUTURE: ::c_int = 0x4000; + +pub const SIGSTKSZ: ::size_t = 16384; +pub const CBAUD: ::tcflag_t = 0x0000100f; +pub const TAB1: ::c_int = 0x800; +pub const TAB2: ::c_int = 0x1000; +pub const TAB3: ::c_int = 0x1800; +pub const CR1: ::c_int = 0x200; +pub const CR2: ::c_int = 0x400; +pub const CR3: ::c_int = 0x600; +pub const FF1: ::c_int = 0x8000; +pub const BS1: ::c_int = 0x2000; +pub const VT1: ::c_int = 0x4000; +pub const VWERASE: usize = 0xe; +pub const VREPRINT: usize = 0xc; +pub const VSUSP: usize = 0xa; +pub const VSTART: usize = 0x8; +pub const VSTOP: usize = 0x9; +pub const VDISCARD: usize = 0xd; +pub const VTIME: usize = 0x5; +pub const IXON: ::tcflag_t = 0x400; +pub const IXOFF: ::tcflag_t = 0x1000; +pub const ONLCR: ::tcflag_t = 0x4; +pub const CSIZE: ::tcflag_t = 0x30; +pub const CS6: ::tcflag_t = 0x10; +pub const CS7: ::tcflag_t = 0x20; +pub const CS8: ::tcflag_t = 0x30; +pub const CSTOPB: ::tcflag_t = 0x40; +pub const CREAD: ::tcflag_t = 0x80; +pub const PARENB: ::tcflag_t = 0x100; +pub const PARODD: ::tcflag_t = 0x200; +pub const HUPCL: ::tcflag_t = 0x400; +pub const CLOCAL: ::tcflag_t = 0x800; +pub const ECHOKE: ::tcflag_t = 0x800; +pub const ECHOE: ::tcflag_t = 0x10; +pub const ECHOK: ::tcflag_t = 0x20; +pub const ECHONL: ::tcflag_t = 0x40; +pub const ECHOPRT: ::tcflag_t = 0x400; +pub const ECHOCTL: ::tcflag_t = 0x200; +pub const ISIG: ::tcflag_t = 0x1; +pub const ICANON: ::tcflag_t = 0x2; +pub const PENDIN: ::tcflag_t = 0x4000; +pub const NOFLSH: ::tcflag_t = 0x80; + +pub const VEOL: usize = 5; +pub const VEOL2: usize = 6; +pub const VMIN: usize = 4; +pub const IEXTEN: ::tcflag_t = 0x8000; +pub const TOSTOP: ::tcflag_t = 0x100; +pub const FLUSHO: ::tcflag_t = 0x2000; +pub const EXTPROC: ::tcflag_t = 0x10000; +pub const TCGETS: ::c_ulong = 0x40245408; +pub const TCSETS: ::c_ulong = 0x80245409; +pub const TCSETSW: ::c_ulong = 0x8024540a; +pub const TCSETSF: ::c_ulong = 0x8024540b; +pub const TCGETA: ::c_ulong = 0x40125401; +pub const TCSETA: ::c_ulong = 0x80125402; +pub const TCSETAW: ::c_ulong = 0x80125403; +pub const TCSETAF: ::c_ulong = 0x80125404; +pub const TCSBRK: ::c_ulong = 0x20005405; +pub const TCXONC: ::c_ulong = 0x20005406; +pub const TCFLSH: ::c_ulong = 0x20005407; +pub const TIOCINQ: ::c_ulong = 0x4004667f; +pub const TIOCGPGRP: ::c_ulong = 0x40047483; +pub const TIOCSPGRP: ::c_ulong = 0x80047482; +pub const TIOCOUTQ: ::c_ulong = 0x40047473; +pub const TIOCGWINSZ: ::c_ulong = 0x40087468; +pub const TIOCSWINSZ: ::c_ulong = 0x80087467; +pub const FIONREAD: ::c_ulong = 0x4004667f; diff --git a/src/liblibc/src/unix/notbsd/linux/other/b64/x86_64.rs b/src/liblibc/src/unix/notbsd/linux/other/b64/x86_64.rs index 69295e6d5d..d7bf149caa 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/b64/x86_64.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/b64/x86_64.rs @@ -5,6 +5,7 @@ pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = i64; pub type greg_t = i64; +pub type suseconds_t = i64; s! { pub struct stat { @@ -120,6 +121,202 @@ s! { } } +pub const TIOCGSOFTCAR: ::c_ulong = 0x5419; +pub const TIOCSSOFTCAR: ::c_ulong = 0x541A; + +pub const RLIMIT_NOFILE: ::c_int = 7; +pub const RLIMIT_NPROC: ::c_int = 6; + +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 O_FSYNC: ::c_int = 0x101000; + +pub const MAP_GROWSDOWN: ::c_int = 0x0100; + +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 EMULTIHOP: ::c_int = 72; +pub const EOVERFLOW: ::c_int = 75; +pub const ENOTUNIQ: ::c_int = 76; +pub const EBADFD: ::c_int = 77; +pub const EBADMSG: ::c_int = 74; +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 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 EHWPOISON: ::c_int = 133; +pub const ERFKILL: ::c_int = 132; + +pub const SOL_SOCKET: ::c_int = 1; + +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_LINGER: ::c_int = 13; +pub const SO_REUSEPORT: ::c_int = 15; +pub const SO_ACCEPTCONN: ::c_int = 30; + +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 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 SIGUNUSED: ::c_int = 31; +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 POLLWRNORM: ::c_short = 0x100; +pub const POLLWRBAND: ::c_short = 0x200; + +pub const O_ASYNC: ::c_int = 0x2000; +pub const O_NDELAY: ::c_int = 0x800; + +pub const PTRACE_DETACH: ::c_uint = 17; + +pub const EFD_NONBLOCK: ::c_int = 0x800; + +pub const F_GETLK: ::c_int = 5; +pub const F_GETOWN: ::c_int = 9; +pub const F_SETOWN: ::c_int = 8; +pub const F_SETLK: ::c_int = 6; +pub const F_SETLKW: ::c_int = 7; + +pub const SFD_NONBLOCK: ::c_int = 0x0800; + +pub const TIOCEXCL: ::c_ulong = 0x540C; +pub const TIOCNXCL: ::c_ulong = 0x540D; +pub const TIOCSCTTY: ::c_ulong = 0x540E; +pub const TIOCSTI: ::c_ulong = 0x5412; +pub const TIOCMGET: ::c_ulong = 0x5415; +pub const TIOCMBIS: ::c_ulong = 0x5416; +pub const TIOCMBIC: ::c_ulong = 0x5417; +pub const TIOCMSET: ::c_ulong = 0x5418; +pub const TIOCCONS: ::c_ulong = 0x541D; + +pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; + +pub const SFD_CLOEXEC: ::c_int = 0x080000; + +pub const NCCS: usize = 32; + +pub const O_TRUNC: ::c_int = 512; + +pub const O_CLOEXEC: ::c_int = 0x80000; + +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 EDOTDOT: ::c_int = 73; + +pub const SA_NODEFER: ::c_int = 0x40000000; +pub const SA_RESETHAND: ::c_int = 0x80000000; +pub const SA_RESTART: ::c_int = 0x10000000; +pub const SA_NOCLDSTOP: ::c_int = 0x00000001; + +pub const EPOLL_CLOEXEC: ::c_int = 0x80000; + +pub const EFD_CLOEXEC: ::c_int = 0x80000; + pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; diff --git a/src/liblibc/src/unix/notbsd/linux/other/mod.rs b/src/liblibc/src/unix/notbsd/linux/other/mod.rs index 774040803f..3beb7886f3 100644 --- a/src/liblibc/src/unix/notbsd/linux/other/mod.rs +++ b/src/liblibc/src/unix/notbsd/linux/other/mod.rs @@ -42,14 +42,22 @@ s! { pub ut_host: [::c_char; __UT_HOSTSIZE], pub ut_exit: __exit_status, - #[cfg(any(target_arch = "aarch64", target_pointer_width = "32"))] + #[cfg(any(target_arch = "aarch64", + target_arch = "sparc64", + target_pointer_width = "32"))] pub ut_session: ::c_long, - #[cfg(any(target_arch = "aarch64", target_pointer_width = "32"))] + #[cfg(any(target_arch = "aarch64", + target_arch = "sparc64", + target_pointer_width = "32"))] pub ut_tv: ::timeval, - #[cfg(not(any(target_arch = "aarch64", target_pointer_width = "32")))] + #[cfg(not(any(target_arch = "aarch64", + target_arch = "sparc64", + target_pointer_width = "32")))] pub ut_session: ::int32_t, - #[cfg(not(any(target_arch = "aarch64", target_pointer_width = "32")))] + #[cfg(not(any(target_arch = "aarch64", + target_arch = "sparc64", + target_pointer_width = "32")))] pub ut_tv: __timeval, pub ut_addr_v6: [::int32_t; 4], @@ -59,6 +67,8 @@ s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, + #[cfg(target_arch = "sparc64")] + __reserved0: ::c_int, pub sa_flags: ::c_int, _restorer: *mut ::c_void, } @@ -122,6 +132,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::size_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, @@ -129,7 +145,9 @@ s! { pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], + #[cfg(not(target_arch = "sparc64"))] pub c_ispeed: ::speed_t, + #[cfg(not(target_arch = "sparc64"))] pub c_ospeed: ::speed_t, } @@ -166,24 +184,12 @@ pub const DEAD_PROCESS: ::c_short = 8; pub const ACCOUNTING: ::c_short = 9; 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 RLIM_INFINITY: ::rlim_t = !0; pub const RLIMIT_RTTIME: ::c_int = 15; pub const RLIMIT_NLIMITS: ::c_int = 16; -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 O_FSYNC: ::c_int = 0x101000; - pub const SOCK_NONBLOCK: ::c_int = O_NONBLOCK; pub const LC_PAPER: ::c_int = 7; @@ -213,117 +219,23 @@ pub const LC_ALL_MASK: ::c_int = ::LC_CTYPE_MASK pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::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_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; -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 EMULTIHOP: ::c_int = 72; -pub const EOVERFLOW: ::c_int = 75; -pub const ENOTUNIQ: ::c_int = 76; -pub const EBADFD: ::c_int = 77; -pub const EBADMSG: ::c_int = 74; -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 EHWPOISON: ::c_int = 133; -pub const ERFKILL: ::c_int = 132; 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 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_LINGER: ::c_int = 13; -pub const SO_REUSEPORT: ::c_int = 15; -pub const SO_ACCEPTCONN: ::c_int = 30; - pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15; pub const TCP_THIN_LINEAR_TIMEOUTS: ::c_int = 16; pub const TCP_THIN_DUPACK: ::c_int = 17; @@ -335,22 +247,6 @@ pub const TCP_REPAIR_OPTIONS: ::c_int = 22; pub const TCP_FASTOPEN: ::c_int = 23; pub const TCP_TIMESTAMP: ::c_int = 24; -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 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 SIGUNUSED: ::c_int = 31; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; @@ -358,18 +254,11 @@ 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 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 SIGEV_THREAD_ID: ::c_int = 4; pub const POLLRDNORM: ::c_short = 0x040; -pub const POLLWRNORM: ::c_short = 0x100; pub const POLLRDBAND: ::c_short = 0x080; -pub const POLLWRBAND: ::c_short = 0x200; pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02; @@ -382,8 +271,6 @@ pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const _SC_2_C_VERSION: ::c_int = 96; pub const O_ACCMODE: ::c_int = 3; -pub const O_ASYNC: ::c_int = 0x2000; -pub const O_NDELAY: ::c_int = 0x800; pub const ST_RELATIME: ::c_ulong = 4096; pub const NI_MAXHOST: ::socklen_t = 1025; @@ -432,7 +319,6 @@ pub const PTRACE_CONT: ::c_uint = 7; pub const PTRACE_KILL: ::c_uint = 8; pub const PTRACE_SINGLESTEP: ::c_uint = 9; pub const PTRACE_ATTACH: ::c_uint = 16; -pub const PTRACE_DETACH: ::c_uint = 17; pub const PTRACE_SYSCALL: ::c_uint = 24; pub const PTRACE_SETOPTIONS: ::c_uint = 0x4200; pub const PTRACE_GETEVENTMSG: ::c_uint = 0x4201; @@ -454,36 +340,15 @@ pub const MADV_HUGEPAGE: ::c_int = 14; pub const MADV_NOHUGEPAGE: ::c_int = 15; pub const MAP_HUGETLB: ::c_int = 0x040000; -pub const EFD_NONBLOCK: ::c_int = 0x800; - -pub const F_GETLK: ::c_int = 5; -pub const F_GETOWN: ::c_int = 9; -pub const F_SETOWN: ::c_int = 8; -pub const F_SETLK: ::c_int = 6; -pub const F_SETLKW: ::c_int = 7; - pub const SEEK_DATA: ::c_int = 3; pub const SEEK_HOLE: ::c_int = 4; -pub const SFD_NONBLOCK: ::c_int = 0x0800; - pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; -pub const TIOCGSOFTCAR: ::c_ulong = 0x5419; -pub const TIOCSSOFTCAR: ::c_ulong = 0x541A; pub const TIOCLINUX: ::c_ulong = 0x541C; pub const TIOCGSERIAL: ::c_ulong = 0x541E; -pub const TIOCEXCL: ::c_ulong = 0x540C; -pub const TIOCNXCL: ::c_ulong = 0x540D; -pub const TIOCSCTTY: ::c_ulong = 0x540E; -pub const TIOCSTI: ::c_ulong = 0x5412; -pub const TIOCMGET: ::c_ulong = 0x5415; -pub const TIOCMBIS: ::c_ulong = 0x5416; -pub const TIOCMBIC: ::c_ulong = 0x5417; -pub const TIOCMSET: ::c_ulong = 0x5418; -pub const TIOCCONS: ::c_ulong = 0x541D; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; @@ -571,6 +436,8 @@ cfg_if! { if #[cfg(any(target_arch = "arm", target_arch = "x86", target_arch = "x86_64"))] { pub const PTHREAD_STACK_MIN: ::size_t = 16384; + } else if #[cfg(target_arch = "sparc64")] { + pub const PTHREAD_STACK_MIN: ::size_t = 0x6000; } else { pub const PTHREAD_STACK_MIN: ::size_t = 131072; } @@ -633,7 +500,8 @@ cfg_if! { pub use self::b32::*; } else if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", - target_arch = "powerpc64"))] { + target_arch = "powerpc64", + target_arch = "sparc64"))] { mod b64; pub use self::b64::*; } else { diff --git a/src/liblibc/src/unix/notbsd/linux/s390x.rs b/src/liblibc/src/unix/notbsd/linux/s390x.rs index 76e9aefe81..b646647b25 100644 --- a/src/liblibc/src/unix/notbsd/linux/s390x.rs +++ b/src/liblibc/src/unix/notbsd/linux/s390x.rs @@ -159,6 +159,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::size_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, @@ -267,6 +273,40 @@ s! { } } +pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; + +pub const SFD_CLOEXEC: ::c_int = 0x080000; + +pub const NCCS: usize = 32; + +pub const O_TRUNC: ::c_int = 512; + +pub const O_CLOEXEC: ::c_int = 0x80000; + +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 EDOTDOT: ::c_int = 73; + +pub const SA_NODEFER: ::c_int = 0x40000000; +pub const SA_RESETHAND: ::c_int = 0x80000000; +pub const SA_RESTART: ::c_int = 0x10000000; +pub const SA_NOCLDSTOP: ::c_int = 0x00000001; + +pub const EPOLL_CLOEXEC: ::c_int = 0x80000; + +pub const EFD_CLOEXEC: ::c_int = 0x80000; + pub const POSIX_FADV_DONTNEED: ::c_int = 6; pub const POSIX_FADV_NOREUSE: ::c_int = 7; diff --git a/src/liblibc/src/unix/notbsd/mod.rs b/src/liblibc/src/unix/notbsd/mod.rs index 03a2b44ae0..39ad6d79c0 100644 --- a/src/liblibc/src/unix/notbsd/mod.rs +++ b/src/liblibc/src/unix/notbsd/mod.rs @@ -253,8 +253,6 @@ pub const RUSAGE_SELF: ::c_int = 0; pub const O_RDONLY: ::c_int = 0; pub const O_WRONLY: ::c_int = 1; pub const O_RDWR: ::c_int = 2; -pub const O_TRUNC: ::c_int = 512; -pub const O_CLOEXEC: ::c_int = 0x80000; pub const SOCK_CLOEXEC: ::c_int = O_CLOEXEC; @@ -395,21 +393,6 @@ pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const EWOULDBLOCK: ::c_int = EAGAIN; -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 EDOTDOT: ::c_int = 73; - pub const AF_PACKET: ::c_int = 17; pub const IPPROTO_RAW: ::c_int = 255; @@ -450,6 +433,7 @@ pub const IFF_DYNAMIC: ::c_int = 0x8000; pub const AF_UNIX: ::c_int = 1; pub const AF_INET: ::c_int = 2; pub const AF_INET6: ::c_int = 10; +pub const AF_UNSPEC: ::c_int = 0; pub const AF_NETLINK: ::c_int = 16; pub const SOCK_RAW: ::c_int = 3; pub const IPPROTO_TCP: ::c_int = 6; @@ -495,11 +479,6 @@ pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; -pub const SA_NODEFER: ::c_int = 0x40000000; -pub const SA_RESETHAND: ::c_int = 0x80000000; -pub const SA_RESTART: ::c_int = 0x10000000; -pub const SA_NOCLDSTOP: ::c_int = 0x00000001; - pub const SS_ONSTACK: ::c_int = 1; pub const SS_DISABLE: ::c_int = 2; @@ -523,8 +502,6 @@ pub const EPOLL_CTL_ADD: ::c_int = 1; pub const EPOLL_CTL_MOD: ::c_int = 3; pub const EPOLL_CTL_DEL: ::c_int = 2; -pub const EPOLL_CLOEXEC: ::c_int = 0x80000; - pub const MNT_DETACH: ::c_int = 0x2; pub const MNT_EXPIRE: ::c_int = 0x4; @@ -542,8 +519,6 @@ pub const QIF_USAGE: ::uint32_t = 10; pub const QIF_TIMES: ::uint32_t = 48; pub const QIF_ALL: ::uint32_t = 63; -pub const EFD_CLOEXEC: ::c_int = 0x80000; - pub const MNT_FORCE: ::c_int = 0x1; pub const Q_SYNC: ::c_int = 0x800001; @@ -685,7 +660,7 @@ f! { } pub fn WIFSIGNALED(status: ::c_int) -> bool { - (status & 0x7f) + 1 >= 2 + ((status & 0x7f) + 1) as i8 >= 2 } pub fn WTERMSIG(status: ::c_int) -> ::c_int { @@ -725,6 +700,7 @@ extern { flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec) -> ::c_int; + pub fn clock_settime(clk_id: clockid_t, tp: *const ::timespec) -> ::c_int; pub fn prctl(option: ::c_int, ...) -> ::c_int; pub fn pthread_getattr_np(native: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; @@ -736,6 +712,7 @@ extern { pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn setgroups(ngroups: ::size_t, ptr: *const ::gid_t) -> ::c_int; + pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int; pub fn sched_setscheduler(pid: ::pid_t, policy: ::c_int, param: *const sched_param) -> ::c_int; @@ -873,6 +850,7 @@ extern { pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int; + pub fn clearenv() -> ::c_int; } cfg_if! { diff --git a/src/liblibc/src/unix/solaris/mod.rs b/src/liblibc/src/unix/solaris/mod.rs index c2db06bc50..96ad0b1186 100644 --- a/src/liblibc/src/unix/solaris/mod.rs +++ b/src/liblibc/src/unix/solaris/mod.rs @@ -114,6 +114,12 @@ s! { pub msg_flags: ::c_int, } + pub struct cmsghdr { + pub cmsg_len: ::size_t, + pub cmsg_level: ::c_int, + pub cmsg_type: ::c_int, + } + pub struct fd_set { fds_bits: [i32; FD_SETSIZE / 32], } @@ -973,6 +979,7 @@ extern { flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec) -> ::c_int; + pub fn clock_settime(clk_id: clockid_t, tp: *const ::timespec) -> ::c_int; pub fn getnameinfo(sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 517cd016e8..057df647c7 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -168,7 +168,7 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] #![deny(missing_docs)] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 8f85bfe2c6..348180a48d 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -21,7 +21,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 73264fab69..e8b3a9a42c 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -133,6 +133,9 @@ const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4 #[cfg(target_arch = "s390x")] const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7 +#[cfg(target_arch = "sparc64")] +const UNWIND_DATA_REG: (i32, i32) = (24, 25); // I0, I1 + // The following code is based on GCC's C and C++ personality routines. For reference, see: // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index b75d9ec652..90f4b36448 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -30,7 +30,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(alloc)] #![feature(core_intrinsics)] diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 22b365fa64..f962c888f4 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -27,7 +27,7 @@ #![stable(feature = "proc_macro_lib", since = "1.15.0")] #![crate_type = "rlib"] #![crate_type = "dylib"] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![deny(missing_docs)] #![feature(rustc_private)] @@ -39,9 +39,9 @@ extern crate syntax; use std::fmt; use std::str::FromStr; -use syntax::ast; +use syntax::errors::DiagnosticBuilder; use syntax::parse; -use syntax::ptr::P; +use syntax::tokenstream::TokenStream as TokenStream_; /// The main type provided by this crate, representing an abstract stream of /// tokens. @@ -54,7 +54,7 @@ use syntax::ptr::P; /// time! #[stable(feature = "proc_macro_lib", since = "1.15.0")] pub struct TokenStream { - inner: Vec>, + inner: TokenStream_, } /// Error returned from `TokenStream::from_str`. @@ -77,17 +77,42 @@ pub struct LexError { #[doc(hidden)] pub mod __internal { use std::cell::Cell; + use std::rc::Rc; use syntax::ast; use syntax::ptr::P; - use syntax::parse::ParseSess; - use super::TokenStream; + use syntax::parse::{self, token, ParseSess}; + use syntax::tokenstream::{TokenTree, TokenStream as TokenStream_}; + + use super::{TokenStream, LexError}; pub fn new_token_stream(item: P) -> TokenStream { - TokenStream { inner: vec![item] } + TokenStream { + inner: TokenTree::Token(item.span, token::Interpolated(Rc::new(token::NtItem(item)))) + .into() + } + } + + pub fn token_stream_wrap(inner: TokenStream_) -> TokenStream { + TokenStream { + inner: inner + } } - pub fn token_stream_items(stream: TokenStream) -> Vec> { + pub fn token_stream_parse_items(stream: TokenStream) -> Result>, LexError> { + with_parse_sess(move |sess| { + let mut parser = parse::new_parser_from_ts(sess, stream.inner); + let mut items = Vec::new(); + + while let Some(item) = try!(parser.parse_item().map_err(super::parse_to_lex_err)) { + items.push(item) + } + + Ok(items) + }) + } + + pub fn token_stream_inner(stream: TokenStream) -> TokenStream_ { stream.inner } @@ -96,6 +121,10 @@ pub mod __internal { trait_name: &str, expand: fn(TokenStream) -> TokenStream, attributes: &[&'static str]); + + fn register_attr_proc_macro(&mut self, + name: &str, + expand: fn(TokenStream, TokenStream) -> TokenStream); } // Emulate scoped_thread_local!() here essentially @@ -125,11 +154,17 @@ pub mod __internal { where F: FnOnce(&ParseSess) -> R { let p = CURRENT_SESS.with(|p| p.get()); - assert!(!p.is_null()); + assert!(!p.is_null(), "proc_macro::__internal::with_parse_sess() called \ + before set_parse_sess()!"); f(unsafe { &*p }) } } +fn parse_to_lex_err(mut err: DiagnosticBuilder) -> LexError { + err.cancel(); + LexError { _inner: () } +} + #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl FromStr for TokenStream { type Err = LexError; @@ -138,18 +173,10 @@ impl FromStr for TokenStream { __internal::with_parse_sess(|sess| { let src = src.to_string(); let name = "".to_string(); - let mut parser = parse::new_parser_from_source_str(sess, name, src); - let mut ret = TokenStream { inner: Vec::new() }; - loop { - match parser.parse_item() { - Ok(Some(item)) => ret.inner.push(item), - Ok(None) => return Ok(ret), - Err(mut err) => { - err.cancel(); - return Err(LexError { _inner: () }) - } - } - } + let tts = try!(parse::parse_tts_from_source_str(name, src, sess) + .map_err(parse_to_lex_err)); + + Ok(__internal::token_stream_wrap(tts.into_iter().collect())) }) } } @@ -157,11 +184,6 @@ impl FromStr for TokenStream { #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl fmt::Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for item in self.inner.iter() { - let item = syntax::print::pprust::item_to_string(item); - try!(f.write_str(&item)); - try!(f.write_str("\n")); - } - Ok(()) + self.inner.fmt(f) } } diff --git a/src/libproc_macro_plugin/Cargo.toml b/src/libproc_macro_plugin/Cargo.toml index 4bc3f488d3..146a66cdf0 100644 --- a/src/libproc_macro_plugin/Cargo.toml +++ b/src/libproc_macro_plugin/Cargo.toml @@ -8,8 +8,6 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] -log = { path = "../liblog" } rustc_plugin = { path = "../librustc_plugin" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -proc_macro_tokens = { path = "../libproc_macro_tokens" } diff --git a/src/libproc_macro_plugin/lib.rs b/src/libproc_macro_plugin/lib.rs index c45762bfb6..e904290957 100644 --- a/src/libproc_macro_plugin/lib.rs +++ b/src/libproc_macro_plugin/lib.rs @@ -15,11 +15,8 @@ //! ## Usage //! This crate provides the `qquote!` macro for syntax creation. //! -//! The `qquote!` macro imports `syntax::ext::proc_macro_shim::prelude::*`, so you -//! will need to `extern crate syntax` for usage. (This is a temporary solution until more -//! of the external API in libproc_macro_tokens is stabilized to support the token construction -//! operations that the qausiquoter relies on.) The shim file also provides additional -//! operations, such as `build_block_emitter` (as used in the `cond` example below). +//! The `qquote!` macro uses the crate `syntax`, so users must declare `extern crate syntax;` +//! at the crate root. This is a temporary solution until we have better hygiene. //! //! ## Quasiquotation //! @@ -80,7 +77,7 @@ #![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/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] #![feature(rustc_diagnostic_macros)] @@ -89,19 +86,19 @@ extern crate rustc_plugin; extern crate syntax; extern crate syntax_pos; -extern crate proc_macro_tokens; -#[macro_use] extern crate log; mod qquote; - use qquote::qquote; use rustc_plugin::Registry; +use syntax::ext::base::SyntaxExtension; +use syntax::symbol::Symbol; // ____________________________________________________________________________________________ // Main macro definition #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_macro("qquote", qquote); + reg.register_syntax_extension(Symbol::intern("qquote"), + SyntaxExtension::ProcMacro(Box::new(qquote))); } diff --git a/src/libproc_macro_plugin/qquote.rs b/src/libproc_macro_plugin/qquote.rs index 1ae906e0aa..300b4df892 100644 --- a/src/libproc_macro_plugin/qquote.rs +++ b/src/libproc_macro_plugin/qquote.rs @@ -9,460 +9,219 @@ // except according to those terms. //! # Quasiquoter -//! This file contains the implementation internals of the quasiquoter provided by `quote!`. -//! -//! ## Ouput -//! The quasiquoter produces output of the form: -//! let tmp0 = ...; -//! let tmp1 = ...; -//! ... -//! concat(from_tokens(...), concat(...)) -//! -//! To the more explicit, the quasiquoter produces a series of bindings that each -//! construct TokenStreams via constructing Tokens and using `from_tokens`, ultimately -//! invoking `concat` on these bindings (and inlined expressions) to construct a -//! TokenStream that resembles the output syntax. -//! - -use proc_macro_tokens::build::*; -use proc_macro_tokens::parse::lex; - -use qquote::int_build::*; +//! This file contains the implementation internals of the quasiquoter provided by `qquote!`. use syntax::ast::Ident; -use syntax::codemap::Span; -use syntax::ext::base::*; -use syntax::ext::base; -use syntax::ext::proc_macro_shim::build_block_emitter; -use syntax::parse::token::{self, Token}; -use syntax::print::pprust; +use syntax::parse::token::{self, Token, Lit}; use syntax::symbol::Symbol; -use syntax::tokenstream::{TokenTree, TokenStream}; +use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream}; +use syntax_pos::DUMMY_SP; -// ____________________________________________________________________________________________ -// Main definition -/// The user should use the macro, not this procedure. -pub fn qquote<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree]) - -> Box { +use std::rc::Rc; - debug!("\nTTs in: {:?}\n", pprust::tts_to_string(&tts[..])); - let output = qquoter(cx, TokenStream::from_tts(tts.clone().to_owned())); - debug!("\nQQ out: {}\n", pprust::tts_to_string(&output.to_tts()[..])); - let imports = concat(lex("use syntax::ext::proc_macro_shim::prelude::*;"), - lex("use proc_macro_tokens::prelude::*;")); - build_block_emitter(cx, sp, build_brace_delimited(concat(imports, output))) +pub fn qquote<'cx>(stream: TokenStream) -> TokenStream { + stream.quote() } -// ____________________________________________________________________________________________ -// Datatype Definitions - -#[derive(Debug)] -struct QDelimited { - delim: token::DelimToken, - open_span: Span, - tts: Vec, - close_span: Span, +trait Quote { + fn quote(&self) -> TokenStream; } -#[derive(Debug)] -enum QTT { - TT(TokenTree), - QDL(QDelimited), - QIdent(TokenTree), +macro_rules! quote_tok { + (,) => { Token::Comma }; + (.) => { Token::Dot }; + (:) => { Token::Colon }; + (::) => { Token::ModSep }; + (!) => { Token::Not }; + (<) => { Token::Lt }; + (>) => { Token::Gt }; + (_) => { Token::Underscore }; + ($i:ident) => { Token::Ident(Ident::from_str(stringify!($i))) }; } -type Bindings = Vec<(Ident, TokenStream)>; - -// ____________________________________________________________________________________________ -// Quasiquoter Algorithm -// This algorithm works as follows: -// Input: TokenStream -// 1. Walk the TokenStream, gathering up the unquoted expressions and marking them separately. -// 2. Hoist any unquoted term into its own let-binding via a gensym'd identifier -// 3. Convert the body from a `complex expression` into a simplified one via `convert_complex_tts -// 4. Stitch everything together with `concat`. -fn qquoter<'cx>(cx: &'cx mut ExtCtxt, ts: TokenStream) -> TokenStream { - if ts.is_empty() { - return lex("TokenStream::mk_empty()"); - } - let qq_res = qquote_iter(cx, 0, ts); - let mut bindings = qq_res.0; - let body = qq_res.1; - let mut cct_res = convert_complex_tts(cx, body); - - bindings.append(&mut cct_res.0); - - if bindings.is_empty() { - cct_res.1 - } else { - debug!("BINDINGS"); - for b in bindings.clone() { - debug!("{:?} = {}", b.0, pprust::tts_to_string(&b.1.to_tts()[..])); - } - TokenStream::concat(unravel(bindings), cct_res.1) - } +macro_rules! quote_tree { + ((unquote $($t:tt)*)) => { $($t)* }; + ((quote $($t:tt)*)) => { ($($t)*).quote() }; + (($($t:tt)*)) => { delimit(token::Paren, quote!($($t)*)) }; + ([$($t:tt)*]) => { delimit(token::Bracket, quote!($($t)*)) }; + ({$($t:tt)*}) => { delimit(token::Brace, quote!($($t)*)) }; + ($t:tt) => { TokenStream::from(TokenTree::Token(DUMMY_SP, quote_tok!($t))) }; } -fn qquote_iter<'cx>(cx: &'cx mut ExtCtxt, depth: i64, ts: TokenStream) -> (Bindings, Vec) { - let mut depth = depth; - let mut bindings: Bindings = Vec::new(); - let mut output: Vec = Vec::new(); - - let mut iter = ts.iter(); - - loop { - let next = iter.next(); - if next.is_none() { - break; - } - let next = next.unwrap().clone(); - match next { - TokenTree::Token(_, Token::Ident(id)) if is_unquote(id) => { - if depth == 0 { - let exp = iter.next(); - if exp.is_none() { - break; - } // produce an error or something first - let exp = vec![exp.unwrap().to_owned()]; - debug!("RHS: {:?}", exp.clone()); - let new_id = Ident::with_empty_ctxt(Symbol::gensym("tmp")); - debug!("RHS TS: {:?}", TokenStream::from_tts(exp.clone())); - debug!("RHS TS TT: {:?}", TokenStream::from_tts(exp.clone()).to_vec()); - bindings.push((new_id, TokenStream::from_tts(exp))); - debug!("BINDINGS"); - for b in bindings.clone() { - debug!("{:?} = {}", b.0, pprust::tts_to_string(&b.1.to_tts()[..])); - } - output.push(QTT::QIdent(as_tt(Token::Ident(new_id.clone())))); - } else { - depth = depth - 1; - output.push(QTT::TT(next.clone())); - } - } - TokenTree::Token(_, Token::Ident(id)) if is_qquote(id) => { - depth = depth + 1; - } - TokenTree::Delimited(_, ref dl) => { - let br = qquote_iter(cx, depth, TokenStream::from_tts(dl.tts.clone().to_owned())); - let mut bind_ = br.0; - let res_ = br.1; - bindings.append(&mut bind_); - - let new_dl = QDelimited { - delim: dl.delim, - open_span: dl.open_span, - tts: res_, - close_span: dl.close_span, - }; - - output.push(QTT::QDL(new_dl)); - } - t => { - output.push(QTT::TT(t)); - } - } - } +fn delimit(delim: token::DelimToken, stream: TokenStream) -> TokenStream { + TokenTree::Delimited(DUMMY_SP, Rc::new(Delimited { + delim: delim, + tts: stream.trees().cloned().collect(), + })).into() +} - (bindings, output) +macro_rules! quote { + () => { TokenStream::empty() }; + ($($t:tt)*) => { [ $( quote_tree!($t), )* ].iter().cloned().collect::() }; } -// ____________________________________________________________________________________________ -// Turns QQTs into a TokenStream and some Bindings. -/// Construct a chain of concatenations. -fn unravel_concats(tss: Vec) -> TokenStream { - let mut pushes: Vec = - tss.into_iter().filter(|&ref ts| !ts.is_empty()).collect(); - let mut output = match pushes.pop() { - Some(ts) => ts, - None => { - return TokenStream::mk_empty(); +impl Quote for Option { + fn quote(&self) -> TokenStream { + match *self { + Some(ref t) => quote!(::std::option::Option::Some((quote t))), + None => quote!(::std::option::Option::None), } - }; - - while let Some(ts) = pushes.pop() { - output = build_fn_call(Ident::from_str("concat"), - concat(concat(ts, - from_tokens(vec![Token::Comma])), - output)); } - output } -/// This converts the vector of QTTs into a seet of Bindings for construction and the main -/// body as a TokenStream. -fn convert_complex_tts<'cx>(cx: &'cx mut ExtCtxt, tts: Vec) -> (Bindings, TokenStream) { - let mut pushes: Vec = Vec::new(); - let mut bindings: Bindings = Vec::new(); +impl Quote for TokenStream { + fn quote(&self) -> TokenStream { + if self.is_empty() { + return quote!(::syntax::tokenstream::TokenStream::empty()); + } - let mut iter = tts.into_iter(); + struct Quote<'a>(tokenstream::Cursor<'a>); - loop { - let next = iter.next(); - if next.is_none() { - break; - } - let next = next.unwrap(); - match next { - QTT::TT(TokenTree::Token(_, t)) => { - let token_out = emit_token(t); - pushes.push(token_out); - } - // FIXME handle sequence repetition tokens - QTT::QDL(qdl) => { - debug!(" QDL: {:?} ", qdl.tts); - let new_id = Ident::with_empty_ctxt(Symbol::gensym("qdl_tmp")); - let mut cct_rec = convert_complex_tts(cx, qdl.tts); - bindings.append(&mut cct_rec.0); - bindings.push((new_id, cct_rec.1)); + impl<'a> Iterator for Quote<'a> { + type Item = TokenStream; - let sep = build_delim_tok(qdl.delim); + fn next(&mut self) -> Option { + let is_unquote = match self.0.peek() { + Some(&TokenTree::Token(_, Token::Ident(ident))) if ident.name == "unquote" => { + self.0.next(); + true + } + _ => false, + }; - pushes.push(build_mod_call( - vec![Ident::from_str("proc_macro_tokens"), - Ident::from_str("build"), - Ident::from_str("build_delimited")], - concat(from_tokens(vec![Token::Ident(new_id)]), concat(lex(","), sep)), - )); - } - QTT::QIdent(t) => { - pushes.push(TokenStream::from_tts(vec![t])); - pushes.push(TokenStream::mk_empty()); + self.0.next().cloned().map(|tree| { + let quoted_tree = if is_unquote { tree.into() } else { tree.quote() }; + quote!(::syntax::tokenstream::TokenStream::from((unquote quoted_tree)),) + }) } - _ => panic!("Unhandled case!"), } + let quoted = Quote(self.trees()).collect::(); + quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>()) } - - (bindings, unravel_concats(pushes)) } -// ____________________________________________________________________________________________ -// Utilities - -/// Unravels Bindings into a TokenStream of `let` declarations. -fn unravel(binds: Bindings) -> TokenStream { - let mut output = TokenStream::mk_empty(); - - for b in binds { - output = concat(output, build_let(b.0, b.1)); +impl Quote for Vec { + fn quote(&self) -> TokenStream { + let stream = self.iter().cloned().collect::(); + quote!((quote stream).trees().cloned().collect::<::std::vec::Vec<_> >()) } - - output } -/// Checks if the Ident is `unquote`. -fn is_unquote(id: Ident) -> bool { - let qq = Ident::from_str("unquote"); - id.name == qq.name // We disregard context; unquote is _reserved_ +impl Quote for TokenTree { + fn quote(&self) -> TokenStream { + match *self { + TokenTree::Token(_, ref token) => quote! { + ::syntax::tokenstream::TokenTree::Token(::syntax::ext::quote::rt::DUMMY_SP, + (quote token)) + }, + TokenTree::Delimited(_, ref delimited) => quote! { + ::syntax::tokenstream::TokenTree::Delimited(::syntax::ext::quote::rt::DUMMY_SP, + (quote delimited)) + }, + _ => panic!("unexpected `TokenTree::Sequence` in `qquote`"), + } + } } -/// Checks if the Ident is `quote`. -fn is_qquote(id: Ident) -> bool { - let qq = Ident::from_str("qquote"); - id.name == qq.name // We disregard context; qquote is _reserved_ +impl Quote for Rc { + fn quote(&self) -> TokenStream { + quote!(::std::rc::Rc::new(::syntax::tokenstream::Delimited { + delim: (quote self.delim), + tts: (quote self.tts), + })) + } } -mod int_build { - use proc_macro_tokens::build::*; - use proc_macro_tokens::parse::*; - - use syntax::ast::{self, Ident}; - use syntax::codemap::{DUMMY_SP}; - use syntax::parse::token::{self, Token, Lit}; - use syntax::symbol::keywords; - use syntax::tokenstream::{TokenTree, TokenStream}; - - // ____________________________________________________________________________________________ - // Emitters - - pub fn emit_token(t: Token) -> TokenStream { - concat(lex("TokenStream::from_tokens"), - build_paren_delimited(build_vec(build_token_tt(t)))) +impl<'a> Quote for &'a str { + fn quote(&self) -> TokenStream { + TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Str_(Symbol::intern(self)), None)) + .into() } +} - pub fn emit_lit(l: Lit, n: Option) -> TokenStream { - let suf = match n { - Some(n) => format!("Some(ast::Name({}))", n.as_u32()), - None => "None".to_string(), - }; - - let lit = match l { - Lit::Byte(n) => format!("Lit::Byte(Symbol::intern(\"{}\"))", n.to_string()), - Lit::Char(n) => format!("Lit::Char(Symbol::intern(\"{}\"))", n.to_string()), - Lit::Float(n) => format!("Lit::Float(Symbol::intern(\"{}\"))", n.to_string()), - Lit::Str_(n) => format!("Lit::Str_(Symbol::intern(\"{}\"))", n.to_string()), - Lit::Integer(n) => format!("Lit::Integer(Symbol::intern(\"{}\"))", n.to_string()), - Lit::ByteStr(n) => format!("Lit::ByteStr(Symbol::intern(\"{}\"))", n.to_string()), - _ => panic!("Unsupported literal"), - }; - - let res = format!("Token::Literal({},{})", lit, suf); - debug!("{}", res); - lex(&res) +impl Quote for Ident { + fn quote(&self) -> TokenStream { + // FIXME(jseyfried) quote hygiene + quote!(::syntax::ast::Ident::from_str((quote &*self.name.as_str()))) } +} - // ____________________________________________________________________________________________ - // Token Builders - - pub fn build_binop_tok(bot: token::BinOpToken) -> TokenStream { - match bot { - token::BinOpToken::Plus => lex("Token::BinOp(BinOpToken::Plus)"), - token::BinOpToken::Minus => lex("Token::BinOp(BinOpToken::Minus)"), - token::BinOpToken::Star => lex("Token::BinOp(BinOpToken::Star)"), - token::BinOpToken::Slash => lex("Token::BinOp(BinOpToken::Slash)"), - token::BinOpToken::Percent => lex("Token::BinOp(BinOpToken::Percent)"), - token::BinOpToken::Caret => lex("Token::BinOp(BinOpToken::Caret)"), - token::BinOpToken::And => lex("Token::BinOp(BinOpToken::And)"), - token::BinOpToken::Or => lex("Token::BinOp(BinOpToken::Or)"), - token::BinOpToken::Shl => lex("Token::BinOp(BinOpToken::Shl)"), - token::BinOpToken::Shr => lex("Token::BinOp(BinOpToken::Shr)"), - } +impl Quote for Symbol { + fn quote(&self) -> TokenStream { + quote!(::syntax::symbol::Symbol::intern((quote &*self.as_str()))) } +} - pub fn build_binopeq_tok(bot: token::BinOpToken) -> TokenStream { - match bot { - token::BinOpToken::Plus => lex("Token::BinOpEq(BinOpToken::Plus)"), - token::BinOpToken::Minus => lex("Token::BinOpEq(BinOpToken::Minus)"), - token::BinOpToken::Star => lex("Token::BinOpEq(BinOpToken::Star)"), - token::BinOpToken::Slash => lex("Token::BinOpEq(BinOpToken::Slash)"), - token::BinOpToken::Percent => lex("Token::BinOpEq(BinOpToken::Percent)"), - token::BinOpToken::Caret => lex("Token::BinOpEq(BinOpToken::Caret)"), - token::BinOpToken::And => lex("Token::BinOpEq(BinOpToken::And)"), - token::BinOpToken::Or => lex("Token::BinOpEq(BinOpToken::Or)"), - token::BinOpToken::Shl => lex("Token::BinOpEq(BinOpToken::Shl)"), - token::BinOpToken::Shr => lex("Token::BinOpEq(BinOpToken::Shr)"), +impl Quote for Token { + fn quote(&self) -> TokenStream { + macro_rules! gen_match { + ($($i:ident),*; $($t:tt)*) => { + match *self { + $( Token::$i => quote!(::syntax::parse::token::$i), )* + $( $t )* + } + } } - } - pub fn build_delim_tok(dt: token::DelimToken) -> TokenStream { - match dt { - token::DelimToken::Paren => lex("DelimToken::Paren"), - token::DelimToken::Bracket => lex("DelimToken::Bracket"), - token::DelimToken::Brace => lex("DelimToken::Brace"), - token::DelimToken::NoDelim => lex("DelimToken::NoDelim"), + gen_match! { + Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot, + Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question, + Underscore; + + Token::OpenDelim(delim) => quote!(::syntax::parse::token::OpenDelim((quote delim))), + Token::CloseDelim(delim) => quote!(::syntax::parse::token::CloseDelim((quote delim))), + Token::BinOp(tok) => quote!(::syntax::parse::token::BinOp((quote tok))), + Token::BinOpEq(tok) => quote!(::syntax::parse::token::BinOpEq((quote tok))), + Token::Ident(ident) => quote!(::syntax::parse::token::Ident((quote ident))), + Token::Lifetime(ident) => quote!(::syntax::parse::token::Lifetime((quote ident))), + Token::Literal(lit, sfx) => quote! { + ::syntax::parse::token::Literal((quote lit), (quote sfx)) + }, + _ => panic!("Unhandled case!"), } } +} - pub fn build_token_tt(t: Token) -> TokenStream { - match t { - Token::Eq => lex("Token::Eq"), - Token::Lt => lex("Token::Lt"), - Token::Le => lex("Token::Le"), - Token::EqEq => lex("Token::EqEq"), - Token::Ne => lex("Token::Ne"), - Token::Ge => lex("Token::Ge"), - Token::Gt => lex("Token::Gt"), - Token::AndAnd => lex("Token::AndAnd"), - Token::OrOr => lex("Token::OrOr"), - Token::Not => lex("Token::Not"), - Token::Tilde => lex("Token::Tilde"), - Token::BinOp(tok) => build_binop_tok(tok), - Token::BinOpEq(tok) => build_binopeq_tok(tok), - Token::At => lex("Token::At"), - Token::Dot => lex("Token::Dot"), - Token::DotDot => lex("Token::DotDot"), - Token::DotDotDot => lex("Token::DotDotDot"), - Token::Comma => lex("Token::Comma"), - Token::Semi => lex("Token::Semi"), - Token::Colon => lex("Token::Colon"), - Token::ModSep => lex("Token::ModSep"), - Token::RArrow => lex("Token::RArrow"), - Token::LArrow => lex("Token::LArrow"), - Token::FatArrow => lex("Token::FatArrow"), - Token::Pound => lex("Token::Pound"), - Token::Dollar => lex("Token::Dollar"), - Token::Question => lex("Token::Question"), - Token::OpenDelim(dt) => { - match dt { - token::DelimToken::Paren => lex("Token::OpenDelim(DelimToken::Paren)"), - token::DelimToken::Bracket => lex("Token::OpenDelim(DelimToken::Bracket)"), - token::DelimToken::Brace => lex("Token::OpenDelim(DelimToken::Brace)"), - token::DelimToken::NoDelim => lex("DelimToken::NoDelim"), +impl Quote for token::BinOpToken { + fn quote(&self) -> TokenStream { + macro_rules! gen_match { + ($($i:ident),*) => { + match *self { + $( token::BinOpToken::$i => quote!(::syntax::parse::token::BinOpToken::$i), )* } } - Token::CloseDelim(dt) => { - match dt { - token::DelimToken::Paren => lex("Token::CloseDelim(DelimToken::Paren)"), - token::DelimToken::Bracket => lex("Token::CloseDelim(DelimToken::Bracket)"), - token::DelimToken::Brace => lex("Token::CloseDelim(DelimToken::Brace)"), - token::DelimToken::NoDelim => lex("DelimToken::NoDelim"), - } - } - Token::Underscore => lex("_"), - Token::Literal(lit, sfx) => emit_lit(lit, sfx), - // fix ident expansion information... somehow - Token::Ident(ident) => - lex(&format!("Token::Ident(Ident::from_str(\"{}\"))", ident.name)), - Token::Lifetime(ident) => - lex(&format!("Token::Ident(Ident::from_str(\"{}\"))", ident.name)), - _ => panic!("Unhandled case!"), } - } - - // ____________________________________________________________________________________________ - // Conversion operators - pub fn as_tt(t: Token) -> TokenTree { - // FIXME do something nicer with the spans - TokenTree::Token(DUMMY_SP, t) - } - - // ____________________________________________________________________________________________ - // Build Procedures - - /// Takes `input` and returns `vec![input]`. - pub fn build_vec(ts: TokenStream) -> TokenStream { - build_mac_call(Ident::from_str("vec"), ts) - // tts.clone().to_owned() - } - - /// Takes `ident` and `rhs` and produces `let ident = rhs;`. - pub fn build_let(id: Ident, tts: TokenStream) -> TokenStream { - concat(from_tokens(vec![keyword_to_token_ident(keywords::Let), - Token::Ident(id), - Token::Eq]), - concat(tts, from_tokens(vec![Token::Semi]))) - } - - /// Takes `ident ...`, and `args ...` and produces `ident::...(args ...)`. - pub fn build_mod_call(ids: Vec, args: TokenStream) -> TokenStream { - let call = from_tokens(intersperse(ids.into_iter().map(|id| Token::Ident(id)).collect(), - Token::ModSep)); - concat(call, build_paren_delimited(args)) - } - - /// Takes `ident` and `args ...` and produces `ident(args ...)`. - pub fn build_fn_call(name: Ident, args: TokenStream) -> TokenStream { - concat(from_tokens(vec![Token::Ident(name)]), build_paren_delimited(args)) - } - - /// Takes `ident` and `args ...` and produces `ident!(args ...)`. - pub fn build_mac_call(name: Ident, args: TokenStream) -> TokenStream { - concat(from_tokens(vec![Token::Ident(name), Token::Not]), - build_paren_delimited(args)) + gen_match!(Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr) } +} - // ____________________________________________________________________________________________ - // Utilities +impl Quote for Lit { + fn quote(&self) -> TokenStream { + macro_rules! gen_match { + ($($i:ident),*) => { + match *self { + $( Lit::$i(lit) => quote!(::syntax::parse::token::Lit::$i((quote lit))), )* + _ => panic!("Unsupported literal"), + } + } + } - /// A wrapper around `TokenStream::from_tokens` to avoid extra namespace specification and - /// provide it as a generic operator. - pub fn from_tokens(tokens: Vec) -> TokenStream { - TokenStream::from_tokens(tokens) + gen_match!(Byte, Char, Float, Str_, Integer, ByteStr) } +} - pub fn intersperse(vs: Vec, t: T) -> Vec - where T: Clone - { - if vs.len() < 2 { - return vs; +impl Quote for token::DelimToken { + fn quote(&self) -> TokenStream { + macro_rules! gen_match { + ($($i:ident),*) => { + match *self { + $(token::DelimToken::$i => { quote!(::syntax::parse::token::DelimToken::$i) })* + } + } } - let mut output = vec![vs.get(0).unwrap().to_owned()]; - for v in vs.into_iter().skip(1) { - output.push(t.clone()); - output.push(v); - } - output + gen_match!(Paren, Bracket, Brace, NoDelim) } } diff --git a/src/libproc_macro_tokens/Cargo.toml b/src/libproc_macro_tokens/Cargo.toml deleted file mode 100644 index 2b66d56759..0000000000 --- a/src/libproc_macro_tokens/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "proc_macro_tokens" -version = "0.0.0" - -[lib] -path = "lib.rs" -crate-type = ["dylib"] - -[dependencies] -syntax = { path = "../libsyntax" } -syntax_pos = { path = "../libsyntax_pos" } -log = { path = "../liblog" } diff --git a/src/libproc_macro_tokens/build.rs b/src/libproc_macro_tokens/build.rs deleted file mode 100644 index d39aba0aa7..0000000000 --- a/src/libproc_macro_tokens/build.rs +++ /dev/null @@ -1,90 +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. - -extern crate syntax; -extern crate syntax_pos; - -use syntax::ast::Ident; -use syntax::codemap::DUMMY_SP; -use syntax::parse::token::{self, Token}; -use syntax::symbol::keywords; -use syntax::tokenstream::{self, TokenTree, TokenStream}; -use std::rc::Rc; - -/// A wrapper around `TokenStream::concat` to avoid extra namespace specification and -/// provide TokenStream concatenation as a generic operator. -pub fn concat(ts1: TokenStream, ts2: TokenStream) -> TokenStream { - TokenStream::concat(ts1, ts2) -} - -/// Checks if two identifiers have the same name, disregarding context. This allows us to -/// fake 'reserved' keywords. -// FIXME We really want `free-identifier-=?` (a la Dybvig 1993). von Tander 2007 is -// probably the easiest way to do that. -pub fn ident_eq(tident: &TokenTree, id: Ident) -> bool { - let tid = match *tident { - TokenTree::Token(_, Token::Ident(ref id)) => id, - _ => { - return false; - } - }; - - tid.name == id.name -} - -// ____________________________________________________________________________________________ -// Conversion operators - -/// Convert a `&str` into a Token. -pub fn str_to_token_ident(s: &str) -> Token { - Token::Ident(Ident::from_str(s)) -} - -/// Converts a keyword (from `syntax::parse::token::keywords`) into a Token that -/// corresponds to it. -pub fn keyword_to_token_ident(kw: keywords::Keyword) -> Token { - Token::Ident(Ident::from_str(&kw.name().as_str()[..])) -} - -// ____________________________________________________________________________________________ -// Build Procedures - -/// Generically takes a `ts` and delimiter and returns `ts` delimited by the specified -/// delimiter. -pub fn build_delimited(ts: TokenStream, delim: token::DelimToken) -> TokenStream { - let tts = ts.to_tts(); - TokenStream::from_tts(vec![TokenTree::Delimited(DUMMY_SP, - Rc::new(tokenstream::Delimited { - delim: delim, - open_span: DUMMY_SP, - tts: tts, - close_span: DUMMY_SP, - }))]) -} - -/// Takes `ts` and returns `[ts]`. -pub fn build_bracket_delimited(ts: TokenStream) -> TokenStream { - build_delimited(ts, token::DelimToken::Bracket) -} - -/// Takes `ts` and returns `{ts}`. -pub fn build_brace_delimited(ts: TokenStream) -> TokenStream { - build_delimited(ts, token::DelimToken::Brace) -} - -/// Takes `ts` and returns `(ts)`. -pub fn build_paren_delimited(ts: TokenStream) -> TokenStream { - build_delimited(ts, token::DelimToken::Paren) -} - -/// Constructs `()`. -pub fn build_empty_args() -> TokenStream { - build_paren_delimited(TokenStream::mk_empty()) -} diff --git a/src/libproc_macro_tokens/lib.rs b/src/libproc_macro_tokens/lib.rs deleted file mode 100644 index 3bfa2fbb29..0000000000 --- a/src/libproc_macro_tokens/lib.rs +++ /dev/null @@ -1,66 +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. - -//! # Proc_Macro -//! -//! A library for procedural macro writers. -//! -//! ## Usage -//! This crate provides the prelude (at libproc_macro_tokens::prelude), which -//! provides a number of operations: -//! - `concat`, for concatenating two TokenStreams. -//! - `ident_eq`, for checking if two identifiers are equal regardless of syntax context. -//! - `str_to_token_ident`, for converting an `&str` into a Token. -//! - `keyword_to_token_delim`, for converting a `parse::token::keywords::Keyword` into a -//! Token. -//! - `build_delimited`, for creating a new TokenStream from an existing one and a delimiter -//! by wrapping the TokenStream in the delimiter. -//! - `build_bracket_delimited`, `build_brace_delimited`, and `build_paren_delimited`, for -//! easing the above. -//! - `build_empty_args`, which returns a TokenStream containing `()`. -//! - `lex`, which takes an `&str` and returns the TokenStream it represents. -//! -//! ## TokenStreams -//! -//! TokenStreams serve as the basis of the macro system. They are, in essence, vectors of -//! TokenTrees, where indexing treats delimited values as a single term. That is, the term -//! `even(a+c) && even(b)` will be indexibly encoded as `even | (a+c) | even | (b)` where, -//! in reality, `(a+c)` is actually a decorated pointer to `a | + | c`. -//! -//! If a user has a TokenStream that is a single, delimited value, they can use -//! `maybe_delimited` to destruct it and receive the internal vector as a new TokenStream -//! as: -//! ``` -//! `(a+c)`.maybe_delimited() ~> Some(a | + | c)` -//! ``` -//! -//! Check the TokenStream documentation for more information; the structure also provides -//! cheap concatenation and slicing. -//! - -#![crate_name = "proc_macro_tokens"] -#![unstable(feature = "rustc_private", issue = "27812")] -#![crate_type = "dylib"] -#![crate_type = "rlib"] -#![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/")] -#![cfg_attr(not(stage0), deny(warnings))] - -#![feature(staged_api)] -#![feature(rustc_private)] - -extern crate syntax; -extern crate syntax_pos; -#[macro_use] extern crate log; - -pub mod build; -pub mod parse; -pub mod prelude; diff --git a/src/libproc_macro_tokens/parse.rs b/src/libproc_macro_tokens/parse.rs deleted file mode 100644 index 5ab4fcd5da..0000000000 --- a/src/libproc_macro_tokens/parse.rs +++ /dev/null @@ -1,26 +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. - -//! Parsing utilities for writing procedural macros. - -extern crate syntax; - -use syntax::parse::{ParseSess, filemap_to_tts}; -use syntax::tokenstream::TokenStream; - -/// Map a string to tts, using a made-up filename. For example, `lex("15")` will return a -/// TokenStream containing the literal 15. -pub fn lex(source_str: &str) -> TokenStream { - let ps = ParseSess::new(); - TokenStream::from_tts(filemap_to_tts(&ps, - ps.codemap().new_filemap("".to_string(), - None, - source_str.to_owned()))) -} diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 7dc0d19e6a..e355eb44e4 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -10,6 +10,7 @@ //! The ChaCha random number generator. +use core::fmt; use {Rand, Rng, SeedableRng}; const KEY_WORDS: usize = 8; // 8 words for the 256-bit key @@ -32,6 +33,16 @@ pub struct ChaChaRng { index: usize, // Index into state } +impl fmt::Debug for ChaChaRng { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ChaChaRng") + .field("buffer", &self.buffer.iter()) + .field("state", &self.state.iter()) + .field("index", &self.index) + .finish() + } +} + static EMPTY: ChaChaRng = ChaChaRng { buffer: [0; STATE_WORDS], state: [0; STATE_WORDS], diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs index 5a8558efc0..3337cc2a62 100644 --- a/src/librand/distributions/exponential.rs +++ b/src/librand/distributions/exponential.rs @@ -10,6 +10,8 @@ //! The exponential distribution. +use core::fmt; + #[cfg(not(test))] // only necessary for no_std use FloatMath; @@ -55,6 +57,14 @@ impl Rand for Exp1 { } } +impl fmt::Debug for Exp1 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("Exp1") + .field(&self.0) + .finish() + } +} + /// The exponential distribution `Exp(lambda)`. /// /// This distribution has density function: `f(x) = lambda * @@ -79,6 +89,7 @@ impl Sample for Exp { self.ind_sample(rng) } } + impl IndependentSample for Exp { fn ind_sample(&self, rng: &mut R) -> f64 { let Exp1(n) = rng.gen::(); @@ -86,6 +97,14 @@ impl IndependentSample for Exp { } } +impl fmt::Debug for Exp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Exp") + .field("lambda_inverse", &self.lambda_inverse) + .finish() + } +} + #[cfg(test)] mod tests { use distributions::{IndependentSample, Sample}; diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs index 9ca13e85b5..e024b62adf 100644 --- a/src/librand/distributions/gamma.rs +++ b/src/librand/distributions/gamma.rs @@ -10,6 +10,8 @@ //! The Gamma and derived distributions. +use core::fmt; + use self::GammaRepr::*; use self::ChiSquaredRepr::*; @@ -44,6 +46,19 @@ pub struct Gamma { repr: GammaRepr, } +impl fmt::Debug for Gamma { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Gamma") + .field("repr", + &match self.repr { + GammaRepr::Large(_) => "Large", + GammaRepr::One(_) => "Exp", + GammaRepr::Small(_) => "Small" + }) + .finish() + } +} + enum GammaRepr { Large(GammaLargeShape), One(Exp), @@ -182,6 +197,18 @@ pub struct ChiSquared { repr: ChiSquaredRepr, } +impl fmt::Debug for ChiSquared { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ChiSquared") + .field("repr", + &match self.repr { + ChiSquaredRepr::DoFExactlyOne => "DoFExactlyOne", + ChiSquaredRepr::DoFAnythingElse(_) => "DoFAnythingElse", + }) + .finish() + } +} + enum ChiSquaredRepr { // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1, // e.g. when alpha = 1/2 as it would be for this case, so special- @@ -203,11 +230,13 @@ impl ChiSquared { ChiSquared { repr: repr } } } + impl Sample for ChiSquared { fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } } + impl IndependentSample for ChiSquared { fn ind_sample(&self, rng: &mut R) -> f64 { match self.repr { @@ -248,17 +277,29 @@ impl FisherF { } } } + impl Sample for FisherF { fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } } + impl IndependentSample for FisherF { fn ind_sample(&self, rng: &mut R) -> f64 { self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio } } +impl fmt::Debug for FisherF { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("FisherF") + .field("numer", &self.numer) + .field("denom", &self.denom) + .field("dof_ratio", &self.dof_ratio) + .finish() + } +} + /// The Student t distribution, `t(nu)`, where `nu` is the degrees of /// freedom. pub struct StudentT { @@ -277,11 +318,13 @@ impl StudentT { } } } + impl Sample for StudentT { fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } } + impl IndependentSample for StudentT { fn ind_sample(&self, rng: &mut R) -> f64 { let StandardNormal(norm) = rng.gen::(); @@ -289,6 +332,15 @@ impl IndependentSample for StudentT { } } +impl fmt::Debug for StudentT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("StudentT") + .field("chi", &self.chi) + .field("dof", &self.dof) + .finish() + } +} + #[cfg(test)] mod tests { use distributions::{IndependentSample, Sample}; diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 41175c81df..eb9476efb7 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -17,6 +17,8 @@ //! internally. The `IndependentSample` trait is for generating values //! that do not need to record state. +use core::fmt; + #[cfg(not(test))] // only necessary for no_std use core::num::Float; @@ -78,6 +80,12 @@ impl IndependentSample for RandSample { } } +impl fmt::Debug for RandSample { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("RandSample { .. }") + } +} + /// A value with a particular weight for use with `WeightedChoice`. pub struct Weighted { /// The numerical weight of this item @@ -86,6 +94,15 @@ pub struct Weighted { pub item: T, } +impl fmt::Debug for Weighted { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Weighted") + .field("weight", &self.weight) + .field("item", &self.item) + .finish() + } +} + /// A distribution that selects from a finite collection of weighted items. /// /// Each item has an associated weight that influences how likely it @@ -189,6 +206,15 @@ impl<'a, T: Clone> IndependentSample for WeightedChoice<'a, T> { } } +impl<'a, T: fmt::Debug> fmt::Debug for WeightedChoice<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("WeightedChoice") + .field("items", &self.items) + .field("weight_range", &self.weight_range) + .finish() + } +} + mod ziggurat_tables; /// Sample a random number using the Ziggurat method (specifically the diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index 811d5b14c7..33de11ab63 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -10,6 +10,8 @@ //! The normal and derived distributions. +use core::fmt; + #[cfg(not(test))] // only necessary for no_std use FloatMath; @@ -73,6 +75,14 @@ impl Rand for StandardNormal { } } +impl fmt::Debug for StandardNormal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("StandardNormal") + .field(&self.0) + .finish() + } +} + /// The normal distribution `N(mean, std_dev**2)`. /// /// This uses the ZIGNOR variant of the Ziggurat method, see @@ -98,11 +108,13 @@ impl Normal { } } } + impl Sample for Normal { fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } } + impl IndependentSample for Normal { fn ind_sample(&self, rng: &mut R) -> f64 { let StandardNormal(n) = rng.gen::(); @@ -110,6 +122,15 @@ impl IndependentSample for Normal { } } +impl fmt::Debug for Normal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Normal") + .field("mean", &self.mean) + .field("std_dev", &self.std_dev) + .finish() + } +} + /// The log-normal distribution `ln N(mean, std_dev**2)`. /// @@ -132,17 +153,27 @@ impl LogNormal { LogNormal { norm: Normal::new(mean, std_dev) } } } + impl Sample for LogNormal { fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } } + impl IndependentSample for LogNormal { fn ind_sample(&self, rng: &mut R) -> f64 { self.norm.ind_sample(rng).exp() } } +impl fmt::Debug for LogNormal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("LogNormal") + .field("norm", &self.norm) + .finish() + } +} + #[cfg(test)] mod tests { use distributions::{IndependentSample, Sample}; diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs index ba8554a979..be238b0b1a 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -12,6 +12,7 @@ // this is surprisingly complicated to be both generic & correct +use core::fmt; use core::marker::Sized; use Rng; use distributions::{IndependentSample, Sample}; @@ -50,12 +51,23 @@ impl Sample for Range { self.ind_sample(rng) } } + impl IndependentSample for Range { fn ind_sample(&self, rng: &mut R) -> Sup { SampleRange::sample_range(self, rng) } } +impl fmt::Debug for Range { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Range") + .field("low", &self.low) + .field("range", &self.range) + .field("accept_zone", &self.accept_zone) + .finish() + } +} + /// The helper trait for types that have a sensible way to sample /// uniformly between two values. This should not be used directly, /// and is only to facilitate `Range`. diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 69d5015f18..2baa07e370 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -12,6 +12,7 @@ #![allow(non_camel_case_types)] +use core::fmt; use core::slice; use core::iter::repeat; use core::num::Wrapping as w; @@ -44,6 +45,19 @@ pub struct IsaacRng { c: w32, } +impl fmt::Debug for IsaacRng { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("IsaacRng") + .field("cnt", &self.cnt) + .field("rsl", &self.rsl.iter()) + .field("mem", &self.mem.iter()) + .field("a", &self.a) + .field("b", &self.b) + .field("c", &self.c) + .finish() + } +} + static EMPTY: IsaacRng = IsaacRng { cnt: 0, rsl: [w(0); RAND_SIZE_USIZE], @@ -322,6 +336,19 @@ pub struct Isaac64Rng { c: w64, } +impl fmt::Debug for Isaac64Rng { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Isaac64Rng") + .field("cnt", &self.cnt) + .field("rsl", &self.rsl.iter()) + .field("mem", &self.mem.iter()) + .field("a", &self.a) + .field("b", &self.b) + .field("c", &self.c) + .finish() + } +} + static EMPTY_64: Isaac64Rng = Isaac64Rng { cnt: 0, rsl: [w(0); RAND_SIZE_64], diff --git a/src/librand/lib.rs b/src/librand/lib.rs index c31a0ed532..f2b43a20f9 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -23,7 +23,8 @@ html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] +#![deny(missing_debug_implementations)] #![no_std] #![unstable(feature = "rand", reason = "use `rand` from crates.io", @@ -32,6 +33,7 @@ #![feature(staged_api)] #![feature(step_by)] #![feature(custom_attribute)] +#![feature(specialization)] #![allow(unused_attributes)] #![cfg_attr(not(test), feature(core_float))] // only necessary for no_std @@ -43,6 +45,7 @@ #[macro_use] extern crate std; +use core::fmt; use core::f64; use core::intrinsics; use core::marker::PhantomData; @@ -288,6 +291,14 @@ impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> { } } +impl<'a, T, R: fmt::Debug> fmt::Debug for Generator<'a, T, R> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Generator") + .field("rng", &self.rng) + .finish() + } +} + /// Iterator which will continuously generate random ascii characters. /// /// This iterator is created via the `gen_ascii_chars` method on `Rng`. @@ -306,6 +317,14 @@ impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> { } } +impl<'a, R: fmt::Debug> fmt::Debug for AsciiGenerator<'a, R> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("AsciiGenerator") + .field("rng", &self.rng) + .finish() + } +} + /// A random number generator that can be explicitly seeded to produce /// the same stream of randomness multiple times. pub trait SeedableRng: Rng { @@ -326,7 +345,7 @@ pub trait SeedableRng: Rng { /// [1]: Marsaglia, George (July 2003). ["Xorshift /// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of /// Statistical Software*. Vol. 8 (Issue 14). -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct XorShiftRng { x: u32, y: u32, @@ -415,6 +434,14 @@ impl Rand for XorShiftRng { /// `[0,1)`. pub struct Open01(pub F); +impl fmt::Debug for Open01 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("Open01") + .field(&self.0) + .finish() + } +} + /// A wrapper for generating floating point numbers uniformly in the /// closed interval `[0,1]` (including both endpoints). /// @@ -423,6 +450,14 @@ pub struct Open01(pub F); /// `[0,1)`. pub struct Closed01(pub F); +impl fmt::Debug for Closed01 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("Closed01") + .field(&self.0) + .finish() + } +} + #[cfg(test)] mod test { use std::__rand as rand; diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index b8a65842e2..21684e38f7 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -11,6 +11,7 @@ //! A wrapper around another RNG that reseeds it after it //! generates a certain number of random bytes. +use core::fmt; use {Rng, SeedableRng}; /// How many bytes of entropy the underling RNG is allowed to generate @@ -54,7 +55,6 @@ impl> ReseedingRng { } } - impl> Rng for ReseedingRng { fn next_u32(&mut self) -> u32 { self.reseed_if_necessary(); @@ -95,6 +95,17 @@ impl, Rsdr: Reseeder + Default> } } +impl fmt::Debug for ReseedingRng { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ReseedingRng") + .field("rng", &self.rng) + .field("generation_threshold", &self.generation_threshold) + .field("bytes_generated", &self.bytes_generated) + .field("reseeder", &self.reseeder) + .finish() + } +} + /// Something that can be used to reseed an RNG via `ReseedingRng`. pub trait Reseeder { /// Reseed the given RNG. @@ -103,7 +114,7 @@ pub trait Reseeder { /// Reseed an RNG using a `Default` instance. This reseeds by /// replacing the RNG with the result of a `Default::default` call. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct ReseedWithDefault; impl Reseeder for ReseedWithDefault { diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 578ef68b00..3c455eb050 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -10,7 +10,6 @@ crate-type = ["dylib"] [dependencies] arena = { path = "../libarena" } -flate = { path = "../libflate" } fmt_macros = { path = "../libfmt_macros" } graphviz = { path = "../libgraphviz" } log = { path = "../liblog" } @@ -20,6 +19,7 @@ rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_llvm = { path = "../librustc_llvm" } +rustc_i128 = { path = "../librustc_i128" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index f21d98a0fc..5950593328 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -18,6 +18,7 @@ use hir::{self, PatKind}; struct CFGBuilder<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, graph: CFGGraph, fn_exit: CFGIndex, loop_scopes: Vec, @@ -42,10 +43,23 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let fn_exit = graph.add_node(CFGNodeData::Exit); let body_exit; + // Find the function this expression is from. + let mut node_id = body.id; + loop { + let node = tcx.hir.get(node_id); + if hir::map::blocks::FnLikeNode::from_node(node).is_some() { + break; + } + let parent = tcx.hir.get_parent_node(node_id); + assert!(node_id != parent); + node_id = parent; + } + let mut cfg_builder = CFGBuilder { + tcx: tcx, + tables: tcx.item_tables(tcx.hir.local_def_id(node_id)), graph: graph, fn_exit: fn_exit, - tcx: tcx, loop_scopes: Vec::new() }; body_exit = cfg_builder.expr(body, entry); @@ -310,11 +324,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprIndex(ref l, ref r) | - hir::ExprBinary(_, ref l, ref r) if self.tcx.tables().is_method_call(expr.id) => { + hir::ExprBinary(_, ref l, ref r) if self.tables.is_method_call(expr.id) => { self.call(expr, pred, &l, Some(&**r).into_iter()) } - hir::ExprUnary(_, ref e) if self.tcx.tables().is_method_call(expr.id) => { + hir::ExprUnary(_, ref e) if self.tables.is_method_call(expr.id) => { self.call(expr, pred, &e, None::.iter()) } @@ -327,10 +341,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.opt_expr(base, field_cfg) } - hir::ExprRepeat(ref elem, ref count) => { - self.straightline(expr, pred, [elem, count].iter().map(|&e| &**e)) - } - hir::ExprAssign(ref l, ref r) | hir::ExprAssignOp(_, ref l, ref r) => { self.straightline(expr, pred, [r, l].iter().map(|&e| &**e)) @@ -347,7 +357,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprType(ref e, _) | hir::ExprUnary(_, ref e) | hir::ExprField(ref e, _) | - hir::ExprTupField(ref e, _) => { + hir::ExprTupField(ref e, _) | + hir::ExprRepeat(ref e, _) => { self.straightline(expr, pred, Some(&**e).into_iter()) } @@ -371,9 +382,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { func_or_rcvr: &hir::Expr, args: I) -> CFGIndex { let method_call = ty::MethodCall::expr(call_expr.id); - let fn_ty = match self.tcx.tables().method_map.get(&method_call) { + let fn_ty = match self.tables.method_map.get(&method_call) { Some(method) => method.ty, - None => self.tcx.tables().expr_ty_adjusted(func_or_rcvr) + None => self.tables.expr_ty_adjusted(func_or_rcvr) }; let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc/cfg/graphviz.rs index c651baae28..944b77dbf0 100644 --- a/src/librustc/cfg/graphviz.rs +++ b/src/librustc/cfg/graphviz.rs @@ -17,14 +17,14 @@ use graphviz::IntoCow; use syntax::ast; -use hir::map as ast_map; +use hir::map as hir_map; use cfg; pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); pub type Edge<'a> = &'a cfg::CFGEdge; -pub struct LabelledCFG<'a, 'ast: 'a> { - pub ast_map: &'a ast_map::Map<'ast>, +pub struct LabelledCFG<'a, 'hir: 'a> { + pub hir_map: &'a hir_map::Map<'hir>, pub cfg: &'a cfg::CFG, pub name: String, /// `labelled_edges` controls whether we emit labels on the edges @@ -52,7 +52,7 @@ fn replace_newline_with_backslash_l(s: String) -> String { } } -impl<'a, 'ast> dot::Labeller<'a> for LabelledCFG<'a, 'ast> { +impl<'a, 'hir> dot::Labeller<'a> for LabelledCFG<'a, 'hir> { type Node = Node<'a>; type Edge = Edge<'a>; fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[..]).unwrap() } @@ -69,7 +69,7 @@ impl<'a, 'ast> dot::Labeller<'a> for LabelledCFG<'a, 'ast> { } else if n.data.id() == ast::DUMMY_NODE_ID { dot::LabelText::LabelStr("(dummy_node)".into_cow()) } else { - let s = self.ast_map.node_to_string(n.data.id()); + let s = self.hir_map.node_to_string(n.data.id()); // left-aligns the lines let s = replace_newline_with_backslash_l(s); dot::LabelText::EscStr(s.into_cow()) @@ -88,7 +88,7 @@ impl<'a, 'ast> dot::Labeller<'a> for LabelledCFG<'a, 'ast> { } else { put_one = true; } - let s = self.ast_map.node_to_string(node_id); + let s = self.hir_map.node_to_string(node_id); // left-aligns the lines let s = replace_newline_with_backslash_l(s); label.push_str(&format!("exiting scope_{} {}", @@ -120,7 +120,7 @@ impl<'a> dot::GraphWalk<'a> for &'a cfg::CFG { } } -impl<'a, 'ast> dot::GraphWalk<'a> for LabelledCFG<'a, 'ast> +impl<'a, 'hir> dot::GraphWalk<'a> for LabelledCFG<'a, 'hir> { type Node = Node<'a>; type Edge = Edge<'a>; diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md index 48f5b7ea25..daed41f047 100644 --- a/src/librustc/dep_graph/README.md +++ b/src/librustc/dep_graph/README.md @@ -326,15 +326,15 @@ The idea is that you can annotate a test like: #[rustc_if_this_changed] fn foo() { } -#[rustc_then_this_would_need(TypeckItemBody)] //~ ERROR OK +#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK fn bar() { foo(); } -#[rustc_then_this_would_need(TypeckItemBody)] //~ ERROR no path +#[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path fn baz() { } ``` This will check whether there is a path in the dependency graph from -`Hir(foo)` to `TypeckItemBody(bar)`. An error is reported for each +`Hir(foo)` to `TypeckTables(bar)`. An error is reported for each `#[rustc_then_this_would_need]` annotation that indicates whether a path exists. `//~ ERROR` annotations can then be used to test if a path is found (as demonstrated above). @@ -371,27 +371,27 @@ A node is considered to match a filter if all of those strings appear in its label. So, for example: ``` -RUST_DEP_GRAPH_FILTER='-> TypeckItemBody' +RUST_DEP_GRAPH_FILTER='-> TypeckTables' ``` -would select the predecessors of all `TypeckItemBody` nodes. Usually though you -want the `TypeckItemBody` node for some particular fn, so you might write: +would select the predecessors of all `TypeckTables` nodes. Usually though you +want the `TypeckTables` node for some particular fn, so you might write: ``` -RUST_DEP_GRAPH_FILTER='-> TypeckItemBody & bar' +RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar' ``` -This will select only the `TypeckItemBody` nodes for fns with `bar` in their name. +This will select only the `TypeckTables` nodes for fns with `bar` in their name. Perhaps you are finding that when you change `foo` you need to re-type-check `bar`, but you don't think you should have to. In that case, you might do: ``` -RUST_DEP_GRAPH_FILTER='Hir&foo -> TypeckItemBody & bar' +RUST_DEP_GRAPH_FILTER='Hir&foo -> TypeckTables & bar' ``` This will dump out all the nodes that lead from `Hir(foo)` to -`TypeckItemBody(bar)`, from which you can (hopefully) see the source +`TypeckTables(bar)`, from which you can (hopefully) see the source of the erroneous edge. #### Tracking down incorrect edges @@ -417,29 +417,8 @@ dep-graph as described in the previous section and open `dep-graph.txt` to see something like: Hir(foo) -> Collect(bar) - Collect(bar) -> TypeckItemBody(bar) + Collect(bar) -> TypeckTables(bar) That first edge looks suspicious to you. So you set `RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and then observe the backtrace. Voila, bug fixed! - -### Inlining of HIR nodes - -For the time being, at least, we still sometimes "inline" HIR nodes -from other crates into the current HIR map. This creates a weird -scenario where the same logical item (let's call it `X`) has two -def-ids: the original def-id `X` and a new, inlined one `X'`. `X'` is -in the current crate, but it's not like other HIR nodes: in -particular, when we restart compilation, it will not be available to -hash. Therefore, we do not want `Hir(X')` nodes appearing in our -graph. Instead, we want a "read" of `Hir(X')` to be represented as a -read of `MetaData(X)`, since the metadata for `X` is where the inlined -representation originated in the first place. - -To achieve this, the HIR map will detect if the def-id originates in -an inlined node and add a dependency to a suitable `MetaData` node -instead. If you are reading a HIR node and are not sure if it may be -inlined or not, you can use `tcx.map.read(node_id)` and it will detect -whether the node is inlined or not and do the right thing. You can -also use `tcx.map.is_inlined_def_id()` and -`tcx.map.is_inlined_node_id()` to test. diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e261c699b6..df6db366df 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -29,10 +29,10 @@ pub enum DepNode { // Represents the `Krate` as a whole (the `hir::Krate` value) (as // distinct from the krate module). This is basically a hash of // the entire krate, so if you read from `Krate` (e.g., by calling - // `tcx.map.krate()`), we will have to assume that any change + // `tcx.hir.krate()`), we will have to assume that any change // means that you need to be recompiled. This is because the // `Krate` value gives you access to all other items. To avoid - // this fate, do not call `tcx.map.krate()`; instead, prefer + // this fate, do not call `tcx.hir.krate()`; instead, prefer // wrappers like `tcx.visit_all_items_in_krate()`. If there is no // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain // access to the krate, but you must remember to add suitable @@ -78,7 +78,6 @@ pub enum DepNode { Variance, WfCheck(D), TypeckItemType(D), - TypeckItemBody(D), Dropck, DropckImpl(D), UnusedTraitCheck, @@ -113,6 +112,7 @@ pub enum DepNode { SizedConstraint(D), AssociatedItemDefIds(D), InherentImpls(D), + TypeckTables(D), // The set of impls for a given trait. Ultimately, it would be // nice to get more fine-grained here (e.g., to include a @@ -157,11 +157,11 @@ impl DepNode { HirBody, TransCrateItem, TypeckItemType, - TypeckItemBody, AssociatedItems, ItemSignature, AssociatedItemDefIds, InherentImpls, + TypeckTables, TraitImpls, ReprHints, } @@ -214,7 +214,6 @@ impl DepNode { CoherenceOrphanCheck(ref d) => op(d).map(CoherenceOrphanCheck), WfCheck(ref d) => op(d).map(WfCheck), TypeckItemType(ref d) => op(d).map(TypeckItemType), - TypeckItemBody(ref d) => op(d).map(TypeckItemBody), DropckImpl(ref d) => op(d).map(DropckImpl), CheckConst(ref d) => op(d).map(CheckConst), IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck), @@ -230,6 +229,7 @@ impl DepNode { SizedConstraint(ref d) => op(d).map(SizedConstraint), AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds), InherentImpls(ref d) => op(d).map(InherentImpls), + TypeckTables(ref d) => op(d).map(TypeckTables), TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index 50dfe9d22f..9660758220 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -117,7 +117,7 @@ impl MemoizationMap for RefCell> { /// /// ``` /// fn type_of_item(..., item: &hir::Item) -> Ty<'tcx> { - /// let item_def_id = ccx.tcx.map.local_def_id(it.id); + /// let item_def_id = ccx.tcx.hir.local_def_id(it.id); /// ccx.tcx.item_types.memoized(item_def_id, || { /// ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); // (*) /// compute_type_of_item(ccx, item) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 2637d34c5c..e6736ccafb 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -51,6 +51,12 @@ impl DepGraph { } } + /// True if we are actually building the full dep-graph. + #[inline] + pub fn is_fully_enabled(&self) -> bool { + self.data.thread.is_fully_enabled() + } + pub fn query(&self) -> DepGraphQuery { self.data.thread.query() } @@ -120,6 +126,12 @@ impl DepGraph { pub fn work_products(&self) -> Ref, WorkProduct>> { self.data.work_products.borrow() } + + /// Access the map of work-products created during the cached run. Only + /// used during saving of the dep-graph. + pub fn previous_work_products(&self) -> Ref, WorkProduct>> { + self.data.previous_work_products.borrow() + } } /// A "work product" is an intermediate result that we save into the diff --git a/src/librustc/dep_graph/thread.rs b/src/librustc/dep_graph/thread.rs index 9f755cf86e..d3a940c811 100644 --- a/src/librustc/dep_graph/thread.rs +++ b/src/librustc/dep_graph/thread.rs @@ -56,7 +56,7 @@ pub struct DepGraphThreadData { // current buffer, where we accumulate messages messages: VecCell, - // whence to receive new buffer when full + // where to receive new buffer when full swap_in: Receiver>, // where to send buffer when full diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs index 600732fc6f..f0a81fd1cf 100644 --- a/src/librustc/dep_graph/visit.rs +++ b/src/librustc/dep_graph/visit.rs @@ -36,29 +36,37 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx> where F: FnMut(DefId) -> DepNode, V: ItemLikeVisitor<'tcx> { fn visit_item(&mut self, i: &'tcx hir::Item) { - let item_def_id = self.tcx.map.local_def_id(i.id); + let item_def_id = self.tcx.hir.local_def_id(i.id); let task_id = (self.dep_node_fn)(item_def_id); let _task = self.tcx.dep_graph.in_task(task_id.clone()); debug!("Started task {:?}", task_id); - assert!(!self.tcx.map.is_inlined_def_id(item_def_id)); self.tcx.dep_graph.read(DepNode::Hir(item_def_id)); self.visitor.visit_item(i); debug!("Ended task {:?}", task_id); } + fn visit_trait_item(&mut self, i: &'tcx hir::TraitItem) { + let trait_item_def_id = self.tcx.hir.local_def_id(i.id); + let task_id = (self.dep_node_fn)(trait_item_def_id); + let _task = self.tcx.dep_graph.in_task(task_id.clone()); + debug!("Started task {:?}", task_id); + self.tcx.dep_graph.read(DepNode::Hir(trait_item_def_id)); + self.visitor.visit_trait_item(i); + debug!("Ended task {:?}", task_id); + } + fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) { - let impl_item_def_id = self.tcx.map.local_def_id(i.id); + let impl_item_def_id = self.tcx.hir.local_def_id(i.id); let task_id = (self.dep_node_fn)(impl_item_def_id); let _task = self.tcx.dep_graph.in_task(task_id.clone()); debug!("Started task {:?}", task_id); - assert!(!self.tcx.map.is_inlined_def_id(impl_item_def_id)); self.tcx.dep_graph.read(DepNode::Hir(impl_item_def_id)); self.visitor.visit_impl_item(i); debug!("Ended task {:?}", task_id); } } - let krate = tcx.dep_graph.with_ignore(|| tcx.map.krate()); + let krate = tcx.dep_graph.with_ignore(|| tcx.hir.krate()); let mut tracking_visitor = TrackingVisitor { tcx: tcx, dep_node_fn: &mut dep_node_fn, diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index ec09877ae1..b51a7d4104 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -327,6 +327,69 @@ struct ListNode { This works because `Box` is a pointer, so its size is well-known. "##, +E0106: r##" +This error indicates that a lifetime is missing from a type. If it is an error +inside a function signature, the problem may be with failing to adhere to the +lifetime elision rules (see below). + +Here are some simple examples of where you'll run into this error: + +```compile_fail,E0106 +struct Foo { x: &bool } // error +struct Foo<'a> { x: &'a bool } // correct + +enum Bar { A(u8), B(&bool), } // error +enum Bar<'a> { A(u8), B(&'a bool), } // correct + +type MyStr = &str; // error +type MyStr<'a> = &'a str; // correct +``` + +Lifetime elision is a special, limited kind of inference for lifetimes in +function signatures which allows you to leave out lifetimes in certain cases. +For more background on lifetime elision see [the book][book-le]. + +The lifetime elision rules require that any function signature with an elided +output lifetime must either have + + - exactly one input lifetime + - or, multiple input lifetimes, but the function must also be a method with a + `&self` or `&mut self` receiver + +In the first case, the output lifetime is inferred to be the same as the unique +input lifetime. In the second case, the lifetime is instead inferred to be the +same as the lifetime on `&self` or `&mut self`. + +Here are some examples of elision errors: + +```compile_fail,E0106 +// error, no input lifetimes +fn foo() -> &str { } + +// error, `x` and `y` have distinct lifetimes inferred +fn bar(x: &str, y: &str) -> &str { } + +// error, `y`'s lifetime is inferred to be distinct from `x`'s +fn baz<'a>(x: &'a str, y: &str) -> &str { } +``` + +Here's an example that is currently an error, but may work in a future version +of Rust: + +```compile_fail,E0106 +struct Foo<'a>(&'a str); + +trait Quux { } +impl Quux for Foo { } +``` + +Lifetime elision in implementation headers was part of the lifetime elision +RFC. It is, however, [currently unimplemented][iss15872]. + +[book-le]: https://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision +[iss15872]: https://github.com/rust-lang/rust/issues/15872 +"##, + E0109: r##" You tried to give a type parameter to a type which doesn't need it. Erroneous code example: @@ -1236,6 +1299,23 @@ struct Foo<'a, T: 'a> { foo: &'a T } ``` + +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: + +```compile_fail,E0309 +struct Foo<'a, T> { + foo: &'a T +} + +fn main() { + let v = "42".to_string(); + let f = Foo{foo: &v}; + drop(v); + println!("{}", f.foo); // but we've already dropped v! +} +``` "##, E0310: r##" @@ -1437,6 +1517,40 @@ struct Prince<'kiss, 'SnowWhite: 'kiss> { // You say here that 'kiss must live ``` "##, +E0491: r##" +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, +} + +// 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 +} +``` + +To fix this issue, you can specify a bound to the lifetime like below: + +``` +struct Struct<'a> { + ref_i32: &'a i32, +} + +// 'a: 'b means 'a outlives 'b +struct Nested<'a: 'b, 'b> { + ref_struct: &'b Struct<'a>, +} +``` +"##, + E0496: r##" A lifetime name is shadowing another lifetime name. Erroneous code example: @@ -1601,8 +1715,7 @@ fn cookie() -> ! { // error: definition of an unknown language item: `cookie` "##, E0525: r##" -A closure was attempted to get used whereas it doesn't implement the expected -trait. +A closure was used but didn't implement the expected trait. Erroneous code example: @@ -1644,6 +1757,30 @@ To understand better how closures work in Rust, read: https://doc.rust-lang.org/book/closures.html "##, +E0580: r##" +The `main` function was incorrectly declared. + +Erroneous code example: + +```compile_fail,E0580 +fn main() -> i32 { // error: main function has wrong type + 0 +} +``` + +The `main` function prototype should never take arguments or return type. +Example: + +``` +fn main() { + // your code +} +``` + +If you want to get command-line arguments, use `std::env::args`. To exit with a +specified exit code, use `std::process::exit`. +"##, + } @@ -1681,7 +1818,6 @@ register_diagnostics! { E0488, // lifetime of variable does not enclose its declaration E0489, // type/lifetime parameter not in scope here E0490, // a value of type `..` is borrowed for too long - E0491, // in type `..`, reference has a longer lifetime than the data it... E0495, // cannot infer an appropriate lifetime due to conflicting requirements E0566 // conflicting representation hints } diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index d3771b1755..cbf162cc13 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -120,9 +120,7 @@ impl fmt::Debug for DefId { ty::tls::with_opt(|opt_tcx| { if let Some(tcx) = opt_tcx { - if let Some(def_path) = tcx.opt_def_path(*self) { - write!(f, " => {}", def_path.to_string(tcx))?; - } + write!(f, " => {}", tcx.def_path(*self).to_string(tcx))?; } Ok(()) })?; diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 625bde2ca8..4b3e0d2910 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -154,7 +154,7 @@ pub trait Visitor<'v> : Sized { /// hashed separately. /// /// **If for some reason you want the nested behavior, but don't - /// have a `Map` are your disposal:** then you should override the + /// have a `Map` at your disposal:** then you should override the /// `visit_nested_XXX` methods, and override this method to /// `panic!()`. This way, if a new `visit_nested_XXX` variant is /// added in the future, we will see the panic in your code and @@ -177,6 +177,17 @@ pub trait Visitor<'v> : Sized { } } + /// Like `visit_nested_item()`, but for trait items. See + /// `visit_nested_item()` for advice on when to override this + /// method. + #[allow(unused_variables)] + fn visit_nested_trait_item(&mut self, id: TraitItemId) { + let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id)); + if let Some(item) = opt_item { + self.visit_trait_item(item); + } + } + /// Like `visit_nested_item()`, but for impl items. See /// `visit_nested_item()` for advice on when to override this /// method. @@ -192,10 +203,10 @@ pub trait Visitor<'v> : Sized { /// visit_nested_item, does nothing by default unless you override /// `nested_visit_map` to return `Some(_)`, in which case it will walk the /// body. - fn visit_body(&mut self, id: ExprId) { - let opt_expr = self.nested_visit_map().intra().map(|map| map.expr(id)); - if let Some(expr) = opt_expr { - self.visit_expr(expr); + fn visit_nested_body(&mut self, id: BodyId) { + let opt_body = self.nested_visit_map().intra().map(|map| map.body(id)); + if let Some(body) = opt_body { + self.visit_body(body); } } @@ -205,6 +216,10 @@ pub trait Visitor<'v> : Sized { walk_item(self, i) } + fn visit_body(&mut self, b: &'v Body) { + walk_body(self, b); + } + /// When invoking `visit_all_item_likes()`, you need to supply an /// item-like visitor. This method converts a "intra-visit" /// visitor into an item-like visitor that walks the entire tree. @@ -253,8 +268,6 @@ pub trait Visitor<'v> : Sized { fn visit_expr(&mut self, ex: &'v Expr) { walk_expr(self, ex) } - fn visit_expr_post(&mut self, _ex: &'v Expr) { - } fn visit_ty(&mut self, t: &'v Ty) { walk_ty(self, t) } @@ -264,12 +277,18 @@ pub trait Visitor<'v> : Sized { fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) { walk_where_predicate(self, predicate) } - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: ExprId, s: Span, id: NodeId) { + fn visit_fn_decl(&mut self, fd: &'v FnDecl) { + walk_fn_decl(self, fd) + } + fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: BodyId, s: Span, id: NodeId) { walk_fn(self, fk, fd, b, s, id) } fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) } + fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) { + walk_trait_item_ref(self, ii) + } fn visit_impl_item(&mut self, ii: &'v ImplItem) { walk_impl_item(self, ii) } @@ -282,7 +301,7 @@ pub trait Visitor<'v> : Sized { fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { walk_ty_param_bound(self, bounds) } - fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) { + fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) { walk_poly_trait_ref(self, t, m) } fn visit_variant_data(&mut self, @@ -365,7 +384,6 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) { pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) { visitor.visit_id(macro_def.id); visitor.visit_name(macro_def.span, macro_def.name); - walk_opt_name(visitor, macro_def.span, macro_def.imported_from); walk_list!(visitor, visit_attribute, ¯o_def.attrs); } @@ -376,6 +394,14 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_node_i } } +pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) { + for argument in &body.arguments { + visitor.visit_id(argument.id); + visitor.visit_pat(&argument.pat); + } + visitor.visit_expr(&body.value); +} + pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { visitor.visit_id(local.id); visitor.visit_pat(&local.pat); @@ -395,7 +421,7 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v PolyTraitRef, - _modifier: &'v TraitBoundModifier) + _modifier: TraitBoundModifier) where V: Visitor<'v> { walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes); @@ -421,11 +447,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_id(item.id); visitor.visit_path(path, item.id); } - ItemStatic(ref typ, _, ref expr) | - ItemConst(ref typ, ref expr) => { + ItemStatic(ref typ, _, body) | + ItemConst(ref typ, body) => { visitor.visit_id(item.id); visitor.visit_ty(typ); - visitor.visit_expr(expr); + visitor.visit_nested_body(body); } ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => { visitor.visit_fn(FnKind::ItemFn(item.name, @@ -467,9 +493,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_generics(type_parameters); walk_list!(visitor, visit_trait_ref, opt_trait_reference); visitor.visit_ty(typ); - for impl_item_ref in impl_item_refs { - visitor.visit_impl_item_ref(impl_item_ref); - } + walk_list!(visitor, visit_impl_item_ref, impl_item_refs); } ItemStruct(ref struct_definition, ref generics) | ItemUnion(ref struct_definition, ref generics) => { @@ -477,11 +501,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_id(item.id); visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span); } - ItemTrait(_, ref generics, ref bounds, ref methods) => { + ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => { visitor.visit_id(item.id); visitor.visit_generics(generics); walk_list!(visitor, visit_ty_param_bound, bounds); - walk_list!(visitor, visit_trait_item, methods); + walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } } walk_list!(visitor, visit_attribute, &item.attrs); @@ -509,7 +533,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, generics, parent_item_id, variant.span); - walk_list!(visitor, visit_expr, &variant.node.disr_expr); + walk_list!(visitor, visit_nested_body, variant.node.disr_expr); walk_list!(visitor, visit_attribute, &variant.node.attrs); } @@ -523,8 +547,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyPtr(ref mutable_type) => { visitor.visit_ty(&mutable_type.ty) } - TyRptr(ref opt_lifetime, ref mutable_type) => { - walk_list!(visitor, visit_lifetime, opt_lifetime); + TyRptr(ref lifetime, ref mutable_type) => { + visitor.visit_lifetime(lifetime); visitor.visit_ty(&mutable_type.ty) } TyNever => {}, @@ -532,28 +556,27 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_list!(visitor, visit_ty, tuple_element_types); } TyBareFn(ref function_declaration) => { - walk_fn_decl(visitor, &function_declaration.decl); + visitor.visit_fn_decl(&function_declaration.decl); walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); } TyPath(ref qpath) => { visitor.visit_qpath(qpath, typ.id, typ.span); } - TyObjectSum(ref ty, ref bounds) => { + TyArray(ref ty, length) => { visitor.visit_ty(ty); - walk_list!(visitor, visit_ty_param_bound, bounds); + visitor.visit_nested_body(length) } - TyArray(ref ty, ref expression) => { - visitor.visit_ty(ty); - visitor.visit_expr(expression) - } - TyPolyTraitRef(ref bounds) => { - walk_list!(visitor, visit_ty_param_bound, bounds); + TyTraitObject(ref bounds, ref lifetime) => { + for bound in bounds { + visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None); + } + visitor.visit_lifetime(lifetime); } TyImplTrait(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); } - TyTypeof(ref expression) => { - visitor.visit_expr(expression) + TyTypeof(expression) => { + visitor.visit_nested_body(expression) } TyInfer => {} } @@ -641,7 +664,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { walk_list!(visitor, visit_pat, optional_subpattern); } PatKind::Lit(ref expression) => visitor.visit_expr(expression), - PatKind::Range(ref lower_bound, ref upper_bound) => { + PatKind::Range(ref lower_bound, ref upper_bound, _) => { visitor.visit_expr(lower_bound); visitor.visit_expr(upper_bound) } @@ -660,9 +683,12 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v visitor.visit_name(foreign_item.span, foreign_item.name); match foreign_item.node { - ForeignItemFn(ref function_declaration, ref generics) => { - walk_fn_decl(visitor, function_declaration); - visitor.visit_generics(generics) + ForeignItemFn(ref function_declaration, ref names, ref generics) => { + visitor.visit_generics(generics); + visitor.visit_fn_decl(function_declaration); + for name in names { + visitor.visit_name(name.span, name.node); + } } ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ), } @@ -672,7 +698,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) { match *bound { - TraitTyParamBound(ref typ, ref modifier) => { + TraitTyParamBound(ref typ, modifier) => { visitor.visit_poly_trait_ref(typ, modifier); } RegionTyParamBound(ref lifetime) => { @@ -713,12 +739,12 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( walk_list!(visitor, visit_lifetime, bounds); } &WherePredicate::EqPredicate(WhereEqPredicate{id, - ref path, - ref ty, + ref lhs_ty, + ref rhs_ty, ..}) => { visitor.visit_id(id); - visitor.visit_path(path, id); - visitor.visit_ty(ty); + visitor.visit_ty(lhs_ty); + visitor.visit_ty(rhs_ty); } } } @@ -730,18 +756,8 @@ pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionR } pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { - for argument in &function_declaration.inputs { - visitor.visit_id(argument.id); - visitor.visit_pat(&argument.pat); - visitor.visit_ty(&argument.ty) - } - walk_fn_ret_ty(visitor, &function_declaration.output) -} - -pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { - for argument in &function_declaration.inputs { - visitor.visit_id(argument.id); - visitor.visit_ty(&argument.ty) + for ty in &function_declaration.inputs { + visitor.visit_ty(ty) } walk_fn_ret_ty(visitor, &function_declaration.output) } @@ -761,42 +777,33 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<' pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>, function_declaration: &'v FnDecl, - body_id: ExprId, + body_id: BodyId, _span: Span, id: NodeId) { visitor.visit_id(id); - walk_fn_decl(visitor, function_declaration); + visitor.visit_fn_decl(function_declaration); walk_fn_kind(visitor, function_kind); - visitor.visit_body(body_id) -} - -pub fn walk_fn_with_body<'v, V: Visitor<'v>>(visitor: &mut V, - function_kind: FnKind<'v>, - function_declaration: &'v FnDecl, - body: &'v Expr, - _span: Span, - id: NodeId) { - visitor.visit_id(id); - walk_fn_decl(visitor, function_declaration); - walk_fn_kind(visitor, function_kind); - visitor.visit_expr(body) + visitor.visit_nested_body(body_id) } pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { visitor.visit_name(trait_item.span, trait_item.name); walk_list!(visitor, visit_attribute, &trait_item.attrs); match trait_item.node { - ConstTraitItem(ref ty, ref default) => { + TraitItemKind::Const(ref ty, default) => { visitor.visit_id(trait_item.id); visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, default); + walk_list!(visitor, visit_nested_body, default); } - MethodTraitItem(ref sig, None) => { + TraitItemKind::Method(ref sig, TraitMethod::Required(ref names)) => { visitor.visit_id(trait_item.id); visitor.visit_generics(&sig.generics); - walk_fn_decl(visitor, &sig.decl); + visitor.visit_fn_decl(&sig.decl); + for name in names { + visitor.visit_name(name.span, name.node); + } } - MethodTraitItem(ref sig, Some(body_id)) => { + TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => { visitor.visit_fn(FnKind::Method(trait_item.name, sig, None, @@ -806,7 +813,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai trait_item.span, trait_item.id); } - TypeTraitItem(ref bounds, ref default) => { + TraitItemKind::Type(ref bounds, ref default) => { visitor.visit_id(trait_item.id); walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_ty, default); @@ -814,6 +821,15 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } } +pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) { + // NB: Deliberately force a compilation error if/when new fields are added. + let TraitItemRef { id, name, ref kind, span, ref defaultness } = *trait_item_ref; + visitor.visit_nested_trait_item(id); + visitor.visit_name(span, name); + visitor.visit_associated_item_kind(kind); + visitor.visit_defaultness(defaultness); +} + pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { // NB: Deliberately force a compilation error if/when new fields are added. let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item; @@ -823,10 +839,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt visitor.visit_defaultness(defaultness); walk_list!(visitor, visit_attribute, attrs); match *node { - ImplItemKind::Const(ref ty, ref expr) => { + ImplItemKind::Const(ref ty, body) => { visitor.visit_id(impl_item.id); visitor.visit_ty(ty); - visitor.visit_expr(expr); + visitor.visit_nested_body(body); } ImplItemKind::Method(ref sig, body_id) => { visitor.visit_fn(FnKind::Method(impl_item.name, @@ -905,9 +921,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprArray(ref subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } - ExprRepeat(ref element, ref count) => { + ExprRepeat(ref element, count) => { visitor.visit_expr(element); - visitor.visit_expr(count) + visitor.visit_nested_body(count) } ExprStruct(ref qpath, ref fields, ref optional_base) => { visitor.visit_qpath(qpath, expression.id, expression.span); @@ -1014,8 +1030,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { } } } - - visitor.visit_expr_post(expression) } pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { @@ -1074,13 +1088,13 @@ impl IdRange { } -pub struct IdRangeComputingVisitor<'a, 'ast: 'a> { +pub struct IdRangeComputingVisitor<'a, 'hir: 'a> { result: IdRange, - map: &'a map::Map<'ast>, + map: &'a map::Map<'hir>, } -impl<'a, 'ast> IdRangeComputingVisitor<'a, 'ast> { - pub fn new(map: &'a map::Map<'ast>) -> IdRangeComputingVisitor<'a, 'ast> { +impl<'a, 'hir> IdRangeComputingVisitor<'a, 'hir> { + pub fn new(map: &'a map::Map<'hir>) -> IdRangeComputingVisitor<'a, 'hir> { IdRangeComputingVisitor { result: IdRange::max(), map: map } } @@ -1089,8 +1103,8 @@ impl<'a, 'ast> IdRangeComputingVisitor<'a, 'ast> { } } -impl<'a, 'ast> Visitor<'ast> for IdRangeComputingVisitor<'a, 'ast> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'ast> { +impl<'a, 'hir> Visitor<'hir> for IdRangeComputingVisitor<'a, 'hir> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { NestedVisitorMap::OnlyBodies(&self.map) } @@ -1098,16 +1112,3 @@ impl<'a, 'ast> Visitor<'ast> for IdRangeComputingVisitor<'a, 'ast> { self.result.add(id); } } - -/// Computes the id range for a single fn body, ignoring nested items. -pub fn compute_id_range_for_fn_body<'v>(fk: FnKind<'v>, - decl: &'v FnDecl, - body: &'v Expr, - sp: Span, - id: NodeId, - map: &map::Map<'v>) - -> IdRange { - let mut visitor = IdRangeComputingVisitor::new(map); - walk_fn_with_body(&mut visitor, fk, decl, body, sp, id); - visitor.result() -} diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs index 71ef713144..0d79017066 100644 --- a/src/librustc/hir/itemlikevisit.rs +++ b/src/librustc/hir/itemlikevisit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{Item, ImplItem}; +use super::{Item, ImplItem, TraitItem}; use super::intravisit::Visitor; /// The "item-like visitor" visitor defines only the top-level methods @@ -44,7 +44,7 @@ use super::intravisit::Visitor; /// - How: Implement `intravisit::Visitor` and override the /// `visit_nested_map()` methods to return /// `NestedVisitorMap::All`. Walk your crate with -/// `intravisit::walk_crate()` invoked on `tcx.map.krate()`. +/// `intravisit::walk_crate()` invoked on `tcx.hir.krate()`. /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. /// - Pro: Preserves nesting information /// - Con: Does not integrate well into dependency tracking. @@ -58,6 +58,7 @@ use super::intravisit::Visitor; /// needed. pub trait ItemLikeVisitor<'hir> { fn visit_item(&mut self, item: &'hir Item); + fn visit_trait_item(&mut self, trait_item: &'hir TraitItem); fn visit_impl_item(&mut self, impl_item: &'hir ImplItem); } @@ -80,6 +81,10 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> self.visitor.visit_item(item); } + fn visit_trait_item(&mut self, trait_item: &'hir TraitItem) { + self.visitor.visit_trait_item(trait_item); + } + fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) { self.visitor.visit_impl_item(impl_item); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 74876eb59e..8a4acb3d03 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -41,18 +41,17 @@ // in the HIR, especially for multiple identifiers. use hir; -use hir::map::Definitions; +use hir::map::{Definitions, DefKey}; use hir::map::definitions::DefPathData; use hir::def_id::{DefIndex, DefId}; use hir::def::{Def, PathResolution}; use session::Session; -use util::nodemap::NodeMap; -use rustc_data_structures::fnv::FnvHashMap; +use util::nodemap::{DefIdMap, NodeMap, FxHashMap}; use std::collections::BTreeMap; use std::iter; -use std::mem; +use syntax::attr; use syntax::ast::*; use syntax::errors; use syntax::ptr::P; @@ -71,17 +70,20 @@ pub struct LoweringContext<'a> { // the form of a DefIndex) so that if we create a new node which introduces // a definition, then we can properly create the def id. parent_def: Option, - exprs: FnvHashMap, resolver: &'a mut Resolver, /// The items being lowered are collected here. items: BTreeMap, + trait_items: BTreeMap, impl_items: BTreeMap, + bodies: FxHashMap, + + type_def_lifetime_params: DefIdMap, } pub trait Resolver { - // Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc. + // Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc. fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool); // Obtain the resolution for a node id @@ -105,10 +107,12 @@ pub fn lower_crate(sess: &Session, crate_root: std_inject::injected_crate_name(krate), sess: sess, parent_def: None, - exprs: FnvHashMap(), resolver: resolver, items: BTreeMap::new(), + trait_items: BTreeMap::new(), impl_items: BTreeMap::new(), + bodies: FxHashMap(), + type_def_lifetime_params: DefIdMap(), }.lower_crate(krate) } @@ -122,23 +126,33 @@ enum ParamMode { impl<'a> LoweringContext<'a> { fn lower_crate(mut self, c: &Crate) -> hir::Crate { - self.lower_items(c); - let module = self.lower_mod(&c.module); - let attrs = self.lower_attrs(&c.attrs); - let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(); + /// Full-crate AST visitor that inserts into a fresh + /// `LoweringContext` any information that may be + /// needed from arbitrary locations in the crate. + /// E.g. The number of lifetime generic parameters + /// declared for every type and trait definition. + struct MiscCollector<'lcx, 'interner: 'lcx> { + lctx: &'lcx mut LoweringContext<'interner>, + } - hir::Crate { - module: module, - attrs: attrs, - span: c.span, - exported_macros: exported_macros, - items: self.items, - impl_items: self.impl_items, - exprs: mem::replace(&mut self.exprs, FnvHashMap()), + impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> { + fn visit_item(&mut self, item: &'lcx Item) { + match item.node { + ItemKind::Struct(_, ref generics) | + ItemKind::Union(_, ref generics) | + ItemKind::Enum(_, ref generics) | + ItemKind::Ty(_, ref generics) | + ItemKind::Trait(_, ref generics, ..) => { + let def_id = self.lctx.resolver.definitions().local_def_id(item.id); + let count = generics.lifetimes.len(); + self.lctx.type_def_lifetime_params.insert(def_id, count); + } + _ => {} + } + visit::walk_item(self, item); + } } - } - fn lower_items(&mut self, c: &Crate) { struct ItemLowerer<'lcx, 'interner: 'lcx> { lctx: &'lcx mut LoweringContext<'interner>, } @@ -150,21 +164,50 @@ impl<'a> LoweringContext<'a> { visit::walk_item(self, item); } + fn visit_trait_item(&mut self, item: &'lcx TraitItem) { + let id = hir::TraitItemId { node_id: item.id }; + let hir_item = self.lctx.lower_trait_item(item); + self.lctx.trait_items.insert(id, hir_item); + visit::walk_trait_item(self, item); + } + fn visit_impl_item(&mut self, item: &'lcx ImplItem) { - let id = self.lctx.lower_impl_item_ref(item).id; + let id = hir::ImplItemId { node_id: item.id }; let hir_item = self.lctx.lower_impl_item(item); self.lctx.impl_items.insert(id, hir_item); visit::walk_impl_item(self, item); } } - let mut item_lowerer = ItemLowerer { lctx: self }; - visit::walk_crate(&mut item_lowerer, c); + visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c); + visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c); + + let module = self.lower_mod(&c.module); + let attrs = self.lower_attrs(&c.attrs); + let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(); + + hir::Crate { + module: module, + attrs: attrs, + span: c.span, + exported_macros: exported_macros, + items: self.items, + trait_items: self.trait_items, + impl_items: self.impl_items, + bodies: self.bodies, + } } - fn record_expr(&mut self, expr: hir::Expr) -> hir::ExprId { - let id = hir::ExprId(expr.id); - self.exprs.insert(id, expr); + fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>) + -> hir::BodyId { + let body = hir::Body { + arguments: decl.map_or(hir_vec![], |decl| { + decl.inputs.iter().map(|x| self.lower_arg(x)).collect() + }), + value: value + }; + let id = body.id(); + self.bodies.insert(id, body); id } @@ -216,6 +259,14 @@ impl<'a> LoweringContext<'a> { result } + fn def_key(&mut self, id: DefId) -> DefKey { + if id.is_local() { + self.resolver.definitions().def_key(id.index) + } else { + self.sess.cstore.def_key(id) + } + } + fn lower_opt_sp_ident(&mut self, o_id: Option>) -> Option> { o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name)) } @@ -259,11 +310,16 @@ impl<'a> LoweringContext<'a> { P(hir::Ty { id: t.id, node: match t.node { - TyKind::Infer | TyKind::ImplicitSelf => hir::TyInfer, + TyKind::Infer => hir::TyInfer, TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)), TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)), TyKind::Rptr(ref region, ref mt) => { - hir::TyRptr(self.lower_opt_lifetime(region), self.lower_mt(mt)) + let span = Span { hi: t.span.lo, ..t.span }; + let lifetime = match *region { + Some(ref lt) => self.lower_lifetime(lt), + None => self.elided_lifetime(span) + }; + hir::TyRptr(lifetime, self.lower_mt(mt)) } TyKind::BareFn(ref f) => { hir::TyBareFn(P(hir::BareFnTy { @@ -281,19 +337,46 @@ impl<'a> LoweringContext<'a> { return self.lower_ty(ty); } TyKind::Path(ref qself, ref path) => { - hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit)) + let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit); + return self.ty_path(t.id, t.span, qpath); } - TyKind::ObjectSum(ref ty, ref bounds) => { - hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds)) + TyKind::ImplicitSelf => { + hir::TyPath(hir::QPath::Resolved(None, P(hir::Path { + def: self.expect_full_def(t.id), + segments: hir_vec![hir::PathSegment { + name: keywords::SelfType.name(), + parameters: hir::PathParameters::none() + }], + span: t.span, + }))) } - TyKind::Array(ref ty, ref e) => { - hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e))) + TyKind::Array(ref ty, ref length) => { + let length = self.lower_expr(length); + hir::TyArray(self.lower_ty(ty), + self.record_body(length, None)) } TyKind::Typeof(ref expr) => { - hir::TyTypeof(P(self.lower_expr(expr))) + let expr = self.lower_expr(expr); + hir::TyTypeof(self.record_body(expr, None)) } - TyKind::PolyTraitRef(ref bounds) => { - hir::TyPolyTraitRef(self.lower_bounds(bounds)) + TyKind::TraitObject(ref bounds) => { + let mut lifetime_bound = None; + let bounds = bounds.iter().filter_map(|bound| { + match *bound { + TraitTyParamBound(ref ty, TraitBoundModifier::None) => { + Some(self.lower_poly_trait_ref(ty)) + } + TraitTyParamBound(_, TraitBoundModifier::Maybe) => None, + RegionTyParamBound(ref lifetime) => { + lifetime_bound = Some(self.lower_lifetime(lifetime)); + None + } + } + }).collect(); + let lifetime_bound = lifetime_bound.unwrap_or_else(|| { + self.elided_lifetime(t.span) + }); + hir::TyTraitObject(bounds, lifetime_bound) } TyKind::ImplTrait(ref bounds) => { hir::TyImplTrait(self.lower_bounds(bounds)) @@ -317,7 +400,10 @@ impl<'a> LoweringContext<'a> { name: v.node.name.name, attrs: self.lower_attrs(&v.node.attrs), data: self.lower_variant_data(&v.node.data), - disr_expr: v.node.disr_expr.as_ref().map(|e| P(self.lower_expr(e))), + disr_expr: v.node.disr_expr.as_ref().map(|e| { + let e = self.lower_expr(e); + self.record_body(e, None) + }), }, span: v.span, } @@ -337,7 +423,6 @@ impl<'a> LoweringContext<'a> { let proj_start = p.segments.len() - resolution.depth; let path = P(hir::Path { - global: p.global, def: resolution.base_def, segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| { let param_mode = match (qself_position, param_mode) { @@ -349,7 +434,40 @@ impl<'a> LoweringContext<'a> { } _ => param_mode }; - self.lower_path_segment(segment, param_mode) + + // Figure out if this is a type/trait segment, + // which may need lifetime elision performed. + let parent_def_id = |this: &mut Self, def_id: DefId| { + DefId { + krate: def_id.krate, + index: this.def_key(def_id).parent.expect("missing parent") + } + }; + let type_def_id = match resolution.base_def { + Def::AssociatedTy(def_id) if i + 2 == proj_start => { + Some(parent_def_id(self, def_id)) + } + Def::Variant(def_id) if i + 1 == proj_start => { + Some(parent_def_id(self, def_id)) + } + Def::Struct(def_id) | + Def::Union(def_id) | + Def::Enum(def_id) | + Def::TyAlias(def_id) | + Def::Trait(def_id) if i + 1 == proj_start => Some(def_id), + _ => None + }; + + let num_lifetimes = type_def_id.map_or(0, |def_id| { + if let Some(&n) = self.type_def_lifetime_params.get(&def_id) { + return n; + } + assert!(!def_id.is_local()); + let (n, _) = self.sess.cstore.item_generics_own_param_counts(def_id); + self.type_def_lifetime_params.insert(def_id, n); + n + }); + self.lower_path_segment(p.span, segment, param_mode, num_lifetimes) }).collect(), span: p.span, }); @@ -369,7 +487,8 @@ impl<'a> LoweringContext<'a> { // Otherwise, the base path is an implicit `Self` type path, // e.g. `Vec` in `Vec::new` or `::Item` in // `::Item::default`. - self.ty(p.span, hir::TyPath(hir::QPath::Resolved(qself, path))) + let new_id = self.next_id(); + self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)) }; // Anything after the base path are associated "extensions", @@ -383,7 +502,7 @@ impl<'a> LoweringContext<'a> { // 3. `<>::IntoIter>::Item` // * final path is `<<>::IntoIter>::Item>::clone` for (i, segment) in p.segments.iter().enumerate().skip(proj_start) { - let segment = P(self.lower_path_segment(segment, param_mode)); + let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0)); let qpath = hir::QPath::TypeRelative(ty, segment); // It's finished, return the extension of the right node type. @@ -392,7 +511,8 @@ impl<'a> LoweringContext<'a> { } // Wrap the associated extension in another type node. - ty = self.ty(p.span, hir::TyPath(qpath)); + let new_id = self.next_id(); + ty = self.ty_path(new_id, p.span, qpath); } // Should've returned in the for loop above. @@ -404,13 +524,18 @@ impl<'a> LoweringContext<'a> { id: NodeId, p: &Path, name: Option, - param_mode: ParamMode) + param_mode: ParamMode, + defaults_to_global: bool) -> hir::Path { + let mut segments = p.segments.iter(); + if defaults_to_global && p.is_global() { + segments.next(); + } + hir::Path { - global: p.global, def: self.expect_full_def(id), - segments: p.segments.iter().map(|segment| { - self.lower_path_segment(segment, param_mode) + segments: segments.map(|segment| { + self.lower_path_segment(p.span, segment, param_mode, 0) }).chain(name.map(|name| { hir::PathSegment { name: name, @@ -424,24 +549,41 @@ impl<'a> LoweringContext<'a> { fn lower_path(&mut self, id: NodeId, p: &Path, - param_mode: ParamMode) + param_mode: ParamMode, + defaults_to_global: bool) -> hir::Path { - self.lower_path_extra(id, p, None, param_mode) + self.lower_path_extra(id, p, None, param_mode, defaults_to_global) } fn lower_path_segment(&mut self, + path_span: Span, segment: &PathSegment, - param_mode: ParamMode) + param_mode: ParamMode, + expected_lifetimes: usize) -> hir::PathSegment { - let parameters = match segment.parameters { - PathParameters::AngleBracketed(ref data) => { - let data = self.lower_angle_bracketed_parameter_data(data, param_mode); - hir::AngleBracketedParameters(data) + let mut parameters = if let Some(ref parameters) = segment.parameters { + match **parameters { + PathParameters::AngleBracketed(ref data) => { + let data = self.lower_angle_bracketed_parameter_data(data, param_mode); + hir::AngleBracketedParameters(data) + } + PathParameters::Parenthesized(ref data) => { + hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)) + } } - PathParameters::Parenthesized(ref data) => - hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)), + } else { + let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode); + hir::AngleBracketedParameters(data) }; + if let hir::AngleBracketedParameters(ref mut data) = parameters { + if data.lifetimes.is_empty() { + data.lifetimes = (0..expected_lifetimes).map(|_| { + self.elided_lifetime(path_span) + }).collect(); + } + } + hir::PathSegment { name: segment.identifier.name, parameters: parameters, @@ -494,13 +636,24 @@ impl<'a> LoweringContext<'a> { hir::Arg { id: arg.id, pat: self.lower_pat(&arg.pat), - ty: self.lower_ty(&arg.ty), } } + fn lower_fn_args_to_names(&mut self, decl: &FnDecl) + -> hir::HirVec> { + decl.inputs.iter().map(|arg| { + match arg.pat.node { + PatKind::Ident(_, ident, None) => { + respan(ident.span, ident.node.name) + } + _ => respan(arg.pat.span, keywords::Invalid.name()), + } + }).collect() + } + fn lower_fn_decl(&mut self, decl: &FnDecl) -> P { P(hir::FnDecl { - inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(), + inputs: decl.inputs.iter().map(|arg| self.lower_ty(&arg.ty)).collect(), output: match decl.output { FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)), FunctionRetTy::Default(span) => hir::DefaultReturn(span), @@ -546,7 +699,7 @@ impl<'a> LoweringContext<'a> { } } - fn lower_ty_params(&mut self, tps: &P<[TyParam]>, add_bounds: &NodeMap>) + fn lower_ty_params(&mut self, tps: &Vec, add_bounds: &NodeMap>) -> hir::HirVec { tps.iter().map(|tp| { self.lower_ty_param(tp, add_bounds.get(&tp.id).map_or(&[][..], |x| &x)) @@ -577,10 +730,6 @@ impl<'a> LoweringContext<'a> { lts.iter().map(|l| self.lower_lifetime_def(l)).collect() } - fn lower_opt_lifetime(&mut self, o_lt: &Option) -> Option { - o_lt.as_ref().map(|lt| self.lower_lifetime(lt)) - } - fn lower_generics(&mut self, g: &Generics) -> hir::Generics { // Collect `?Trait` bounds in where clause and move them to parameter definitions. let mut add_bounds = NodeMap(); @@ -596,8 +745,8 @@ impl<'a> LoweringContext<'a> { // Check if the where clause type is a plain type parameter. match bound_pred.bounded_ty.node { TyKind::Path(None, ref path) - if !path.global && path.segments.len() == 1 && - bound_pred.bound_lifetimes.is_empty() => { + if path.segments.len() == 1 && + bound_pred.bound_lifetimes.is_empty() => { if let Some(Def::TyParam(def_id)) = self.resolver.get_resolution(bound_pred.bounded_ty.id) .map(|d| d.base_def) { @@ -666,13 +815,13 @@ impl<'a> LoweringContext<'a> { }) } WherePredicate::EqPredicate(WhereEqPredicate{ id, - ref path, - ref ty, + ref lhs_ty, + ref rhs_ty, span}) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { id: id, - path: self.lower_path(id, path, ParamMode::Explicit), - ty: self.lower_ty(ty), + lhs_ty: self.lower_ty(lhs_ty), + rhs_ty: self.lower_ty(rhs_ty), span: span, }) } @@ -700,8 +849,12 @@ impl<'a> LoweringContext<'a> { } fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef { + let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit) { + hir::QPath::Resolved(None, path) => path.and_then(|path| path), + qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath) + }; hir::TraitRef { - path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit), + path: path, ref_id: p.ref_id, } } @@ -794,7 +947,7 @@ impl<'a> LoweringContext<'a> { }; let mut path = self.lower_path_extra(import.id, path, suffix, - ParamMode::Explicit); + ParamMode::Explicit, true); path.span = span; self.items.insert(import.id, hir::Item { id: import.id, @@ -808,7 +961,7 @@ impl<'a> LoweringContext<'a> { path } }; - let path = P(self.lower_path(id, path, ParamMode::Explicit)); + let path = P(self.lower_path(id, path, ParamMode::Explicit, true)); let kind = match view_path.node { ViewPathSimple(ident, _) => { *name = ident.name; @@ -828,17 +981,20 @@ impl<'a> LoweringContext<'a> { hir::ItemUse(path, kind) } ItemKind::Static(ref t, m, ref e) => { + let value = self.lower_expr(e); hir::ItemStatic(self.lower_ty(t), self.lower_mutability(m), - P(self.lower_expr(e))) + self.record_body(value, None)) } ItemKind::Const(ref t, ref e) => { - hir::ItemConst(self.lower_ty(t), P(self.lower_expr(e))) + let value = self.lower_expr(e); + hir::ItemConst(self.lower_ty(t), + self.record_body(value, None)) } ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { let body = self.lower_block(body); let body = self.expr_block(body, ThinVec::new()); - let body_id = self.record_expr(body); + let body_id = self.record_body(body, Some(decl)); hir::ItemFn(self.lower_fn_decl(decl), self.lower_unsafety(unsafety), self.lower_constness(constness), @@ -886,7 +1042,7 @@ impl<'a> LoweringContext<'a> { } ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => { let bounds = self.lower_bounds(bounds); - let items = items.iter().map(|item| self.lower_trait_item(item)).collect(); + let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect(); hir::ItemTrait(self.lower_unsafety(unsafety), self.lower_generics(generics), bounds, @@ -904,20 +1060,27 @@ impl<'a> LoweringContext<'a> { attrs: this.lower_attrs(&i.attrs), node: match i.node { TraitItemKind::Const(ref ty, ref default) => { - hir::ConstTraitItem(this.lower_ty(ty), - default.as_ref().map(|x| P(this.lower_expr(x)))) - } - TraitItemKind::Method(ref sig, ref body) => { - hir::MethodTraitItem(this.lower_method_sig(sig), - body.as_ref().map(|x| { - let body = this.lower_block(x); - let expr = this.expr_block(body, ThinVec::new()); - this.record_expr(expr) + hir::TraitItemKind::Const(this.lower_ty(ty), + default.as_ref().map(|x| { + let value = this.lower_expr(x); + this.record_body(value, None) })) } + TraitItemKind::Method(ref sig, None) => { + let names = this.lower_fn_args_to_names(&sig.decl); + hir::TraitItemKind::Method(this.lower_method_sig(sig), + hir::TraitMethod::Required(names)) + } + TraitItemKind::Method(ref sig, Some(ref body)) => { + let body = this.lower_block(body); + let expr = this.expr_block(body, ThinVec::new()); + let body_id = this.record_body(expr, Some(&sig.decl)); + hir::TraitItemKind::Method(this.lower_method_sig(sig), + hir::TraitMethod::Provided(body_id)) + } TraitItemKind::Type(ref bounds, ref default) => { - hir::TypeTraitItem(this.lower_bounds(bounds), - default.as_ref().map(|x| this.lower_ty(x))) + hir::TraitItemKind::Type(this.lower_bounds(bounds), + default.as_ref().map(|x| this.lower_ty(x))) } TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"), }, @@ -926,6 +1089,30 @@ impl<'a> LoweringContext<'a> { }) } + fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef { + let (kind, has_default) = match i.node { + TraitItemKind::Const(_, ref default) => { + (hir::AssociatedItemKind::Const, default.is_some()) + } + TraitItemKind::Type(_, ref default) => { + (hir::AssociatedItemKind::Type, default.is_some()) + } + TraitItemKind::Method(ref sig, ref default) => { + (hir::AssociatedItemKind::Method { + has_self: sig.decl.has_self(), + }, default.is_some()) + } + TraitItemKind::Macro(..) => unimplemented!(), + }; + hir::TraitItemRef { + id: hir::TraitItemId { node_id: i.id }, + name: i.ident.name, + span: i.span, + defaultness: self.lower_defaultness(Defaultness::Default, has_default), + kind: kind, + } + } + fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { self.with_parent_def(i.id, |this| { hir::ImplItem { @@ -936,13 +1123,15 @@ impl<'a> LoweringContext<'a> { defaultness: this.lower_defaultness(i.defaultness, true /* [1] */), node: match i.node { ImplItemKind::Const(ref ty, ref expr) => { - hir::ImplItemKind::Const(this.lower_ty(ty), P(this.lower_expr(expr))) + let value = this.lower_expr(expr); + let body_id = this.record_body(value, None); + hir::ImplItemKind::Const(this.lower_ty(ty), body_id) } ImplItemKind::Method(ref sig, ref body) => { let body = this.lower_block(body); let expr = this.expr_block(body, ThinVec::new()); - let expr_id = this.record_expr(expr); - hir::ImplItemKind::Method(this.lower_method_sig(sig), expr_id) + let body_id = this.record_body(expr, Some(&sig.decl)); + hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id) } ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -965,7 +1154,7 @@ impl<'a> LoweringContext<'a> { ImplItemKind::Const(..) => hir::AssociatedItemKind::Const, ImplItemKind::Type(..) => hir::AssociatedItemKind::Type, ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method { - has_self: sig.decl.get_self().is_some(), + has_self: sig.decl.has_self(), }, ImplItemKind::Macro(..) => unimplemented!(), }, @@ -987,8 +1176,6 @@ impl<'a> LoweringContext<'a> { attrs: self.lower_attrs(&m.attrs), id: m.id, span: m.span, - imported_from: m.imported_from.map(|x| x.name), - allow_internal_unstable: m.allow_internal_unstable, body: m.body.clone().into(), } } @@ -1029,7 +1216,9 @@ impl<'a> LoweringContext<'a> { attrs: this.lower_attrs(&i.attrs), node: match i.node { ForeignItemKind::Fn(ref fdec, ref generics) => { - hir::ForeignItemFn(this.lower_fn_decl(fdec), this.lower_generics(generics)) + hir::ForeignItemFn(this.lower_fn_decl(fdec), + this.lower_fn_args_to_names(fdec), + this.lower_generics(generics)) } ForeignItemKind::Static(ref t, m) => { hir::ForeignItemStatic(this.lower_ty(t), m) @@ -1042,24 +1231,13 @@ impl<'a> LoweringContext<'a> { } fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { - let hir_sig = hir::MethodSig { + hir::MethodSig { generics: self.lower_generics(&sig.generics), abi: sig.abi, unsafety: self.lower_unsafety(sig.unsafety), constness: self.lower_constness(sig.constness), decl: self.lower_fn_decl(&sig.decl), - }; - // Check for `self: _` and `self: &_` - if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) { - match hir_sig.decl.get_self().map(|eself| eself.node) { - Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => { - self.diagnostic().span_err(sig.decl.inputs[0].ty.span, - "the type placeholder `_` is not allowed within types on item signatures"); - } - _ => {} - } } - hir_sig } fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety { @@ -1131,7 +1309,6 @@ impl<'a> LoweringContext<'a> { Some(def) => { hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path { span: pth1.span, - global: false, def: def, segments: hir_vec![ hir::PathSegment::from_name(pth1.node.name) @@ -1175,8 +1352,10 @@ impl<'a> LoweringContext<'a> { PatKind::Ref(ref inner, mutbl) => { hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl)) } - PatKind::Range(ref e1, ref e2) => { - hir::PatKind::Range(P(self.lower_expr(e1)), P(self.lower_expr(e2))) + PatKind::Range(ref e1, ref e2, ref end) => { + hir::PatKind::Range(P(self.lower_expr(e1)), + P(self.lower_expr(e2)), + self.lower_range_end(end)) } PatKind::Slice(ref before, ref slice, ref after) => { hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(), @@ -1189,6 +1368,13 @@ impl<'a> LoweringContext<'a> { }) } + fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd { + match *e { + RangeEnd::Included => hir::RangeEnd::Included, + RangeEnd::Excluded => hir::RangeEnd::Excluded, + } + } + fn lower_expr(&mut self, e: &Expr) -> hir::Expr { hir::Expr { id: e.id, @@ -1305,13 +1491,13 @@ impl<'a> LoweringContext<'a> { return self.expr_block(P(block), e.attrs.clone()); } - ExprKind::Vec(ref exprs) => { + ExprKind::Array(ref exprs) => { hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect()) } ExprKind::Repeat(ref expr, ref count) => { let expr = P(self.lower_expr(expr)); - let count = P(self.lower_expr(count)); - hir::ExprRepeat(expr, count) + let count = self.lower_expr(count); + hir::ExprRepeat(expr, self.record_body(count, None)) } ExprKind::Tup(ref elts) => { hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect()) @@ -1394,7 +1580,7 @@ impl<'a> LoweringContext<'a> { let expr = this.lower_expr(body); hir::ExprClosure(this.lower_capture_clause(capture_clause), this.lower_fn_decl(decl), - this.record_expr(expr), + this.record_body(expr, Some(decl)), fn_decl_span) }) } @@ -1678,13 +1864,7 @@ impl<'a> LoweringContext<'a> { // `::std::option::Option::Some() => ` let pat_arm = { let body_block = self.lower_block(body); - let body_span = body_block.span; - let body_expr = P(hir::Expr { - id: self.next_id(), - node: hir::ExprBlock(body_block), - span: body_span, - attrs: ThinVec::new(), - }); + let body_expr = P(self.expr_block(body_block, ThinVec::new())); let pat = self.lower_pat(pat); let some_pat = self.pat_some(e.span, pat); @@ -1763,8 +1943,9 @@ impl<'a> LoweringContext<'a> { // to: // // match Carrier::translate() { - // Ok(val) => val, - // Err(err) => return Carrier::from_error(From::from(err)) + // Ok(val) => #[allow(unreachable_code)] val, + // Err(err) => #[allow(unreachable_code)] + // return Carrier::from_error(From::from(err)), // } let unstable_span = self.allow_internal_unstable("?", e.span); @@ -1778,17 +1959,36 @@ impl<'a> LoweringContext<'a> { P(self.expr_call(e.span, path, hir_vec![sub_expr])) }; - // Ok(val) => val + // #[allow(unreachable_code)] + let attr = { + // allow(unreachable_code) + let allow = { + let allow_ident = self.str_to_ident("allow"); + let uc_ident = self.str_to_ident("unreachable_code"); + let uc_meta_item = attr::mk_spanned_word_item(e.span, uc_ident); + let uc_nested = NestedMetaItemKind::MetaItem(uc_meta_item); + let uc_spanned = respan(e.span, uc_nested); + attr::mk_spanned_list_item(e.span, allow_ident, vec![uc_spanned]) + }; + attr::mk_spanned_attr_outer(e.span, attr::mk_attr_id(), allow) + }; + let attrs = vec![attr]; + + // Ok(val) => #[allow(unreachable_code)] val, let ok_arm = { let val_ident = self.str_to_ident("val"); let val_pat = self.pat_ident(e.span, val_ident); - let val_expr = P(self.expr_ident(e.span, val_ident, val_pat.id)); + let val_expr = P(self.expr_ident_with_attrs(e.span, + val_ident, + val_pat.id, + ThinVec::from(attrs.clone()))); let ok_pat = self.pat_ok(e.span, val_pat); self.arm(hir_vec![ok_pat], val_expr) }; - // Err(err) => return Carrier::from_error(From::from(err)) + // Err(err) => #[allow(unreachable_code)] + // return Carrier::from_error(From::from(err)), let err_arm = { let err_ident = self.str_to_ident("err"); let err_local = self.pat_ident(e.span, err_ident); @@ -1808,7 +2008,7 @@ impl<'a> LoweringContext<'a> { let ret_expr = P(self.expr(e.span, hir::Expr_::ExprRet(Some(from_err_expr)), - ThinVec::new())); + ThinVec::from(attrs))); let err_pat = self.pat_err(e.span, err_local); self.arm(hir_vec![err_pat], ret_expr) @@ -1874,7 +2074,7 @@ impl<'a> LoweringContext<'a> { Visibility::Crate(_) => hir::Visibility::Crate, Visibility::Restricted { ref path, id } => { hir::Visibility::Restricted { - path: P(self.lower_path(id, path, ParamMode::Explicit)), + path: P(self.lower_path(id, path, ParamMode::Explicit, true)), id: id } } @@ -1960,6 +2160,13 @@ impl<'a> LoweringContext<'a> { } fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr { + self.expr_ident_with_attrs(span, id, binding, ThinVec::new()) + } + + fn expr_ident_with_attrs(&mut self, span: Span, + id: Name, + binding: NodeId, + attrs: ThinVec) -> hir::Expr { let def = { let defs = self.resolver.definitions(); Def::Local(defs.local_def_id(binding)) @@ -1967,12 +2174,11 @@ impl<'a> LoweringContext<'a> { let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path { span: span, - global: false, def: def, segments: hir_vec![hir::PathSegment::from_name(id)], }))); - self.expr(span, expr_path, ThinVec::new()) + self.expr(span, expr_path, attrs) } fn expr_mut_addr_of(&mut self, span: Span, e: P) -> hir::Expr { @@ -2135,17 +2341,12 @@ impl<'a> LoweringContext<'a> { /// `fld.cx.use_std`, and `::core::b::c::d` otherwise. /// The path is also resolved according to `is_value`. fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path { - let idents = self.crate_root.iter().chain(components); - - let segments: Vec<_> = idents.map(|name| { - hir::PathSegment::from_name(Symbol::intern(name)) - }).collect(); - let mut path = hir::Path { span: span, - global: true, def: Def::Err, - segments: segments.into(), + segments: iter::once(keywords::CrateRoot.name()).chain({ + self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern) + }).map(hir::PathSegment::from_name).collect(), }; self.resolver.resolve_hir_path(&mut path, is_value); @@ -2170,11 +2371,40 @@ impl<'a> LoweringContext<'a> { self.expr_block(block, attrs) } - fn ty(&mut self, span: Span, node: hir::Ty_) -> P { - P(hir::Ty { + fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P { + let mut id = id; + let node = match qpath { + hir::QPath::Resolved(None, path) => { + // Turn trait object paths into `TyTraitObject` instead. + if let Def::Trait(_) = path.def { + let principal = hir::PolyTraitRef { + bound_lifetimes: hir_vec![], + trait_ref: hir::TraitRef { + path: path.and_then(|path| path), + ref_id: id, + }, + span, + }; + + // The original ID is taken by the `PolyTraitRef`, + // so the `Ty` itself needs a different one. + id = self.next_id(); + + hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span)) + } else { + hir::TyPath(hir::QPath::Resolved(None, path)) + } + } + _ => hir::TyPath(qpath) + }; + P(hir::Ty { id, node, span }) + } + + fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime { + hir::Lifetime { id: self.next_id(), - node: node, span: span, - }) + name: keywords::Invalid.name() + } } } diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 068e7ed862..ff2f1dc1ba 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -38,22 +38,13 @@ use syntax_pos::Span; /// - The default implementation for a trait method. /// /// To construct one, use the `Code::from_node` function. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct FnLikeNode<'a> { node: map::Node<'a> } /// MaybeFnLike wraps a method that indicates if an object /// corresponds to some FnLikeNode. pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } -/// Components shared by fn-like things (fn items, methods, closures). -pub struct FnParts<'a> { - pub decl: &'a FnDecl, - pub body: ast::ExprId, - pub kind: FnKind<'a>, - pub span: Span, - pub id: NodeId, -} - impl MaybeFnLike for ast::Item { fn is_fn_like(&self) -> bool { match self.node { ast::ItemFn(..) => true, _ => false, } @@ -62,7 +53,10 @@ impl MaybeFnLike for ast::Item { impl MaybeFnLike for ast::TraitItem { fn is_fn_like(&self) -> bool { - match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, } + match self.node { + ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true, + _ => false, + } } } @@ -115,7 +109,7 @@ struct ItemFnParts<'a> { abi: abi::Abi, vis: &'a ast::Visibility, generics: &'a ast::Generics, - body: ast::ExprId, + body: ast::BodyId, id: NodeId, span: Span, attrs: &'a [Attribute], @@ -125,14 +119,14 @@ struct ItemFnParts<'a> { /// for use when implementing FnLikeNode operations. struct ClosureParts<'a> { decl: &'a FnDecl, - body: ast::ExprId, + body: ast::BodyId, id: NodeId, span: Span, attrs: &'a [Attribute], } impl<'a> ClosureParts<'a> { - fn new(d: &'a FnDecl, b: ast::ExprId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self { + fn new(d: &'a FnDecl, b: ast::BodyId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self { ClosureParts { decl: d, body: b, @@ -162,19 +156,9 @@ impl<'a> FnLikeNode<'a> { } } - pub fn to_fn_parts(self) -> FnParts<'a> { - FnParts { - decl: self.decl(), - body: self.body(), - kind: self.kind(), - span: self.span(), - id: self.id(), - } - } - - pub fn body(self) -> ast::ExprId { + pub fn body(self) -> ast::BodyId { self.handle(|i: ItemFnParts<'a>| i.body, - |_, _, _: &'a ast::MethodSig, _, body: ast::ExprId, _, _| body, + |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _| body, |c: ClosureParts<'a>| c.body) } @@ -227,7 +211,7 @@ impl<'a> FnLikeNode<'a> { Name, &'a ast::MethodSig, Option<&'a ast::Visibility>, - ast::ExprId, + ast::BodyId, Span, &'a [Attribute]) -> A, @@ -252,7 +236,7 @@ impl<'a> FnLikeNode<'a> { _ => bug!("item FnLikeNode that is not fn-like"), }, map::NodeTraitItem(ti) => match ti.node { - ast::MethodTraitItem(ref sig, Some(body)) => { + ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => { method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs) } _ => bug!("trait method FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index c46c8f044e..904f74b878 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -11,61 +11,34 @@ use super::*; use hir::intravisit::{Visitor, NestedVisitorMap}; -use hir::def_id::DefId; -use middle::cstore::InlinedItem; use std::iter::repeat; use syntax::ast::{NodeId, CRATE_NODE_ID}; use syntax_pos::Span; /// A Visitor that walks over the HIR and collects Nodes into a HIR map -pub struct NodeCollector<'ast> { +pub struct NodeCollector<'hir> { /// The crate - pub krate: &'ast Crate, + pub krate: &'hir Crate, /// The node map - pub map: Vec>, + pub(super) map: Vec>, /// The parent of this node pub parent_node: NodeId, - /// If true, completely ignore nested items. We set this when loading - /// HIR from metadata, since in that case we only want the HIR for - /// one specific item (and not the ones nested inside of it). - pub ignore_nested_items: bool } -impl<'ast> NodeCollector<'ast> { - pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> { +impl<'hir> NodeCollector<'hir> { + pub fn root(krate: &'hir Crate) -> NodeCollector<'hir> { let mut collector = NodeCollector { krate: krate, map: vec![], parent_node: CRATE_NODE_ID, - ignore_nested_items: false }; collector.insert_entry(CRATE_NODE_ID, RootCrate); collector } - pub fn extend(krate: &'ast Crate, - parent: &'ast InlinedItem, - parent_node: NodeId, - parent_def_path: DefPath, - parent_def_id: DefId, - map: Vec>) - -> NodeCollector<'ast> { - let mut collector = NodeCollector { - krate: krate, - map: map, - parent_node: parent_node, - ignore_nested_items: true - }; - - assert_eq!(parent_def_path.krate, parent_def_id.krate); - collector.insert_entry(parent_node, RootInlinedParent(parent)); - - collector - } - - fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) { - debug!("ast_map: {:?} => {:?}", id, entry); + fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'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)); @@ -73,7 +46,7 @@ impl<'ast> NodeCollector<'ast> { self.map[id.as_usize()] = entry; } - fn insert(&mut self, id: NodeId, node: Node<'ast>) { + fn insert(&mut self, id: NodeId, node: Node<'hir>) { let entry = MapEntry::from_node(self.parent_node, node); self.insert_entry(id, entry); } @@ -86,42 +59,39 @@ impl<'ast> NodeCollector<'ast> { } } -impl<'ast> Visitor<'ast> for NodeCollector<'ast> { +impl<'hir> Visitor<'hir> for NodeCollector<'hir> { /// Because we want to track parent items and so forth, enable /// deep walking so that we walk nested items in the context of /// their outer items. - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'ast> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { panic!("visit_nested_xxx must be manually implemented in this visitor") } fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); - if !self.ignore_nested_items { - self.visit_item(self.krate.item(item.id)) - } + self.visit_item(self.krate.item(item.id)); + } + + fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { + self.visit_trait_item(self.krate.trait_item(item_id)); } fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - self.visit_impl_item(self.krate.impl_item(item_id)) + self.visit_impl_item(self.krate.impl_item(item_id)); } - fn visit_body(&mut self, id: ExprId) { - self.visit_expr(self.krate.expr(id)) + fn visit_nested_body(&mut self, id: BodyId) { + self.visit_body(self.krate.body(id)); } - fn visit_item(&mut self, i: &'ast Item) { + fn visit_item(&mut self, i: &'hir Item) { debug!("visit_item: {:?}", i); self.insert(i.id, NodeItem(i)); self.with_parent(i.id, |this| { match i.node { - ItemEnum(ref enum_definition, _) => { - for v in &enum_definition.variants { - this.insert(v.node.data.id(), NodeVariant(v)); - } - } ItemStruct(ref struct_def, _) => { // If this is a tuple-like struct, register the constructor. if !struct_def.is_struct() { @@ -134,7 +104,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { + fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem) { self.insert(foreign_item.id, NodeForeignItem(foreign_item)); self.with_parent(foreign_item.id, |this| { @@ -142,7 +112,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_generics(&mut self, generics: &'ast Generics) { + fn visit_generics(&mut self, generics: &'hir Generics) { for ty_param in generics.ty_params.iter() { self.insert(ty_param.id, NodeTyParam(ty_param)); } @@ -150,7 +120,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { intravisit::walk_generics(self, generics); } - fn visit_trait_item(&mut self, ti: &'ast TraitItem) { + fn visit_trait_item(&mut self, ti: &'hir TraitItem) { self.insert(ti.id, NodeTraitItem(ti)); self.with_parent(ti.id, |this| { @@ -158,7 +128,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_impl_item(&mut self, ii: &'ast ImplItem) { + fn visit_impl_item(&mut self, ii: &'hir ImplItem) { self.insert(ii.id, NodeImplItem(ii)); self.with_parent(ii.id, |this| { @@ -166,7 +136,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_pat(&mut self, pat: &'ast Pat) { + fn visit_pat(&mut self, pat: &'hir Pat) { let node = if let PatKind::Binding(..) = pat.node { NodeLocal(pat) } else { @@ -179,7 +149,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_expr(&mut self, expr: &'ast Expr) { + fn visit_expr(&mut self, expr: &'hir Expr) { self.insert(expr.id, NodeExpr(expr)); self.with_parent(expr.id, |this| { @@ -187,7 +157,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_stmt(&mut self, stmt: &'ast Stmt) { + fn visit_stmt(&mut self, stmt: &'hir Stmt) { let id = stmt.node.id(); self.insert(id, NodeStmt(stmt)); @@ -196,7 +166,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_ty(&mut self, ty: &'ast Ty) { + fn visit_ty(&mut self, ty: &'hir Ty) { self.insert(ty.id, NodeTy(ty)); self.with_parent(ty.id, |this| { @@ -204,7 +174,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_trait_ref(&mut self, tr: &'ast TraitRef) { + fn visit_trait_ref(&mut self, tr: &'hir TraitRef) { self.insert(tr.ref_id, NodeTraitRef(tr)); self.with_parent(tr.ref_id, |this| { @@ -212,24 +182,24 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } - fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl, - b: ExprId, s: Span, id: NodeId) { + fn visit_fn(&mut self, fk: intravisit::FnKind<'hir>, fd: &'hir FnDecl, + b: BodyId, s: Span, id: NodeId) { assert_eq!(self.parent_node, id); intravisit::walk_fn(self, fk, fd, b, s, id); } - fn visit_block(&mut self, block: &'ast Block) { + fn visit_block(&mut self, block: &'hir Block) { self.insert(block.id, NodeBlock(block)); self.with_parent(block.id, |this| { intravisit::walk_block(this, block); }); } - fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) { + fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) { self.insert(lifetime.id, NodeLifetime(lifetime)); } - fn visit_vis(&mut self, visibility: &'ast Visibility) { + fn visit_vis(&mut self, visibility: &'hir Visibility) { match *visibility { Visibility::Public | Visibility::Crate | @@ -243,11 +213,19 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } } - fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) { + fn visit_macro_def(&mut self, macro_def: &'hir MacroDef) { self.insert_entry(macro_def.id, NotPresent); } - fn visit_struct_field(&mut self, field: &'ast StructField) { + 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.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.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 eb5a89f320..ccaf663c7a 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -9,23 +9,15 @@ // except according to those terms. use hir::map::definitions::*; - -use hir; -use hir::intravisit::{self, Visitor, NestedVisitorMap}; -use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; - -use middle::cstore::InlinedItem; +use hir::def_id::{CRATE_DEF_INDEX, DefIndex}; use syntax::ast::*; use syntax::ext::hygiene::Mark; use syntax::visit; use syntax::symbol::{Symbol, keywords}; -/// Creates def ids for nodes in the HIR. +/// Creates def ids for nodes in the AST. pub struct DefCollector<'a> { - // If we are walking HIR (c.f., AST), we need to keep a reference to the - // crate. - hir_crate: Option<&'a hir::Crate>, definitions: &'a mut Definitions, parent_def: Option, pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>, @@ -34,49 +26,22 @@ pub struct DefCollector<'a> { pub struct MacroInvocationData { pub mark: Mark, pub def_index: DefIndex, - pub const_integer: bool, + pub const_expr: bool, } impl<'a> DefCollector<'a> { pub fn new(definitions: &'a mut Definitions) -> Self { DefCollector { - hir_crate: None, definitions: definitions, parent_def: None, visit_macro_invoc: None, } } - pub fn extend(parent_node: NodeId, - parent_def_path: DefPath, - parent_def_id: DefId, - definitions: &'a mut Definitions) - -> Self { - let mut collector = DefCollector::new(definitions); - - assert_eq!(parent_def_path.krate, parent_def_id.krate); - let root_path = Box::new(InlinedRootPath { - data: parent_def_path.data, - def_id: parent_def_id, - }); - - let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path)); - collector.parent_def = Some(def); - - collector - } - pub fn collect_root(&mut self) { let root = self.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot); assert_eq!(root, CRATE_DEF_INDEX); self.parent_def = Some(root); - - self.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc); - } - - pub fn walk_item(&mut self, ii: &'a InlinedItem, krate: &'a hir::Crate) { - self.hir_crate = Some(krate); - ii.visit(self); } fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex { @@ -100,10 +65,10 @@ impl<'a> DefCollector<'a> { self.parent_def = parent; } - pub fn visit_ast_const_integer(&mut self, expr: &Expr) { + pub fn visit_const_expr(&mut self, expr: &Expr) { match expr.node { // Find the node which will be used after lowering. - ExprKind::Paren(ref inner) => return self.visit_ast_const_integer(inner), + ExprKind::Paren(ref inner) => return self.visit_const_expr(inner), ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, true), // FIXME(eddyb) Closures should have separate // function definition IDs and expression IDs. @@ -114,21 +79,11 @@ impl<'a> DefCollector<'a> { self.create_def(expr.id, DefPathData::Initializer); } - fn visit_hir_const_integer(&mut self, expr: &hir::Expr) { - // FIXME(eddyb) Closures should have separate - // function definition IDs and expression IDs. - if let hir::ExprClosure(..) = expr.node { - return; - } - - self.create_def(expr.id, DefPathData::Initializer); - } - - fn visit_macro_invoc(&mut self, id: NodeId, const_integer: bool) { + fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) { if let Some(ref mut visit) = self.visit_macro_invoc { visit(MacroInvocationData { mark: Mark::from_placeholder_id(id), - const_integer: const_integer, + const_expr: const_expr, def_index: self.parent_def.unwrap(), }) } @@ -187,7 +142,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } if let Some(ref expr) = v.node.disr_expr { - this.visit_ast_const_integer(expr); + this.visit_const_expr(expr); } }); } @@ -239,7 +194,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def = self.create_def(ti.id, def_data); self.with_parent(def, |this| { if let TraitItemKind::Const(_, Some(ref expr)) = ti.node { - this.create_def(expr.id, DefPathData::Initializer); + this.visit_const_expr(expr); } visit::walk_trait_item(this, ti); @@ -257,7 +212,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def = self.create_def(ii.id, def_data); self.with_parent(def, |this| { if let ImplItemKind::Const(_, ref expr) = ii.node { - this.create_def(expr.id, DefPathData::Initializer); + this.visit_const_expr(expr); } visit::walk_impl_item(this, ii); @@ -285,7 +240,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { match expr.node { ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false), - ExprKind::Repeat(_, ref count) => self.visit_ast_const_integer(count), + ExprKind::Repeat(_, ref count) => self.visit_const_expr(count), ExprKind::Closure(..) => { let def = self.create_def(expr.id, DefPathData::ClosureExpr); self.parent_def = Some(def); @@ -300,10 +255,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_ty(&mut self, ty: &'a Ty) { match ty.node { TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false), - TyKind::Array(_, ref length) => self.visit_ast_const_integer(length), + TyKind::Array(_, ref length) => self.visit_const_expr(length), TyKind::ImplTrait(..) => { self.create_def(ty.id, DefPathData::ImplTrait); } + TyKind::Typeof(ref expr) => self.visit_const_expr(expr), _ => {} } visit::walk_ty(self, ty); @@ -324,169 +280,3 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } } } - -// We walk the HIR rather than the AST when reading items from metadata. -impl<'ast> Visitor<'ast> for DefCollector<'ast> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'ast> { - // note however that we override `visit_body` below - NestedVisitorMap::None - } - - fn visit_body(&mut self, id: hir::ExprId) { - if let Some(krate) = self.hir_crate { - self.visit_expr(krate.expr(id)); - } - } - - fn visit_item(&mut self, i: &'ast hir::Item) { - debug!("visit_item: {:?}", i); - - // Pick the def data. This need not be unique, but the more - // information we encapsulate into - let def_data = match i.node { - hir::ItemDefaultImpl(..) | hir::ItemImpl(..) => - DefPathData::Impl, - hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) | - hir::ItemTrait(..) | hir::ItemExternCrate(..) | hir::ItemMod(..) | - hir::ItemForeignMod(..) | hir::ItemTy(..) => - DefPathData::TypeNs(i.name.as_str()), - hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => - DefPathData::ValueNs(i.name.as_str()), - hir::ItemUse(..) => DefPathData::Misc, - }; - let def = self.create_def(i.id, def_data); - - self.with_parent(def, |this| { - match i.node { - hir::ItemEnum(ref enum_definition, _) => { - for v in &enum_definition.variants { - let variant_def_index = - this.create_def(v.node.data.id(), - DefPathData::EnumVariant(v.node.name.as_str())); - - this.with_parent(variant_def_index, |this| { - for field in v.node.data.fields() { - this.create_def(field.id, - DefPathData::Field(field.name.as_str())); - } - if let Some(ref expr) = v.node.disr_expr { - this.visit_hir_const_integer(expr); - } - }); - } - } - hir::ItemStruct(ref struct_def, _) | - hir::ItemUnion(ref struct_def, _) => { - // If this is a tuple-like struct, register the constructor. - if !struct_def.is_struct() { - this.create_def(struct_def.id(), - DefPathData::StructCtor); - } - - for field in struct_def.fields() { - this.create_def(field.id, DefPathData::Field(field.name.as_str())); - } - } - _ => {} - } - intravisit::walk_item(this, i); - }); - } - - fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) { - let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.name.as_str())); - - self.with_parent(def, |this| { - intravisit::walk_foreign_item(this, foreign_item); - }); - } - - fn visit_generics(&mut self, generics: &'ast hir::Generics) { - for ty_param in generics.ty_params.iter() { - self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name.as_str())); - } - - intravisit::walk_generics(self, generics); - } - - fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) { - let def_data = match ti.node { - hir::MethodTraitItem(..) | hir::ConstTraitItem(..) => - DefPathData::ValueNs(ti.name.as_str()), - hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name.as_str()), - }; - - let def = self.create_def(ti.id, def_data); - self.with_parent(def, |this| { - if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node { - this.create_def(expr.id, DefPathData::Initializer); - } - - intravisit::walk_trait_item(this, ti); - }); - } - - fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) { - let def_data = match ii.node { - hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) => - DefPathData::ValueNs(ii.name.as_str()), - hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name.as_str()), - }; - - let def = self.create_def(ii.id, def_data); - self.with_parent(def, |this| { - if let hir::ImplItemKind::Const(_, ref expr) = ii.node { - this.create_def(expr.id, DefPathData::Initializer); - } - - intravisit::walk_impl_item(this, ii); - }); - } - - fn visit_pat(&mut self, pat: &'ast hir::Pat) { - let parent_def = self.parent_def; - - if let hir::PatKind::Binding(_, _, name, _) = pat.node { - let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str())); - self.parent_def = Some(def); - } - - intravisit::walk_pat(self, pat); - self.parent_def = parent_def; - } - - fn visit_expr(&mut self, expr: &'ast hir::Expr) { - let parent_def = self.parent_def; - - if let hir::ExprRepeat(_, ref count) = expr.node { - self.visit_hir_const_integer(count); - } - - if let hir::ExprClosure(..) = expr.node { - let def = self.create_def(expr.id, DefPathData::ClosureExpr); - self.parent_def = Some(def); - } - - intravisit::walk_expr(self, expr); - self.parent_def = parent_def; - } - - fn visit_ty(&mut self, ty: &'ast hir::Ty) { - if let hir::TyArray(_, ref length) = ty.node { - self.visit_hir_const_integer(length); - } - if let hir::TyImplTrait(..) = ty.node { - self.create_def(ty.id, DefPathData::ImplTrait); - } - intravisit::walk_ty(self, ty); - } - - fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) { - self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str())); - } - - fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) { - self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name.as_str())); - } -} diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index a684563512..b28c5e80ea 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -8,9 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! For each definition, we track the following data. A definition +//! here is defined somewhat circularly as "something with a def-id", +//! but it generally corresponds to things like structs, enums, etc. +//! There are also some rather random cases (like const initializer +//! expressions) that are mostly just leftovers. + use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; +use serialize::{Encodable, Decodable, Encoder, Decoder}; use std::fmt::Write; use std::hash::{Hash, Hasher}; use syntax::ast; @@ -18,12 +25,102 @@ use syntax::symbol::{Symbol, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; -/// The definition table containing node definitions +/// The DefPathTable maps DefIndexes to DefKeys and vice versa. +/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey +/// stores the DefIndex of its parent. +/// There is one DefPathTable for each crate. +#[derive(Clone)] +pub struct DefPathTable { + index_to_key: Vec, + key_to_index: FxHashMap, +} + +impl DefPathTable { + fn insert(&mut self, key: DefKey) -> DefIndex { + let index = DefIndex::new(self.index_to_key.len()); + debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index); + self.index_to_key.push(key.clone()); + self.key_to_index.insert(key, index); + index + } + + #[inline(always)] + pub fn def_key(&self, index: DefIndex) -> DefKey { + self.index_to_key[index.as_usize()].clone() + } + + #[inline(always)] + pub fn def_index_for_def_key(&self, key: &DefKey) -> Option { + self.key_to_index.get(key).cloned() + } + + #[inline(always)] + pub fn contains_key(&self, key: &DefKey) -> bool { + self.key_to_index.contains_key(key) + } + + pub fn retrace_path(&self, + path_data: &[DisambiguatedDefPathData]) + -> Option { + let root_key = DefKey { + parent: None, + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::CrateRoot, + disambiguator: 0, + }, + }; + + let root_index = self.key_to_index + .get(&root_key) + .expect("no root key?") + .clone(); + + debug!("retrace_path: root_index={:?}", root_index); + + let mut index = root_index; + for data in path_data { + let key = DefKey { parent: Some(index), disambiguated_data: data.clone() }; + debug!("retrace_path: key={:?}", key); + match self.key_to_index.get(&key) { + Some(&i) => index = i, + None => return None, + } + } + + Some(index) + } +} + + +impl Encodable for DefPathTable { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + self.index_to_key.encode(s) + } +} + +impl Decodable for DefPathTable { + fn decode(d: &mut D) -> Result { + let index_to_key: Vec = Decodable::decode(d)?; + let key_to_index = index_to_key.iter() + .enumerate() + .map(|(index, key)| (key.clone(), DefIndex::new(index))) + .collect(); + Ok(DefPathTable { + index_to_key: index_to_key, + key_to_index: key_to_index, + }) + } +} + + +/// The definition table containing node definitions. +/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a +/// mapping from NodeIds to local DefIds. #[derive(Clone)] pub struct Definitions { - data: Vec, - key_map: FxHashMap, - node_map: NodeMap, + table: DefPathTable, + node_to_def_index: NodeMap, + def_index_to_node: Vec, } /// A unique identifier that we can use to lookup a definition @@ -50,19 +147,6 @@ pub struct DisambiguatedDefPathData { pub disambiguator: u32 } -/// For each definition, we track the following data. A definition -/// here is defined somewhat circularly as "something with a def-id", -/// but it generally corresponds to things like structs, enums, etc. -/// There are also some rather random cases (like const initializer -/// expressions) that are mostly just leftovers. -#[derive(Clone, Debug)] -pub struct DefData { - pub key: DefKey, - - /// Local ID within the HIR. - pub node_id: ast::NodeId, -} - #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct DefPath { /// the path leading from the crate root to the item @@ -77,12 +161,11 @@ impl DefPath { self.krate == LOCAL_CRATE } - pub fn make(start_krate: CrateNum, + pub fn make(krate: CrateNum, start_index: DefIndex, mut get_key: FN) -> DefPath where FN: FnMut(DefIndex) -> DefKey { - let mut krate = start_krate; let mut data = vec![]; let mut index = Some(start_index); loop { @@ -95,13 +178,6 @@ impl DefPath { assert!(key.parent.is_none()); break; } - DefPathData::InlinedRoot(ref p) => { - assert!(key.parent.is_none()); - assert!(!p.def_id.is_local()); - data.extend(p.data.iter().cloned().rev()); - krate = p.def_id.krate; - break; - } _ => { data.push(key.disambiguated_data); index = key.parent; @@ -144,40 +220,12 @@ impl DefPath { } } -/// Root of an inlined item. We track the `DefPath` of the item within -/// the original crate but also its def-id. This is kind of an -/// augmented version of a `DefPath` that includes a `DefId`. This is -/// all sort of ugly but the hope is that inlined items will be going -/// away soon anyway. -/// -/// Some of the constraints that led to the current approach: -/// -/// - I don't want to have a `DefId` in the main `DefPath` because -/// that gets serialized for incr. comp., and when reloaded the -/// `DefId` is no longer valid. I'd rather maintain the invariant -/// that every `DefId` is valid, and a potentially outdated `DefId` is -/// represented as a `DefPath`. -/// - (We don't serialize def-paths from inlined items, so it's ok to have one here.) -/// - We need to be able to extract the def-id from inline items to -/// make the symbol name. In theory we could retrace it from the -/// data, but the metadata doesn't have the required indices, and I -/// don't want to write the code to create one just for this. -/// - It may be that we don't actually need `data` at all. We'll have -/// to see about that. -#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub struct InlinedRootPath { - pub data: Vec, - pub def_id: DefId, -} - #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum DefPathData { // Root: these should only be used for the root nodes, because // they are treated specially by the `def_path` function. /// The crate root (marker) CrateRoot, - /// An inlined root - InlinedRoot(Box), // Catch-all for random DefId things like DUMMY_NODE_ID Misc, @@ -219,23 +267,30 @@ impl Definitions { /// Create new empty definition map. pub fn new() -> Definitions { Definitions { - data: vec![], - key_map: FxHashMap(), - node_map: NodeMap(), + table: DefPathTable { + index_to_key: vec![], + key_to_index: FxHashMap(), + }, + node_to_def_index: NodeMap(), + def_index_to_node: vec![], } } + pub fn def_path_table(&self) -> &DefPathTable { + &self.table + } + /// Get the number of definitions. pub fn len(&self) -> usize { - self.data.len() + self.def_index_to_node.len() } pub fn def_key(&self, index: DefIndex) -> DefKey { - self.data[index.as_usize()].key.clone() + self.table.def_key(index) } pub fn def_index_for_def_key(&self, key: DefKey) -> Option { - self.key_map.get(&key).cloned() + self.table.def_index_for_def_key(&key) } /// Returns the path from the crate root to `index`. The root @@ -248,7 +303,7 @@ impl Definitions { } pub fn opt_def_index(&self, node: ast::NodeId) -> Option { - self.node_map.get(&node).cloned() + self.node_to_def_index.get(&node).cloned() } pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option { @@ -261,8 +316,8 @@ impl Definitions { pub fn as_local_node_id(&self, def_id: DefId) -> Option { if def_id.krate == LOCAL_CRATE { - assert!(def_id.index.as_usize() < self.data.len()); - Some(self.data[def_id.index.as_usize()].node_id) + assert!(def_id.index.as_usize() < self.def_index_to_node.len()); + Some(self.def_index_to_node[def_id.index.as_usize()]) } else { None } @@ -277,16 +332,13 @@ impl Definitions { debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", parent, node_id, data); - assert!(!self.node_map.contains_key(&node_id), + assert!(!self.node_to_def_index.contains_key(&node_id), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.data[self.node_map[&node_id].as_usize()]); + self.table.def_key(self.node_to_def_index[&node_id])); - assert!(parent.is_some() ^ match data { - DefPathData::CrateRoot | DefPathData::InlinedRoot(_) => true, - _ => false, - }); + assert_eq!(parent.is_some(), data != DefPathData::CrateRoot); // Find a unique DefKey. This basically means incrementing the disambiguator // until we get no match. @@ -298,20 +350,18 @@ impl Definitions { } }; - while self.key_map.contains_key(&key) { + while self.table.contains_key(&key) { key.disambiguated_data.disambiguator += 1; } debug!("create_def_with_parent: after disambiguation, key = {:?}", key); // Create the definition. - let index = DefIndex::new(self.data.len()); - self.data.push(DefData { key: key.clone(), node_id: node_id }); - debug!("create_def_with_parent: node_map[{:?}] = {:?}", node_id, index); - self.node_map.insert(node_id, index); - debug!("create_def_with_parent: key_map[{:?}] = {:?}", key, index); - self.key_map.insert(key, index); - + let index = self.table.insert(key); + debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); + self.node_to_def_index.insert(node_id, index); + assert_eq!(index.as_usize(), self.def_index_to_node.len()); + self.def_index_to_node.push(node_id); index } @@ -333,7 +383,6 @@ impl DefPathData { Impl | CrateRoot | - InlinedRoot(_) | Misc | ClosureExpr | StructCtor | @@ -360,9 +409,6 @@ impl DefPathData { // note that this does not show up in user printouts CrateRoot => "{{root}}", - // note that this does not show up in user printouts - InlinedRoot(_) => "{{inlined-root}}", - Impl => "{{impl}}", Misc => "{{?}}", ClosureExpr => "{{closure}}", diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 117edcf14a..9f31b5b456 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -13,11 +13,10 @@ use self::MapEntry::*; use self::collector::NodeCollector; pub use self::def_collector::{DefCollector, MacroInvocationData}; pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, - DisambiguatedDefPathData, InlinedRootPath}; + DisambiguatedDefPathData}; use dep_graph::{DepGraph, DepNode}; -use middle::cstore::InlinedItem; use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; use syntax::abi::Abi; @@ -26,12 +25,12 @@ use syntax::codemap::Spanned; use syntax_pos::Span; use hir::*; -use hir::print as pprust; +use hir::print::Nested; +use util::nodemap::DefIdMap; use arena::TypedArena; use std::cell::RefCell; use std::io; -use std::mem; pub mod blocks; mod collector; @@ -39,70 +38,67 @@ mod def_collector; pub mod definitions; #[derive(Copy, Clone, Debug)] -pub enum Node<'ast> { - NodeItem(&'ast Item), - NodeForeignItem(&'ast ForeignItem), - NodeTraitItem(&'ast TraitItem), - NodeImplItem(&'ast ImplItem), - NodeVariant(&'ast Variant), - NodeField(&'ast StructField), - NodeExpr(&'ast Expr), - NodeStmt(&'ast Stmt), - NodeTy(&'ast Ty), - NodeTraitRef(&'ast TraitRef), - NodeLocal(&'ast Pat), - NodePat(&'ast Pat), - NodeBlock(&'ast Block), +pub enum Node<'hir> { + NodeItem(&'hir Item), + NodeForeignItem(&'hir ForeignItem), + NodeTraitItem(&'hir TraitItem), + NodeImplItem(&'hir ImplItem), + NodeVariant(&'hir Variant), + NodeField(&'hir StructField), + NodeExpr(&'hir Expr), + NodeStmt(&'hir Stmt), + NodeTy(&'hir Ty), + NodeTraitRef(&'hir TraitRef), + NodeLocal(&'hir Pat), + NodePat(&'hir Pat), + NodeBlock(&'hir Block), /// NodeStructCtor represents a tuple struct. - NodeStructCtor(&'ast VariantData), + NodeStructCtor(&'hir VariantData), - NodeLifetime(&'ast Lifetime), - NodeTyParam(&'ast TyParam), - NodeVisibility(&'ast Visibility), - - NodeInlinedItem(&'ast InlinedItem), + NodeLifetime(&'hir Lifetime), + NodeTyParam(&'hir TyParam), + NodeVisibility(&'hir Visibility), } /// Represents an entry and its parent NodeID. /// The odd layout is to bring down the total size. #[derive(Copy, Debug)] -pub enum MapEntry<'ast> { +enum MapEntry<'hir> { /// Placeholder for holes in the map. NotPresent, /// All the node types, with a parent ID. - EntryItem(NodeId, &'ast Item), - EntryForeignItem(NodeId, &'ast ForeignItem), - EntryTraitItem(NodeId, &'ast TraitItem), - EntryImplItem(NodeId, &'ast ImplItem), - EntryVariant(NodeId, &'ast Variant), - EntryField(NodeId, &'ast StructField), - EntryExpr(NodeId, &'ast Expr), - EntryStmt(NodeId, &'ast Stmt), - EntryTy(NodeId, &'ast Ty), - EntryTraitRef(NodeId, &'ast TraitRef), - EntryLocal(NodeId, &'ast Pat), - EntryPat(NodeId, &'ast Pat), - EntryBlock(NodeId, &'ast Block), - EntryStructCtor(NodeId, &'ast VariantData), - EntryLifetime(NodeId, &'ast Lifetime), - EntryTyParam(NodeId, &'ast TyParam), - EntryVisibility(NodeId, &'ast Visibility), + EntryItem(NodeId, &'hir Item), + EntryForeignItem(NodeId, &'hir ForeignItem), + EntryTraitItem(NodeId, &'hir TraitItem), + EntryImplItem(NodeId, &'hir ImplItem), + EntryVariant(NodeId, &'hir Variant), + EntryField(NodeId, &'hir StructField), + EntryExpr(NodeId, &'hir Expr), + EntryStmt(NodeId, &'hir Stmt), + EntryTy(NodeId, &'hir Ty), + EntryTraitRef(NodeId, &'hir TraitRef), + EntryLocal(NodeId, &'hir Pat), + EntryPat(NodeId, &'hir Pat), + EntryBlock(NodeId, &'hir Block), + EntryStructCtor(NodeId, &'hir VariantData), + EntryLifetime(NodeId, &'hir Lifetime), + EntryTyParam(NodeId, &'hir TyParam), + EntryVisibility(NodeId, &'hir Visibility), /// Roots for node trees. RootCrate, - RootInlinedParent(&'ast InlinedItem) } -impl<'ast> Clone for MapEntry<'ast> { - fn clone(&self) -> MapEntry<'ast> { +impl<'hir> Clone for MapEntry<'hir> { + fn clone(&self) -> MapEntry<'hir> { *self } } -impl<'ast> MapEntry<'ast> { - fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> { +impl<'hir> MapEntry<'hir> { + fn from_node(p: NodeId, node: Node<'hir>) -> MapEntry<'hir> { match node { NodeItem(n) => EntryItem(p, n), NodeForeignItem(n) => EntryForeignItem(p, n), @@ -121,8 +117,6 @@ impl<'ast> MapEntry<'ast> { NodeLifetime(n) => EntryLifetime(p, n), NodeTyParam(n) => EntryTyParam(p, n), NodeVisibility(n) => EntryVisibility(p, n), - - NodeInlinedItem(n) => RootInlinedParent(n), } } @@ -147,12 +141,11 @@ impl<'ast> MapEntry<'ast> { EntryVisibility(id, _) => id, NotPresent | - RootCrate | - RootInlinedParent(_) => return None, + RootCrate => return None, }) } - fn to_node(self) -> Option> { + fn to_node(self) -> Option> { Some(match self { EntryItem(_, n) => NodeItem(n), EntryForeignItem(_, n) => NodeForeignItem(n), @@ -171,17 +164,56 @@ impl<'ast> MapEntry<'ast> { EntryLifetime(_, n) => NodeLifetime(n), EntryTyParam(_, n) => NodeTyParam(n), EntryVisibility(_, n) => NodeVisibility(n), - RootInlinedParent(n) => NodeInlinedItem(n), _ => return None }) } + + fn is_body_owner(self, node_id: NodeId) -> bool { + match self { + EntryItem(_, item) => { + match item.node { + ItemConst(_, body) | + ItemStatic(.., body) | + ItemFn(_, _, _, _, _, body) => body.node_id == node_id, + _ => false + } + } + + EntryTraitItem(_, item) => { + match item.node { + TraitItemKind::Const(_, Some(body)) | + TraitItemKind::Method(_, TraitMethod::Provided(body)) => { + body.node_id == node_id + } + _ => false + } + } + + EntryImplItem(_, item) => { + match item.node { + ImplItemKind::Const(_, body) | + ImplItemKind::Method(_, body) => body.node_id == node_id, + _ => false + } + } + + EntryExpr(_, expr) => { + match expr.node { + ExprClosure(.., body, _) => body.node_id == node_id, + _ => false + } + } + + _ => false + } + } } /// Stores a crate and any number of inlined items from other crates. pub struct Forest { krate: Crate, pub dep_graph: DepGraph, - inlined_items: TypedArena + inlined_bodies: TypedArena } impl Forest { @@ -189,11 +221,11 @@ impl Forest { Forest { krate: krate, dep_graph: dep_graph.clone(), - inlined_items: TypedArena::new() + inlined_bodies: TypedArena::new() } } - pub fn krate<'ast>(&'ast self) -> &'ast Crate { + pub fn krate<'hir>(&'hir self) -> &'hir Crate { self.dep_graph.read(DepNode::Krate); &self.krate } @@ -202,9 +234,9 @@ impl Forest { /// Represents a mapping from Node IDs to AST elements and their parent /// Node IDs #[derive(Clone)] -pub struct Map<'ast> { +pub struct Map<'hir> { /// The backing storage for all the AST nodes. - pub forest: &'ast Forest, + pub forest: &'hir Forest, /// Same as the dep_graph in forest, just available with one fewer /// deref. This is a gratuitious micro-optimization. @@ -219,28 +251,15 @@ pub struct Map<'ast> { /// /// Also, indexing is pretty quick when you've got a vector and /// plain old integers. - map: RefCell>>, - - definitions: RefCell, + map: Vec>, - /// All NodeIds that are numerically greater or equal to this value come - /// from inlined items. - local_node_id_watermark: NodeId, + definitions: Definitions, - /// All def-indices that are numerically greater or equal to this value come - /// from inlined items. - local_def_id_watermark: usize, + /// Bodies inlined from other crates are cached here. + inlined_bodies: RefCell>, } -impl<'ast> Map<'ast> { - pub fn is_inlined_def_id(&self, id: DefId) -> bool { - id.is_local() && id.index.as_usize() >= self.local_def_id_watermark - } - - pub fn is_inlined_node_id(&self, id: NodeId) -> bool { - id >= self.local_node_id_watermark - } - +impl<'hir> Map<'hir> { /// Registers a read in the dependency graph of the AST node with /// the given `id`. This needs to be called each time a public /// function returns the HIR for a node -- in other words, when it @@ -253,151 +272,86 @@ impl<'ast> Map<'ast> { } fn dep_node(&self, id0: NodeId) -> DepNode { - let map = self.map.borrow(); let mut id = id0; - if !self.is_inlined_node_id(id) { - let mut last_expr = None; - loop { - match map[id.as_usize()] { - EntryItem(_, item) => { - assert_eq!(id, item.id); - let def_id = self.local_def_id(id); - assert!(!self.is_inlined_def_id(def_id)); - - if let Some(last_id) = last_expr { - // The body of the item may have a separate dep node - // (Note that trait items don't currently have - // their own dep node, so there's also just one - // HirBody node for all the items) - if self.is_body(last_id, item) { - return DepNode::HirBody(def_id); - } + let mut last_expr = None; + loop { + let entry = self.map[id.as_usize()]; + match entry { + EntryItem(..) | + EntryTraitItem(..) | + EntryImplItem(..) => { + if let Some(last_id) = last_expr { + // The body may have a separate dep node + if entry.is_body_owner(last_id) { + let def_id = self.local_def_id(id); + return DepNode::HirBody(def_id); } - return DepNode::Hir(def_id); } + return DepNode::Hir(self.local_def_id(id)); + } - EntryImplItem(_, item) => { - let def_id = self.local_def_id(id); - assert!(!self.is_inlined_def_id(def_id)); + EntryVariant(p, v) => { + id = p; - if let Some(last_id) = last_expr { - // The body of the item may have a separate dep node - if self.is_impl_item_body(last_id, item) { - return DepNode::HirBody(def_id); - } + if last_expr.is_some() { + if v.node.disr_expr.map(|e| e.node_id) == last_expr { + // The enum parent holds both Hir and HirBody nodes. + let def_id = self.local_def_id(id); + return DepNode::HirBody(def_id); } - return DepNode::Hir(def_id); - } - - EntryForeignItem(p, _) | - EntryTraitItem(p, _) | - EntryVariant(p, _) | - EntryField(p, _) | - EntryStmt(p, _) | - EntryTy(p, _) | - EntryTraitRef(p, _) | - EntryLocal(p, _) | - EntryPat(p, _) | - EntryBlock(p, _) | - EntryStructCtor(p, _) | - EntryLifetime(p, _) | - EntryTyParam(p, _) | - EntryVisibility(p, _) => - id = p, - - EntryExpr(p, _) => { - last_expr = Some(id); - id = p; - } - - RootCrate => { - return DepNode::Hir(DefId::local(CRATE_DEF_INDEX)); } + } - RootInlinedParent(_) => - bug!("node {} has inlined ancestor but is not inlined", id0), - - NotPresent => - // Some nodes, notably struct fields, are not - // present in the map for whatever reason, but - // they *do* have def-ids. So if we encounter an - // empty hole, check for that case. - return self.opt_local_def_id(id) - .map(|def_id| DepNode::Hir(def_id)) - .unwrap_or_else(|| { - bug!("Walking parents from `{}` \ - led to `NotPresent` at `{}`", - id0, id) - }), + EntryForeignItem(p, _) | + EntryField(p, _) | + EntryStmt(p, _) | + EntryTy(p, _) | + EntryTraitRef(p, _) | + EntryLocal(p, _) | + EntryPat(p, _) | + EntryBlock(p, _) | + EntryStructCtor(p, _) | + EntryLifetime(p, _) | + EntryTyParam(p, _) | + EntryVisibility(p, _) => + id = p, + + EntryExpr(p, _) => { + last_expr = Some(id); + id = p; } - } - } else { - // reading from an inlined def-id is really a read out of - // the metadata from which we loaded the item. - loop { - match map[id.as_usize()] { - EntryItem(p, _) | - EntryForeignItem(p, _) | - EntryTraitItem(p, _) | - EntryImplItem(p, _) | - EntryVariant(p, _) | - EntryField(p, _) | - EntryExpr(p, _) | - EntryStmt(p, _) | - EntryTy(p, _) | - EntryTraitRef(p, _) | - EntryLocal(p, _) | - EntryPat(p, _) | - EntryBlock(p, _) | - EntryStructCtor(p, _) | - EntryLifetime(p, _) | - EntryTyParam(p, _) | - EntryVisibility(p, _) => - id = p, - - RootInlinedParent(parent) => - return DepNode::MetaData(parent.def_id), - - RootCrate => - bug!("node {} has crate ancestor but is inlined", id0), - - NotPresent => - bug!("node {} is inlined but not present in map", id0), + + RootCrate => { + return DepNode::Hir(DefId::local(CRATE_DEF_INDEX)); } - } - } - } - fn is_body(&self, node_id: NodeId, item: &Item) -> bool { - match item.node { - ItemFn(_, _, _, _, _, body) => body.node_id() == node_id, - // Since trait items currently don't get their own dep nodes, - // we check here whether node_id is the body of any of the items. - // If they get their own dep nodes, this can go away - ItemTrait(_, _, _, ref trait_items) => { - trait_items.iter().any(|trait_item| { match trait_item.node { - MethodTraitItem(_, Some(body)) => body.node_id() == node_id, - _ => false - }}) + NotPresent => + // Some nodes, notably macro definitions, are not + // present in the map for whatever reason, but + // they *do* have def-ids. So if we encounter an + // empty hole, check for that case. + return self.opt_local_def_id(id) + .map(|def_id| DepNode::Hir(def_id)) + .unwrap_or_else(|| { + bug!("Walking parents from `{}` \ + led to `NotPresent` at `{}`", + id0, id) + }), } - _ => false } } - fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool { - match item.node { - ImplItemKind::Method(_, body) => body.node_id() == node_id, - _ => false - } + pub fn num_local_def_ids(&self) -> usize { + self.definitions.len() } - pub fn num_local_def_ids(&self) -> usize { - self.definitions.borrow().len() + pub fn definitions(&self) -> &Definitions { + &self.definitions } pub fn def_key(&self, def_id: DefId) -> DefKey { assert!(def_id.is_local()); - self.definitions.borrow().def_key(def_id.index) + self.definitions.def_key(def_id.index) } pub fn def_path_from_id(&self, id: NodeId) -> Option { @@ -408,11 +362,11 @@ impl<'ast> Map<'ast> { pub fn def_path(&self, def_id: DefId) -> DefPath { assert!(def_id.is_local()); - self.definitions.borrow().def_path(def_id.index) + self.definitions.def_path(def_id.index) } pub fn def_index_for_def_key(&self, def_key: DefKey) -> Option { - self.definitions.borrow().def_index_for_def_key(def_key) + self.definitions.def_index_for_def_key(def_key) } pub fn local_def_id(&self, node: NodeId) -> DefId { @@ -423,26 +377,34 @@ impl<'ast> Map<'ast> { } pub fn opt_local_def_id(&self, node: NodeId) -> Option { - self.definitions.borrow().opt_local_def_id(node) + self.definitions.opt_local_def_id(node) } pub fn as_local_node_id(&self, def_id: DefId) -> Option { - self.definitions.borrow().as_local_node_id(def_id) + self.definitions.as_local_node_id(def_id) } fn entry_count(&self) -> usize { - self.map.borrow().len() + self.map.len() } - fn find_entry(&self, id: NodeId) -> Option> { - self.map.borrow().get(id.as_usize()).cloned() + fn find_entry(&self, id: NodeId) -> Option> { + self.map.get(id.as_usize()).cloned() } - pub fn krate(&self) -> &'ast Crate { + pub fn krate(&self) -> &'hir Crate { self.forest.krate() } - pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem { + pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem { + self.read(id.node_id); + + // NB: intentionally bypass `self.forest.krate()` so that we + // do not trigger a read of the whole krate here + self.forest.krate.trait_item(id) + } + + pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem { self.read(id.node_id); // NB: intentionally bypass `self.forest.krate()` so that we @@ -450,10 +412,35 @@ impl<'ast> Map<'ast> { self.forest.krate.impl_item(id) } + pub fn body(&self, id: BodyId) -> &'hir Body { + self.read(id.node_id); + + // NB: intentionally bypass `self.forest.krate()` so that we + // do not trigger a read of the whole krate here + self.forest.krate.body(id) + } + + /// Returns the `NodeId` that corresponds to the definition of + /// which this is the body of, i.e. a `fn`, `const` or `static` + /// item (possibly associated), or a closure, or the body itself + /// for embedded constant expressions (e.g. `N` in `[T; N]`). + pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId { + let parent = self.get_parent_node(node_id); + if self.map[parent.as_usize()].is_body_owner(node_id) { + parent + } else { + node_id + } + } + + pub fn body_owner_def_id(&self, id: BodyId) -> DefId { + self.local_def_id(self.body_owner(id)) + } + /// Get the attributes on the krate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. - pub fn krate_attrs(&self) -> &'ast [ast::Attribute] { + pub fn krate_attrs(&self) -> &'hir [ast::Attribute] { let crate_root_def_id = DefId::local(CRATE_DEF_INDEX); self.dep_graph.read(DepNode::Hir(crate_root_def_id)); &self.forest.krate.attrs @@ -461,20 +448,20 @@ impl<'ast> Map<'ast> { /// Retrieve the Node corresponding to `id`, panicking if it cannot /// be found. - pub fn get(&self, id: NodeId) -> Node<'ast> { + 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) } } - pub fn get_if_local(&self, id: DefId) -> Option> { + pub fn get_if_local(&self, id: DefId) -> Option> { self.as_local_node_id(id).map(|id| self.get(id)) // read recorded by `get` } /// Retrieve the Node corresponding to `id`, returning None if /// cannot be found. - pub fn find(&self, id: NodeId) -> Option> { + pub fn find(&self, id: NodeId) -> Option> { let result = self.find_entry(id).and_then(|x| x.to_node()); if result.is_some() { self.read(id); @@ -521,7 +508,7 @@ impl<'ast> Map<'ast> { /// is not an error, since items in the crate module have the crate root as /// parent. fn walk_parent_nodes(&self, start_id: NodeId, found: F) -> Result - where F: Fn(&Node<'ast>) -> bool + where F: Fn(&Node<'hir>) -> bool { let mut id = start_id; loop { @@ -600,11 +587,7 @@ impl<'ast> Map<'ast> { } pub fn get_parent_did(&self, id: NodeId) -> DefId { - let parent = self.get_parent(id); - match self.find_entry(parent) { - Some(RootInlinedParent(ii)) => ii.def_id, - _ => self.local_def_id(parent) - } + self.local_def_id(self.get_parent(id)) } pub fn get_foreign_abi(&self, id: NodeId) -> Abi { @@ -616,8 +599,6 @@ impl<'ast> Map<'ast> { _ => None } } - /// Wrong but OK, because the only inlined foreign items are intrinsics. - Some(RootInlinedParent(_)) => Some(Abi::RustIntrinsic), _ => None }; match abi { @@ -630,28 +611,28 @@ impl<'ast> Map<'ast> { } } - pub fn expect_item(&self, id: NodeId) -> &'ast Item { + pub fn expect_item(&self, id: NodeId) -> &'hir Item { match self.find(id) { // read recorded by `find` Some(NodeItem(item)) => item, _ => bug!("expected item, found {}", self.node_to_string(id)) } } - pub fn expect_impl_item(&self, id: NodeId) -> &'ast ImplItem { + pub fn expect_impl_item(&self, id: NodeId) -> &'hir ImplItem { match self.find(id) { Some(NodeImplItem(item)) => item, _ => bug!("expected impl item, found {}", self.node_to_string(id)) } } - pub fn expect_trait_item(&self, id: NodeId) -> &'ast TraitItem { + pub fn expect_trait_item(&self, id: NodeId) -> &'hir TraitItem { match self.find(id) { Some(NodeTraitItem(item)) => item, _ => bug!("expected trait item, found {}", self.node_to_string(id)) } } - pub fn expect_variant_data(&self, id: NodeId) -> &'ast VariantData { + pub fn expect_variant_data(&self, id: NodeId) -> &'hir VariantData { match self.find(id) { Some(NodeItem(i)) => { match i.node { @@ -672,36 +653,38 @@ impl<'ast> Map<'ast> { } } - pub fn expect_variant(&self, id: NodeId) -> &'ast Variant { + pub fn expect_variant(&self, id: NodeId) -> &'hir Variant { match self.find(id) { Some(NodeVariant(variant)) => variant, _ => bug!("expected variant, found {}", self.node_to_string(id)), } } - pub fn expect_foreign_item(&self, id: NodeId) -> &'ast ForeignItem { + pub fn expect_foreign_item(&self, id: NodeId) -> &'hir ForeignItem { match self.find(id) { Some(NodeForeignItem(item)) => item, _ => bug!("expected foreign item, found {}", self.node_to_string(id)) } } - pub fn expect_expr(&self, id: NodeId) -> &'ast Expr { + pub fn expect_expr(&self, id: NodeId) -> &'hir Expr { match self.find(id) { // read recorded by find Some(NodeExpr(expr)) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)) } } - pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem { - match self.find_entry(id) { - Some(RootInlinedParent(inlined_item)) => inlined_item, - _ => bug!("expected inlined item, found {}", self.node_to_string(id)), - } + pub fn get_inlined_body(&self, def_id: DefId) -> Option<&'hir Body> { + self.inlined_bodies.borrow().get(&def_id).map(|&body| { + self.dep_graph.read(DepNode::MetaData(def_id)); + body + }) } - pub fn expr(&self, id: ExprId) -> &'ast Expr { - self.expect_expr(id.node_id()) + pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'hir Body { + let body = self.forest.inlined_bodies.alloc(body); + self.inlined_bodies.borrow_mut().insert(def_id, body); + body } /// Returns the name associated with the given NodeId's AST. @@ -723,7 +706,7 @@ impl<'ast> Map<'ast> { /// Given a node ID, get a list of attributes associated with the AST /// corresponding to the Node ID - pub fn attrs(&self, id: NodeId) -> &'ast [ast::Attribute] { + 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[..]), @@ -752,7 +735,7 @@ impl<'ast> Map<'ast> { /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and /// any other such items it can find in the map. pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) - -> NodesMatchingSuffix<'a, 'ast> { + -> NodesMatchingSuffix<'a, 'hir> { NodesMatchingSuffix { map: self, item_name: parts.last().unwrap(), @@ -784,7 +767,6 @@ impl<'ast> Map<'ast> { Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v), Some(RootCrate) => self.forest.krate.span, - Some(RootInlinedParent(parent)) => parent.body.span, Some(NotPresent) | None => { bug!("hir::map::Map::span: id not in map: {:?}", id) } @@ -802,16 +784,20 @@ impl<'ast> Map<'ast> { pub fn node_to_user_string(&self, id: NodeId) -> String { node_id_to_string(self, id, false) } + + pub fn node_to_pretty_string(&self, id: NodeId) -> String { + print::to_string(self, |s| s.print_node(self.get(id))) + } } -pub struct NodesMatchingSuffix<'a, 'ast:'a> { - map: &'a Map<'ast>, +pub struct NodesMatchingSuffix<'a, 'hir:'a> { + map: &'a Map<'hir>, item_name: &'a String, in_which: &'a [String], idx: NodeId, } -impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> { +impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { /// Returns true only if some suffix of the module path for parent /// matches `self.in_which`. /// @@ -867,7 +853,7 @@ impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> { } } -impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> { +impl<'a, 'hir> Iterator for NodesMatchingSuffix<'a, 'hir> { type Item = NodeId; fn next(&mut self) -> Option { @@ -906,9 +892,9 @@ impl Named for StructField { fn name(&self) -> Name { self.name } } impl Named for TraitItem { fn name(&self) -> Name { self.name } } impl Named for ImplItem { fn name(&self) -> Name { self.name } } -pub fn map_crate<'ast>(forest: &'ast mut Forest, +pub fn map_crate<'hir>(forest: &'hir mut Forest, definitions: Definitions) - -> Map<'ast> { + -> Map<'hir> { let mut collector = NodeCollector::root(&forest.krate); intravisit::walk_crate(&mut collector, &forest.krate); let map = collector.map; @@ -929,57 +915,32 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, entries, vector_length, (entries as f64 / vector_length as f64) * 100.); } - let local_node_id_watermark = NodeId::new(map.len()); - let local_def_id_watermark = definitions.len(); - Map { forest: forest, dep_graph: forest.dep_graph.clone(), - map: RefCell::new(map), - definitions: RefCell::new(definitions), - local_node_id_watermark: local_node_id_watermark, - local_def_id_watermark: local_def_id_watermark, + map: map, + definitions: definitions, + inlined_bodies: RefCell::new(DefIdMap()), } } -/// Used for items loaded from external crate that are being inlined into this -/// crate. -pub fn map_decoded_item<'ast>(map: &Map<'ast>, - parent_def_path: DefPath, - parent_def_id: DefId, - ii: InlinedItem, - ii_parent_id: NodeId) - -> &'ast InlinedItem { - let _ignore = map.forest.dep_graph.in_ignore(); - - let ii = map.forest.inlined_items.alloc(ii); - - let defs = &mut *map.definitions.borrow_mut(); - let mut def_collector = DefCollector::extend(ii_parent_id, - parent_def_path.clone(), - parent_def_id, - defs); - def_collector.walk_item(ii, map.krate()); - - let mut collector = NodeCollector::extend(map.krate(), - ii, - ii_parent_id, - parent_def_path, - parent_def_id, - mem::replace(&mut *map.map.borrow_mut(), vec![])); - ii.visit(&mut collector); - *map.map.borrow_mut() = collector.map; - - ii -} - -pub trait NodePrinter { - fn print_node(&mut self, node: &Node) -> io::Result<()>; +/// Identical to the `PpAnn` implementation for `hir::Crate`, +/// except it avoids creating a dependency on the whole crate. +impl<'hir> print::PpAnn for Map<'hir> { + fn nested(&self, state: &mut print::State, nested: print::Nested) -> io::Result<()> { + match nested { + Nested::Item(id) => state.print_item(self.expect_item(id.id)), + Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), + Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), + Nested::Body(id) => state.print_expr(&self.body(id).value), + Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat) + } + } } -impl<'a> NodePrinter for pprust::State<'a> { - fn print_node(&mut self, node: &Node) -> io::Result<()> { - match *node { +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), @@ -989,19 +950,25 @@ impl<'a> NodePrinter for pprust::State<'a> { NodeStmt(a) => self.print_stmt(&a), NodeTy(a) => self.print_type(&a), NodeTraitRef(a) => self.print_trait_ref(&a), + NodeLocal(a) | NodePat(a) => self.print_pat(&a), - NodeBlock(a) => self.print_block(&a), + NodeBlock(a) => { + use syntax::print::pprust::PrintState; + + // containing cbox, will be closed by print-block at } + self.cbox(print::indent_unit)?; + // head-ibox, will be closed by print-block after { + self.ibox(0)?; + self.print_block(&a) + } NodeLifetime(a) => self.print_lifetime(&a), NodeVisibility(a) => self.print_visibility(&a), NodeTyParam(_) => bug!("cannot print TyParam"), NodeField(_) => bug!("cannot print StructField"), // these cases do not carry enough information in the - // ast_map to reconstruct their full structure for pretty + // hir_map to reconstruct their full structure for pretty // printing. - NodeLocal(_) => bug!("cannot print isolated Local"), NodeStructCtor(_) => bug!("cannot print isolated StructCtor"), - - NodeInlinedItem(_) => bug!("cannot print inlined item"), } } } @@ -1064,9 +1031,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { } Some(NodeTraitItem(ti)) => { let kind = match ti.node { - ConstTraitItem(..) => "assoc constant", - MethodTraitItem(..) => "trait method", - TypeTraitItem(..) => "assoc type", + TraitItemKind::Const(..) => "assoc constant", + TraitItemKind::Method(..) => "trait method", + TraitItemKind::Type(..) => "assoc type", }; format!("{} {} in {}{}", kind, ti.name, path_str(), id_str) @@ -1081,33 +1048,32 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { field.name, path_str(), id_str) } - Some(NodeExpr(ref expr)) => { - format!("expr {}{}", pprust::expr_to_string(&expr), id_str) + Some(NodeExpr(_)) => { + format!("expr {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeStmt(ref stmt)) => { - format!("stmt {}{}", pprust::stmt_to_string(&stmt), id_str) + Some(NodeStmt(_)) => { + format!("stmt {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeTy(ref ty)) => { - format!("type {}{}", pprust::ty_to_string(&ty), id_str) + Some(NodeTy(_)) => { + format!("type {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeTraitRef(ref tr)) => { - format!("trait_ref {}{}", pprust::path_to_string(&tr.path), id_str) + Some(NodeTraitRef(_)) => { + format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeLocal(ref pat)) => { - format!("local {}{}", pprust::pat_to_string(&pat), id_str) + Some(NodeLocal(_)) => { + format!("local {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodePat(ref pat)) => { - format!("pat {}{}", pprust::pat_to_string(&pat), id_str) + Some(NodePat(_)) => { + format!("pat {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeBlock(ref block)) => { - format!("block {}{}", pprust::block_to_string(&block), id_str) + Some(NodeBlock(_)) => { + format!("block {}{}", map.node_to_pretty_string(id), id_str) } Some(NodeStructCtor(_)) => { format!("struct_ctor {}{}", path_str(), id_str) } - Some(NodeLifetime(ref l)) => { - format!("lifetime {}{}", - pprust::lifetime_to_string(&l), id_str) + Some(NodeLifetime(_)) => { + format!("lifetime {}{}", map.node_to_pretty_string(id), id_str) } Some(NodeTyParam(ref ty_param)) => { format!("typaram {:?}{}", ty_param, id_str) @@ -1115,9 +1081,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeVisibility(ref vis)) => { format!("visibility {:?}{}", vis, id_str) } - Some(NodeInlinedItem(_)) => { - format!("inlined item {}", id_str) - } None => { format!("unknown node{}", id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 4fd8f96ba0..4ebe416e1b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -22,7 +22,6 @@ pub use self::Item_::*; pub use self::Mutability::*; pub use self::PrimTy::*; pub use self::Stmt_::*; -pub use self::TraitItem_::*; pub use self::Ty_::*; pub use self::TyParamBound::*; pub use self::UnOp::*; @@ -32,11 +31,10 @@ pub use self::PathParameters::*; use hir::def::Def; use hir::def_id::DefId; -use util::nodemap::{NodeMap, FxHashSet}; -use rustc_data_structures::fnv::FnvHashMap; +use util::nodemap::{NodeMap, FxHashMap, FxHashSet}; -use syntax_pos::{mk_sp, Span, ExpnId, DUMMY_SP}; -use syntax::codemap::{self, respan, Spanned}; +use syntax_pos::{Span, ExpnId, DUMMY_SP}; +use syntax::codemap::{self, Spanned}; use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; @@ -79,6 +77,13 @@ pub mod svh; pub struct Lifetime { pub id: NodeId, pub span: Span, + + /// Either "'a", referring to a named lifetime definition, + /// or "" (aka keywords::Invalid), for elision placeholders. + /// + /// HIR lowering inserts these placeholders in type paths that + /// refer to type definitions needing lifetime parameters, + /// `&T` and `&mut T`, and trait objects without `... + 'a`. pub name: Name, } @@ -87,7 +92,13 @@ impl fmt::Debug for Lifetime { write!(f, "lifetime({}: {})", self.id, - print::lifetime_to_string(self)) + print::to_string(print::NO_ANN, |s| s.print_lifetime(self))) + } +} + +impl Lifetime { + pub fn is_elided(&self) -> bool { + self.name == keywords::Invalid.name() } } @@ -105,24 +116,22 @@ pub struct LifetimeDef { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct Path { pub span: Span, - /// A `::foo` path, is relative to the crate root rather than current - /// module (like paths in an import). - pub global: bool, /// The definition that the path resolved to. pub def: Def, /// The segments in the path: the things separated by `::`. pub segments: HirVec, } -impl fmt::Debug for Path { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "path({})", print::path_to_string(self)) +impl Path { + pub fn is_global(&self) -> bool { + !self.segments.is_empty() && self.segments[0].name == keywords::CrateRoot.name() } } -impl fmt::Display for Path { +impl fmt::Debug for Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", print::path_to_string(self)) + write!(f, "path({})", + print::to_string(print::NO_ANN, |s| s.print_path(self, false))) } } @@ -169,30 +178,6 @@ impl PathParameters { }) } - pub fn is_empty(&self) -> bool { - match *self { - AngleBracketedParameters(ref data) => data.is_empty(), - - // Even if the user supplied no types, something like - // `X()` is equivalent to `X<(),()>`. - ParenthesizedParameters(..) => false, - } - } - - pub fn has_lifetimes(&self) -> bool { - match *self { - AngleBracketedParameters(ref data) => !data.lifetimes.is_empty(), - ParenthesizedParameters(_) => false, - } - } - - pub fn has_types(&self) -> bool { - match *self { - AngleBracketedParameters(ref data) => !data.types.is_empty(), - ParenthesizedParameters(..) => true, - } - } - /// Returns the types that the user wrote. Note that these do not necessarily map to the type /// parameters in the parenthesized case. pub fn types(&self) -> HirVec<&P> { @@ -249,12 +234,6 @@ pub struct AngleBracketedParameterData { pub bindings: HirVec, } -impl AngleBracketedParameterData { - fn is_empty(&self) -> bool { - self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty() - } -} - /// A path like `Foo(A,B) -> C` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct ParenthesizedParameterData { @@ -407,8 +386,8 @@ pub struct WhereRegionPredicate { pub struct WhereEqPredicate { pub id: NodeId, pub span: Span, - pub path: Path, - pub ty: P, + pub lhs_ty: P, + pub rhs_ty: P, } pub type CrateConfig = HirVec>; @@ -428,8 +407,9 @@ pub struct Crate { // slightly different results. pub items: BTreeMap, + pub trait_items: BTreeMap, pub impl_items: BTreeMap, - pub exprs: FnvHashMap, + pub bodies: FxHashMap, } impl Crate { @@ -437,6 +417,10 @@ impl Crate { &self.items[&id] } + pub fn trait_item(&self, id: TraitItemId) -> &TraitItem { + &self.trait_items[&id] + } + pub fn impl_item(&self, id: ImplItemId) -> &ImplItem { &self.impl_items[&id] } @@ -456,13 +440,17 @@ impl Crate { visitor.visit_item(item); } + for (_, trait_item) in &self.trait_items { + visitor.visit_trait_item(trait_item); + } + for (_, impl_item) in &self.impl_items { visitor.visit_impl_item(impl_item); } } - pub fn expr(&self, id: ExprId) -> &Expr { - &self.exprs[&id] + pub fn body(&self, id: BodyId) -> &Body { + &self.bodies[&id] } } @@ -475,8 +463,6 @@ pub struct MacroDef { pub attrs: HirVec, pub id: NodeId, pub span: Span, - pub imported_from: Option, - pub allow_internal_unstable: bool, pub body: HirVec, } @@ -502,7 +488,8 @@ pub struct Pat { impl fmt::Debug for Pat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "pat({}: {})", self.id, print::pat_to_string(self)) + write!(f, "pat({}: {})", self.id, + print::to_string(print::NO_ANN, |s| s.print_pat(self))) } } @@ -568,6 +555,12 @@ pub enum BindingMode { BindByValue(Mutability), } +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum RangeEnd { + Included, + Excluded, +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum PatKind { /// Represents a wildcard pattern (`_`) @@ -599,8 +592,8 @@ pub enum PatKind { Ref(P, Mutability), /// A literal Lit(P), - /// A range pattern, e.g. `1...2` - Range(P, P), + /// A range pattern, e.g. `1...2` or `1..2` + Range(P, P, RangeEnd), /// `[a, b, ..i, y, z]` is represented as: /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` Slice(HirVec>, Option>, HirVec>), @@ -754,7 +747,7 @@ impl fmt::Debug for Stmt_ { write!(f, "stmt({}: {})", spanned.node.id(), - print::stmt_to_string(&spanned)) + print::to_string(print::NO_ANN, |s| s.print_stmt(&spanned))) } } @@ -852,12 +845,23 @@ pub enum UnsafeSource { UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ExprId(NodeId); +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct BodyId { + pub node_id: NodeId, +} + +/// The body of a function or constant value. +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct Body { + pub arguments: HirVec, + pub value: Expr +} -impl ExprId { - pub fn node_id(self) -> NodeId { - self.0 +impl Body { + pub fn id(&self) -> BodyId { + BodyId { + node_id: self.value.id + } } } @@ -870,15 +874,10 @@ pub struct Expr { pub attrs: ThinVec, } -impl Expr { - pub fn expr_id(&self) -> ExprId { - ExprId(self.id) - } -} - impl fmt::Debug for Expr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "expr({}: {})", self.id, print::expr_to_string(self)) + write!(f, "expr({}: {})", self.id, + print::to_string(print::NO_ANN, |s| s.print_expr(self))) } } @@ -935,7 +934,7 @@ pub enum Expr_ { /// A closure (for example, `move |a, b, c| {a + b + c}`). /// /// The final span is the span of the argument block `|...|` - ExprClosure(CaptureClause, P, ExprId, Span), + ExprClosure(CaptureClause, P, BodyId, Span), /// A block (`{ ... }`) ExprBlock(P), @@ -979,7 +978,7 @@ pub enum Expr_ { /// /// For example, `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - ExprRepeat(P, P), + ExprRepeat(P, BodyId), } /// Optionally `Self`-qualified value/type path or associated extension. @@ -998,16 +997,10 @@ pub enum QPath { /// /// UFCS source paths can desugar into this, with `Vec::new` turning into /// `::new`, and `T::X::Y::method` into `<<::X>::Y>::method`, - /// the `X` and `Y` nodes being each a `TyPath(QPath::TypeRelative(..))`. + /// the `X` and `Y` nodes each being a `TyPath(QPath::TypeRelative(..))`. TypeRelative(P, P) } -impl fmt::Display for QPath { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", print::qpath_to_string(self)) - } -} - /// Hints at the original code for a `match _ { .. }` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum MatchSource { @@ -1069,6 +1062,14 @@ pub struct MethodSig { pub generics: Generics, } +// The bodies for items are stored "out of line", in a separate +// hashmap in the `Crate`. Here we just record the node-id of the item +// so it can fetched later. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct TraitItemId { + pub node_id: NodeId, +} + /// Represents an item declaration within a trait declaration, /// possibly including a default implementation. A trait item is /// either required (meaning it doesn't have an implementation, just a @@ -1078,21 +1079,31 @@ pub struct TraitItem { pub id: NodeId, pub name: Name, pub attrs: HirVec, - pub node: TraitItem_, + pub node: TraitItemKind, pub span: Span, } +/// A trait method's body (or just argument names). +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum TraitMethod { + /// No default body in the trait, just a signature. + Required(HirVec>), + + /// Both signature and body are provided in the trait. + Provided(BodyId), +} + /// Represents a trait method or associated constant or type #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TraitItem_ { +pub enum TraitItemKind { /// An associated constant with an optional value (otherwise `impl`s /// must contain a value) - ConstTraitItem(P, Option>), + Const(P, Option), /// A method with an optional body - MethodTraitItem(MethodSig, Option), + Method(MethodSig, TraitMethod), /// An associated type with (possibly empty) bounds and optional concrete /// type - TypeTraitItem(TyParamBounds, Option>), + Type(TyParamBounds, Option>), } // The bodies for items are stored "out of line", in a separate @@ -1120,9 +1131,9 @@ pub struct ImplItem { pub enum ImplItemKind { /// An associated constant of the given type, set to the constant result /// of the expression - Const(P, P), + Const(P, BodyId), /// A method implementation with the given signature and body - Method(MethodSig, ExprId), + Method(MethodSig, BodyId), /// An associated type Type(P), } @@ -1146,7 +1157,8 @@ pub struct Ty { impl fmt::Debug for Ty { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "type({})", print::ty_to_string(self)) + write!(f, "type({})", + print::to_string(print::NO_ANN, |s| s.print_type(self))) } } @@ -1175,11 +1187,11 @@ pub enum Ty_ { /// A variable length slice (`[T]`) TySlice(P), /// A fixed length array (`[T; n]`) - TyArray(P, P), + TyArray(P, BodyId), /// A raw pointer (`*const T` or `*mut T`) TyPtr(MutTy), /// A reference (`&'a T` or `&'a mut T`) - TyRptr(Option, MutTy), + TyRptr(Lifetime, MutTy), /// A bare function (e.g. `fn(usize) -> bool`) TyBareFn(P), /// The never type (`!`) @@ -1191,15 +1203,14 @@ pub enum Ty_ { /// /// Type parameters may be stored in each `PathSegment`. TyPath(QPath), - - /// Something like `A+B`. Note that `B` must always be a path. - TyObjectSum(P, TyParamBounds), - /// A type like `for<'a> Foo<&'a Bar>` - TyPolyTraitRef(TyParamBounds), - /// An `impl TraitA+TraitB` type. + /// A trait object type `Bound1 + Bound2 + Bound3` + /// where `Bound` is a trait or a lifetime. + TyTraitObject(HirVec, Lifetime), + /// An `impl Bound1 + Bound2 + Bound3` type + /// where `Bound` is a trait or a lifetime. TyImplTrait(TyParamBounds), /// Unused for now - TyTypeof(P), + TyTypeof(BodyId), /// TyInfer means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. TyInfer, @@ -1228,67 +1239,18 @@ pub struct InlineAsm { /// represents an argument in a function header #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Arg { - pub ty: P, pub pat: P, pub id: NodeId, } -/// Alternative representation for `Arg`s describing `self` parameter of methods. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum SelfKind { - /// `self`, `mut self` - Value(Mutability), - /// `&'lt self`, `&'lt mut self` - Region(Option, Mutability), - /// `self: TYPE`, `mut self: TYPE` - Explicit(P, Mutability), -} - -pub type ExplicitSelf = Spanned; - -impl Arg { - pub fn to_self(&self) -> Option { - if let PatKind::Binding(BindByValue(mutbl), _, name, _) = self.pat.node { - if name.node == keywords::SelfValue.name() { - return match self.ty.node { - TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyRptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyInfer => { - Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) - } - _ => Some(respan(mk_sp(self.pat.span.lo, self.ty.span.hi), - SelfKind::Explicit(self.ty.clone(), mutbl))) - } - } - } - None - } - - pub fn is_self(&self) -> bool { - if let PatKind::Binding(_, _, name, _) = self.pat.node { - name.node == keywords::SelfValue.name() - } else { - false - } - } -} - /// Represents the header (not the body) of a function declaration #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct FnDecl { - pub inputs: HirVec, + pub inputs: HirVec>, pub output: FunctionRetTy, pub variadic: bool, } -impl FnDecl { - pub fn get_self(&self) -> Option { - self.inputs.get(0).and_then(Arg::to_self) - } - pub fn has_self(&self) -> bool { - self.inputs.get(0).map(Arg::is_self).unwrap_or(false) - } -} - #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Unsafety { Unsafe, @@ -1402,7 +1364,7 @@ pub struct Variant_ { pub attrs: HirVec, pub data: VariantData, /// Explicit discriminant, eg `Foo = 1` - pub disr_expr: Option>, + pub disr_expr: Option, } pub type Variant = Spanned; @@ -1533,8 +1495,6 @@ pub struct ItemId { pub id: NodeId, } -// FIXME (#3300): Should allow items to be anonymous. Right now -// we just use dummy names for anon items. /// An item /// /// The name might be a dummy name in case of anonymous items @@ -1563,11 +1523,11 @@ pub enum Item_ { ItemUse(P, UseKind), /// A `static` item - ItemStatic(P, Mutability, P), + ItemStatic(P, Mutability, BodyId), /// A `const` item - ItemConst(P, P), + ItemConst(P, BodyId), /// A function declaration - ItemFn(P, Unsafety, Constness, Abi, Generics, ExprId), + ItemFn(P, Unsafety, Constness, Abi, Generics, BodyId), /// A module ItemMod(Mod), /// An external module @@ -1581,7 +1541,7 @@ pub enum Item_ { /// A union definition, e.g. `union Foo {x: A, y: B}` ItemUnion(VariantData, Generics), /// Represents a Trait Declaration - ItemTrait(Unsafety, Generics, TyParamBounds, HirVec), + ItemTrait(Unsafety, Generics, TyParamBounds, HirVec), // Default trait implementations /// @@ -1617,6 +1577,21 @@ impl Item_ { } } +/// A reference from an trait to one of its associated items. This +/// contains the item's id, naturally, but also the item's name and +/// some other high-level details (like whether it is an associated +/// type or method, and whether it is public). This allows other +/// passes to find the impl they want without loading the id (which +/// means fewer edges in the incremental compilation graph). +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct TraitItemRef { + pub id: TraitItemId, + pub name: Name, + pub kind: AssociatedItemKind, + pub span: Span, + pub defaultness: Defaultness, +} + /// A reference from an impl to one of its associated items. This /// contains the item's id, naturally, but also the item's name and /// some other high-level details (like whether it is an associated @@ -1654,7 +1629,7 @@ pub struct ForeignItem { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum ForeignItem_ { /// A foreign function - ForeignItemFn(P, Generics), + ForeignItemFn(P, HirVec>, Generics), /// A foreign static item (`static ext: u8`), with optional mutability /// (the boolean is true when mutable) ForeignItemStatic(P, bool), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 74920b1328..e058c48c59 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -13,7 +13,7 @@ pub use self::AnnNode::*; use syntax::abi::Abi; use syntax::ast; use syntax::codemap::{CodeMap, Spanned}; -use syntax::parse::token::{self, BinOpToken}; +use syntax::parse::ParseSess; use syntax::parse::lexer::comments; use syntax::print::pp::{self, break_offset, word, space, hardbreak}; use syntax::print::pp::{Breaks, eof}; @@ -22,11 +22,11 @@ use syntax::print::pprust::{self as ast_pp, PrintState}; use syntax::ptr::P; use syntax::symbol::keywords; use syntax_pos::{self, BytePos}; -use errors; use hir; -use hir::{Crate, PatKind, RegionTyParamBound, SelfKind, TraitTyParamBound, TraitBoundModifier}; +use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd}; +use std::cell::Cell; use std::io::{self, Write, Read}; pub enum AnnNode<'a> { @@ -38,7 +38,18 @@ pub enum AnnNode<'a> { NodePat(&'a hir::Pat), } +pub enum Nested { + Item(hir::ItemId), + TraitItem(hir::TraitItemId), + ImplItem(hir::ImplItemId), + Body(hir::BodyId), + BodyArgPat(hir::BodyId, usize) +} + pub trait PpAnn { + fn nested(&self, _state: &mut State, _nested: Nested) -> io::Result<()> { + Ok(()) + } fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) } @@ -47,14 +58,23 @@ pub trait PpAnn { } } -#[derive(Copy, Clone)] pub struct NoAnn; - impl PpAnn for NoAnn {} +pub const NO_ANN: &'static PpAnn = &NoAnn; +impl PpAnn for hir::Crate { + fn nested(&self, state: &mut State, nested: Nested) -> io::Result<()> { + match nested { + Nested::Item(id) => state.print_item(self.item(id.id)), + Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), + Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), + Nested::Body(id) => state.print_expr(&self.body(id).value), + Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat) + } + } +} pub struct State<'a> { - krate: Option<&'a Crate>, pub s: pp::Printer<'a>, cm: Option<&'a CodeMap>, comments: Option>, @@ -86,30 +106,6 @@ impl<'a> PrintState<'a> for State<'a> { } } -pub fn rust_printer<'a>(writer: Box, krate: Option<&'a Crate>) -> State<'a> { - static NO_ANN: NoAnn = NoAnn; - rust_printer_annotated(writer, &NO_ANN, krate) -} - -pub fn rust_printer_annotated<'a>(writer: Box, - ann: &'a PpAnn, - krate: Option<&'a Crate>) - -> State<'a> { - State { - krate: krate, - s: pp::mk_printer(writer, default_columns), - cm: None, - comments: None, - literals: None, - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0, - }, - boxes: Vec::new(), - ann: ann, - } -} - #[allow(non_upper_case_globals)] pub const indent_unit: usize = 4; @@ -121,7 +117,7 @@ pub const default_columns: usize = 78; /// it can scan the input text for comments and literals to /// copy forward. pub fn print_crate<'a>(cm: &'a CodeMap, - span_diagnostic: &errors::Handler, + sess: &ParseSess, krate: &hir::Crate, filename: String, input: &mut Read, @@ -129,8 +125,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, ann: &'a PpAnn, is_expanded: bool) -> io::Result<()> { - let mut s = State::new_from_input(cm, span_diagnostic, filename, input, - out, ann, is_expanded, Some(krate)); + let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded); // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. @@ -142,17 +137,14 @@ pub fn print_crate<'a>(cm: &'a CodeMap, impl<'a> State<'a> { pub fn new_from_input(cm: &'a CodeMap, - span_diagnostic: &errors::Handler, + sess: &ParseSess, filename: String, input: &mut Read, out: Box, ann: &'a PpAnn, - is_expanded: bool, - krate: Option<&'a Crate>) + is_expanded: bool) -> State<'a> { - let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic, - filename, - input); + let (cmnts, lits) = comments::gather_comments_and_literals(sess, filename, input); State::new(cm, out, @@ -165,19 +157,16 @@ impl<'a> State<'a> { None } else { Some(lits) - }, - krate) + }) } pub fn new(cm: &'a CodeMap, out: Box, ann: &'a PpAnn, comments: Option>, - literals: Option>, - krate: Option<&'a Crate>) + literals: Option>) -> State<'a> { State { - krate: krate, s: pp::mk_printer(out, default_columns), cm: Some(cm), comments: comments.clone(), @@ -192,144 +181,36 @@ impl<'a> State<'a> { } } -pub fn to_string(f: F) -> String +pub fn to_string(ann: &PpAnn, f: F) -> String where F: FnOnce(&mut State) -> io::Result<()> { let mut wr = Vec::new(); { - let mut printer = rust_printer(Box::new(&mut wr), None); + let mut printer = State { + s: pp::mk_printer(Box::new(&mut wr), default_columns), + cm: None, + comments: None, + literals: None, + cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { + cur_cmnt: 0, + cur_lit: 0, + }, + boxes: Vec::new(), + ann: ann, + }; f(&mut printer).unwrap(); eof(&mut printer.s).unwrap(); } String::from_utf8(wr).unwrap() } -pub fn binop_to_string(op: BinOpToken) -> &'static str { - match op { - token::Plus => "+", - token::Minus => "-", - token::Star => "*", - token::Slash => "/", - token::Percent => "%", - token::Caret => "^", - token::And => "&", - token::Or => "|", - token::Shl => "<<", - token::Shr => ">>", - } -} - -pub fn ty_to_string(ty: &hir::Ty) -> String { - to_string(|s| s.print_type(ty)) -} - -pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String { - to_string(|s| s.print_bounds("", bounds)) -} - -pub fn pat_to_string(pat: &hir::Pat) -> String { - to_string(|s| s.print_pat(pat)) -} - -pub fn arm_to_string(arm: &hir::Arm) -> String { - to_string(|s| s.print_arm(arm)) -} - -pub fn expr_to_string(e: &hir::Expr) -> String { - to_string(|s| s.print_expr(e)) -} - -pub fn lifetime_to_string(e: &hir::Lifetime) -> String { - to_string(|s| s.print_lifetime(e)) -} - -pub fn stmt_to_string(stmt: &hir::Stmt) -> String { - to_string(|s| s.print_stmt(stmt)) -} - -pub fn item_to_string(i: &hir::Item) -> String { - to_string(|s| s.print_item(i)) -} - -pub fn impl_item_to_string(i: &hir::ImplItem) -> String { - to_string(|s| s.print_impl_item(i)) -} - -pub fn trait_item_to_string(i: &hir::TraitItem) -> String { - to_string(|s| s.print_trait_item(i)) -} - -pub fn generics_to_string(generics: &hir::Generics) -> String { - to_string(|s| s.print_generics(generics)) -} - -pub fn where_clause_to_string(i: &hir::WhereClause) -> String { - to_string(|s| s.print_where_clause(i)) -} - -pub fn fn_block_to_string(p: &hir::FnDecl) -> String { - to_string(|s| s.print_fn_block_args(p)) -} - -pub fn path_to_string(p: &hir::Path) -> String { - to_string(|s| s.print_path(p, false)) -} - -pub fn qpath_to_string(p: &hir::QPath) -> String { - to_string(|s| s.print_qpath(p, false)) -} - -pub fn name_to_string(name: ast::Name) -> String { - to_string(|s| s.print_name(name)) -} - -pub fn fun_to_string(decl: &hir::FnDecl, - unsafety: hir::Unsafety, - constness: hir::Constness, - name: ast::Name, - generics: &hir::Generics) - -> String { - to_string(|s| { - s.head("")?; - s.print_fn(decl, - unsafety, - constness, - Abi::Rust, - Some(name), - generics, - &hir::Inherited)?; - s.end()?; // Close the head box - s.end() // Close the outer box - }) -} - -pub fn block_to_string(blk: &hir::Block) -> String { - to_string(|s| { - // containing cbox, will be closed by print-block at } - s.cbox(indent_unit)?; - // head-ibox, will be closed by print-block after { - s.ibox(0)?; - s.print_block(blk) +pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String { + to_string(NO_ANN, |s| { + s.print_visibility(vis)?; + word(&mut s.s, w) }) } -pub fn variant_to_string(var: &hir::Variant) -> String { - to_string(|s| s.print_variant(var)) -} - -pub fn arg_to_string(arg: &hir::Arg) -> String { - to_string(|s| s.print_arg(arg, false)) -} - -pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String { - match *vis { - hir::Public => format!("pub {}", s), - hir::Visibility::Crate => format!("pub(crate) {}", s), - hir::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s), - hir::Inherited => s.to_string(), - } -} - fn needs_parentheses(expr: &hir::Expr) -> bool { match expr.node { hir::ExprAssign(..) | @@ -462,8 +343,8 @@ impl<'a> State<'a> { pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> { self.print_inner_attributes(attrs)?; - for item_id in &_mod.item_ids { - self.print_item_id(item_id)?; + for &item_id in &_mod.item_ids { + self.ann.nested(self, Nested::Item(item_id))?; } Ok(()) } @@ -479,9 +360,9 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_opt_lifetime(&mut self, lifetime: &Option) -> io::Result<()> { - if let Some(l) = *lifetime { - self.print_lifetime(&l)?; + pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> { + if !lifetime.is_elided() { + self.print_lifetime(lifetime)?; self.nbsp()?; } Ok(()) @@ -535,26 +416,35 @@ impl<'a> State<'a> { hir::TyPath(ref qpath) => { self.print_qpath(qpath, false)? } - hir::TyObjectSum(ref ty, ref bounds) => { - self.print_type(&ty)?; - self.print_bounds("+", &bounds[..])?; - } - hir::TyPolyTraitRef(ref bounds) => { - self.print_bounds("", &bounds[..])?; + hir::TyTraitObject(ref bounds, ref lifetime) => { + let mut first = true; + for bound in bounds { + self.nbsp()?; + if first { + first = false; + } else { + self.word_space("+")?; + } + self.print_poly_trait_ref(bound)?; + } + if !lifetime.is_elided() { + self.word_space("+")?; + self.print_lifetime(lifetime)?; + } } hir::TyImplTrait(ref bounds) => { self.print_bounds("impl ", &bounds[..])?; } - hir::TyArray(ref ty, ref v) => { + hir::TyArray(ref ty, v) => { word(&mut self.s, "[")?; self.print_type(&ty)?; word(&mut self.s, "; ")?; - self.print_expr(&v)?; + self.ann.nested(self, Nested::Body(v))?; word(&mut self.s, "]")?; } - hir::TyTypeof(ref e) => { + hir::TyTypeof(e) => { word(&mut self.s, "typeof(")?; - self.print_expr(&e)?; + self.ann.nested(self, Nested::Body(e))?; word(&mut self.s, ")")?; } hir::TyInfer => { @@ -569,7 +459,7 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo)?; self.print_outer_attributes(&item.attrs)?; match item.node { - hir::ForeignItemFn(ref decl, ref generics) => { + hir::ForeignItemFn(ref decl, ref arg_names, ref generics) => { self.head("")?; self.print_fn(decl, hir::Unsafety::Normal, @@ -577,7 +467,9 @@ impl<'a> State<'a> { Abi::Rust, Some(item.name), generics, - &item.vis)?; + &item.vis, + arg_names, + None)?; self.end()?; // end head-ibox word(&mut self.s, ";")?; self.end() // end the outer fn box @@ -600,7 +492,7 @@ impl<'a> State<'a> { fn print_associated_const(&mut self, name: ast::Name, ty: &hir::Ty, - default: Option<&hir::Expr>, + default: Option, vis: &hir::Visibility) -> io::Result<()> { word(&mut self.s, &visibility_qualified(vis, ""))?; @@ -611,7 +503,7 @@ impl<'a> State<'a> { if let Some(expr) = default { space(&mut self.s)?; self.word_space("=")?; - self.print_expr(expr)?; + self.ann.nested(self, Nested::Body(expr))?; } word(&mut self.s, ";") } @@ -634,25 +526,6 @@ impl<'a> State<'a> { word(&mut self.s, ";") } - pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> { - if let Some(krate) = self.krate { - // skip nested items if krate context was not provided - let item = &krate.items[&item_id.id]; - self.print_item(item) - } else { - Ok(()) - } - } - - pub fn print_expr_id(&mut self, expr_id: &hir::ExprId) -> io::Result<()> { - if let Some(krate) = self.krate { - let expr = &krate.exprs[expr_id]; - self.print_expr(expr) - } else { - Ok(()) - } - } - /// Pretty-print an item pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> { self.hardbreak_if_not_bol()?; @@ -697,7 +570,7 @@ impl<'a> State<'a> { self.end()?; // end inner head-block self.end()?; // end outer head-block } - hir::ItemStatic(ref ty, m, ref expr) => { + hir::ItemStatic(ref ty, m, expr) => { self.head(&visibility_qualified(&item.vis, "static"))?; if m == hir::MutMutable { self.word_space("mut")?; @@ -709,11 +582,11 @@ impl<'a> State<'a> { self.end()?; // end the head-ibox self.word_space("=")?; - self.print_expr(&expr)?; + self.ann.nested(self, Nested::Body(expr))?; word(&mut self.s, ";")?; self.end()?; // end the outer cbox } - hir::ItemConst(ref ty, ref expr) => { + hir::ItemConst(ref ty, expr) => { self.head(&visibility_qualified(&item.vis, "const"))?; self.print_name(item.name)?; self.word_space(":")?; @@ -722,11 +595,11 @@ impl<'a> State<'a> { self.end()?; // end the head-ibox self.word_space("=")?; - self.print_expr(&expr)?; + self.ann.nested(self, Nested::Body(expr))?; word(&mut self.s, ";")?; self.end()?; // end the outer cbox } - hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => { + hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, body) => { self.head("")?; self.print_fn(decl, unsafety, @@ -734,11 +607,13 @@ impl<'a> State<'a> { abi, Some(item.name), typarams, - &item.vis)?; + &item.vis, + &[], + Some(body))?; word(&mut self.s, " ")?; self.end()?; // need to close a box self.end()?; // need to close a box - self.print_expr_id(body)?; + self.ann.nested(self, Nested::Body(body))?; } hir::ItemMod(ref _mod) => { self.head(&visibility_qualified(&item.vis, "mod"))?; @@ -832,7 +707,7 @@ impl<'a> State<'a> { self.bopen()?; self.print_inner_attributes(&item.attrs)?; for impl_item in impl_items { - self.print_impl_item_ref(impl_item)?; + self.ann.nested(self, Nested::ImplItem(impl_item.id))?; } self.bclose(item.span)?; } @@ -858,7 +733,7 @@ impl<'a> State<'a> { word(&mut self.s, " ")?; self.bopen()?; for trait_item in trait_items { - self.print_trait_item(trait_item)?; + self.ann.nested(self, Nested::TraitItem(trait_item.id))?; } self.bclose(item.span)?; } @@ -928,8 +803,11 @@ impl<'a> State<'a> { match *vis { hir::Public => self.word_nbsp("pub"), hir::Visibility::Crate => self.word_nbsp("pub(crate)"), - hir::Visibility::Restricted { ref path, .. } => - self.word_nbsp(&format!("pub({})", path)), + hir::Visibility::Restricted { ref path, .. } => { + word(&mut self.s, "pub(")?; + self.print_path(path, false)?; + self.word_nbsp(")") + } hir::Inherited => Ok(()), } } @@ -985,19 +863,19 @@ impl<'a> State<'a> { self.head("")?; let generics = hir::Generics::empty(); self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; - match v.node.disr_expr { - Some(ref d) => { - space(&mut self.s)?; - self.word_space("=")?; - self.print_expr(&d) - } - _ => Ok(()), + if let Some(d) = v.node.disr_expr { + space(&mut self.s)?; + self.word_space("=")?; + self.ann.nested(self, Nested::Body(d))?; } + Ok(()) } pub fn print_method_sig(&mut self, name: ast::Name, m: &hir::MethodSig, - vis: &hir::Visibility) + vis: &hir::Visibility, + arg_names: &[Spanned], + body_id: Option) -> io::Result<()> { self.print_fn(&m.decl, m.unsafety, @@ -1005,7 +883,9 @@ impl<'a> State<'a> { m.abi, Some(name), &m.generics, - vis) + vis, + arg_names, + body_id) } pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> { @@ -1014,27 +894,22 @@ impl<'a> State<'a> { self.maybe_print_comment(ti.span.lo)?; self.print_outer_attributes(&ti.attrs)?; match ti.node { - hir::ConstTraitItem(ref ty, ref default) => { - self.print_associated_const(ti.name, - &ty, - default.as_ref().map(|expr| &**expr), - &hir::Inherited)?; - } - hir::MethodTraitItem(ref sig, ref body) => { - if body.is_some() { - self.head("")?; - } - self.print_method_sig(ti.name, sig, &hir::Inherited)?; - if let Some(ref body) = *body { - self.nbsp()?; - self.end()?; // need to close a box - self.end()?; // need to close a box - self.print_expr_id(body)?; - } else { - word(&mut self.s, ";")?; - } + hir::TraitItemKind::Const(ref ty, default) => { + self.print_associated_const(ti.name, &ty, default, &hir::Inherited)?; } - hir::TypeTraitItem(ref bounds, ref default) => { + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => { + self.print_method_sig(ti.name, sig, &hir::Inherited, arg_names, None)?; + word(&mut self.s, ";")?; + } + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { + self.head("")?; + self.print_method_sig(ti.name, sig, &hir::Inherited, &[], Some(body))?; + self.nbsp()?; + self.end()?; // need to close a box + self.end()?; // need to close a box + self.ann.nested(self, Nested::Body(body))?; + } + hir::TraitItemKind::Type(ref bounds, ref default) => { self.print_associated_type(ti.name, Some(bounds), default.as_ref().map(|ty| &**ty))?; @@ -1043,16 +918,6 @@ impl<'a> State<'a> { self.ann.post(self, NodeSubItem(ti.id)) } - pub fn print_impl_item_ref(&mut self, item_ref: &hir::ImplItemRef) -> io::Result<()> { - if let Some(krate) = self.krate { - // skip nested items if krate context was not provided - let item = &krate.impl_item(item_ref.id); - self.print_impl_item(item) - } else { - Ok(()) - } - } - pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> { self.ann.pre(self, NodeSubItem(ii.id))?; self.hardbreak_if_not_bol()?; @@ -1065,16 +930,16 @@ impl<'a> State<'a> { } match ii.node { - hir::ImplItemKind::Const(ref ty, ref expr) => { - self.print_associated_const(ii.name, &ty, Some(&expr), &ii.vis)?; + hir::ImplItemKind::Const(ref ty, expr) => { + self.print_associated_const(ii.name, &ty, Some(expr), &ii.vis)?; } - hir::ImplItemKind::Method(ref sig, ref body) => { + hir::ImplItemKind::Method(ref sig, body) => { self.head("")?; - self.print_method_sig(ii.name, sig, &ii.vis)?; + self.print_method_sig(ii.name, sig, &ii.vis, &[], Some(body))?; self.nbsp()?; self.end()?; // need to close a box self.end()?; // need to close a box - self.print_expr_id(body)?; + self.ann.nested(self, Nested::Body(body))?; } hir::ImplItemKind::Type(ref ty) => { self.print_associated_type(ii.name, None, Some(ty))?; @@ -1246,12 +1111,12 @@ impl<'a> State<'a> { self.end() } - fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> { + fn print_expr_repeat(&mut self, element: &hir::Expr, count: hir::BodyId) -> io::Result<()> { self.ibox(indent_unit)?; word(&mut self.s, "[")?; self.print_expr(element)?; self.word_space(";")?; - self.print_expr(count)?; + self.ann.nested(self, Nested::Body(count))?; word(&mut self.s, "]")?; self.end() } @@ -1352,6 +1217,7 @@ impl<'a> State<'a> { pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> { self.maybe_print_comment(expr.span.lo)?; + self.print_outer_attributes(&expr.attrs)?; self.ibox(indent_unit)?; self.ann.pre(self, NodeExpr(expr))?; match expr.node { @@ -1362,8 +1228,8 @@ impl<'a> State<'a> { hir::ExprArray(ref exprs) => { self.print_expr_vec(exprs)?; } - hir::ExprRepeat(ref element, ref count) => { - self.print_expr_repeat(&element, &count)?; + hir::ExprRepeat(ref element, count) => { + self.print_expr_repeat(&element, count)?; } hir::ExprStruct(ref qpath, ref fields, ref wth) => { self.print_expr_struct(qpath, &fields[..], wth)?; @@ -1434,14 +1300,14 @@ impl<'a> State<'a> { } self.bclose_(expr.span, indent_unit)?; } - hir::ExprClosure(capture_clause, ref decl, ref body, _fn_decl_span) => { + hir::ExprClosure(capture_clause, ref decl, body, _fn_decl_span) => { self.print_capture_clause(capture_clause)?; - self.print_fn_block_args(&decl)?; + self.print_closure_args(&decl, body)?; space(&mut self.s)?; // this is a bare expression - self.print_expr_id(body)?; + self.ann.nested(self, Nested::Body(body))?; self.end()?; // need to close a box // a box will be closed by print_expr, but we didn't want an overall @@ -1615,8 +1481,8 @@ impl<'a> State<'a> { } self.end() } - hir::DeclItem(ref item) => { - self.print_item_id(item) + hir::DeclItem(item) => { + self.ann.nested(self, Nested::Item(item)) } } } @@ -1637,32 +1503,29 @@ impl<'a> State<'a> { self.print_expr(coll) } - fn print_path(&mut self, - path: &hir::Path, - colons_before_params: bool) - -> io::Result<()> { + pub fn print_path(&mut self, + path: &hir::Path, + colons_before_params: bool) + -> io::Result<()> { self.maybe_print_comment(path.span.lo)?; - let mut first = !path.global; - for segment in &path.segments { - if first { - first = false - } else { + for (i, segment) in path.segments.iter().enumerate() { + if i > 0 { word(&mut self.s, "::")? } - - self.print_name(segment.name)?; - - self.print_path_parameters(&segment.parameters, colons_before_params)?; + if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" { + self.print_name(segment.name)?; + self.print_path_parameters(&segment.parameters, colons_before_params)?; + } } Ok(()) } - fn print_qpath(&mut self, - qpath: &hir::QPath, - colons_before_params: bool) - -> io::Result<()> { + pub fn print_qpath(&mut self, + qpath: &hir::QPath, + colons_before_params: bool) + -> io::Result<()> { match *qpath { hir::QPath::Resolved(None, ref path) => { self.print_path(path, colons_before_params) @@ -1673,15 +1536,14 @@ impl<'a> State<'a> { space(&mut self.s)?; self.word_space("as")?; - let mut first = !path.global; - for segment in &path.segments[..path.segments.len() - 1] { - if first { - first = false - } else { + for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() { + if i > 0 { word(&mut self.s, "::")? } - self.print_name(segment.name)?; - self.print_path_parameters(&segment.parameters, colons_before_params)?; + if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" { + self.print_name(segment.name)?; + self.print_path_parameters(&segment.parameters, colons_before_params)?; + } } word(&mut self.s, ">")?; @@ -1705,65 +1567,49 @@ impl<'a> State<'a> { parameters: &hir::PathParameters, colons_before_params: bool) -> io::Result<()> { - if parameters.is_empty() { - let infer_types = match *parameters { - hir::AngleBracketedParameters(ref data) => data.infer_types, - hir::ParenthesizedParameters(_) => false - }; - - // FIXME(eddyb) See the comment below about infer_types. - if !(infer_types && false) { - return Ok(()); - } - } - - if colons_before_params { - word(&mut self.s, "::")? - } - match *parameters { hir::AngleBracketedParameters(ref data) => { - word(&mut self.s, "<")?; + let start = if colons_before_params { "::<" } else { "<" }; + let empty = Cell::new(true); + let start_or_comma = |this: &mut Self| { + if empty.get() { + empty.set(false); + word(&mut this.s, start) + } else { + this.word_space(",") + } + }; - let mut comma = false; - for lifetime in &data.lifetimes { - if comma { - self.word_space(",")? + if !data.lifetimes.iter().all(|lt| lt.is_elided()) { + for lifetime in &data.lifetimes { + start_or_comma(self)?; + self.print_lifetime(lifetime)?; } - self.print_lifetime(lifetime)?; - comma = true; } if !data.types.is_empty() { - if comma { - self.word_space(",")? - } + start_or_comma(self)?; self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?; - comma = true; } // FIXME(eddyb) This would leak into error messages, e.g.: // "non-exhaustive patterns: `Some::<..>(_)` not covered". if data.infer_types && false { - if comma { - self.word_space(",")? - } + start_or_comma(self)?; word(&mut self.s, "..")?; - comma = true; } for binding in data.bindings.iter() { - if comma { - self.word_space(",")? - } + start_or_comma(self)?; self.print_name(binding.name)?; space(&mut self.s)?; self.word_space("=")?; self.print_type(&binding.ty)?; - comma = true; } - word(&mut self.s, ">")? + if !empty.get() { + word(&mut self.s, ">")? + } } hir::ParenthesizedParameters(ref data) => { @@ -1884,10 +1730,13 @@ impl<'a> State<'a> { self.print_pat(&inner)?; } PatKind::Lit(ref e) => self.print_expr(&e)?, - PatKind::Range(ref begin, ref end) => { + PatKind::Range(ref begin, ref end, ref end_kind) => { self.print_expr(&begin)?; space(&mut self.s)?; - word(&mut self.s, "...")?; + match *end_kind { + RangeEnd::Included => word(&mut self.s, "...")?, + RangeEnd::Excluded => word(&mut self.s, "..")?, + } self.print_expr(&end)?; } PatKind::Slice(ref before, ref slice, ref after) => { @@ -1958,27 +1807,6 @@ impl<'a> State<'a> { self.end() // close enclosing cbox } - fn print_explicit_self(&mut self, explicit_self: &hir::ExplicitSelf) -> io::Result<()> { - match explicit_self.node { - SelfKind::Value(m) => { - self.print_mutability(m)?; - word(&mut self.s, "self") - } - SelfKind::Region(ref lt, m) => { - word(&mut self.s, "&")?; - self.print_opt_lifetime(lt)?; - self.print_mutability(m)?; - word(&mut self.s, "self") - } - SelfKind::Explicit(ref typ, m) => { - self.print_mutability(m)?; - word(&mut self.s, "self")?; - self.word_space(":")?; - self.print_type(&typ) - } - } - } - pub fn print_fn(&mut self, decl: &hir::FnDecl, unsafety: hir::Unsafety, @@ -1986,7 +1814,9 @@ impl<'a> State<'a> { abi: Abi, name: Option, generics: &hir::Generics, - vis: &hir::Visibility) + vis: &hir::Visibility, + arg_names: &[Spanned], + body_id: Option) -> io::Result<()> { self.print_fn_header_info(unsafety, constness, abi, vis)?; @@ -1995,24 +1825,51 @@ impl<'a> State<'a> { self.print_name(name)?; } self.print_generics(generics)?; - self.print_fn_args_and_ret(decl)?; - self.print_where_clause(&generics.where_clause) - } - pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl) -> io::Result<()> { self.popen()?; - self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?; + let mut i = 0; + // Make sure we aren't supplied *both* `arg_names` and `body_id`. + assert!(arg_names.is_empty() || body_id.is_none()); + self.commasep(Inconsistent, &decl.inputs, |s, ty| { + s.ibox(indent_unit)?; + if let Some(name) = arg_names.get(i) { + word(&mut s.s, &name.node.as_str())?; + word(&mut s.s, ":")?; + space(&mut s.s)?; + } else if let Some(body_id) = body_id { + s.ann.nested(s, Nested::BodyArgPat(body_id, i))?; + word(&mut s.s, ":")?; + space(&mut s.s)?; + } + i += 1; + s.print_type(ty)?; + s.end() + })?; if decl.variadic { word(&mut self.s, ", ...")?; } self.pclose()?; - self.print_fn_output(decl) + self.print_fn_output(decl)?; + self.print_where_clause(&generics.where_clause) } - pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> { + fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) -> io::Result<()> { word(&mut self.s, "|")?; - self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?; + let mut i = 0; + self.commasep(Inconsistent, &decl.inputs, |s, ty| { + s.ibox(indent_unit)?; + + s.ann.nested(s, Nested::BodyArgPat(body_id, i))?; + i += 1; + + if ty.node != hir::TyInfer { + word(&mut s.s, ":")?; + space(&mut s.s)?; + s.print_type(ty)?; + } + s.end() + })?; word(&mut self.s, "|")?; if let hir::DefaultReturn(..) = decl.output { @@ -2160,11 +2017,13 @@ impl<'a> State<'a> { } } } - &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => { - self.print_path(path, false)?; + &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref lhs_ty, + ref rhs_ty, + ..}) => { + self.print_type(lhs_ty)?; space(&mut self.s)?; self.word_space("=")?; - self.print_type(&ty)?; + self.print_type(rhs_ty)?; } } } @@ -2184,31 +2043,6 @@ impl<'a> State<'a> { self.print_type(&mt.ty) } - pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> { - self.ibox(indent_unit)?; - match input.ty.node { - hir::TyInfer if is_closure => self.print_pat(&input.pat)?, - _ => { - if let Some(eself) = input.to_self() { - self.print_explicit_self(&eself)?; - } else { - let invalid = if let PatKind::Binding(_, _, name, _) = input.pat.node { - name.node == keywords::Invalid.name() - } else { - false - }; - if !invalid { - self.print_pat(&input.pat)?; - word(&mut self.s, ":")?; - space(&mut self.s)?; - } - self.print_type(&input.ty)?; - } - } - } - self.end() - } - pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> { if let hir::DefaultReturn(..) = decl.output { return Ok(()); @@ -2256,7 +2090,9 @@ impl<'a> State<'a> { abi, name, &generics, - &hir::Inherited)?; + &hir::Inherited, + &[], + None)?; self.end() } diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 28edf3c587..1fb5a5d697 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -55,8 +55,6 @@ //! ported to this system, and which relies on string concatenation at the //! time of error detection. -use self::FreshOrKept::*; - use super::InferCtxt; use super::TypeTrace; use super::SubregionOrigin; @@ -67,33 +65,22 @@ use super::region_inference::ConcreteFailure; use super::region_inference::SubSupConflict; use super::region_inference::GenericBoundFailure; use super::region_inference::GenericKind; -use super::region_inference::ProcessedErrors; -use super::region_inference::ProcessedErrorOrigin; -use super::region_inference::SameRegions; - -use std::collections::HashSet; -use hir::map as ast_map; +use hir::map as hir_map; use hir; -use hir::print as pprust; use lint; -use hir::def::Def; use hir::def_id::DefId; use infer; use middle::region; use traits::{ObligationCause, ObligationCauseCode}; use ty::{self, TyCtxt, TypeFoldable}; -use ty::{Region, ReFree}; +use ty::Region; use ty::error::TypeError; -use std::cell::{Cell, RefCell}; -use std::char::from_u32; use std::fmt; +use syntax_pos::{Pos, Span}; use syntax::ast; -use syntax::ptr::P; -use syntax::symbol::Symbol; -use syntax_pos::{self, Pos, Span}; use errors::DiagnosticBuilder; impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -116,9 +103,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str { match item.node { - hir::MethodTraitItem(..) => "method body", - hir::ConstTraitItem(..) | - hir::TypeTraitItem(..) => "associated item" + hir::TraitItemKind::Method(..) => "method body", + hir::TraitItemKind::Const(..) | + hir::TraitItemKind::Type(..) => "associated item" } } @@ -145,16 +132,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { format!("{}unknown scope: {:?}{}. Please report a bug.", prefix, scope, suffix) }; - let span = match scope.span(&self.region_maps, &self.map) { + let span = match scope.span(&self.region_maps, &self.hir) { Some(s) => s, None => { err.note(&unknown_scope()); return; } }; - let tag = match self.map.find(scope.node_id(&self.region_maps)) { - Some(ast_map::NodeBlock(_)) => "block", - Some(ast_map::NodeExpr(expr)) => match expr.node { + let tag = match self.hir.find(scope.node_id(&self.region_maps)) { + Some(hir_map::NodeBlock(_)) => "block", + Some(hir_map::NodeExpr(expr)) => match expr.node { hir::ExprCall(..) => "call", hir::ExprMethodCall(..) => "method call", hir::ExprMatch(.., hir::MatchSource::IfLetDesugar { .. }) => "if let", @@ -163,10 +150,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { hir::ExprMatch(..) => "match", _ => "expression", }, - Some(ast_map::NodeStmt(_)) => "statement", - Some(ast_map::NodeItem(it)) => item_scope_tag(&it), - Some(ast_map::NodeTraitItem(it)) => trait_item_scope_tag(&it), - Some(ast_map::NodeImplItem(it)) => impl_item_scope_tag(&it), + Some(hir_map::NodeStmt(_)) => "statement", + Some(hir_map::NodeItem(it)) => item_scope_tag(&it), + Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it), + Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it), Some(_) | None => { err.span_note(span, &unknown_scope()); return; @@ -207,19 +194,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let node = fr.scope.node_id(&self.region_maps); let unknown; - let tag = match self.map.find(node) { - Some(ast_map::NodeBlock(_)) | - Some(ast_map::NodeExpr(_)) => "body", - Some(ast_map::NodeItem(it)) => item_scope_tag(&it), - Some(ast_map::NodeTraitItem(it)) => trait_item_scope_tag(&it), - Some(ast_map::NodeImplItem(it)) => impl_item_scope_tag(&it), + let tag = match self.hir.find(node) { + Some(hir_map::NodeBlock(_)) | + Some(hir_map::NodeExpr(_)) => "body", + Some(hir_map::NodeItem(it)) => item_scope_tag(&it), + Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it), + Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it), // this really should not happen, but it does: // FIXME(#27942) Some(_) => { unknown = format!("unexpected node ({}) for scope {:?}. \ Please report a bug.", - self.map.node_to_string(node), fr.scope); + self.hir.node_to_string(node), fr.scope); &unknown } None => { @@ -228,7 +215,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { &unknown } }; - let (msg, opt_span) = explain_span(self, tag, self.map.span(node)); + let (msg, opt_span) = explain_span(self, tag, self.hir.span(node)); (format!("{} {}", prefix, msg), opt_span) } @@ -266,8 +253,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // try to pre-process the errors, which will group some of them // together into a `ProcessedErrors` group: - let processed_errors = self.process_errors(errors); - let errors = processed_errors.as_ref().unwrap_or(errors); + let errors = self.process_errors(errors); debug!("report_region_errors: {} errors after preprocessing", errors.len()); @@ -289,13 +275,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sub_origin, sub_r, sup_origin, sup_r); } - - ProcessedErrors(ref origins, - ref same_regions) => { - if !same_regions.is_empty() { - self.report_processed_errors(origins, same_regions); - } - } } } } @@ -311,202 +290,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // duplicates that will be unhelpful to the end-user. But // obviously it never weeds out ALL errors. fn process_errors(&self, errors: &Vec>) - -> Option>> { + -> Vec> { debug!("process_errors()"); - let mut origins = Vec::new(); - - // we collect up ConcreteFailures and SubSupConflicts that are - // relating free-regions bound on the fn-header and group them - // together into this vector - let mut same_regions = Vec::new(); - - // here we put errors that we will not be able to process nicely - let mut other_errors = Vec::new(); - - // we collect up GenericBoundFailures in here. - let mut bound_failures = Vec::new(); - - for error in errors { - // Check whether we can process this error into some other - // form; if not, fall through. - match *error { - ConcreteFailure(ref origin, sub, sup) => { - debug!("processing ConcreteFailure"); - if let SubregionOrigin::CompareImplMethodObligation { .. } = *origin { - // When comparing an impl method against a - // trait method, it is not helpful to suggest - // changes to the impl method. This is - // because the impl method signature is being - // checked using the trait's environment, so - // usually the changes we suggest would - // actually have to be applied to the *trait* - // method (and it's not clear that the trait - // method is even under the user's control). - } else if let Some(same_frs) = free_regions_from_same_fn(self.tcx, sub, sup) { - origins.push( - ProcessedErrorOrigin::ConcreteFailure( - origin.clone(), - sub, - sup)); - append_to_same_regions(&mut same_regions, &same_frs); - continue; - } - } - SubSupConflict(ref var_origin, ref sub_origin, sub, ref sup_origin, sup) => { - debug!("processing SubSupConflict sub: {:?} sup: {:?}", sub, sup); - match (sub_origin, sup_origin) { - (&SubregionOrigin::CompareImplMethodObligation { .. }, _) => { - // As above, when comparing an impl method - // against a trait method, it is not helpful - // to suggest changes to the impl method. - } - (_, &SubregionOrigin::CompareImplMethodObligation { .. }) => { - // See above. - } - _ => { - if let Some(same_frs) = free_regions_from_same_fn(self.tcx, sub, sup) { - origins.push( - ProcessedErrorOrigin::VariableFailure( - var_origin.clone())); - append_to_same_regions(&mut same_regions, &same_frs); - continue; - } - } - } - } - GenericBoundFailure(ref origin, ref kind, region) => { - bound_failures.push((origin.clone(), kind.clone(), region)); - continue; - } - ProcessedErrors(..) => { - bug!("should not encounter a `ProcessedErrors` yet: {:?}", error) - } - } - - // No changes to this error. - other_errors.push(error.clone()); - } - - // ok, let's pull together the errors, sorted in an order that - // we think will help user the best - let mut processed_errors = vec![]; - // first, put the processed errors, if any - if !same_regions.is_empty() { - let common_scope_id = same_regions[0].scope_id; - for sr in &same_regions { - // Since ProcessedErrors is used to reconstruct the function - // declaration, we want to make sure that they are, in fact, - // from the same scope - if sr.scope_id != common_scope_id { - debug!("returning empty result from process_errors because - {} != {}", sr.scope_id, common_scope_id); - return None; - } - } - assert!(origins.len() > 0); - let pe = ProcessedErrors(origins, same_regions); - debug!("errors processed: {:?}", pe); - processed_errors.push(pe); - } - - // next, put the other misc errors - processed_errors.extend(other_errors); - - // finally, put the `T: 'a` errors, but only if there were no - // other errors. otherwise, these have a very high rate of - // being unhelpful in practice. This is because they are - // basically secondary checks that test the state of the - // region graph after the rest of inference is done, and the - // other kinds of errors indicate that the region constraint - // graph is internally inconsistent, so these test results are - // likely to be meaningless. - if processed_errors.is_empty() { - for (origin, kind, region) in bound_failures { - processed_errors.push(GenericBoundFailure(origin, kind, region)); - } - } - - // we should always wind up with SOME errors, unless there were no - // errors to start - assert!(if errors.len() > 0 {processed_errors.len() > 0} else {true}); - - return Some(processed_errors); - - #[derive(Debug)] - struct FreeRegionsFromSameFn { - sub_fr: ty::FreeRegion, - sup_fr: ty::FreeRegion, - scope_id: ast::NodeId - } - - impl FreeRegionsFromSameFn { - fn new(sub_fr: ty::FreeRegion, - sup_fr: ty::FreeRegion, - scope_id: ast::NodeId) - -> FreeRegionsFromSameFn { - FreeRegionsFromSameFn { - sub_fr: sub_fr, - sup_fr: sup_fr, - scope_id: scope_id - } - } - } - - fn free_regions_from_same_fn<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - sub: &'tcx Region, - sup: &'tcx Region) - -> Option { - debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup); - let (scope_id, fr1, fr2) = match (sub, sup) { - (&ReFree(fr1), &ReFree(fr2)) => { - if fr1.scope != fr2.scope { - return None - } - assert!(fr1.scope == fr2.scope); - (fr1.scope.node_id(&tcx.region_maps), fr1, fr2) - }, - _ => return None - }; - let parent = tcx.map.get_parent(scope_id); - let parent_node = tcx.map.find(parent); - match parent_node { - Some(node) => match node { - ast_map::NodeItem(item) => match item.node { - hir::ItemFn(..) => { - Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id)) - }, - _ => None - }, - ast_map::NodeImplItem(..) | - ast_map::NodeTraitItem(..) => { - Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id)) - }, - _ => None - }, - None => { - debug!("no parent node of scope_id {}", scope_id); - None - } - } - } + // We want to avoid reporting generic-bound failures if we can + // avoid it: these have a very high rate of being unhelpful in + // practice. This is because they are basically secondary + // checks that test the state of the region graph after the + // rest of inference is done, and the other kinds of errors + // indicate that the region constraint graph is internally + // inconsistent, so these test results are likely to be + // meaningless. + // + // Therefore, we filter them out of the list unless they are + // the only thing in the list. + + let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e { + ConcreteFailure(..) => false, + SubSupConflict(..) => false, + GenericBoundFailure(..) => true, + }; - fn append_to_same_regions(same_regions: &mut Vec, - same_frs: &FreeRegionsFromSameFn) { - debug!("append_to_same_regions(same_regions={:?}, same_frs={:?})", - same_regions, same_frs); - let scope_id = same_frs.scope_id; - let (sub_fr, sup_fr) = (same_frs.sub_fr, same_frs.sup_fr); - for sr in same_regions.iter_mut() { - if sr.contains(&sup_fr.bound_region) && scope_id == sr.scope_id { - sr.push(sub_fr.bound_region); - return - } - } - same_regions.push(SameRegions { - scope_id: scope_id, - regions: vec![sub_fr.bound_region, sup_fr.bound_region] - }) + if errors.iter().all(|e| is_bound_failure(e)) { + errors.clone() + } else { + errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect() } } @@ -630,10 +438,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut diag = match trace.cause.code { ObligationCauseCode::IfExpressionWithNoElse => { struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str) - }, + } + ObligationCauseCode::MainFunctionType => { + struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str) + } _ => { struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str) - }, + } }; self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr); diag @@ -1047,87 +858,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.emit(); } - fn report_processed_errors(&self, - origins: &[ProcessedErrorOrigin<'tcx>], - same_regions: &[SameRegions]) { - for (i, origin) in origins.iter().enumerate() { - let mut err = match *origin { - ProcessedErrorOrigin::VariableFailure(ref var_origin) => - self.report_inference_failure(var_origin.clone()), - ProcessedErrorOrigin::ConcreteFailure(ref sr_origin, sub, sup) => - self.report_concrete_failure(sr_origin.clone(), sub, sup), - }; - - // attach the suggestion to the last such error - if i == origins.len() - 1 { - self.give_suggestion(&mut err, same_regions); - } - - err.emit(); - } - } - - fn give_suggestion(&self, err: &mut DiagnosticBuilder, same_regions: &[SameRegions]) { - let scope_id = same_regions[0].scope_id; - let parent = self.tcx.map.get_parent(scope_id); - let parent_node = self.tcx.map.find(parent); - let taken = lifetimes_in_scope(self.tcx, scope_id); - let life_giver = LifeGiver::with_taken(&taken[..]); - let node_inner = match parent_node { - Some(ref node) => match *node { - ast_map::NodeItem(ref item) => { - match item.node { - hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => { - Some((fn_decl, gen, unsafety, constness, item.name, item.span)) - } - _ => None, - } - } - ast_map::NodeImplItem(item) => { - let id = self.tcx.map.get_parent(item.id); - if let Some(ast_map::NodeItem(parent_scope)) = self.tcx.map.find(id) { - if let hir::ItemImpl(_, _, _, None, _, _) = parent_scope.node { - // this impl scope implements a trait, do not recomend - // using explicit lifetimes (#37363) - return; - } - } - if let hir::ImplItemKind::Method(ref sig, _) = item.node { - Some((&sig.decl, - &sig.generics, - sig.unsafety, - sig.constness, - item.name, - item.span)) - } else { - None - } - }, - ast_map::NodeTraitItem(item) => { - match item.node { - hir::MethodTraitItem(ref sig, Some(_)) => { - Some((&sig.decl, - &sig.generics, - sig.unsafety, - sig.constness, - item.name, - item.span)) - } - _ => None, - } - } - _ => None, - }, - None => None, - }; - let (fn_decl, generics, unsafety, constness, name, span) - = node_inner.expect("expect item fn"); - let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver); - let (fn_decl, generics) = rebuilder.rebuild(); - self.give_expl_lifetime_param( - err, &fn_decl, unsafety, constness, name, &generics, span); - } - pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) { for issue32330 in issue32330s { match *issue32330 { @@ -1150,524 +880,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } -struct RebuildPathInfo<'a> { - path: &'a hir::Path, - // indexes to insert lifetime on path.lifetimes - indexes: Vec, - // number of lifetimes we expect to see on the type referred by `path` - // (e.g., expected=1 for struct Foo<'a>) - expected: u32, - anon_nums: &'a HashSet, - region_names: &'a HashSet -} - -struct Rebuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, - fn_decl: &'a hir::FnDecl, - generics: &'a hir::Generics, - same_regions: &'a [SameRegions], - life_giver: &'a LifeGiver, - cur_anon: Cell, - inserted_anons: RefCell>, -} - -enum FreshOrKept { - Fresh, - Kept -} - -impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { - fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, - fn_decl: &'a hir::FnDecl, - generics: &'a hir::Generics, - same_regions: &'a [SameRegions], - life_giver: &'a LifeGiver) - -> Rebuilder<'a, 'gcx, 'tcx> { - Rebuilder { - tcx: tcx, - fn_decl: fn_decl, - generics: generics, - same_regions: same_regions, - life_giver: life_giver, - cur_anon: Cell::new(0), - inserted_anons: RefCell::new(HashSet::new()), - } - } - - fn rebuild(&self) -> (hir::FnDecl, hir::Generics) { - let mut inputs = self.fn_decl.inputs.clone(); - let mut output = self.fn_decl.output.clone(); - let mut ty_params = self.generics.ty_params.clone(); - let where_clause = self.generics.where_clause.clone(); - let mut kept_lifetimes = HashSet::new(); - for sr in self.same_regions { - self.cur_anon.set(0); - self.offset_cur_anon(); - let (anon_nums, region_names) = - self.extract_anon_nums_and_names(sr); - let (lifetime, fresh_or_kept) = self.pick_lifetime(®ion_names); - match fresh_or_kept { - Kept => { kept_lifetimes.insert(lifetime.name); } - _ => () - } - inputs = self.rebuild_args_ty(&inputs[..], lifetime, - &anon_nums, ®ion_names); - output = self.rebuild_output(&output, lifetime, &anon_nums, ®ion_names); - ty_params = self.rebuild_ty_params(ty_params, lifetime, - ®ion_names); - } - let fresh_lifetimes = self.life_giver.get_generated_lifetimes(); - let all_region_names = self.extract_all_region_names(); - let generics = self.rebuild_generics(self.generics, - &fresh_lifetimes, - &kept_lifetimes, - &all_region_names, - ty_params, - where_clause); - let new_fn_decl = hir::FnDecl { - inputs: inputs, - output: output, - variadic: self.fn_decl.variadic - }; - (new_fn_decl, generics) - } - - fn pick_lifetime(&self, - region_names: &HashSet) - -> (hir::Lifetime, FreshOrKept) { - if !region_names.is_empty() { - // It's not necessary to convert the set of region names to a - // vector of string and then sort them. However, it makes the - // choice of lifetime name deterministic and thus easier to test. - let mut names = Vec::new(); - for rn in region_names { - let lt_name = rn.to_string(); - names.push(lt_name); - } - names.sort(); - let name = Symbol::intern(&names[0]); - return (name_to_dummy_lifetime(name), Kept); - } - return (self.life_giver.give_lifetime(), Fresh); - } - - fn extract_anon_nums_and_names(&self, same_regions: &SameRegions) - -> (HashSet, HashSet) { - let mut anon_nums = HashSet::new(); - let mut region_names = HashSet::new(); - for br in &same_regions.regions { - match *br { - ty::BrAnon(i) => { - anon_nums.insert(i); - } - ty::BrNamed(_, name, _) => { - region_names.insert(name); - } - _ => () - } - } - (anon_nums, region_names) - } - - fn extract_all_region_names(&self) -> HashSet { - let mut all_region_names = HashSet::new(); - for sr in self.same_regions { - for br in &sr.regions { - match *br { - ty::BrNamed(_, name, _) => { - all_region_names.insert(name); - } - _ => () - } - } - } - all_region_names - } - - fn inc_cur_anon(&self, n: u32) { - let anon = self.cur_anon.get(); - self.cur_anon.set(anon+n); - } - - fn offset_cur_anon(&self) { - let mut anon = self.cur_anon.get(); - while self.inserted_anons.borrow().contains(&anon) { - anon += 1; - } - self.cur_anon.set(anon); - } - - fn inc_and_offset_cur_anon(&self, n: u32) { - self.inc_cur_anon(n); - self.offset_cur_anon(); - } - - fn track_anon(&self, anon: u32) { - self.inserted_anons.borrow_mut().insert(anon); - } - - fn rebuild_ty_params(&self, - ty_params: hir::HirVec, - lifetime: hir::Lifetime, - region_names: &HashSet) - -> hir::HirVec { - ty_params.into_iter().map(|ty_param| { - let bounds = self.rebuild_ty_param_bounds(ty_param.bounds, - lifetime, - region_names); - hir::TyParam { - name: ty_param.name, - id: ty_param.id, - bounds: bounds, - default: ty_param.default, - span: ty_param.span, - pure_wrt_drop: ty_param.pure_wrt_drop, - } - }).collect() - } - - fn rebuild_ty_param_bounds(&self, - ty_param_bounds: hir::TyParamBounds, - lifetime: hir::Lifetime, - region_names: &HashSet) - -> hir::TyParamBounds { - ty_param_bounds.iter().map(|tpb| { - match tpb { - &hir::RegionTyParamBound(lt) => { - // FIXME -- it's unclear whether I'm supposed to - // substitute lifetime here. I suspect we need to - // be passing down a map. - hir::RegionTyParamBound(lt) - } - &hir::TraitTyParamBound(ref poly_tr, modifier) => { - let tr = &poly_tr.trait_ref; - let last_seg = tr.path.segments.last().unwrap(); - let mut insert = Vec::new(); - let lifetimes = last_seg.parameters.lifetimes(); - for (i, lt) in lifetimes.iter().enumerate() { - if region_names.contains(<.name) { - insert.push(i as u32); - } - } - let rebuild_info = RebuildPathInfo { - path: &tr.path, - indexes: insert, - expected: lifetimes.len() as u32, - anon_nums: &HashSet::new(), - region_names: region_names - }; - let new_path = self.rebuild_path(rebuild_info, lifetime); - hir::TraitTyParamBound(hir::PolyTraitRef { - bound_lifetimes: poly_tr.bound_lifetimes.clone(), - trait_ref: hir::TraitRef { - path: new_path, - ref_id: tr.ref_id, - }, - span: poly_tr.span, - }, modifier) - } - } - }).collect() - } - - fn rebuild_generics(&self, - generics: &hir::Generics, - add: &Vec, - keep: &HashSet, - remove: &HashSet, - ty_params: hir::HirVec, - where_clause: hir::WhereClause) - -> hir::Generics { - let mut lifetimes = Vec::new(); - for lt in add { - lifetimes.push(hir::LifetimeDef { - lifetime: *lt, - bounds: hir::HirVec::new(), - pure_wrt_drop: false, - }); - } - for lt in &generics.lifetimes { - if keep.contains(<.lifetime.name) || - !remove.contains(<.lifetime.name) { - lifetimes.push((*lt).clone()); - } - } - hir::Generics { - lifetimes: lifetimes.into(), - ty_params: ty_params, - where_clause: where_clause, - span: generics.span, - } - } - - fn rebuild_args_ty(&self, - inputs: &[hir::Arg], - lifetime: hir::Lifetime, - anon_nums: &HashSet, - region_names: &HashSet) - -> hir::HirVec { - let mut new_inputs = Vec::new(); - for arg in inputs { - let new_ty = self.rebuild_arg_ty_or_output(&arg.ty, lifetime, - anon_nums, region_names); - let possibly_new_arg = hir::Arg { - ty: new_ty, - pat: arg.pat.clone(), - id: arg.id - }; - new_inputs.push(possibly_new_arg); - } - new_inputs.into() - } - - fn rebuild_output(&self, ty: &hir::FunctionRetTy, - lifetime: hir::Lifetime, - anon_nums: &HashSet, - region_names: &HashSet) -> hir::FunctionRetTy { - match *ty { - hir::Return(ref ret_ty) => hir::Return( - self.rebuild_arg_ty_or_output(&ret_ty, lifetime, anon_nums, region_names) - ), - hir::DefaultReturn(span) => hir::DefaultReturn(span), - } - } - - fn rebuild_arg_ty_or_output(&self, - ty: &hir::Ty, - lifetime: hir::Lifetime, - anon_nums: &HashSet, - region_names: &HashSet) - -> P { - let mut new_ty = P(ty.clone()); - let mut ty_queue = vec![ty]; - while !ty_queue.is_empty() { - let cur_ty = ty_queue.remove(0); - match cur_ty.node { - hir::TyRptr(lt_opt, ref mut_ty) => { - let rebuild = match lt_opt { - Some(lt) => region_names.contains(<.name), - None => { - let anon = self.cur_anon.get(); - let rebuild = anon_nums.contains(&anon); - if rebuild { - self.track_anon(anon); - } - self.inc_and_offset_cur_anon(1); - rebuild - } - }; - if rebuild { - let to = hir::Ty { - id: cur_ty.id, - node: hir::TyRptr(Some(lifetime), mut_ty.clone()), - span: cur_ty.span - }; - new_ty = self.rebuild_ty(new_ty, P(to)); - } - ty_queue.push(&mut_ty.ty); - } - hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => { - match path.def { - Def::Enum(did) | Def::TyAlias(did) | - Def::Struct(did) | Def::Union(did) => { - let generics = self.tcx.item_generics(did); - - let expected = - generics.regions.len() as u32; - let lifetimes = - path.segments.last().unwrap().parameters.lifetimes(); - let mut insert = Vec::new(); - if lifetimes.is_empty() { - let anon = self.cur_anon.get(); - for (i, a) in (anon..anon+expected).enumerate() { - if anon_nums.contains(&a) { - insert.push(i as u32); - } - self.track_anon(a); - } - self.inc_and_offset_cur_anon(expected); - } else { - for (i, lt) in lifetimes.iter().enumerate() { - if region_names.contains(<.name) { - insert.push(i as u32); - } - } - } - let rebuild_info = RebuildPathInfo { - path: path, - indexes: insert, - expected: expected, - anon_nums: anon_nums, - region_names: region_names - }; - let new_path = self.rebuild_path(rebuild_info, lifetime); - let qself = maybe_qself.as_ref().map(|qself| { - self.rebuild_arg_ty_or_output(qself, lifetime, - anon_nums, region_names) - }); - let to = hir::Ty { - id: cur_ty.id, - node: hir::TyPath(hir::QPath::Resolved(qself, P(new_path))), - span: cur_ty.span - }; - new_ty = self.rebuild_ty(new_ty, P(to)); - } - _ => () - } - } - - hir::TyPtr(ref mut_ty) => { - ty_queue.push(&mut_ty.ty); - } - hir::TySlice(ref ty) | - hir::TyArray(ref ty, _) => { - ty_queue.push(&ty); - } - hir::TyTup(ref tys) => ty_queue.extend(tys.iter().map(|ty| &**ty)), - _ => {} - } - } - new_ty - } - - fn rebuild_ty(&self, - from: P, - to: P) - -> P { - - fn build_to(from: P, - to: &mut Option>) - -> P { - if Some(from.id) == to.as_ref().map(|ty| ty.id) { - return to.take().expect("`to` type found more than once during rebuild"); - } - from.map(|hir::Ty {id, node, span}| { - let new_node = match node { - hir::TyRptr(lifetime, mut_ty) => { - hir::TyRptr(lifetime, hir::MutTy { - mutbl: mut_ty.mutbl, - ty: build_to(mut_ty.ty, to), - }) - } - hir::TyPtr(mut_ty) => { - hir::TyPtr(hir::MutTy { - mutbl: mut_ty.mutbl, - ty: build_to(mut_ty.ty, to), - }) - } - hir::TySlice(ty) => hir::TySlice(build_to(ty, to)), - hir::TyArray(ty, e) => { - hir::TyArray(build_to(ty, to), e) - } - hir::TyTup(tys) => { - hir::TyTup(tys.into_iter().map(|ty| build_to(ty, to)).collect()) - } - other => other - }; - hir::Ty { id: id, node: new_node, span: span } - }) - } - - build_to(from, &mut Some(to)) - } - - fn rebuild_path(&self, - rebuild_info: RebuildPathInfo, - lifetime: hir::Lifetime) - -> hir::Path - { - let RebuildPathInfo { - path, - indexes, - expected, - anon_nums, - region_names, - } = rebuild_info; - - let last_seg = path.segments.last().unwrap(); - let new_parameters = match last_seg.parameters { - hir::ParenthesizedParameters(..) => { - last_seg.parameters.clone() - } - - hir::AngleBracketedParameters(ref data) => { - let mut new_lts = Vec::new(); - if data.lifetimes.is_empty() { - // traverse once to see if there's a need to insert lifetime - let need_insert = (0..expected).any(|i| { - indexes.contains(&i) - }); - if need_insert { - for i in 0..expected { - if indexes.contains(&i) { - new_lts.push(lifetime); - } else { - new_lts.push(self.life_giver.give_lifetime()); - } - } - } - } else { - for (i, lt) in data.lifetimes.iter().enumerate() { - if indexes.contains(&(i as u32)) { - new_lts.push(lifetime); - } else { - new_lts.push(*lt); - } - } - } - let new_types = data.types.iter().map(|t| { - self.rebuild_arg_ty_or_output(&t, lifetime, anon_nums, region_names) - }).collect(); - let new_bindings = data.bindings.iter().map(|b| { - hir::TypeBinding { - id: b.id, - name: b.name, - ty: self.rebuild_arg_ty_or_output(&b.ty, - lifetime, - anon_nums, - region_names), - span: b.span - } - }).collect(); - hir::AngleBracketedParameters(hir::AngleBracketedParameterData { - lifetimes: new_lts.into(), - types: new_types, - infer_types: data.infer_types, - bindings: new_bindings, - }) - } - }; - let new_seg = hir::PathSegment { - name: last_seg.name, - parameters: new_parameters - }; - let mut new_segs = Vec::new(); - new_segs.extend_from_slice(path.segments.split_last().unwrap().1); - new_segs.push(new_seg); - hir::Path { - span: path.span, - global: path.global, - def: path.def, - segments: new_segs.into() - } - } -} - impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn give_expl_lifetime_param(&self, - err: &mut DiagnosticBuilder, - decl: &hir::FnDecl, - unsafety: hir::Unsafety, - constness: hir::Constness, - name: ast::Name, - generics: &hir::Generics, - span: Span) { - let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, name, generics); - let msg = format!("consider using an explicit lifetime \ - parameter as shown: {}", suggested_fn); - err.span_help(span, &msg[..]); - } - fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> DiagnosticBuilder<'tcx> { @@ -1880,114 +1093,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } -fn lifetimes_in_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - scope_id: ast::NodeId) - -> Vec { - let mut taken = Vec::new(); - let parent = tcx.map.get_parent(scope_id); - let method_id_opt = match tcx.map.find(parent) { - Some(node) => match node { - ast_map::NodeItem(item) => match item.node { - hir::ItemFn(.., ref gen, _) => { - taken.extend_from_slice(&gen.lifetimes); - None - }, - _ => None - }, - ast_map::NodeImplItem(ii) => { - match ii.node { - hir::ImplItemKind::Method(ref sig, _) => { - taken.extend_from_slice(&sig.generics.lifetimes); - Some(ii.id) - } - _ => None, - } - } - _ => None - }, - None => None - }; - if let Some(method_id) = method_id_opt { - let parent = tcx.map.get_parent(method_id); - if let Some(node) = tcx.map.find(parent) { - match node { - ast_map::NodeItem(item) => match item.node { - hir::ItemImpl(_, _, ref gen, ..) => { - taken.extend_from_slice(&gen.lifetimes); - } - _ => () - }, - _ => () - } - } - } - return taken; -} - -// LifeGiver is responsible for generating fresh lifetime names -struct LifeGiver { - taken: HashSet, - counter: Cell, - generated: RefCell>, -} - -impl LifeGiver { - fn with_taken(taken: &[hir::LifetimeDef]) -> LifeGiver { - let mut taken_ = HashSet::new(); - for lt in taken { - let lt_name = lt.lifetime.name.to_string(); - taken_.insert(lt_name); - } - LifeGiver { - taken: taken_, - counter: Cell::new(0), - generated: RefCell::new(Vec::new()), - } - } - - fn inc_counter(&self) { - let c = self.counter.get(); - self.counter.set(c+1); - } - - fn give_lifetime(&self) -> hir::Lifetime { - let lifetime; - loop { - let mut s = String::from("'"); - s.push_str(&num_to_string(self.counter.get())); - if !self.taken.contains(&s) { - lifetime = name_to_dummy_lifetime(Symbol::intern(&s)); - self.generated.borrow_mut().push(lifetime); - break; - } - self.inc_counter(); - } - self.inc_counter(); - return lifetime; - - // 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on - fn num_to_string(counter: usize) -> String { - let mut s = String::new(); - let (n, r) = (counter/26 + 1, counter % 26); - let letter: char = from_u32((r+97) as u32).unwrap(); - for _ in 0..n { - s.push(letter); - } - s - } - } - - fn get_generated_lifetimes(&self) -> Vec { - self.generated.borrow().clone() - } -} - -fn name_to_dummy_lifetime(name: ast::Name) -> hir::Lifetime { - hir::Lifetime { id: ast::DUMMY_NODE_ID, - span: syntax_pos::DUMMY_SP, - name: name } -} - impl<'tcx> ObligationCause<'tcx> { fn as_failure_str(&self) -> &'static str { use traits::ObligationCauseCode::*; @@ -2028,4 +1133,3 @@ impl<'tcx> ObligationCause<'tcx> { } } } - diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 19183892e4..697a1ecadc 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -156,7 +156,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::TyUint(..) | ty::TyFloat(..) | ty::TyAdt(..) | - ty::TyBox(..) | ty::TyStr | ty::TyError | ty::TyArray(..) | diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 9b58334e65..ef93a10808 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -23,11 +23,9 @@ use hir; use middle::free_region::FreeRegionMap; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; -use middle::region::CodeExtent; use middle::lang_items; use mir::tcx::LvalueTy; use ty::subst::{Kind, Subst, Substs}; -use ty::adjustment; use ty::{TyVid, IntVid, FloatVid}; use ty::{self, Ty, TyCtxt}; use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; @@ -37,10 +35,12 @@ use traits::{self, ObligationCause, PredicateObligations, Reveal}; use rustc_data_structures::unify::{self, UnificationTable}; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::fmt; +use std::ops::Deref; use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; -use util::nodemap::{FxHashMap, FxHashSet, NodeMap}; +use util::nodemap::{FxHashMap, FxHashSet}; +use arena::DroplessArena; use self::combine::CombineFields; use self::higher_ranked::HrMatchResult; @@ -75,28 +75,63 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" -/// A version of &ty::Tables which can be global or local. -/// Only the local version supports borrow_mut. +/// A version of &ty::TypeckTables which can be `Missing` (not needed), +/// `InProgress` (during typeck) or `Interned` (result of typeck). +/// Only the `InProgress` version supports `borrow_mut`. #[derive(Copy, Clone)] pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - Global(&'a RefCell>), - Local(&'a RefCell>) + Interned(&'a ty::TypeckTables<'gcx>), + InProgress(&'a RefCell>), + Missing +} + +pub enum InferTablesRef<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + Interned(&'a ty::TypeckTables<'gcx>), + InProgress(Ref<'a, ty::TypeckTables<'tcx>>) +} + +impl<'a, 'gcx, 'tcx> Deref for InferTablesRef<'a, 'gcx, 'tcx> { + type Target = ty::TypeckTables<'tcx>; + fn deref(&self) -> &Self::Target { + match *self { + InferTablesRef::Interned(tables) => tables, + InferTablesRef::InProgress(ref tables) => tables + } + } } impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> { - pub fn borrow(self) -> Ref<'a, ty::Tables<'tcx>> { + pub fn borrow(self) -> InferTablesRef<'a, 'gcx, 'tcx> { + match self { + InferTables::Interned(tables) => InferTablesRef::Interned(tables), + InferTables::InProgress(tables) => InferTablesRef::InProgress(tables.borrow()), + InferTables::Missing => { + bug!("InferTables: infcx.tables.borrow() with no tables") + } + } + } + + pub fn expect_interned(self) -> &'a ty::TypeckTables<'gcx> { match self { - InferTables::Global(tables) => tables.borrow(), - InferTables::Local(tables) => tables.borrow() + InferTables::Interned(tables) => tables, + InferTables::InProgress(_) => { + bug!("InferTables: infcx.tables.expect_interned() during type-checking"); + } + InferTables::Missing => { + bug!("InferTables: infcx.tables.expect_interned() with no tables") + } } } - pub fn borrow_mut(self) -> RefMut<'a, ty::Tables<'tcx>> { + pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { match self { - InferTables::Global(_) => { + InferTables::Interned(_) => { bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking"); } - InferTables::Local(tables) => tables.borrow_mut() + InferTables::InProgress(tables) => tables.borrow_mut(), + InferTables::Missing => { + bug!("InferTables: infcx.tables.borrow_mut() with no tables") + } } } } @@ -369,27 +404,84 @@ impl fmt::Display for FixupError { } } +pub trait InferEnv<'a, 'tcx> { + fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::TypeckTables<'tcx>>, + Option>, + Option>); +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for () { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::TypeckTables<'tcx>>, + Option>, + Option>) { + (None, None, None) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParameterEnvironment<'tcx> { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::TypeckTables<'tcx>>, + Option>, + Option>) { + (None, None, Some(self)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::TypeckTables<'tcx>>, + Option>, + Option>) { + (Some(self.0), None, Some(self.1)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::TypeckTables<'tcx>>, + Option>, + Option>) { + (None, Some(self.0), Some(self.1)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId { + fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::TypeckTables<'tcx>>, + Option>, + Option>) { + let item_id = tcx.hir.body_owner(self); + (Some(tcx.item_tables(tcx.hir.local_def_id(item_id))), + None, + Some(ty::ParameterEnvironment::for_item(tcx, item_id))) + } +} + /// 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> { global_tcx: TyCtxt<'a, 'gcx, 'gcx>, - arenas: ty::CtxtArenas<'tcx>, - tables: Option>>, + arena: DroplessArena, + fresh_tables: Option>>, + tables: Option<&'a ty::TypeckTables<'gcx>>, param_env: Option>, projection_mode: Reveal, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { - pub fn infer_ctxt(self, - tables: Option>, - param_env: Option>, - projection_mode: Reveal) - -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + pub fn infer_ctxt>(self, + env: E, + projection_mode: Reveal) + -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + let (tables, fresh_tables, param_env) = env.to_parts(self); InferCtxtBuilder { global_tcx: self, - arenas: ty::CtxtArenas::new(), - tables: tables.map(RefCell::new), + arena: DroplessArena::new(), + fresh_tables: fresh_tables.map(RefCell::new), + tables: tables, param_env: param_env, projection_mode: projection_mode, } @@ -398,16 +490,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck /// for MemCategorizationContext/ExprUseVisitor. /// If any inference functionality is used, ICEs will occur. - pub fn borrowck_fake_infer_ctxt(self, param_env: ty::ParameterEnvironment<'gcx>) + pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId) -> InferCtxt<'a, 'gcx, 'gcx> { + let (tables, _, param_env) = body.to_parts(self); InferCtxt { tcx: self, - tables: InferTables::Global(&self.tables), + tables: InferTables::Interned(tables.unwrap()), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), float_unification_table: RefCell::new(UnificationTable::new()), region_vars: RegionVarBindings::new(self), - parameter_environment: param_env, + parameter_environment: param_env.unwrap(), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), projection_cache: RefCell::new(traits::ProjectionCache::new()), @@ -426,20 +519,19 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { { let InferCtxtBuilder { global_tcx, - ref arenas, - ref tables, + ref arena, + ref fresh_tables, + tables, ref mut param_env, projection_mode, } = *self; - let tables = if let Some(ref tables) = *tables { - InferTables::Local(tables) - } else { - InferTables::Global(&global_tcx.tables) - }; + let tables = tables.map(InferTables::Interned).unwrap_or_else(|| { + fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress) + }); let param_env = param_env.take().unwrap_or_else(|| { global_tcx.empty_parameter_environment() }); - global_tcx.enter_local(arenas, |tcx| f(InferCtxt { + global_tcx.enter_local(arena, |tcx| f(InferCtxt { tcx: tcx, tables: tables, projection_cache: RefCell::new(traits::ProjectionCache::new()), @@ -554,7 +646,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + self.infer_ctxt((), Reveal::All).enter(|infcx| { value.trans_normalize(&infcx) }) } @@ -572,7 +664,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(None, Some(env.clone()), Reveal::All).enter(|infcx| { + self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| { value.trans_normalize(&infcx) }) } @@ -1176,7 +1268,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.types.err, None => { bug!("no type for node {}: {} in fcx", - id, self.tcx.map.node_to_string(id)); + id, self.tcx.hir.node_to_string(id)); } } } @@ -1367,9 +1459,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, - err: TypeError<'tcx>) { + err: TypeError<'tcx>) + -> DiagnosticBuilder<'tcx> { let trace = TypeTrace::types(cause, true, expected, actual); - self.report_and_explain_type_error(trace, &err).emit(); + self.report_and_explain_type_error(trace, &err) } pub fn report_conflicting_default_types(&self, @@ -1488,8 +1581,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Even if the type may have no inference variables, during // type-checking closure types are in local tables only. let local_closures = match self.tables { - InferTables::Local(_) => ty.has_closure_types(), - InferTables::Global(_) => false + InferTables::InProgress(_) => ty.has_closure_types(), + _ => false }; if !local_closures { return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span); @@ -1524,23 +1617,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .map(|method| method.def_id) } - pub fn adjustments(&self) -> Ref>> { - fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) - -> &'a NodeMap> { - &tables.adjustments - } - - Ref::map(self.tables.borrow(), project_adjustments) - } - pub fn is_method_call(&self, id: ast::NodeId) -> bool { self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) } - pub fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option { - self.tcx.region_maps.temporary_scope(rvalue_id) - } - pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() } @@ -1553,15 +1633,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { def_id: DefId) -> Option { - if def_id.is_local() { - self.tables.borrow().closure_kinds.get(&def_id).cloned() - } else { - // During typeck, ALL closures are local. But afterwards, - // during trans, we see closure ids from other traits. - // That may require loading the closure data out of the - // cstore. - Some(self.tcx.closure_kind(def_id)) + if let InferTables::InProgress(tables) = self.tables { + if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { + return tables.borrow().closure_kinds.get(&id).cloned(); + } } + + // During typeck, ALL closures are local. But afterwards, + // during trans, we see closure ids from other traits. + // That may require loading the closure data out of the + // cstore. + Some(self.tcx.closure_kind(def_id)) } pub fn closure_type(&self, @@ -1569,14 +1651,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { substs: ty::ClosureSubsts<'tcx>) -> ty::ClosureTy<'tcx> { - if let InferTables::Local(tables) = self.tables { - if let Some(ty) = tables.borrow().closure_tys.get(&def_id) { - return ty.subst(self.tcx, substs.substs); + if let InferTables::InProgress(tables) = self.tables { + if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { + if let Some(ty) = tables.borrow().closure_tys.get(&id) { + return ty.subst(self.tcx, substs.substs); + } } } - let closure_ty = self.tcx.closure_type(def_id, substs); - closure_ty + self.tcx.closure_type(def_id, substs) } } diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index af6f2c50e7..0bb9e2c7fa 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -24,7 +24,7 @@ use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING}; use rustc_data_structures::unify::{self, UnificationTable}; use middle::free_region::FreeRegionMap; use ty::{self, Ty, TyCtxt}; -use ty::{BoundRegion, Region, RegionVid}; +use ty::{Region, RegionVid}; use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased}; use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh}; @@ -171,13 +171,6 @@ pub enum RegionResolutionError<'tcx> { &'tcx Region, SubregionOrigin<'tcx>, &'tcx Region), - - /// For subsets of `ConcreteFailure` and `SubSupConflict`, we can derive - /// more specific errors message by suggesting to the user where they - /// should put a lifetime. In those cases we process and put those errors - /// into `ProcessedErrors` before we do any reporting. - ProcessedErrors(Vec>, - Vec), } #[derive(Clone, Debug)] @@ -186,33 +179,6 @@ pub enum ProcessedErrorOrigin<'tcx> { VariableFailure(RegionVariableOrigin), } -/// SameRegions is used to group regions that we think are the same and would -/// like to indicate so to the user. -/// For example, the following function -/// ``` -/// struct Foo { bar: i32 } -/// fn foo2<'a, 'b>(x: &'a Foo) -> &'b i32 { -/// &x.bar -/// } -/// ``` -/// would report an error because we expect 'a and 'b to match, and so we group -/// 'a and 'b together inside a SameRegions struct -#[derive(Clone, Debug)] -pub struct SameRegions { - pub scope_id: ast::NodeId, - pub regions: Vec, -} - -impl SameRegions { - pub fn contains(&self, other: &BoundRegion) -> bool { - self.regions.contains(other) - } - - pub fn push(&mut self, other: BoundRegion) { - self.regions.push(other); - } -} - pub type CombineMap<'tcx> = FxHashMap, RegionVid>; pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 17cc34fcd8..0ff9626ae1 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -21,29 +21,28 @@ #![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/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(associated_consts)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(collections)] #![feature(conservative_impl_trait)] #![feature(const_fn)] #![feature(core_intrinsics)] -#![cfg_attr(stage0, feature(item_like_imports))] +#![feature(field_init_shorthand)] #![feature(libc)] +#![feature(loop_break_value)] #![feature(nonzero)] +#![feature(pub_restricted)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(staged_api)] #![feature(unboxed_closures)] -#![cfg_attr(test, feature(test))] extern crate arena; extern crate core; -extern crate flate; extern crate fmt_macros; extern crate getopts; extern crate graphviz; @@ -52,18 +51,17 @@ extern crate rustc_llvm as llvm; extern crate rustc_back; extern crate rustc_data_structures; extern crate serialize; -extern crate collections; extern crate rustc_const_math; extern crate rustc_errors as errors; #[macro_use] extern crate log; #[macro_use] extern crate syntax; -#[macro_use] extern crate syntax_pos; +extern crate syntax_pos; #[macro_use] #[no_link] extern crate rustc_bitflags; extern crate serialize as rustc_serialize; // used by deriving -#[cfg(test)] -extern crate test; +// SNAP: +extern crate rustc_i128; #[macro_use] mod macros; @@ -80,9 +78,8 @@ pub mod lint; pub mod middle { pub mod astconv_util; - pub mod expr_use_visitor; // STAGE0: increase glitch immunity + pub mod expr_use_visitor; pub mod const_val; - pub mod const_qualif; pub mod cstore; pub mod dataflow; pub mod dead; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 667c2590fa..b0db3b7502 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -70,6 +70,12 @@ declare_lint! { "detects unreachable code paths" } +declare_lint! { + pub UNREACHABLE_PATTERNS, + Warn, + "detects unreachable patterns" +} + declare_lint! { pub WARNINGS, Warn, @@ -200,7 +206,7 @@ declare_lint! { declare_lint! { pub EXTRA_REQUIREMENT_IN_IMPL, - Warn, + Deny, "detects extra requirements in impls that were erroneously allowed" } @@ -239,6 +245,7 @@ impl LintPass for HardwiredLints { UNUSED_ASSIGNMENTS, DEAD_CODE, UNREACHABLE_CODE, + UNREACHABLE_PATTERNS, WARNINGS, UNUSED_FEATURES, STABLE_FEATURES, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 3ff2abac27..3506a9c067 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -27,7 +27,7 @@ use self::TargetLint::*; use dep_graph::DepNode; use middle::privacy::AccessLevels; -use ty::TyCtxt; +use ty::{self, TyCtxt}; use session::{config, early_error, Session}; use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource}; use lint::{EarlyLintPassObject, LateLintPassObject}; @@ -336,6 +336,9 @@ pub struct LateContext<'a, 'tcx: 'a> { /// Type context we're checking in. pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + /// Side-tables for the body we are in. + pub tables: &'a ty::TypeckTables<'tcx>, + /// The crate being checked. pub krate: &'a hir::Crate, @@ -559,7 +562,7 @@ pub trait LintContext<'tcx>: Sized { let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span"); let mut err = self.struct_span_lint(early_lint.id.lint, span, - &early_lint.diagnostic.message); + &early_lint.diagnostic.message()); err.copy_details_not_message(&early_lint.diagnostic); err.emit(); } @@ -702,33 +705,6 @@ impl<'a> EarlyContext<'a> { } } -impl<'a, 'tcx> LateContext<'a, 'tcx> { - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - krate: &'a hir::Crate, - access_levels: &'a AccessLevels) -> LateContext<'a, 'tcx> { - // We want to own the lint store, so move it out of the session. - let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), - LintStore::new()); - - LateContext { - tcx: tcx, - krate: krate, - access_levels: access_levels, - lints: lint_store, - level_stack: vec![], - } - } - - fn visit_ids<'b, F: 'b>(&'b mut self, f: F) - where F: FnOnce(&mut IdVisitor<'b, 'a, 'tcx>) - { - let mut v = IdVisitor::<'b, 'a, 'tcx> { - cx: self - }; - f(&mut v); - } -} - impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> { /// Get the overall compiler `Session` object. fn sess(&self) -> &Session { @@ -792,13 +768,30 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { /// items in the context of the outer item, so enable /// deep-walking. fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'tcx> { - hir_visit::NestedVisitorMap::All(&self.tcx.map) + hir_visit::NestedVisitorMap::All(&self.tcx.hir) + } + + // Output any lints that were previously added to the session. + fn visit_id(&mut self, id: ast::NodeId) { + if let Some(lints) = self.sess().lints.borrow_mut().remove(&id) { + debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints); + for early_lint in lints { + self.early_lint(early_lint); + } + } + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.hir.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_item(&mut self, it: &'tcx hir::Item) { self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_item, late_passes, it); - cx.visit_ids(|v| v.visit_item(it)); hir_visit::walk_item(cx, it); run_lints!(cx, check_item_post, late_passes, it); }) @@ -821,6 +814,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { self.with_lint_attrs(&e.attrs, |cx| { run_lints!(cx, check_expr, late_passes, e); hir_visit::walk_expr(cx, e); + run_lints!(cx, check_expr_post, late_passes, e); }) } @@ -835,11 +829,16 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, span: Span, id: ast::NodeId) { - let body = self.tcx.map.expr(body_id); + body_id: hir::BodyId, span: Span, id: ast::NodeId) { + // Wrap in tables here, not just in visit_nested_body, + // in order for `check_fn` to be able to use them. + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body_id); + let body = self.tcx.hir.body(body_id); run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body_id, span, id); run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id); + self.tables = old_tables; } fn visit_variant_data(&mut self, @@ -909,10 +908,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::walk_decl(self, d); } - fn visit_expr_post(&mut self, e: &'tcx hir::Expr) { - run_lints!(self, check_expr_post, late_passes, e); - } - fn visit_generics(&mut self, g: &'tcx hir::Generics) { run_lints!(self, check_generics, late_passes, g); hir_visit::walk_generics(self, g); @@ -921,7 +916,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { self.with_lint_attrs(&trait_item.attrs, |cx| { run_lints!(cx, check_trait_item, late_passes, trait_item); - cx.visit_ids(|v| hir_visit::walk_trait_item(v, trait_item)); hir_visit::walk_trait_item(cx, trait_item); run_lints!(cx, check_trait_item_post, late_passes, trait_item); }); @@ -930,7 +924,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { self.with_lint_attrs(&impl_item.attrs, |cx| { run_lints!(cx, check_impl_item, late_passes, impl_item); - cx.visit_ids(|v| hir_visit::walk_impl_item(v, impl_item)); hir_visit::walk_impl_item(cx, impl_item); run_lints!(cx, check_impl_item_post, late_passes, impl_item); }); @@ -938,10 +931,12 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { run_lints!(self, check_lifetime, late_passes, lt); + hir_visit::walk_lifetime(self, lt); } fn visit_lifetime_def(&mut self, lt: &'tcx hir::LifetimeDef) { run_lints!(self, check_lifetime_def, late_passes, lt); + hir_visit::walk_lifetime_def(self, lt); } fn visit_path(&mut self, p: &'tcx hir::Path, id: ast::NodeId) { @@ -1103,35 +1098,6 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { } } -struct IdVisitor<'a, 'b: 'a, 'tcx: 'a+'b> { - cx: &'a mut LateContext<'b, 'tcx> -} - -// Output any lints that were previously added to the session. -impl<'a, 'b, 'tcx> hir_visit::Visitor<'tcx> for IdVisitor<'a, 'b, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'tcx> { - hir_visit::NestedVisitorMap::OnlyBodies(&self.cx.tcx.map) - } - - fn visit_id(&mut self, id: ast::NodeId) { - if let Some(lints) = self.cx.sess().lints.borrow_mut().remove(&id) { - debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints); - for early_lint in lints { - self.cx.early_lint(early_lint); - } - } - } - - fn visit_trait_item(&mut self, _ti: &'tcx hir::TraitItem) { - // Do not recurse into trait or impl items automatically. These are - // processed separately by calling hir_visit::walk_trait_item() - } - - fn visit_impl_item(&mut self, _ii: &'tcx hir::ImplItem) { - // See visit_trait_item() - } -} - enum CheckLintNameResult { Ok, // Lint doesn't exist @@ -1240,15 +1206,21 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &AccessLevels) { let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck); - let krate = tcx.map.krate(); - let mut cx = LateContext::new(tcx, krate, access_levels); + let krate = tcx.hir.krate(); + + // We want to own the lint store, so move it out of the session. + let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), LintStore::new()); + let mut cx = LateContext { + tcx: tcx, + tables: &ty::TypeckTables::empty(), + krate: krate, + access_levels: access_levels, + lints: lint_store, + level_stack: vec![], + }; // Visit the whole crate. cx.with_lint_attrs(&krate.attrs, |cx| { - cx.visit_ids(|v| { - hir_visit::walk_crate(v, krate); - }); - // since the root module isn't visited as an item (because it isn't an // item), warn for it here. run_lints!(cx, check_crate, late_passes, krate); @@ -1264,7 +1236,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for early_lint in v { span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?} at {}", - early_lint, tcx.map.node_to_string(*id)); + early_lint, tcx.hir.node_to_string(*id)); } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index ccf53f01cd..7e0da00694 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -162,14 +162,14 @@ pub trait LateLintPass<'a, 'tcx>: LintPass { _: &LateContext<'a, 'tcx>, _: FnKind<'tcx>, _: &'tcx hir::FnDecl, - _: &'tcx hir::Expr, + _: &'tcx hir::Body, _: Span, _: ast::NodeId) { } fn check_fn_post(&mut self, _: &LateContext<'a, 'tcx>, _: FnKind<'tcx>, _: &'tcx hir::FnDecl, - _: &'tcx hir::Expr, + _: &'tcx hir::Body, _: Span, _: ast::NodeId) { } fn check_trait_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { } diff --git a/src/librustc/middle/const_qualif.rs b/src/librustc/middle/const_qualif.rs deleted file mode 100644 index ec98637922..0000000000 --- a/src/librustc/middle/const_qualif.rs +++ /dev/null @@ -1,44 +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. - -// Const qualification, from partial to completely promotable. -bitflags! { - #[derive(RustcEncodable, RustcDecodable)] - flags ConstQualif: u8 { - // Inner mutability (can not be placed behind a reference) or behind - // &mut in a non-global expression. Can be copied from static memory. - const MUTABLE_MEM = 1 << 0, - // Constant value with a type that implements Drop. Can be copied - // from static memory, similar to MUTABLE_MEM. - const NEEDS_DROP = 1 << 1, - // Even if the value can be placed in static memory, copying it from - // there is more expensive than in-place instantiation, and/or it may - // be too large. This applies to [T; N] and everything containing it. - // N.B.: references need to clear this flag to not end up on the stack. - const PREFER_IN_PLACE = 1 << 2, - // May use more than 0 bytes of memory, doesn't impact the constness - // directly, but is not allowed to be borrowed mutably in a constant. - const NON_ZERO_SIZED = 1 << 3, - // Actually borrowed, has to always be in static memory. Does not - // propagate, and requires the expression to behave like a 'static - // lvalue. The set of expressions with this flag is the minimum - // that have to be promoted. - const HAS_STATIC_BORROWS = 1 << 4, - // Invalid const for miscellaneous reasons (e.g. not implemented). - const NOT_CONST = 1 << 5, - - // Borrowing the expression won't produce &'static T if any of these - // bits are set, though the value could be copied from static memory - // if `NOT_CONST` isn't set. - const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits | - ConstQualif::NEEDS_DROP.bits | - ConstQualif::NOT_CONST.bits - } -} diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 9677082a43..f583f60172 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -15,6 +15,8 @@ use hir::def_id::DefId; use rustc_const_math::*; use self::ConstVal::*; +use std::collections::BTreeMap; + #[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)] pub enum ConstVal { Float(ConstFloat), @@ -22,16 +24,12 @@ pub enum ConstVal { Str(InternedString), ByteStr(Rc>), Bool(bool), - Struct(ast::NodeId), - Tuple(ast::NodeId), Function(DefId), - Array(ast::NodeId, u64), - Repeat(ast::NodeId, u64), + Struct(BTreeMap), + Tuple(Vec), + Array(Vec), + Repeat(Box, u64), Char(char), - /// A value that only occurs in case `eval_const_expr` reported an error. You should never - /// handle this case. Its sole purpose is to allow more errors to be reported instead of - /// causing a fatal error. - Dummy, } impl ConstVal { @@ -48,7 +46,6 @@ impl ConstVal { Array(..) => "array", Repeat(..) => "repeat", Char(..) => "char", - Dummy => "dummy value", } } } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 7ec0ef0078..d11e6e3fc7 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -25,25 +25,26 @@ use hir::def::{self, Def}; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; -use hir::map::definitions::{Definitions, DefKey}; +use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData}; use hir::svh::Svh; use middle::lang_items; +use middle::resolve_lifetime::ObjectLifetimeDefault; use ty::{self, Ty, TyCtxt}; use mir::Mir; use session::Session; use session::search_paths::PathKind; use util::nodemap::{NodeSet, DefIdMap}; + +use std::collections::BTreeMap; use std::path::PathBuf; use std::rc::Rc; use syntax::ast; use syntax::attr; use syntax::ext::base::SyntaxExtension; -use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_back::target::Target; use hir; -use hir::intravisit::Visitor; use rustc_back::PanicStrategy; pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown}; @@ -134,102 +135,6 @@ pub struct NativeLibrary { pub foreign_items: Vec, } -/// The data we save and restore about an inlined item or method. This is not -/// part of the AST that we parse from a file, but it becomes part of the tree -/// that we trans. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct InlinedItem { - pub def_id: DefId, - pub body: P, - pub const_fn_args: Vec>, -} - -/// A borrowed version of `hir::InlinedItem`. This is what's encoded when saving -/// a crate; it then gets read as an InlinedItem. -#[derive(Clone, PartialEq, Eq, RustcEncodable, Hash, Debug)] -pub struct InlinedItemRef<'a> { - pub def_id: DefId, - pub body: &'a hir::Expr, - pub const_fn_args: Vec>, -} - -fn get_fn_args(decl: &hir::FnDecl) -> Vec> { - decl.inputs.iter().map(|arg| match arg.pat.node { - hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), - _ => None - }).collect() -} - -impl<'a> InlinedItemRef<'a> { - pub fn from_item<'b, 'tcx>(def_id: DefId, - item: &'a hir::Item, - tcx: TyCtxt<'b, 'a, 'tcx>) - -> InlinedItemRef<'a> { - let (body, args) = match item.node { - hir::ItemFn(ref decl, _, _, _, _, body_id) => - (tcx.map.expr(body_id), get_fn_args(decl)), - hir::ItemConst(_, ref body) => (&**body, Vec::new()), - _ => bug!("InlinedItemRef::from_item wrong kind") - }; - InlinedItemRef { - def_id: def_id, - body: body, - const_fn_args: args - } - } - - pub fn from_trait_item(def_id: DefId, - item: &'a hir::TraitItem, - _tcx: TyCtxt) - -> InlinedItemRef<'a> { - let (body, args) = match item.node { - hir::ConstTraitItem(_, Some(ref body)) => - (&**body, Vec::new()), - hir::ConstTraitItem(_, None) => { - bug!("InlinedItemRef::from_trait_item called for const without body") - }, - _ => bug!("InlinedItemRef::from_trait_item wrong kind") - }; - InlinedItemRef { - def_id: def_id, - body: body, - const_fn_args: args - } - } - - pub fn from_impl_item<'b, 'tcx>(def_id: DefId, - item: &'a hir::ImplItem, - tcx: TyCtxt<'b, 'a, 'tcx>) - -> InlinedItemRef<'a> { - let (body, args) = match item.node { - hir::ImplItemKind::Method(ref sig, body_id) => - (tcx.map.expr(body_id), get_fn_args(&sig.decl)), - hir::ImplItemKind::Const(_, ref body) => - (&**body, Vec::new()), - _ => bug!("InlinedItemRef::from_impl_item wrong kind") - }; - InlinedItemRef { - def_id: def_id, - body: body, - const_fn_args: args - } - } - - pub fn visit(&self, visitor: &mut V) - where V: Visitor<'a> - { - visitor.visit_expr(&self.body); - } -} - -impl InlinedItem { - pub fn visit<'ast,V>(&'ast self, visitor: &mut V) - where V: Visitor<'ast> - { - visitor.visit_expr(&self.body); - } -} - pub enum LoadedMacro { MacroRules(ast::MacroDef), ProcMacro(Rc), @@ -278,6 +183,9 @@ pub trait CrateStore<'tcx> { -> ty::GenericPredicates<'tcx>; fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::Generics<'tcx>; + fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize); + fn item_generics_object_lifetime_defaults(&self, def: DefId) + -> Vec; fn item_attrs(&self, def_id: DefId) -> Vec; fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef; fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef; @@ -307,6 +215,7 @@ pub trait CrateStore<'tcx> { fn is_foreign_item(&self, did: DefId) -> bool; fn is_dllimport_foreign_item(&self, def: DefId) -> bool; fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool; + fn is_exported_symbol(&self, def_id: DefId) -> bool; // crate metadata fn dylib_dependency_formats(&self, cnum: CrateNum) @@ -335,30 +244,25 @@ pub trait CrateStore<'tcx> { fn is_no_builtins(&self, cnum: CrateNum) -> bool; // resolve - fn def_index_for_def_key(&self, - cnum: CrateNum, - def: DefKey) - -> Option; - fn def_key(&self, def: DefId) -> hir_map::DefKey; - fn relative_def_path(&self, def: DefId) -> Option; + fn retrace_path(&self, + cnum: CrateNum, + path_data: &[DisambiguatedDefPathData]) + -> Option; + fn def_key(&self, def: DefId) -> DefKey; + fn def_path(&self, def: DefId) -> hir_map::DefPath; fn struct_field_names(&self, def: DefId) -> Vec; fn item_children(&self, did: DefId) -> Vec; fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro; // misc. metadata - fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option<(&'tcx InlinedItem, ast::NodeId)>; - fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option; - fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option; + fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option<&'tcx hir::Body>; + fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap; + fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool; fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>; fn is_item_mir_available(&self, def: DefId) -> bool; - /// Take a look if we need to inline or monomorphize this. If so, we - /// will emit code for this item in the local crate, and thus - /// create a translation item for it. - fn can_have_local_instance<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> bool; - // This is basically a 1-based range of ints, which is a little // silly - I may fix that. fn crates(&self) -> Vec; @@ -431,6 +335,11 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") } fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::Generics<'tcx> { bug!("item_generics") } + fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize) + { bug!("item_generics_own_param_counts") } + fn item_generics_object_lifetime_defaults(&self, def: DefId) + -> Vec + { bug!("item_generics_object_lifetime_defaults") } fn item_attrs(&self, def_id: DefId) -> Vec { bug!("item_attrs") } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef { bug!("trait_def") } @@ -441,12 +350,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // trait info fn implementations_of_trait(&self, filter: Option) -> Vec { vec![] } - fn def_index_for_def_key(&self, - cnum: CrateNum, - def: DefKey) - -> Option { - None - } // impl info fn associated_item_def_ids(&self, def_id: DefId) -> Vec @@ -461,8 +364,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // trait/impl-item info fn trait_of_item(&self, def_id: DefId) -> Option { bug!("trait_of_item") } - fn associated_item<'a>(&self, def: DefId) - -> Option { bug!("associated_item") } + fn associated_item(&self, def: DefId) -> Option { bug!("associated_item") } // flags fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") } @@ -471,6 +373,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") } fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false } fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false } + fn is_exported_symbol(&self, def_id: DefId) -> bool { false } // crate metadata fn dylib_dependency_formats(&self, cnum: CrateNum) @@ -507,8 +410,15 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") } // resolve - fn def_key(&self, def: DefId) -> hir_map::DefKey { bug!("def_key") } - fn relative_def_path(&self, def: DefId) -> Option { + fn retrace_path(&self, + cnum: CrateNum, + path_data: &[DisambiguatedDefPathData]) + -> Option { + None + } + + fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") } + fn def_path(&self, def: DefId) -> hir_map::DefPath { bug!("relative_def_path") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } @@ -516,15 +426,15 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } // misc. metadata - fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option<(&'tcx InlinedItem, ast::NodeId)> { - bug!("maybe_get_item_ast") + fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option<&'tcx hir::Body> { + bug!("maybe_get_item_body") } - fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option { - bug!("local_node_for_inlined_defid") + fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap { + bug!("item_body_nested_bodies") } - fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option { - bug!("defid_for_inlined_node") + fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool { + bug!("const_is_rvalue_promotable_to_static") } fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) @@ -532,9 +442,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_item_mir_available(&self, def: DefId) -> bool { bug!("is_item_mir_available") } - fn can_have_local_instance<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> bool { - bug!("can_have_local_instance") - } // This is basically a 1-based range of ints, which is a little // silly - I may fix that. diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index f7a34c43cc..7d62103e38 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -108,6 +108,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> { + fn nested(&self, state: &mut pprust::State, nested: pprust::Nested) -> io::Result<()> { + pprust::PpAnn::nested(&self.tcx.hir, state, nested) + } fn pre(&self, ps: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { @@ -160,7 +163,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O } } -fn build_nodeid_to_index(decl: Option<&hir::FnDecl>, +fn build_nodeid_to_index(body: Option<&hir::Body>, cfg: &cfg::CFG) -> NodeMap> { let mut index = NodeMap(); @@ -168,8 +171,8 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>, // into cfg itself? i.e. introduce a fn-based flow-graph in // addition to the current block-based flow-graph, rather than // have to put traversals like this here? - if let Some(decl) = decl { - add_entries_from_fn_decl(&mut index, decl, cfg.entry); + if let Some(body) = body { + add_entries_from_fn_body(&mut index, body, cfg.entry); } cfg.graph.each_node(|node_idx, node| { @@ -181,20 +184,24 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>, return index; - fn add_entries_from_fn_decl(index: &mut NodeMap>, - decl: &hir::FnDecl, + /// Add mappings from the ast nodes for the formal bindings to + /// the entry-node in the graph. + fn add_entries_from_fn_body(index: &mut NodeMap>, + body: &hir::Body, entry: CFGIndex) { - //! add mappings from the ast nodes for the formal bindings to - //! the entry-node in the graph. + use hir::intravisit::Visitor; + struct Formals<'a> { entry: CFGIndex, index: &'a mut NodeMap>, } let mut formals = Formals { entry: entry, index: index }; - intravisit::walk_fn_decl(&mut formals, decl); - impl<'a, 'v> intravisit::Visitor<'v> for Formals<'a> { + for arg in &body.arguments { + formals.visit_pat(&arg.pat); + } + impl<'a, 'v> Visitor<'v> for Formals<'a> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> { - panic!("should not encounter fn bodies or items") + intravisit::NestedVisitorMap::None } fn visit_pat(&mut self, p: &hir::Pat) { @@ -227,7 +234,7 @@ pub enum KillFrom { impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis_name: &'static str, - decl: Option<&hir::FnDecl>, + body: Option<&hir::Body>, cfg: &cfg::CFG, oper: O, id_range: IdRange, @@ -250,7 +257,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let kills2 = zeroes; let on_entry = vec![entry; num_nodes * words_per_id]; - let nodeid_to_index = build_nodeid_to_index(decl, cfg); + let nodeid_to_index = build_nodeid_to_index(body, cfg); DataFlowContext { tcx: tcx, @@ -502,7 +509,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { // ^^^^^^^^^^^^^ only needed for pretty printing - pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) { + pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Body) { //! Performs the data flow analysis. if self.bits_per_id == 0 { @@ -526,20 +533,11 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { } debug!("Dataflow result for {}:", self.analysis_name); - debug!("{}", { - let mut v = Vec::new(); - self.pretty_print_to(box &mut v, body).unwrap(); - String::from_utf8(v).unwrap() - }); - } - - fn pretty_print_to<'b>(&self, wr: Box, - body: &hir::Expr) -> io::Result<()> { - let mut ps = pprust::rust_printer_annotated(wr, self, None); - ps.cbox(pprust::indent_unit)?; - ps.ibox(0)?; - ps.print_expr(body)?; - pp::eof(&mut ps.s) + debug!("{}", pprust::to_string(self, |s| { + s.cbox(pprust::indent_unit)?; + s.ibox(0)?; + s.print_expr(&body.value) + })); } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 1c5dd97b74..ae349667f9 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -13,7 +13,7 @@ // from live codes are live, and everything else is dead. use dep_graph::DepNode; -use hir::map as ast_map; +use hir::map as hir_map; use hir::{self, PatKind}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::itemlikevisit::ItemLikeVisitor; @@ -35,11 +35,11 @@ use syntax_pos; // may need to be marked as live. fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) -> bool { - match tcx.map.find(node_id) { - Some(ast_map::NodeItem(..)) | - Some(ast_map::NodeImplItem(..)) | - Some(ast_map::NodeForeignItem(..)) | - Some(ast_map::NodeTraitItem(..)) => + match tcx.hir.find(node_id) { + Some(hir_map::NodeItem(..)) | + Some(hir_map::NodeImplItem(..)) | + Some(hir_map::NodeForeignItem(..)) | + Some(hir_map::NodeTraitItem(..)) => true, _ => false @@ -49,6 +49,7 @@ fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct MarkSymbolVisitor<'a, 'tcx: 'a> { worklist: Vec, tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, live_symbols: Box>, struct_has_extern_repr: bool, ignore_non_const_paths: bool, @@ -57,21 +58,8 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { } impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - worklist: Vec) -> MarkSymbolVisitor<'a, 'tcx> { - MarkSymbolVisitor { - worklist: worklist, - tcx: tcx, - live_symbols: box FxHashSet(), - struct_has_extern_repr: false, - ignore_non_const_paths: false, - inherited_pub_visibility: false, - ignore_variant_stack: vec![], - } - } - fn check_def_id(&mut self, def_id: DefId) { - if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { + if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { if should_explore(self.tcx, node_id) { self.worklist.push(node_id); } @@ -80,7 +68,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn insert_def_id(&mut self, def_id: DefId) { - if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { + if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { debug_assert!(!should_explore(self.tcx, node_id)); self.live_symbols.insert(node_id); } @@ -109,12 +97,12 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_method(&mut self, id: ast::NodeId) { let method_call = ty::MethodCall::expr(id); - let method = self.tcx.tables().method_map[&method_call]; + let method = self.tables.method_map[&method_call]; self.check_def_id(method.def_id); } fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) { - match self.tcx.tables().expr_ty_adjusted(lhs).sty { + match self.tables.expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().field_named(name).did); } @@ -123,7 +111,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) { - match self.tcx.tables().expr_ty_adjusted(lhs).sty { + match self.tables.expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().fields[idx].did); } @@ -134,7 +122,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def, pats: &[codemap::Spanned]) { - let variant = match self.tcx.tables().node_id_to_type(lhs.id).sty { + let variant = match self.tables.node_id_to_type(lhs.id).sty { ty::TyAdt(adt, _) => adt.variant_of_def(def), _ => span_bug!(lhs.span, "non-ADT in struct pattern") }; @@ -155,20 +143,20 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } scanned.insert(id); - if let Some(ref node) = self.tcx.map.find(id) { + if let Some(ref node) = self.tcx.hir.find(id) { self.live_symbols.insert(id); self.visit_node(node); } } } - fn visit_node(&mut self, node: &ast_map::Node<'tcx>) { + fn visit_node(&mut self, node: &hir_map::Node<'tcx>) { let had_extern_repr = self.struct_has_extern_repr; self.struct_has_extern_repr = false; let had_inherited_pub_visibility = self.inherited_pub_visibility; self.inherited_pub_visibility = false; match *node { - ast_map::NodeItem(item) => { + hir_map::NodeItem(item) => { match item.node { hir::ItemStruct(..) | hir::ItemUnion(..) => { self.struct_has_extern_repr = item.attrs.iter().any(|attr| { @@ -191,13 +179,13 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { _ => () } } - ast_map::NodeTraitItem(trait_item) => { + hir_map::NodeTraitItem(trait_item) => { intravisit::walk_trait_item(self, trait_item); } - ast_map::NodeImplItem(impl_item) => { + hir_map::NodeImplItem(impl_item) => { intravisit::walk_impl_item(self, impl_item); } - ast_map::NodeForeignItem(foreign_item) => { + hir_map::NodeForeignItem(foreign_item) => { intravisit::walk_foreign_item(self, &foreign_item); } _ => () @@ -209,7 +197,15 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.hir.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name, @@ -227,7 +223,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => { - let def = self.tcx.tables().qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.id); self.handle_definition(def); } hir::ExprMethodCall(..) => { @@ -267,7 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_field_pattern_match(pat, path.def, fields); } PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); self.handle_definition(def); } _ => () @@ -328,11 +324,12 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { self.worklist.extend(enum_def.variants.iter() .map(|variant| variant.node.data.id())); } - hir::ItemTrait(.., ref trait_items) => { - for trait_item in trait_items { + hir::ItemTrait(.., ref trait_item_refs) => { + for trait_item_ref in trait_item_refs { + let trait_item = self.krate.trait_item(trait_item_ref.id); match trait_item.node { - hir::ConstTraitItem(_, Some(_)) | - hir::MethodTraitItem(_, Some(_)) => { + hir::TraitItemKind::Const(_, Some(_)) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => { if has_allow_dead_code_or_lang_attr(&trait_item.attrs) { self.worklist.push(trait_item.id); } @@ -354,6 +351,10 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { } } + fn visit_trait_item(&mut self, _item: &hir::TraitItem) { + // ignore: we are handling this in `visit_item` above + } + fn visit_impl_item(&mut self, _item: &hir::ImplItem) { // ignore: we are handling this in `visit_item` above } @@ -388,7 +389,16 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: &hir::Crate) -> Box> { let worklist = create_and_seed_worklist(tcx, access_levels, krate); - let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist); + let mut symbol_visitor = MarkSymbolVisitor { + worklist: worklist, + tcx: tcx, + tables: &ty::TypeckTables::empty(), + live_symbols: box FxHashSet(), + struct_has_extern_repr: false, + ignore_non_const_paths: false, + inherited_pub_visibility: false, + ignore_variant_stack: vec![], + }; symbol_visitor.mark_live_symbols(); symbol_visitor.live_symbols } @@ -424,7 +434,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { } fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool { - let field_type = self.tcx.item_type(self.tcx.map.local_def_id(field.id)); + let field_type = self.tcx.item_type(self.tcx.hir.local_def_id(field.id)); let is_marker_field = match field_type.ty_to_def_id() { Some(def_id) => self.tcx.lang_items.items().iter().any(|item| *item == Some(def_id)), _ => false @@ -440,6 +450,11 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { && !has_allow_dead_code_or_lang_attr(&variant.attrs) } + fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool { + !self.symbol_is_live(fi.id, None) + && !has_allow_dead_code_or_lang_attr(&fi.attrs) + } + // id := node id of an item's definition. // ctor_id := `Some` if the item is a struct_ctor (tuple struct), // `None` otherwise. @@ -463,10 +478,10 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { // method of a private type is used, but the type itself is never // called directly. if let Some(impl_list) = - self.tcx.inherent_impls.borrow().get(&self.tcx.map.local_def_id(id)) { + self.tcx.inherent_impls.borrow().get(&self.tcx.hir.local_def_id(id)) { for &impl_did in impl_list.iter() { for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] { - if let Some(item_node_id) = self.tcx.map.as_local_node_id(item_did) { + if let Some(item_node_id) = self.tcx.hir.as_local_node_id(item_did) { if self.live_symbols.contains(&item_node_id) { return true; } @@ -499,7 +514,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { /// an error. We could do this also by checking the parents, but /// this is how the code is setup and it seems harmless enough. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.map) + NestedVisitorMap::All(&self.tcx.hir) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -529,7 +544,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { } fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem) { - if !self.symbol_is_live(fi.id, None) { + if self.should_warn_about_foreign_item(fi) { self.warn_dead_code(fi.id, fi.span, fi.name, fi.node.descriptive_variant()); } intravisit::walk_foreign_item(self, fi); @@ -546,19 +561,19 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { match impl_item.node { - hir::ImplItemKind::Const(_, ref expr) => { + hir::ImplItemKind::Const(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { self.warn_dead_code(impl_item.id, impl_item.span, impl_item.name, "associated const"); } - intravisit::walk_expr(self, expr) + self.visit_nested_body(body_id) } hir::ImplItemKind::Method(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { self.warn_dead_code(impl_item.id, impl_item.span, impl_item.name, "method"); } - self.visit_body(body_id) + self.visit_nested_body(body_id) } hir::ImplItemKind::Type(..) => {} } @@ -567,15 +582,13 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { // Overwrite so that we don't warn the trait item itself. fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { match trait_item.node { - hir::ConstTraitItem(_, Some(ref body)) => { - intravisit::walk_expr(self, body) - } - hir::MethodTraitItem(_, Some(body_id)) => { - self.visit_body(body_id) + hir::TraitItemKind::Const(_, Some(body_id)) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => { + self.visit_nested_body(body_id) } - hir::ConstTraitItem(_, None) | - hir::MethodTraitItem(_, None) | - hir::TypeTraitItem(..) => {} + hir::TraitItemKind::Const(_, None) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | + hir::TraitItemKind::Type(..) => {} } } } @@ -583,7 +596,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &privacy::AccessLevels) { let _task = tcx.dep_graph.in_task(DepNode::DeadCheck); - let krate = tcx.map.krate(); + let krate = tcx.hir.krate(); let live_symbols = find_live(tcx, access_levels, krate); let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols }; intravisit::walk_crate(&mut visitor, krate); diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 075b3d7a8e..e60d0533c9 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -103,6 +103,10 @@ pub fn calculate(sess: &session::Session) { fn calculate_type(sess: &session::Session, ty: config::CrateType) -> DependencyList { + if !sess.opts.output_types.should_trans() { + return Vec::new(); + } + match ty { // If the global prefer_dynamic switch is turned off, first attempt // static linkage (this can fail). @@ -114,7 +118,7 @@ fn calculate_type(sess: &session::Session, // No linkage happens with rlibs, we just needed the metadata (which we // got long ago), so don't bother with anything. - config::CrateTypeRlib | config::CrateTypeMetadata => return Vec::new(), + config::CrateTypeRlib => return Vec::new(), // Staticlibs and cdylibs must have all static dependencies. If any fail // to be found, we generate some nice pretty errors. diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 2ec7aa4c4d..ab33c3843a 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -52,6 +52,7 @@ fn type_is_unsafe_function(ty: Ty) -> bool { struct EffectCheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, /// Whether we're in an unsafe context. unsafe_context: UnsafeContext, @@ -94,11 +95,19 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.hir.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, span: Span, id: ast::NodeId) { + body_id: hir::BodyId, span: Span, id: ast::NodeId) { let (is_item_fn, is_unsafe_fn) = match fn_kind { FnKind::ItemFn(_, _, unsafety, ..) => @@ -163,7 +172,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = MethodCall::expr(expr.id); - let base_type = self.tcx.tables().method_map[&method_call].ty; + let base_type = self.tables.method_map[&method_call].ty; debug!("effect: method call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -172,7 +181,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprCall(ref base, _) => { - let base_type = self.tcx.tables().expr_ty_adjusted(base); + let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -180,7 +189,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprUnary(hir::UnDeref, ref base) => { - let base_type = self.tcx.tables().expr_ty_adjusted(base); + let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: unary case, base type is {:?}", base_type); if let ty::TyRawPtr(_) = base_type.sty { @@ -194,7 +203,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { if let Def::Static(def_id, mutbl) = path.def { if mutbl { self.require_unsafe(expr.span, "use of mutable static"); - } else if match self.tcx.map.get_if_local(def_id) { + } else if match self.tcx.hir.get_if_local(def_id) { Some(hir::map::NodeForeignItem(..)) => true, Some(..) => false, None => self.tcx.sess.cstore.is_foreign_item(def_id), @@ -204,7 +213,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprField(ref base_expr, field) => { - if let ty::TyAdt(adt, ..) = self.tcx.tables().expr_ty_adjusted(base_expr).sty { + if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty { if adt.is_union() { self.require_unsafe(field.span, "access to union field"); } @@ -218,7 +227,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx hir::Pat) { if let PatKind::Struct(_, ref fields, _) = pat.node { - if let ty::TyAdt(adt, ..) = self.tcx.tables().pat_ty(pat).sty { + if let ty::TyAdt(adt, ..) = self.tables.pat_ty(pat).sty { if adt.is_union() { for field in fields { self.require_unsafe(field.span, "matching on union field"); @@ -236,8 +245,9 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = EffectCheckVisitor { tcx: tcx, + tables: &ty::TypeckTables::empty(), unsafe_context: UnsafeContext::new(SafeContext), }; - tcx.map.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); } diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index e927843a98..ff7adfb327 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -10,20 +10,20 @@ use dep_graph::DepNode; -use hir::map as ast_map; +use hir::map as hir_map; use hir::def_id::{CRATE_DEF_INDEX}; use session::{config, Session}; use syntax::ast::NodeId; use syntax::attr; use syntax::entry::EntryPointType; use syntax_pos::Span; -use hir::{Item, ItemFn, ImplItem}; +use hir::{Item, ItemFn, ImplItem, TraitItem}; use hir::itemlikevisit::ItemLikeVisitor; struct EntryContext<'a, 'tcx: 'a> { session: &'a Session, - map: &'a ast_map::Map<'tcx>, + map: &'a hir_map::Map<'tcx>, // The top-level function called 'main' main_fn: Option<(NodeId, Span)>, @@ -47,14 +47,17 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { find_item(item, self, at_root); } + fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) { + // entry fn is never a trait item + } fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) { // entry fn is never an impl item } } -pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) { - let _task = ast_map.dep_graph.in_task(DepNode::EntryPoint); +pub fn find_entry_point(session: &Session, hir_map: &hir_map::Map) { + let _task = hir_map.dep_graph.in_task(DepNode::EntryPoint); let any_exe = session.crate_types.borrow().iter().any(|ty| { *ty == config::CrateTypeExecutable @@ -65,21 +68,21 @@ pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) { } // If the user wants no main function at all, then stop here. - if attr::contains_name(&ast_map.krate().attrs, "no_main") { + if attr::contains_name(&hir_map.krate().attrs, "no_main") { session.entry_type.set(Some(config::EntryNone)); return } let mut ctxt = EntryContext { session: session, - map: ast_map, + map: hir_map, main_fn: None, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new(), }; - ast_map.krate().visit_all_item_likes(&mut ctxt); + hir_map.krate().visit_all_item_likes(&mut ctxt); configure_main(&mut ctxt); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index b3e61f1e57..2ca0069560 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -287,28 +287,22 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } - pub fn walk_fn(&mut self, - decl: &hir::FnDecl, - body: &hir::Expr) { - self.walk_arg_patterns(decl, body); - self.consume_expr(body); - } - - fn walk_arg_patterns(&mut self, - decl: &hir::FnDecl, - body: &hir::Expr) { - for arg in &decl.inputs { + pub fn consume_body(&mut self, body: &hir::Body) { + for arg in &body.arguments { let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id)); - let fn_body_scope_r = self.tcx().node_scope_region(body.id); + let fn_body_scope_r = self.tcx().node_scope_region(body.value.id); let arg_cmt = self.mc.cat_rvalue( arg.id, arg.pat.span, fn_body_scope_r, // Args live only as long as the fn body. + fn_body_scope_r, arg_ty); self.walk_irrefutable_pat(arg_cmt, &arg.pat); } + + self.consume_expr(&body.value); } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { @@ -537,9 +531,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } - hir::ExprRepeat(ref base, ref count) => { + hir::ExprRepeat(ref base, _) => { self.consume_expr(&base); - self.consume_expr(&count); } hir::ExprClosure(.., fn_decl_span) => { @@ -716,7 +709,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_adjustment(&mut self, expr: &hir::Expr) { let infcx = self.mc.infcx; //NOTE(@jroesch): mixed RefCell borrow causes crash - let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone()); + let adj = infcx.tables.borrow().adjustments.get(&expr.id).map(|x| x.clone()); if let Some(adjustment) = adj { match adjustment.kind { adjustment::Adjust::NeverToAny | @@ -997,7 +990,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { PatKind::Struct(ref qpath, ..) => qpath, _ => return }; - let def = tcx.tables().qpath_def(qpath, pat.id); + let def = infcx.tables.borrow().qpath_def(qpath, pat.id); match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { @@ -1028,7 +1021,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.tcx().with_freevars(closure_expr.id, |freevars| { for freevar in freevars { let def_id = freevar.def.def_id(); - let id_var = self.tcx().map.as_local_node_id(def_id).unwrap(); + let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id }; let upvar_capture = self.mc.infcx.upvar_capture(upvar_id).unwrap(); @@ -1060,7 +1053,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { -> mc::McResult> { // Create the cmt for the variable being borrowed, from the // caller's perspective - let var_id = self.tcx().map.as_local_node_id(upvar_def.def_id()).unwrap(); + let var_id = self.tcx().hir.as_local_node_id(upvar_def.def_id()).unwrap(); let var_ty = self.mc.infcx.node_ty(var_id)?; self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def) } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 2357549c82..05be35df95 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -19,7 +19,7 @@ use ty::layout::{LayoutError, Pointer, SizeSkeleton}; use syntax::abi::Abi::RustIntrinsic; use syntax::ast; use syntax_pos::Span; -use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; +use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir; pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -33,18 +33,6 @@ struct ItemVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } -impl<'a, 'tcx> ItemVisitor<'a, 'tcx> { - fn visit_const(&mut self, item_id: ast::NodeId, expr: &'tcx hir::Expr) { - let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); - self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { - let mut visitor = ExprVisitor { - infcx: &infcx - }; - visitor.visit_expr(expr); - }); - } -} - struct ExprVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx> } @@ -118,64 +106,36 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) - } - - // const, static and N in [T; N]. - fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { - let mut visitor = ExprVisitor { - infcx: &infcx - }; - visitor.visit_expr(expr); - }); - } - - fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::ConstTraitItem(_, Some(ref expr)) = item.node { - self.visit_const(item.id, expr); - } else { - intravisit::walk_trait_item(self, item); - } + NestedVisitorMap::None } - fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(_, ref expr) = item.node { - self.visit_const(item.id, expr); - } else { - intravisit::walk_impl_item(self, item); - } - } - - fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::ExprId, s: Span, id: ast::NodeId) { - if let FnKind::Closure(..) = fk { - span_bug!(s, "intrinsicck: closure outside of function") - } - let param_env = ty::ParameterEnvironment::for_item(self.tcx, id); - self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + let body = self.tcx.hir.body(body_id); + self.tcx.infer_ctxt(body_id, Reveal::All).enter(|infcx| { let mut visitor = ExprVisitor { infcx: &infcx }; - visitor.visit_fn(fk, fd, b, s, id); + visitor.visit_body(body); }); + self.visit_body(body); } } impl<'a, 'gcx, 'tcx> Visitor<'gcx> for ExprVisitor<'a, 'gcx, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::OnlyBodies(&self.infcx.tcx.map) + NestedVisitorMap::None } fn visit_expr(&mut self, expr: &'gcx hir::Expr) { let def = if let hir::ExprPath(ref qpath) = expr.node { - self.infcx.tcx.tables().qpath_def(qpath, expr.id) + self.infcx.tables.borrow().qpath_def(qpath, expr.id) } else { Def::Err }; match def { Def::Fn(did) if self.def_id_is_transmute(did) => { - let typ = self.infcx.tcx.tables().node_id_to_type(expr.id); + let typ = self.infcx.tables.borrow().node_id_to_type(expr.id); + let typ = self.infcx.tcx.lift_to_global(&typ).unwrap(); match typ.sty { ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { let from = bare_fn_ty.sig.skip_binder().inputs()[0]; diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 1efc211b8c..b9f1611f62 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -117,7 +117,7 @@ impl LanguageItems { struct LanguageItemCollector<'a, 'tcx: 'a> { items: LanguageItems, - ast_map: &'a hir_map::Map<'tcx>, + hir_map: &'a hir_map::Map<'tcx>, session: &'a Session, @@ -130,9 +130,9 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { let item_index = self.item_refs.get(&*value.as_str()).cloned(); if let Some(item_index) = item_index { - self.collect_item(item_index, self.ast_map.local_def_id(item.id)) + self.collect_item(item_index, self.hir_map.local_def_id(item.id)) } else { - let span = self.ast_map.span(item.id); + let span = self.hir_map.span(item.id); span_err!(self.session, span, E0522, "definition of an unknown language item: `{}`.", value); @@ -140,13 +140,17 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + // at present, lang items are always items, not trait items + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { // at present, lang items are always items, not impl items } } impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { - pub fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>) + pub fn new(session: &'a Session, hir_map: &'a hir_map::Map<'tcx>) -> LanguageItemCollector<'a, 'tcx> { let mut item_refs = FxHashMap(); @@ -154,7 +158,7 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { LanguageItemCollector { session: session, - ast_map: ast_map, + hir_map: hir_map, items: LanguageItems::new(), item_refs: item_refs, } @@ -167,7 +171,7 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { Some(original_def_id) if original_def_id != item_def_id => { let cstore = &self.session.cstore; let name = LanguageItems::item_name(item_index); - let mut err = match self.ast_map.span_if_local(item_def_id) { + let mut err = match self.hir_map.span_if_local(item_def_id) { Some(span) => struct_span_err!( self.session, span, @@ -179,7 +183,7 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { cstore.crate_name(item_def_id.krate), name)), }; - if let Some(span) = self.ast_map.span_if_local(original_def_id) { + if let Some(span) = self.hir_map.span_if_local(original_def_id) { span_note!(&mut err, span, "first defined here."); } else { @@ -256,11 +260,13 @@ language_item_table! { I16ImplItem, "i16", i16_impl; I32ImplItem, "i32", i32_impl; I64ImplItem, "i64", i64_impl; + I128ImplItem, "i128", i128_impl; IsizeImplItem, "isize", isize_impl; U8ImplItem, "u8", u8_impl; U16ImplItem, "u16", u16_impl; U32ImplItem, "u32", u32_impl; U64ImplItem, "u64", u64_impl; + U128ImplItem, "u128", u128_impl; UsizeImplItem, "usize", usize_impl; F32ImplItem, "f32", f32_impl; F64ImplItem, "f64", f64_impl; @@ -328,7 +334,6 @@ language_item_table! { PanicFmtLangItem, "panic_fmt", panic_fmt; ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; - ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn; BoxFreeFnLangItem, "box_free", box_free_fn; StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 445aed8f97..7fa3365694 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -127,7 +127,6 @@ use syntax_pos::Span; use hir::Expr; use hir; -use hir::print::{expr_to_string, block_to_string}; use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; /// For use with `propagate_through_loop`. @@ -184,11 +183,11 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt) -> String { impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::OnlyBodies(&self.tcx.hir) } fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::ExprId, s: Span, id: NodeId) { + b: hir::BodyId, s: Span, id: NodeId) { visit_fn(self, fk, fd, b, s, id); } fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); } @@ -198,7 +197,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let _task = tcx.dep_graph.in_task(DepNode::Liveness); - tcx.map.krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor()); + tcx.hir.krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor()); tcx.sess.abort_if_errors(); } @@ -352,30 +351,10 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.ir.tcx.map) - } - - fn visit_fn(&mut self, _: FnKind<'tcx>, _: &'tcx hir::FnDecl, - _: hir::ExprId, _: Span, _: NodeId) { - // do not check contents of nested fns - } - fn visit_local(&mut self, l: &'tcx hir::Local) { - check_local(self, l); - } - fn visit_expr(&mut self, ex: &'tcx Expr) { - check_expr(self, ex); - } - fn visit_arm(&mut self, a: &'tcx hir::Arm) { - check_arm(self, a); - } -} - fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, sp: Span, id: ast::NodeId) { debug!("visit_fn"); @@ -385,7 +364,9 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps); - for arg in &decl.inputs { + let body = ir.tcx.hir.body(body_id); + + for arg in &body.arguments { arg.pat.each_binding(|_bm, arg_id, _x, path1| { debug!("adding argument {}", arg_id); let name = path1.node; @@ -397,27 +378,14 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // and so forth: intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id); - // Special nodes and variables: - // - exit_ln represents the end of the fn, either by return or panic - // - implicit_ret_var is a pseudo-variable that represents - // an implicit return - let specials = Specials { - exit_ln: fn_maps.add_live_node(ExitNode), - fallthrough_ln: fn_maps.add_live_node(ExitNode), - no_ret_var: fn_maps.add_variable(ImplicitRet), - clean_exit_var: fn_maps.add_variable(CleanExit) - }; - - let body = ir.tcx.map.expr(body_id); - // compute liveness - let mut lsets = Liveness::new(&mut fn_maps, specials); - let entry_ln = lsets.compute(body); + let mut lsets = Liveness::new(&mut fn_maps, body_id); + let entry_ln = lsets.compute(&body.value); // check for various error conditions - lsets.visit_expr(body); - lsets.check_ret(id, sp, fk, entry_ln, body); - lsets.warn_about_unused_args(decl, entry_ln); + lsets.visit_body(body); + lsets.check_ret(id, sp, entry_ln, body); + lsets.warn_about_unused_args(body, entry_ln); } fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { @@ -472,7 +440,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { ir.tcx.with_freevars(expr.id, |freevars| { for fv in freevars { if let Def::Local(def_id) = fv.def { - let rv = ir.tcx.map.as_local_node_id(def_id).unwrap(); + let rv = ir.tcx.hir.as_local_node_id(def_id).unwrap(); let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); call_caps.push(CaptureInfo {ln: fv_ln, var_nid: rv}); @@ -544,6 +512,7 @@ const ACC_USE: u32 = 4; struct Liveness<'a, 'tcx: 'a> { ir: &'a mut IrMaps<'a, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, s: Specials, successors: Vec, users: Vec, @@ -558,11 +527,26 @@ struct Liveness<'a, 'tcx: 'a> { } impl<'a, 'tcx> Liveness<'a, 'tcx> { - fn new(ir: &'a mut IrMaps<'a, 'tcx>, specials: Specials) -> Liveness<'a, 'tcx> { + fn new(ir: &'a mut IrMaps<'a, 'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> { + // Special nodes and variables: + // - exit_ln represents the end of the fn, either by return or panic + // - implicit_ret_var is a pseudo-variable that represents + // an implicit return + let specials = Specials { + exit_ln: ir.add_live_node(ExitNode), + fallthrough_ln: ir.add_live_node(ExitNode), + no_ret_var: ir.add_variable(ImplicitRet), + clean_exit_var: ir.add_variable(CleanExit) + }; + + let tables = ir.tcx.body_tables(body); + let num_live_nodes = ir.num_live_nodes; let num_vars = ir.num_vars; + Liveness { ir: ir, + tables: tables, s: specials, successors: vec![invalid_node(); num_live_nodes], users: vec![invalid_users(); num_live_nodes * num_vars], @@ -823,7 +807,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // effectively a return---this only occurs in `for` loops, // where the body is really a closure. - debug!("compute: using id for body, {}", expr_to_string(body)); + debug!("compute: using id for body, {}", self.ir.tcx.hir.node_to_pretty_string(body.id)); let exit_ln = self.s.exit_ln; let entry_ln: LiveNode = self.with_loop_nodes(body.id, exit_ln, exit_ln, |this| { @@ -916,7 +900,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) -> LiveNode { - debug!("propagate_through_expr: {}", expr_to_string(expr)); + debug!("propagate_through_expr: {}", self.ir.tcx.hir.node_to_pretty_string(expr.id)); match expr.node { // Interesting cases with control flow or which gen/kill @@ -935,14 +919,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprClosure(.., blk_id, _) => { debug!("{} is an ExprClosure", - expr_to_string(expr)); + self.ir.tcx.hir.node_to_pretty_string(expr.id)); /* The next-node for a break is the successor of the entire loop. The next-node for a continue is the top of this loop. */ let node = self.live_node(expr.id, expr.span); - self.with_loop_nodes(blk_id.node_id(), succ, node, |this| { + self.with_loop_nodes(blk_id.node_id, succ, node, |this| { // the construction of a closure itself is not important, // but we have to consider the closed over variables. @@ -1070,7 +1054,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprAssignOp(_, ref l, ref r) => { // an overloaded assign op is like a method call - if self.ir.tcx.tables().is_method_call(expr.id) { + if self.tables.is_method_call(expr.id) { let succ = self.propagate_through_expr(&l, succ); self.propagate_through_expr(&r, succ) } else { @@ -1088,11 +1072,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_exprs(exprs, succ) } - hir::ExprRepeat(ref element, ref count) => { - let succ = self.propagate_through_expr(&count, succ); - self.propagate_through_expr(&element, succ) - } - hir::ExprStruct(_, ref fields, ref with_expr) => { let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ); fields.iter().rev().fold(succ, |succ, field| { @@ -1102,8 +1081,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprCall(ref f, ref args) => { // FIXME(canndrew): This is_never should really be an is_uninhabited - let diverges = !self.ir.tcx.tables().is_method_call(expr.id) && - self.ir.tcx.tables().expr_ty_adjusted(&f).fn_ret().0.is_never(); + let diverges = !self.tables.is_method_call(expr.id) && + self.tables.expr_ty_adjusted(&f).fn_ret().0.is_never(); let succ = if diverges { self.s.exit_ln } else { @@ -1115,7 +1094,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprMethodCall(.., ref args) => { let method_call = ty::MethodCall::expr(expr.id); - let method_ty = self.ir.tcx.tables().method_map[&method_call].ty; + let method_ty = self.tables.method_map[&method_call].ty; // FIXME(canndrew): This is_never should really be an is_uninhabited let succ = if method_ty.fn_ret().0.is_never() { self.s.exit_ln @@ -1149,7 +1128,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprAddrOf(_, ref e) | hir::ExprCast(ref e, _) | hir::ExprType(ref e, _) | - hir::ExprUnary(_, ref e) => { + hir::ExprUnary(_, ref e) | + hir::ExprRepeat(ref e, _) => { self.propagate_through_expr(&e, succ) } @@ -1261,7 +1241,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { -> LiveNode { match path.def { Def::Local(def_id) => { - let nid = self.ir.tcx.map.as_local_node_id(def_id).unwrap(); + let nid = self.ir.tcx.hir.as_local_node_id(def_id).unwrap(); let ln = self.live_node(id, path.span); if acc != 0 { self.init_from_succ(ln, succ); @@ -1315,7 +1295,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } debug!("propagate_through_loop: using id for loop body {} {}", - expr.id, block_to_string(body)); + expr.id, self.ir.tcx.hir.node_to_pretty_string(body.id)); let cond_ln = match kind { LoopLoop => ln, @@ -1364,6 +1344,22 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // _______________________________________________________________________ // Checking for error conditions +impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + + fn visit_local(&mut self, l: &'tcx hir::Local) { + check_local(self, l); + } + fn visit_expr(&mut self, ex: &'tcx Expr) { + check_expr(self, ex); + } + fn visit_arm(&mut self, a: &'tcx hir::Arm) { + check_arm(self, a); + } +} + fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local) { match local.init { Some(_) => { @@ -1398,7 +1394,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } hir::ExprAssignOp(_, ref l, _) => { - if !this.ir.tcx.tables().is_method_call(expr.id) { + if !this.tables.is_method_call(expr.id) { this.check_lvalue(&l); } @@ -1441,15 +1437,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_ret(&self, id: NodeId, sp: Span, - fk: FnKind, entry_ln: LiveNode, - body: &hir::Expr) + body: &hir::Body) { - let fn_ty = if let FnKind::Closure(_) = fk { - self.ir.tcx.tables().node_id_to_type(id) - } else { - self.ir.tcx.item_type(self.ir.tcx.map.local_def_id(id)) - }; + let fn_ty = self.ir.tcx.item_type(self.ir.tcx.hir.local_def_id(id)); let fn_ret = match fn_ty.sty { ty::TyClosure(closure_def_id, substs) => self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), @@ -1460,14 +1451,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // and must outlive the *call-site* of the function. let fn_ret = self.ir.tcx.liberate_late_bound_regions( - self.ir.tcx.region_maps.call_site_extent(id, body.id), + self.ir.tcx.region_maps.call_site_extent(id, body.value.id), &fn_ret); if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { let param_env = ParameterEnvironment::for_item(self.ir.tcx, id); let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs); - let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env), - Reveal::All).enter(|infcx| { + let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| { let cause = traits::ObligationCause::dummy(); traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil() }); @@ -1487,7 +1477,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // if there is no later assignment. If this local is actually // mutable, then check for a reassignment to flag the mutability // as being used. - let nid = self.ir.tcx.map.as_local_node_id(def_id).unwrap(); + let nid = self.ir.tcx.hir.as_local_node_id(def_id).unwrap(); let ln = self.live_node(expr.id, expr.span); let var = self.variable(nid, expr.span); self.warn_about_dead_assign(expr.span, expr.id, ln, var); @@ -1510,8 +1500,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) { - for arg in &decl.inputs { + fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) { + for arg in &body.arguments { arg.pat.each_binding(|_bm, p_id, sp, path1| { let var = self.variable(p_id, sp); // Ignore unused self. diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 4c3b102e54..3cd7517baa 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -71,9 +71,8 @@ pub use self::Note::*; use self::Aliasability::*; use hir::def_id::DefId; -use hir::map as ast_map; +use hir::map as hir_map; use infer::InferCtxt; -use middle::const_qualif::ConstQualif; use hir::def::{Def, CtorKind}; use ty::adjustment; use ty::{self, Ty, TyCtxt}; @@ -89,7 +88,8 @@ use std::rc::Rc; #[derive(Clone, PartialEq)] pub enum Categorization<'tcx> { - Rvalue(&'tcx ty::Region), // temporary val, argument is its scope + // temporary val, argument is its scope + Rvalue(&'tcx ty::Region, &'tcx ty::Region), StaticItem, Upvar(Upvar), // upvar referenced by closure env Local(ast::NodeId), // local variable @@ -194,6 +194,65 @@ pub struct cmt_<'tcx> { pub type cmt<'tcx> = Rc>; +impl<'tcx> cmt_<'tcx> { + pub fn get_field(&self, name: ast::Name) -> Option { + match self.cat { + Categorization::Deref(ref cmt, ..) | + Categorization::Interior(ref cmt, _) | + Categorization::Downcast(ref cmt, _) => { + if let Categorization::Local(_) = cmt.cat { + if let ty::TyAdt(def, _) = self.ty.sty { + if def.is_struct() { + return def.struct_variant().find_field_named(name).map(|x| x.did); + } + } + None + } else { + cmt.get_field(name) + } + } + _ => None + } + } + + pub fn get_field_name(&self) -> Option { + match self.cat { + Categorization::Interior(_, ref ik) => { + if let InteriorKind::InteriorField(FieldName::NamedField(name)) = *ik { + Some(name) + } else { + None + } + } + Categorization::Deref(ref cmt, ..) | + Categorization::Downcast(ref cmt, _) => { + cmt.get_field_name() + } + _ => None, + } + } + + pub fn get_arg_if_immutable(&self, map: &hir_map::Map) -> Option { + match self.cat { + Categorization::Deref(ref cmt, ..) | + Categorization::Interior(ref cmt, _) | + Categorization::Downcast(ref cmt, _) => { + if let Categorization::Local(nid) = cmt.cat { + if let ty::TyAdt(_, _) = self.ty.sty { + if let ty::TyRef(_, ty::TypeAndMut{mutbl: MutImmutable, ..}) = cmt.ty.sty { + return Some(nid); + } + } + None + } else { + cmt.get_arg_if_immutable(map) + } + } + _ => None + } + } +} + pub trait ast_node { fn id(&self) -> ast::NodeId; fn span(&self) -> Span; @@ -269,8 +328,8 @@ impl MutabilityCategory { } fn from_local(tcx: TyCtxt, id: ast::NodeId) -> MutabilityCategory { - let ret = match tcx.map.get(id) { - ast_map::NodeLocal(p) => match p.node { + let ret = match tcx.hir.get(id) { + hir_map::NodeLocal(p) => match p.node { PatKind::Binding(bind_mode, ..) => { if bind_mode == hir::BindByValue(hir::MutMutable) { McDeclared @@ -280,7 +339,7 @@ impl MutabilityCategory { } _ => span_bug!(p.span, "expected identifier pattern") }, - _ => span_bug!(tcx.map.span(id), "expected identifier pattern") + _ => span_bug!(tcx.hir.span(id), "expected identifier pattern") }; debug!("MutabilityCategory::{}(tcx, id={:?}) => {:?}", "from_local", id, ret); @@ -385,7 +444,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } pub fn cat_expr(&self, expr: &hir::Expr) -> McResult> { - match self.infcx.adjustments().get(&expr.id) { + match self.infcx.tables.borrow().adjustments.get(&expr.id) { None => { // No adjustments. self.cat_expr_unadjusted(expr) @@ -540,7 +599,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Def::Upvar(def_id, _, fn_node_id) => { - let var_id = self.tcx().map.as_local_node_id(def_id).unwrap(); + let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); let ty = self.node_ty(fn_node_id)?; match ty.sty { ty::TyClosure(closure_id, _) => { @@ -577,7 +636,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Def::Local(def_id) => { - let vid = self.tcx().map.as_local_node_id(def_id).unwrap(); + let vid = self.tcx().hir.as_local_node_id(def_id).unwrap(); Ok(Rc::new(cmt_ { id: id, span: span, @@ -699,13 +758,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // Look up the node ID of the closure body so we can construct // a free region within it let fn_body_id = { - let fn_expr = match self.tcx().map.find(upvar_id.closure_expr_id) { - Some(ast_map::NodeExpr(e)) => e, + let fn_expr = match self.tcx().hir.find(upvar_id.closure_expr_id) { + Some(hir_map::NodeExpr(e)) => e, _ => bug!() }; match fn_expr.node { - hir::ExprClosure(.., body_id, _) => body_id.node_id(), + hir::ExprClosure(.., body_id, _) => body_id.node_id, _ => bug!() } }; @@ -761,11 +820,18 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { /// Returns the lifetime of a temporary created by expr with id `id`. /// This could be `'static` if `id` is part of a constant expression. - pub fn temporary_scope(&self, id: ast::NodeId) -> &'tcx ty::Region { - self.tcx().mk_region(match self.infcx.temporary_scope(id) { + pub fn temporary_scope(&self, id: ast::NodeId) -> (&'tcx ty::Region, &'tcx ty::Region) + { + let (scope, old_scope) = + self.tcx().region_maps.old_and_new_temporary_scope(id); + (self.tcx().mk_region(match scope { Some(scope) => ty::ReScope(scope), None => ty::ReStatic - }) + }), + self.tcx().mk_region(match old_scope { + Some(scope) => ty::ReScope(scope), + None => ty::ReStatic + })) } pub fn cat_rvalue_node(&self, @@ -773,25 +839,26 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span: Span, expr_ty: Ty<'tcx>) -> cmt<'tcx> { - let qualif = self.tcx().const_qualif_map.borrow().get(&id).cloned() - .unwrap_or(ConstQualif::NOT_CONST); + let promotable = self.tcx().rvalue_promotable_to_static.borrow().get(&id).cloned() + .unwrap_or(false); // Only promote `[T; 0]` before an RFC for rvalue promotions // is accepted. - let qualif = match expr_ty.sty { - ty::TyArray(_, 0) => qualif, - _ => ConstQualif::NOT_CONST + let promotable = match expr_ty.sty { + ty::TyArray(_, 0) => true, + _ => promotable & false }; // Compute maximum lifetime of this rvalue. This is 'static if // we can promote to a constant, otherwise equal to enclosing temp // lifetime. - let re = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) { - self.temporary_scope(id) + let (re, old_re) = if promotable { + (self.tcx().mk_region(ty::ReStatic), + self.tcx().mk_region(ty::ReStatic)) } else { - self.tcx().mk_region(ty::ReStatic) + self.temporary_scope(id) }; - let ret = self.cat_rvalue(id, span, re, expr_ty); + let ret = self.cat_rvalue(id, span, re, old_re, expr_ty); debug!("cat_rvalue_node ret {:?}", ret); ret } @@ -800,11 +867,12 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { cmt_id: ast::NodeId, span: Span, temp_scope: &'tcx ty::Region, + old_temp_scope: &'tcx ty::Region, expr_ty: Ty<'tcx>) -> cmt<'tcx> { let ret = Rc::new(cmt_ { id:cmt_id, span:span, - cat:Categorization::Rvalue(temp_scope), + cat:Categorization::Rvalue(temp_scope, old_temp_scope), mutbl:McDeclared, ty:expr_ty, note: NoteNone @@ -895,7 +963,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { -> cmt<'tcx> { let ptr = match base_cmt.ty.sty { - ty::TyBox(..) => Unique, + ty::TyAdt(def, ..) if def.is_box() => Unique, ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl), ty::TyRef(r, mt) => { let bk = ty::BorrowKind::from_mutbl(mt.mutbl); @@ -1314,7 +1382,7 @@ impl<'tcx> cmt_<'tcx> { "non-lvalue".to_string() } Categorization::Local(vid) => { - if tcx.map.is_argument(vid) { + if tcx.hir.is_argument(vid) { "argument".to_string() } else { "local variable".to_string() @@ -1387,7 +1455,9 @@ impl<'tcx> fmt::Debug for Categorization<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Categorization::StaticItem => write!(f, "static"), - Categorization::Rvalue(r) => write!(f, "rvalue({:?})", r), + Categorization::Rvalue(r, or) => { + write!(f, "rvalue({:?}, {:?})", r, or) + } Categorization::Local(id) => { let name = ty::tls::with(|tcx| tcx.local_var_name_str(id)); write!(f, "local({})", name) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 2c4710f1e4..4ec43e368a 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -16,7 +16,7 @@ // reachable as well. use dep_graph::DepNode; -use hir::map as ast_map; +use hir::map as hir_map; use hir::def::Def; use hir::def_id::DefId; use ty::{self, TyCtxt}; @@ -63,9 +63,9 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, generics_require_inlining(&sig.generics) { return true } - if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_src) { - match tcx.map.find(impl_node_id) { - Some(ast_map::NodeItem(item)) => + 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)) => item_might_be_inlined(&item), Some(..) | None => span_bug!(impl_item.span, "impl did is not an item") @@ -79,6 +79,7 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct ReachableContext<'a, 'tcx: 'a> { // The type context. tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, // The set of items which must be exported in the linkage sense. reachable_symbols: NodeSet, // A worklist of item IDs. Each item ID in this worklist will be inlined @@ -90,17 +91,25 @@ struct ReachableContext<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.hir.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_expr(&mut self, expr: &'tcx hir::Expr) { let def = match expr.node { hir::ExprPath(ref qpath) => { - Some(self.tcx.tables().qpath_def(qpath, expr.id)) + Some(self.tables.qpath_def(qpath, expr.id)) } hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let def_id = self.tables.method_map[&method_call].def_id; Some(Def::Method(def_id)) } _ => None @@ -108,7 +117,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { if let Some(def) = def { let def_id = def.def_id(); - if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { + if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { if self.def_id_represents_local_inlined_item(def_id) { self.worklist.push(node_id); } else { @@ -135,43 +144,30 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { } impl<'a, 'tcx> ReachableContext<'a, 'tcx> { - // Creates a new reachability computation context. - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> { - let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { - *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || - *ty == config::CrateTypeProcMacro || *ty == config::CrateTypeMetadata - }); - ReachableContext { - tcx: tcx, - reachable_symbols: NodeSet(), - worklist: Vec::new(), - any_library: any_library, - } - } - // Returns true if the given def ID represents a local item that is // eligible for inlining and false otherwise. fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool { - let node_id = match self.tcx.map.as_local_node_id(def_id) { + let node_id = match self.tcx.hir.as_local_node_id(def_id) { Some(node_id) => node_id, None => { return false; } }; - match self.tcx.map.find(node_id) { - Some(ast_map::NodeItem(item)) => { + match self.tcx.hir.find(node_id) { + Some(hir_map::NodeItem(item)) => { match item.node { hir::ItemFn(..) => item_might_be_inlined(&item), _ => false, } } - Some(ast_map::NodeTraitItem(trait_method)) => { + Some(hir_map::NodeTraitItem(trait_method)) => { match trait_method.node { - hir::ConstTraitItem(_, ref default) => default.is_some(), - hir::MethodTraitItem(_, ref body) => body.is_some(), - hir::TypeTraitItem(..) => false, + hir::TraitItemKind::Const(_, ref default) => default.is_some(), + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true, + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | + hir::TraitItemKind::Type(..) => false, } } - Some(ast_map::NodeImplItem(impl_item)) => { + Some(hir_map::NodeImplItem(impl_item)) => { match impl_item.node { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Method(ref sig, _) => { @@ -180,13 +176,13 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { true } else { let impl_did = self.tcx - .map + .hir .get_parent_did(node_id); // Check the impl. If the generics on the self // type of the impl require inlining, this method // does too. - let impl_node_id = self.tcx.map.as_local_node_id(impl_did).unwrap(); - match self.tcx.map.expect_item(impl_node_id).node { + let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap(); + match self.tcx.hir.expect_item(impl_node_id).node { hir::ItemImpl(_, _, ref generics, ..) => { generics_require_inlining(generics) } @@ -214,18 +210,18 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { continue } - if let Some(ref item) = self.tcx.map.find(search_item) { + if let Some(ref item) = self.tcx.hir.find(search_item) { self.propagate_node(item, search_item); } } } - fn propagate_node(&mut self, node: &ast_map::Node<'tcx>, + fn propagate_node(&mut self, node: &hir_map::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 ast_map::NodeItem(item) = *node { + if let hir_map::NodeItem(item) = *node { let reachable = if let hir::ItemFn(.., abi, _, _) = item.node { abi != Abi::Rust } else { @@ -246,19 +242,19 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } match *node { - ast_map::NodeItem(item) => { + hir_map::NodeItem(item) => { match item.node { hir::ItemFn(.., body) => { if item_might_be_inlined(&item) { - self.visit_body(body); + self.visit_nested_body(body); } } // Reachable constants will be inlined into other crates // unconditionally, so we need to make sure that their // contents are also reachable. - hir::ItemConst(_, ref init) => { - self.visit_expr(&init); + hir::ItemConst(_, init) => { + self.visit_nested_body(init); } // These are normal, nothing reachable about these @@ -272,44 +268,42 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ItemUnion(..) | hir::ItemDefaultImpl(..) => {} } } - ast_map::NodeTraitItem(trait_method) => { + hir_map::NodeTraitItem(trait_method) => { match trait_method.node { - hir::ConstTraitItem(_, None) | - hir::MethodTraitItem(_, None) => { + hir::TraitItemKind::Const(_, None) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => { // Keep going, nothing to get exported } - hir::ConstTraitItem(_, Some(ref body)) => { - self.visit_expr(body); + hir::TraitItemKind::Const(_, Some(body_id)) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => { + self.visit_nested_body(body_id); } - hir::MethodTraitItem(_, Some(body_id)) => { - self.visit_body(body_id); - } - hir::TypeTraitItem(..) => {} + hir::TraitItemKind::Type(..) => {} } } - ast_map::NodeImplItem(impl_item) => { + hir_map::NodeImplItem(impl_item) => { match impl_item.node { - hir::ImplItemKind::Const(_, ref expr) => { - self.visit_expr(&expr); + hir::ImplItemKind::Const(_, body) => { + self.visit_nested_body(body); } hir::ImplItemKind::Method(ref sig, body) => { - let did = self.tcx.map.get_parent_did(search_item); + let did = self.tcx.hir.get_parent_did(search_item); if method_might_be_inlined(self.tcx, sig, impl_item, did) { - self.visit_body(body) + self.visit_nested_body(body) } } hir::ImplItemKind::Type(_) => {} } } // Nothing to recurse on for these - ast_map::NodeForeignItem(_) | - ast_map::NodeVariant(_) | - ast_map::NodeStructCtor(_) | - ast_map::NodeField(_) | - ast_map::NodeTy(_) => {} + hir_map::NodeForeignItem(_) | + hir_map::NodeVariant(_) | + hir_map::NodeStructCtor(_) | + hir_map::NodeField(_) | + hir_map::NodeTy(_) => {} _ => { bug!("found unexpected thingy in worklist: {}", - self.tcx.map.node_to_string(search_item)) + self.tcx.hir.node_to_string(search_item)) } } } @@ -349,7 +343,7 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, for default_method in self.tcx.provided_trait_methods(trait_def_id) { let node_id = self.tcx - .map + .hir .as_local_node_id(default_method.def_id) .unwrap(); self.worklist.push(node_id); @@ -358,6 +352,8 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {} + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { // processed in visit_item above } @@ -368,7 +364,17 @@ pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> NodeSet { let _task = tcx.dep_graph.in_task(DepNode::Reachability); - let mut reachable_context = ReachableContext::new(tcx); + let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { + *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || + *ty == config::CrateTypeProcMacro + }); + let mut reachable_context = ReachableContext { + tcx: tcx, + tables: &ty::TypeckTables::empty(), + reachable_symbols: NodeSet(), + worklist: Vec::new(), + any_library: any_library, + }; // Step 1: Seed the worklist with all nodes which were found to be public as // a result of the privacy pass along with all local lang items and impl items. @@ -380,7 +386,7 @@ pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } for item in tcx.lang_items.items().iter() { if let Some(did) = *item { - if let Some(node_id) = tcx.map.as_local_node_id(did) { + if let Some(node_id) = tcx.hir.as_local_node_id(did) { reachable_context.worklist.push(node_id); } } @@ -391,7 +397,7 @@ pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: access_levels, worklist: &mut reachable_context.worklist, }; - tcx.map.krate().visit_all_item_likes(&mut collect_private_impl_items); + tcx.hir.krate().visit_all_item_likes(&mut collect_private_impl_items); } // Step 2: Mark all symbols that the symbols on the worklist touch. diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index b1e35e54eb..a19f15a932 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -17,7 +17,7 @@ //! `middle/infer/region_inference/README.md` use dep_graph::DepNode; -use hir::map as ast_map; +use hir::map as hir_map; use session::Session; use util::nodemap::{FxHashMap, NodeMap, NodeSet}; use ty; @@ -217,9 +217,9 @@ impl CodeExtent { /// Returns the span of this CodeExtent. Note that in general the /// returned span may not correspond to the span of any node id in /// the AST. - pub fn span(&self, region_maps: &RegionMaps, ast_map: &ast_map::Map) -> Option { - match ast_map.find(self.node_id(region_maps)) { - Some(ast_map::NodeBlock(ref blk)) => { + pub fn span(&self, region_maps: &RegionMaps, hir_map: &hir_map::Map) -> Option { + match hir_map.find(self.node_id(region_maps)) { + Some(hir_map::NodeBlock(ref blk)) => { match region_maps.code_extent_data(*self) { CodeExtentData::CallSiteScope { .. } | CodeExtentData::ParameterScope { .. } | @@ -240,9 +240,9 @@ impl CodeExtent { } } } - Some(ast_map::NodeExpr(ref expr)) => Some(expr.span), - Some(ast_map::NodeStmt(ref stmt)) => Some(stmt.span), - Some(ast_map::NodeItem(ref item)) => Some(item.span), + Some(hir_map::NodeExpr(ref expr)) => Some(expr.span), + Some(hir_map::NodeStmt(ref stmt)) => Some(stmt.span), + Some(hir_map::NodeItem(ref item)) => Some(item.span), Some(_) | None => None, } } @@ -272,6 +272,13 @@ pub struct RegionMaps { /// block (see `terminating_scopes`). rvalue_scopes: RefCell>, + /// Records the value of rvalue scopes before they were shrunk by + /// #36082, for error reporting. + /// + /// FIXME: this should be temporary. Remove this by 1.18.0 or + /// so. + shrunk_rvalue_scopes: RefCell>, + /// Encodes the hierarchy of fn bodies. Every fn body (including /// closures) forms its own distinct region hierarchy, rooted in /// the block that is the fn body. This map points from the id of @@ -302,7 +309,7 @@ pub struct Context { parent: CodeExtent } -struct RegionResolutionVisitor<'ast: 'a, 'a> { +struct RegionResolutionVisitor<'hir: 'a, 'a> { sess: &'a Session, // Generated maps: @@ -310,7 +317,7 @@ struct RegionResolutionVisitor<'ast: 'a, 'a> { cx: Context, - map: &'a ast_map::Map<'ast>, + map: &'a hir_map::Map<'hir>, /// `terminating_scopes` is a set containing the ids of each /// statement, or conditional/repeating expression. These scopes @@ -419,11 +426,7 @@ impl RegionMaps { e(child, parent) } } - pub fn each_rvalue_scope(&self, mut e:E) where E: FnMut(&ast::NodeId, &CodeExtent) { - for (child, parent) in self.rvalue_scopes.borrow().iter() { - e(child, parent) - } - } + /// Records that `sub_fn` is defined within `sup_fn`. These ids /// should be the id of the block that is the fn body, which is /// also the root of the region hierarchy for that fn. @@ -457,6 +460,12 @@ impl RegionMaps { self.rvalue_scopes.borrow_mut().insert(var, lifetime); } + fn record_shrunk_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { + debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime); + assert!(var != lifetime.node_id(self)); + self.shrunk_rvalue_scopes.borrow_mut().insert(var, lifetime); + } + pub fn opt_encl_scope(&self, id: CodeExtent) -> Option { //! Returns the narrowest scope that encloses `id`, if any. self.scope_map.borrow()[id.0 as usize].into_option() @@ -476,6 +485,30 @@ impl RegionMaps { } } + pub fn temporary_scope2(&self, expr_id: ast::NodeId) -> (Option, bool) { + let temporary_scope = self.temporary_scope(expr_id); + let was_shrunk = match self.shrunk_rvalue_scopes.borrow().get(&expr_id) { + Some(&s) => { + info!("temporary_scope2({:?}, scope={:?}, shrunk={:?})", + expr_id, temporary_scope, s); + temporary_scope != Some(s) + } + _ => false + }; + info!("temporary_scope2({:?}) - was_shrunk={:?}", expr_id, was_shrunk); + (temporary_scope, was_shrunk) + } + + pub fn old_and_new_temporary_scope(&self, expr_id: ast::NodeId) -> + (Option, Option) + { + let temporary_scope = self.temporary_scope(expr_id); + (temporary_scope, + self.shrunk_rvalue_scopes + .borrow().get(&expr_id).cloned() + .or(temporary_scope)) + } + pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option { //! Returns the scope when temp created by expr_id will be cleaned up @@ -929,8 +962,10 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, let is_borrow = if let Some(ref ty) = local.ty { is_borrowed_ty(&ty) } else { false }; - if is_binding_pat(&local.pat) || is_borrow { - record_rvalue_scope(visitor, &expr, blk_scope); + if is_binding_pat(&local.pat) { + record_rvalue_scope(visitor, &expr, blk_scope, false); + } else if is_borrow { + record_rvalue_scope(visitor, &expr, blk_scope, true); } } @@ -995,7 +1030,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, match expr.node { hir::ExprAddrOf(_, ref subexpr) => { record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id); - record_rvalue_scope(visitor, &subexpr, blk_id); + record_rvalue_scope(visitor, &subexpr, blk_id, false); } hir::ExprStruct(_, ref fields, _) => { for field in fields { @@ -1040,7 +1075,8 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, /// Note: ET is intended to match "rvalues or lvalues based on rvalues". fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor, expr: &'a hir::Expr, - blk_scope: CodeExtent) { + blk_scope: CodeExtent, + is_shrunk: bool) { let mut expr = expr; loop { // Note: give all the expressions matching `ET` with the @@ -1048,7 +1084,12 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, // because in trans if we must compile e.g. `*rvalue()` // into a temporary, we request the temporary scope of the // outer expression. - visitor.region_maps.record_rvalue_scope(expr.id, blk_scope); + if is_shrunk { + // this changed because of #36082 + visitor.region_maps.record_shrunk_rvalue_scope(expr.id, blk_scope); + } else { + visitor.region_maps.record_rvalue_scope(expr.id, blk_scope); + } match expr.node { hir::ExprAddrOf(_, ref subexpr) | @@ -1088,7 +1129,7 @@ fn resolve_item_like<'a, 'tcx, F>(visitor: &mut RegionResolutionVisitor<'tcx, 'a fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, kind: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, sp: Span, id: ast::NodeId) { debug!("region::resolve_fn(id={:?}, \ @@ -1101,22 +1142,22 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, visitor.cx.parent); visitor.cx.parent = visitor.new_code_extent( - CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id() }); + CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id }); let fn_decl_scope = visitor.new_code_extent( - CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id() }); + CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id }); if let Some(root_id) = visitor.cx.root_id { - visitor.region_maps.record_fn_parent(body_id.node_id(), root_id); + visitor.region_maps.record_fn_parent(body_id.node_id, root_id); } let outer_cx = visitor.cx; let outer_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet()); - visitor.terminating_scopes.insert(body_id.node_id()); + visitor.terminating_scopes.insert(body_id.node_id); // The arguments and `self` are parented to the fn. visitor.cx = Context { - root_id: Some(body_id.node_id()), + root_id: Some(body_id.node_id), parent: ROOT_CODE_EXTENT, var_parent: fn_decl_scope, }; @@ -1126,18 +1167,18 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, // The body of the every fn is a root scope. visitor.cx = Context { - root_id: Some(body_id.node_id()), + root_id: Some(body_id.node_id), parent: fn_decl_scope, var_parent: fn_decl_scope }; - visitor.visit_body(body_id); + visitor.visit_nested_body(body_id); // Restore context we had at the start. visitor.cx = outer_cx; visitor.terminating_scopes = outer_ts; } -impl<'ast, 'a> RegionResolutionVisitor<'ast, 'a> { +impl<'hir, 'a> RegionResolutionVisitor<'hir, 'a> { /// Records the current parent (if any) as the parent of `child_scope`. fn new_code_extent(&mut self, child_scope: CodeExtentData) -> CodeExtent { self.region_maps.intern_code_extent(child_scope, self.cx.parent) @@ -1173,49 +1214,49 @@ impl<'ast, 'a> RegionResolutionVisitor<'ast, 'a> { } } -impl<'ast, 'a> Visitor<'ast> for RegionResolutionVisitor<'ast, 'a> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'ast> { +impl<'hir, 'a> Visitor<'hir> for RegionResolutionVisitor<'hir, 'a> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { NestedVisitorMap::OnlyBodies(&self.map) } - fn visit_block(&mut self, b: &'ast Block) { + fn visit_block(&mut self, b: &'hir Block) { resolve_block(self, b); } - fn visit_item(&mut self, i: &'ast Item) { + fn visit_item(&mut self, i: &'hir Item) { resolve_item_like(self, i.id, |this| intravisit::walk_item(this, i)); } - fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) { + fn visit_impl_item(&mut self, ii: &'hir hir::ImplItem) { resolve_item_like(self, ii.id, |this| intravisit::walk_impl_item(this, ii)); } - fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) { + fn visit_trait_item(&mut self, ti: &'hir hir::TraitItem) { resolve_item_like(self, ti.id, |this| intravisit::walk_trait_item(this, ti)); } - fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, - b: hir::ExprId, s: Span, n: NodeId) { + fn visit_fn(&mut self, fk: FnKind<'hir>, fd: &'hir FnDecl, + b: hir::BodyId, s: Span, n: NodeId) { resolve_fn(self, fk, fd, b, s, n); } - fn visit_arm(&mut self, a: &'ast Arm) { + fn visit_arm(&mut self, a: &'hir Arm) { resolve_arm(self, a); } - fn visit_pat(&mut self, p: &'ast Pat) { + fn visit_pat(&mut self, p: &'hir Pat) { resolve_pat(self, p); } - fn visit_stmt(&mut self, s: &'ast Stmt) { + fn visit_stmt(&mut self, s: &'hir Stmt) { resolve_stmt(self, s); } - fn visit_expr(&mut self, ex: &'ast Expr) { + fn visit_expr(&mut self, ex: &'hir Expr) { resolve_expr(self, ex); } - fn visit_local(&mut self, l: &'ast Local) { + fn visit_local(&mut self, l: &'hir Local) { resolve_local(self, l); } } -pub fn resolve_crate(sess: &Session, map: &ast_map::Map) -> RegionMaps { +pub fn resolve_crate(sess: &Session, map: &hir_map::Map) -> RegionMaps { let _task = map.dep_graph.in_task(DepNode::RegionResolveCrate); let krate = map.krate(); @@ -1225,6 +1266,7 @@ pub fn resolve_crate(sess: &Session, map: &ast_map::Map) -> RegionMaps { scope_map: RefCell::new(vec![]), var_map: RefCell::new(NodeMap()), rvalue_scopes: RefCell::new(NodeMap()), + shrunk_rvalue_scopes: RefCell::new(NodeMap()), fn_tree: RefCell::new(NodeMap()), }; let root_extent = maps.bogus_code_extent( diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index c5b03a4a32..88ef2c69a0 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -15,9 +15,6 @@ //! used between functions, and they operate in a purely top-down //! way. Therefore we break lifetime name resolution into a separate pass. -pub use self::DefRegion::*; -use self::ScopeChain::*; - use dep_graph::DepNode; use hir::map::Map; use session::Session; @@ -25,46 +22,149 @@ use hir::def::Def; use hir::def_id::DefId; use middle::region; use ty; + +use std::cell::Cell; use std::mem::replace; use syntax::ast; +use syntax::attr; +use syntax::ptr::P; use syntax::symbol::keywords; use syntax_pos::Span; -use util::nodemap::NodeMap; +use errors::DiagnosticBuilder; +use util::nodemap::{NodeMap, FxHashSet, FxHashMap, DefIdMap}; +use rustc_back::slice; -use rustc_data_structures::fx::FxHashSet; use hir; -use hir::print::lifetime_to_string; -use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; +use hir::intravisit::{self, Visitor, NestedVisitorMap}; #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] -pub enum DefRegion { - DefStaticRegion, - DefEarlyBoundRegion(/* index */ u32, - /* lifetime decl */ ast::NodeId), - DefLateBoundRegion(ty::DebruijnIndex, - /* lifetime decl */ ast::NodeId), - DefFreeRegion(region::CallSiteScopeData, - /* lifetime decl */ ast::NodeId), +pub enum Region { + Static, + EarlyBound(/* index */ u32, /* lifetime decl */ ast::NodeId), + LateBound(ty::DebruijnIndex, /* lifetime decl */ ast::NodeId), + LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32), + Free(region::CallSiteScopeData, /* lifetime decl */ ast::NodeId), } +impl Region { + fn early(index: &mut u32, def: &hir::LifetimeDef) -> (ast::Name, Region) { + let i = *index; + *index += 1; + (def.lifetime.name, Region::EarlyBound(i, def.lifetime.id)) + } + + fn late(def: &hir::LifetimeDef) -> (ast::Name, Region) { + let depth = ty::DebruijnIndex::new(1); + (def.lifetime.name, Region::LateBound(depth, def.lifetime.id)) + } + + fn late_anon(index: &Cell) -> Region { + let i = index.get(); + index.set(i + 1); + let depth = ty::DebruijnIndex::new(1); + Region::LateBoundAnon(depth, i) + } + + fn id(&self) -> Option { + match *self { + Region::Static | + Region::LateBoundAnon(..) => None, + + Region::EarlyBound(_, id) | + Region::LateBound(_, id) | + Region::Free(_, id) => Some(id) + } + } + + fn shifted(self, amount: u32) -> Region { + match self { + Region::LateBound(depth, id) => { + Region::LateBound(depth.shifted(amount), id) + } + Region::LateBoundAnon(depth, index) => { + Region::LateBoundAnon(depth.shifted(amount), index) + } + _ => self + } + } + + fn from_depth(self, depth: u32) -> Region { + match self { + Region::LateBound(debruijn, id) => { + Region::LateBound(ty::DebruijnIndex { + depth: debruijn.depth - (depth - 1) + }, id) + } + Region::LateBoundAnon(debruijn, index) => { + Region::LateBoundAnon(ty::DebruijnIndex { + depth: debruijn.depth - (depth - 1) + }, index) + } + _ => self + } + } + + fn subst(self, params: &[hir::Lifetime], map: &NamedRegionMap) + -> Option { + if let Region::EarlyBound(index, _) = self { + params.get(index as usize).and_then(|lifetime| { + map.defs.get(&lifetime.id).cloned() + }) + } else { + Some(self) + } + } +} + +/// A set containing, at most, one known element. +/// If two distinct values are inserted into a set, then it +/// becomes `Many`, which can be used to detect ambiguities. +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] +pub enum Set1 { + Empty, + One(T), + Many +} + +impl Set1 { + pub fn insert(&mut self, value: T) { + if let Set1::Empty = *self { + *self = Set1::One(value); + return; + } + if let Set1::One(ref old) = *self { + if *old == value { + return; + } + } + *self = Set1::Many; + } +} + +pub type ObjectLifetimeDefault = Set1; + // Maps the id of each lifetime reference to the lifetime decl // that it corresponds to. pub struct NamedRegionMap { // maps from every use of a named (not anonymous) lifetime to a - // `DefRegion` describing how that region is bound - pub defs: NodeMap, + // `Region` describing how that region is bound + pub defs: NodeMap, // the set of lifetime def ids that are late-bound; late-bound ids // are named regions appearing in fn arguments that do not appear // in where-clauses pub late_bound: NodeMap, + + // For each type and trait definition, maps type parameters + // to the trait object lifetime defaults computed from them. + pub object_lifetime_defaults: NodeMap>, } struct LifetimeContext<'a, 'tcx: 'a> { sess: &'a Session, hir_map: &'a Map<'tcx>, map: &'a mut NamedRegionMap, - scope: Scope<'a>, + scope: ScopeRef<'a>, // Deep breath. Our representation for poly trait refs contains a single // binder and thus we only allow a single level of quantification. However, // the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>` @@ -84,28 +184,75 @@ struct LifetimeContext<'a, 'tcx: 'a> { // List of labels in the function/method currently under analysis. labels_in_fn: Vec<(ast::Name, Span)>, + + // Cache for cross-crate per-definition object lifetime defaults. + xcrate_object_lifetime_defaults: DefIdMap>, +} + +#[derive(Debug)] +enum Scope<'a> { + /// Declares lifetimes, and each can be early-bound or late-bound. + /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and + /// it should be shifted by the number of `Binder`s in between the + /// declaration `Binder` and the location it's referenced from. + Binder { + lifetimes: FxHashMap, + s: ScopeRef<'a> + }, + + /// Lifetimes introduced by a fn are scoped to the call-site for that fn, + /// if this is a fn body, otherwise the original definitions are used. + /// Unspecified lifetimes are inferred, unless an elision scope is nested, + /// e.g. `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`. + Body { + id: hir::BodyId, + s: ScopeRef<'a> + }, + + /// A scope which either determines unspecified lifetimes or errors + /// on them (e.g. due to ambiguity). For more details, see `Elide`. + Elision { + elide: Elide, + s: ScopeRef<'a> + }, + + /// Use a specific lifetime (if `Some`) or leave it unset (to be + /// inferred in a function body or potentially error outside one), + /// for the default choice of lifetime in a trait object type. + ObjectLifetimeDefault { + lifetime: Option, + s: ScopeRef<'a> + }, + + Root +} + +#[derive(Clone, Debug)] +enum Elide { + /// Use a fresh anonymous late-bound lifetime each time, by + /// incrementing the counter to generate sequential indices. + FreshLateAnon(Cell), + /// Always use this one lifetime. + Exact(Region), + /// Like `Exact(Static)` but requires `#![feature(static_in_const)]`. + Static, + /// Less or more than one lifetime were found, error on unspecified. + Error(Vec) } -#[derive(PartialEq, Debug)] -enum ScopeChain<'a> { - /// EarlyScope(['a, 'b, ...], start, s) extends s with early-bound - /// lifetimes, with consecutive parameter indices from `start`. - /// That is, 'a has index `start`, 'b has index `start + 1`, etc. - /// Indices before `start` correspond to other generic parameters - /// of a parent item (trait/impl of a method), or `Self` in traits. - EarlyScope(&'a [hir::LifetimeDef], u32, Scope<'a>), - /// LateScope(['a, 'b, ...], s) extends s with late-bound - /// lifetimes introduced by the declaration binder_id. - LateScope(&'a [hir::LifetimeDef], Scope<'a>), - - /// lifetimes introduced by a fn are scoped to the call-site for that fn. - FnScope { fn_id: ast::NodeId, body_id: ast::NodeId, s: Scope<'a> }, - RootScope +#[derive(Clone, Debug)] +struct ElisionFailureInfo { + /// Where we can find the argument pattern. + parent: Option, + /// The index of the argument in the original definition. + index: usize, + lifetime_count: usize, + have_bound_regions: bool } -type Scope<'a> = &'a ScopeChain<'a>; +type ScopeRef<'a> = &'a Scope<'a>; -static ROOT_SCOPE: ScopeChain<'static> = RootScope; +const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root; pub fn krate(sess: &Session, hir_map: &Map) @@ -115,118 +262,104 @@ pub fn krate(sess: &Session, let mut map = NamedRegionMap { defs: NodeMap(), late_bound: NodeMap(), + object_lifetime_defaults: compute_object_lifetime_defaults(sess, hir_map), }; sess.track_errors(|| { - intravisit::walk_crate(&mut LifetimeContext { + let mut visitor = LifetimeContext { sess: sess, hir_map: hir_map, map: &mut map, - scope: &ROOT_SCOPE, + scope: ROOT_SCOPE, trait_ref_hack: false, labels_in_fn: vec![], - }, krate); + xcrate_object_lifetime_defaults: DefIdMap(), + }; + for (_, item) in &krate.items { + visitor.visit_item(item); + } })?; Ok(map) } impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { - // Override the nested functions -- lifetimes follow lexical scope, - // so it's convenient to walk the tree in lexical order. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.hir_map) + NestedVisitorMap::All(self.hir_map) + } + + // We want to nest trait/impl items in their parent, but nothing else. + fn visit_nested_item(&mut self, _: hir::ItemId) {} + + fn visit_nested_body(&mut self, body: hir::BodyId) { + // Each body has their own set of labels, save labels. + let saved = replace(&mut self.labels_in_fn, vec![]); + let body = self.hir_map.body(body); + extract_labels(self, body); + self.with(Scope::Body { id: body.id(), s: self.scope }, |_, this| { + this.visit_body(body); + }); + replace(&mut self.labels_in_fn, saved); } fn visit_item(&mut self, item: &'tcx hir::Item) { - // Save labels for nested items. - let saved_labels_in_fn = replace(&mut self.labels_in_fn, vec![]); - - // Items always introduce a new root scope - self.with(RootScope, |_, this| { - match item.node { - hir::ItemFn(..) => { - // Fn lifetimes get added in visit_fn below: + match item.node { + hir::ItemFn(ref decl, _, _, _, ref generics, _) => { + self.visit_early_late(item.id, None, decl, generics, |this| { intravisit::walk_item(this, item); - } - hir::ItemExternCrate(_) | - hir::ItemUse(..) | - hir::ItemMod(..) | - hir::ItemDefaultImpl(..) | - hir::ItemForeignMod(..) | - hir::ItemStatic(..) | - hir::ItemConst(..) => { - // These sorts of items have no lifetime parameters at all. + }); + } + hir::ItemExternCrate(_) | + hir::ItemUse(..) | + hir::ItemMod(..) | + hir::ItemDefaultImpl(..) | + hir::ItemForeignMod(..) => { + // These sorts of items have no lifetime parameters at all. + intravisit::walk_item(self, item); + } + hir::ItemStatic(..) | + hir::ItemConst(..) => { + // No lifetime parameters, but implied 'static. + let scope = Scope::Elision { + elide: Elide::Static, + s: ROOT_SCOPE + }; + self.with(scope, |_, this| intravisit::walk_item(this, item)); + } + hir::ItemTy(_, ref generics) | + hir::ItemEnum(_, ref generics) | + hir::ItemStruct(_, ref generics) | + hir::ItemUnion(_, ref generics) | + hir::ItemTrait(_, ref generics, ..) | + hir::ItemImpl(_, _, ref generics, ..) => { + // These kinds of items have only early bound lifetime parameters. + let mut index = if let hir::ItemTrait(..) = item.node { + 1 // Self comes before lifetimes + } else { + 0 + }; + let lifetimes = generics.lifetimes.iter().map(|def| { + Region::early(&mut index, def) + }).collect(); + let scope = Scope::Binder { + lifetimes: lifetimes, + s: ROOT_SCOPE + }; + self.with(scope, |old_scope, this| { + this.check_lifetime_defs(old_scope, &generics.lifetimes); intravisit::walk_item(this, item); - } - hir::ItemTy(_, ref generics) | - hir::ItemEnum(_, ref generics) | - hir::ItemStruct(_, ref generics) | - hir::ItemUnion(_, ref generics) | - hir::ItemTrait(_, ref generics, ..) | - hir::ItemImpl(_, _, ref generics, ..) => { - // These kinds of items have only early bound lifetime parameters. - let lifetimes = &generics.lifetimes; - let start = if let hir::ItemTrait(..) = item.node { - 1 // Self comes before lifetimes - } else { - 0 - }; - this.with(EarlyScope(lifetimes, start, &ROOT_SCOPE), |old_scope, this| { - this.check_lifetime_defs(old_scope, lifetimes); - intravisit::walk_item(this, item); - }); - } + }); } - }); - - // Done traversing the item; remove any labels it created - self.labels_in_fn = saved_labels_in_fn; + } } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) { - // Items save/restore the set of labels. This way inner items - // can freely reuse names, be they loop labels or lifetimes. - let saved = replace(&mut self.labels_in_fn, vec![]); - - // Items always introduce a new root scope - self.with(RootScope, |_, this| { - match item.node { - hir::ForeignItemFn(ref decl, ref generics) => { - this.visit_early_late(item.id, decl, generics, |this| { - intravisit::walk_foreign_item(this, item); - }) - } - hir::ForeignItemStatic(..) => { + match item.node { + hir::ForeignItemFn(ref decl, _, ref generics) => { + self.visit_early_late(item.id, None, decl, generics, |this| { intravisit::walk_foreign_item(this, item); - } - } - }); - - // Done traversing the item; restore saved set of labels. - replace(&mut self.labels_in_fn, saved); - } - - fn visit_fn(&mut self, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - b: hir::ExprId, s: Span, fn_id: ast::NodeId) { - match fk { - FnKind::ItemFn(_, generics, ..) => { - self.visit_early_late(fn_id,decl, generics, |this| { - this.add_scope_and_walk_fn(fk, decl, b, s, fn_id) }) } - FnKind::Method(_, sig, ..) => { - self.visit_early_late( - fn_id, - decl, - &sig.generics, - |this| this.add_scope_and_walk_fn(fk, decl, b, s, fn_id)); - } - FnKind::Closure(_) => { - // Closures have their own set of labels, save labels just - // like for foreign items above. - let saved = replace(&mut self.labels_in_fn, vec![]); - let result = self.add_scope_and_walk_fn(fk, decl, b, s, fn_id); - replace(&mut self.labels_in_fn, saved); - result + hir::ForeignItemStatic(..) => { + intravisit::walk_foreign_item(self, item); } } } @@ -234,27 +367,35 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty) { match ty.node { hir::TyBareFn(ref c) => { - self.with(LateScope(&c.lifetimes, self.scope), |old_scope, this| { + let scope = Scope::Binder { + lifetimes: c.lifetimes.iter().map(Region::late).collect(), + s: self.scope + }; + self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything // contained within is scoped within its binder. this.check_lifetime_defs(old_scope, &c.lifetimes); intravisit::walk_ty(this, ty); }); } - hir::TyPath(hir::QPath::Resolved(None, ref path)) => { - // if this path references a trait, then this will resolve to - // a trait ref, which introduces a binding scope. - match path.def { - Def::Trait(..) => { - self.with(LateScope(&[], self.scope), |_, this| { - this.visit_path(path, ty.id); - }); - } - _ => { - intravisit::walk_ty(self, ty); - } + hir::TyTraitObject(ref bounds, ref lifetime) => { + for bound in bounds { + self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); + } + if lifetime.is_elided() { + self.resolve_object_lifetime_default(lifetime) + } else { + self.visit_lifetime(lifetime); } } + hir::TyRptr(ref lifetime_ref, ref mt) => { + self.visit_lifetime(lifetime_ref); + let scope = Scope::ObjectLifetimeDefault { + lifetime: self.map.defs.get(&lifetime_ref.id).cloned(), + s: self.scope + }; + self.with(scope, |_, this| this.visit_ty(&mt.ty)); + } _ => { intravisit::walk_ty(self, ty) } @@ -262,30 +403,56 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { - // We reset the labels on every trait item, so that different - // methods in an impl can reuse label names. - let saved = replace(&mut self.labels_in_fn, vec![]); - - if let hir::MethodTraitItem(ref sig, None) = trait_item.node { + if let hir::TraitItemKind::Method(ref sig, _) = trait_item.node { self.visit_early_late( trait_item.id, + Some(self.hir_map.get_parent(trait_item.id)), &sig.decl, &sig.generics, |this| intravisit::walk_trait_item(this, trait_item)) } else { intravisit::walk_trait_item(self, trait_item); } + } - replace(&mut self.labels_in_fn, saved); + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { + if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { + self.visit_early_late( + impl_item.id, + Some(self.hir_map.get_parent(impl_item.id)), + &sig.decl, &sig.generics, + |this| intravisit::walk_impl_item(this, impl_item)) + } else { + intravisit::walk_impl_item(self, impl_item); + } } fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { + if lifetime_ref.is_elided() { + self.resolve_elided_lifetimes(slice::ref_slice(lifetime_ref)); + return; + } if lifetime_ref.name == keywords::StaticLifetime.name() { - self.insert_lifetime(lifetime_ref, DefStaticRegion); + self.insert_lifetime(lifetime_ref, Region::Static); return; } self.resolve_lifetime_ref(lifetime_ref); } + fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) { + for (i, segment) in path.segments.iter().enumerate() { + let depth = path.segments.len() - i - 1; + self.visit_segment_parameters(path.def, depth, &segment.parameters); + } + } + + fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl) { + let output = match fd.output { + hir::DefaultReturn(_) => None, + hir::Return(ref ty) => Some(ty) + }; + self.visit_fn_like_elision(&fd.inputs, output); + } + fn visit_generics(&mut self, generics: &'tcx hir::Generics) { for ty_param in generics.ty_params.iter() { walk_list!(self, visit_ty_param_bound, &ty_param.bounds); @@ -301,8 +468,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .. }) => { if !bound_lifetimes.is_empty() { self.trait_ref_hack = true; - let result = self.with(LateScope(bound_lifetimes, self.scope), - |old_scope, this| { + let scope = Scope::Binder { + lifetimes: bound_lifetimes.iter().map(Region::late).collect(), + s: self.scope + }; + let result = self.with(scope, |old_scope, this| { this.check_lifetime_defs(old_scope, bound_lifetimes); this.visit_ty(&bounded_ty); walk_list!(this, visit_ty_param_bound, bounds); @@ -323,12 +493,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.visit_lifetime(bound); } } - &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ id, - ref path, - ref ty, - .. }) => { - self.visit_path(path, id); - self.visit_ty(&ty); + &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref lhs_ty, + ref rhs_ty, + .. }) => { + self.visit_ty(lhs_ty); + self.visit_ty(rhs_ty); } } } @@ -336,7 +505,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef, - _modifier: &'tcx hir::TraitBoundModifier) { + _modifier: hir::TraitBoundModifier) { debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref); if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() { @@ -344,12 +513,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { span_err!(self.sess, trait_ref.span, E0316, "nested quantification of lifetimes"); } - self.with(LateScope(&trait_ref.bound_lifetimes, self.scope), |old_scope, this| { + let scope = Scope::Binder { + lifetimes: trait_ref.bound_lifetimes.iter().map(Region::late).collect(), + s: self.scope + }; + self.with(scope, |old_scope, this| { this.check_lifetime_defs(old_scope, &trait_ref.bound_lifetimes); for lifetime in &trait_ref.bound_lifetimes { this.visit_lifetime_def(lifetime); } - intravisit::walk_path(this, &trait_ref.trait_ref.path) + this.visit_trait_ref(&trait_ref.trait_ref) }) } else { self.visit_trait_ref(&trait_ref.trait_ref) @@ -368,8 +541,8 @@ fn original_label(span: Span) -> Original { fn shadower_label(span: Span) -> Shadower { Shadower { kind: ShadowKind::Label, span: span } } -fn original_lifetime(l: &hir::Lifetime) -> Original { - Original { kind: ShadowKind::Lifetime, span: l.span } +fn original_lifetime(span: Span) -> Original { + Original { kind: ShadowKind::Lifetime, span: span } } fn shadower_lifetime(l: &hir::Lifetime) -> Shadower { Shadower { kind: ShadowKind::Lifetime, span: l.span } @@ -407,33 +580,28 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning // if one of the label shadows a lifetime or another label. -fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) { - struct GatherLabels<'a> { +fn extract_labels(ctxt: &mut LifetimeContext, body: &hir::Body) { + struct GatherLabels<'a, 'tcx: 'a> { sess: &'a Session, - scope: Scope<'a>, + hir_map: &'a Map<'tcx>, + scope: ScopeRef<'a>, labels_in_fn: &'a mut Vec<(ast::Name, Span)>, } let mut gather = GatherLabels { sess: ctxt.sess, + hir_map: ctxt.hir_map, scope: ctxt.scope, labels_in_fn: &mut ctxt.labels_in_fn, }; - gather.visit_expr(ctxt.hir_map.expr(b)); - return; + gather.visit_body(body); - impl<'v, 'a> Visitor<'v> for GatherLabels<'a> { + impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { NestedVisitorMap::None } - fn visit_expr(&mut self, ex: &'v hir::Expr) { - // do not recurse into closures defined in the block - // since they are treated as separate fns from the POV of - // labels_in_fn - if let hir::ExprClosure(..) = ex.node { - return - } + fn visit_expr(&mut self, ex: &hir::Expr) { if let Some((label, label_span)) = expression_label(ex) { for &(prior, prior_span) in &self.labels_in_fn[..] { // FIXME (#24278): non-hygienic comparison @@ -446,6 +614,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) { } check_if_label_shadows_lifetime(self.sess, + self.hir_map, self.scope, label, label_span); @@ -454,10 +623,6 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) { } intravisit::walk_expr(self, ex) } - - fn visit_item(&mut self, _: &hir::Item) { - // do not recurse into items defined in the block - } } fn expression_label(ex: &hir::Expr) -> Option<(ast::Name, Span)> { @@ -469,26 +634,27 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) { } fn check_if_label_shadows_lifetime<'a>(sess: &'a Session, - mut scope: Scope<'a>, + hir_map: &Map, + mut scope: ScopeRef<'a>, label: ast::Name, label_span: Span) { loop { match *scope { - FnScope { s, .. } => { scope = s; } - RootScope => { return; } - - EarlyScope(lifetimes, _, s) | - LateScope(lifetimes, s) => { - for lifetime_def in lifetimes { - // FIXME (#24278): non-hygienic comparison - if label == lifetime_def.lifetime.name { - signal_shadowing_problem( - sess, - label, - original_lifetime(&lifetime_def.lifetime), - shadower_label(label_span)); - return; - } + Scope::Body { s, .. } | + Scope::Elision { s, .. } | + Scope::ObjectLifetimeDefault { s, .. } => { scope = s; } + + Scope::Root => { return; } + + Scope::Binder { ref lifetimes, s } => { + // FIXME (#24278): non-hygienic comparison + if let Some(def) = lifetimes.get(&label) { + signal_shadowing_problem( + sess, + label, + original_lifetime(hir_map.span(def.id().unwrap())), + shadower_label(label_span)); + return; } scope = s; } @@ -497,35 +663,104 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) { } } -impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { - fn add_scope_and_walk_fn(&mut self, - fk: FnKind<'tcx>, - fd: &'tcx hir::FnDecl, - fb: hir::ExprId, - _span: Span, - fn_id: ast::NodeId) { - match fk { - FnKind::ItemFn(_, generics, ..) => { - intravisit::walk_fn_decl(self, fd); - self.visit_generics(generics); - } - FnKind::Method(_, sig, ..) => { - intravisit::walk_fn_decl(self, fd); - self.visit_generics(&sig.generics); +fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map) + -> NodeMap> { + let mut map = NodeMap(); + for item in hir_map.krate().items.values() { + match item.node { + hir::ItemStruct(_, ref generics) | + hir::ItemUnion(_, ref generics) | + hir::ItemEnum(_, ref generics) | + hir::ItemTy(_, ref generics) | + hir::ItemTrait(_, ref generics, ..) => { + let result = object_lifetime_defaults_for_item(hir_map, generics); + + // Debugging aid. + if attr::contains_name(&item.attrs, "rustc_object_lifetime_default") { + let object_lifetime_default_reprs: String = + result.iter().map(|set| { + match *set { + Set1::Empty => "BaseDefault".to_string(), + Set1::One(Region::Static) => "'static".to_string(), + Set1::One(Region::EarlyBound(i, _)) => { + generics.lifetimes[i as usize].lifetime.name.to_string() + } + Set1::One(_) => bug!(), + Set1::Many => "Ambiguous".to_string(), + } + }).collect::>().join(","); + sess.span_err(item.span, &object_lifetime_default_reprs); + } + + map.insert(item.id, result); } - FnKind::Closure(_) => { - intravisit::walk_fn_decl(self, fd); + _ => {} + } + } + map +} + +/// Scan the bounds and where-clauses on parameters to extract bounds +/// of the form `T:'a` so as to determine the `ObjectLifetimeDefault` +/// for each type parameter. +fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics) + -> Vec { + fn add_bounds(set: &mut Set1, bounds: &[hir::TyParamBound]) { + for bound in bounds { + if let hir::RegionTyParamBound(ref lifetime) = *bound { + set.insert(lifetime.name); } } + } - // After inpsecting the decl, add all labels from the body to - // `self.labels_in_fn`. - extract_labels(self, fb); + generics.ty_params.iter().map(|param| { + let mut set = Set1::Empty; - self.with(FnScope { fn_id: fn_id, body_id: fb.node_id(), s: self.scope }, - |_old_scope, this| this.visit_body(fb)) - } + add_bounds(&mut set, ¶m.bounds); + + let param_def_id = hir_map.local_def_id(param.id); + for predicate in &generics.where_clause.predicates { + // Look for `type: ...` where clauses. + let data = match *predicate { + hir::WherePredicate::BoundPredicate(ref data) => data, + _ => continue + }; + + // Ignore `for<'a> type: ...` as they can change what + // lifetimes mean (although we could "just" handle it). + if !data.bound_lifetimes.is_empty() { + continue; + } + + let def = match data.bounded_ty.node { + hir::TyPath(hir::QPath::Resolved(None, ref path)) => path.def, + _ => continue + }; + if def == Def::TyParam(param_def_id) { + add_bounds(&mut set, &data.bounds); + } + } + + match set { + Set1::Empty => Set1::Empty, + Set1::One(name) => { + if name == keywords::StaticLifetime.name() { + Set1::One(Region::Static) + } else { + generics.lifetimes.iter().enumerate().find(|&(_, def)| { + def.lifetime.name == name + }).map_or(Set1::Many, |(i, def)| { + Set1::One(Region::EarlyBound(i as u32, def.lifetime.id)) + }) + } + } + Set1::Many => Set1::Many + } + }).collect() +} + +impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // FIXME(#37666) this works around a limitation in the region inferencer fn hack(&mut self, f: F) where F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>), @@ -533,21 +768,27 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { f(self) } - fn with(&mut self, wrap_scope: ScopeChain, f: F) where - F: for<'b> FnOnce(Scope, &mut LifetimeContext<'b, 'tcx>), + fn with(&mut self, wrap_scope: Scope, f: F) where + F: for<'b> FnOnce(ScopeRef, &mut LifetimeContext<'b, 'tcx>), { let LifetimeContext {sess, hir_map, ref mut map, ..} = *self; + let labels_in_fn = replace(&mut self.labels_in_fn, vec![]); + let xcrate_object_lifetime_defaults = + replace(&mut self.xcrate_object_lifetime_defaults, DefIdMap()); let mut this = LifetimeContext { sess: sess, hir_map: hir_map, map: *map, scope: &wrap_scope, trait_ref_hack: self.trait_ref_hack, - labels_in_fn: self.labels_in_fn.clone(), + labels_in_fn: labels_in_fn, + xcrate_object_lifetime_defaults: xcrate_object_lifetime_defaults, }; debug!("entering scope {:?}", this.scope); f(self.scope, &mut this); debug!("exiting scope {:?}", this.scope); + self.labels_in_fn = this.labels_in_fn; + self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults; } /// Visits self by adding a scope and handling recursive walk over the contents with `walk`. @@ -570,6 +811,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// ordering is not important there. fn visit_early_late(&mut self, fn_id: ast::NodeId, + parent_id: Option, decl: &'tcx hir::FnDecl, generics: &'tcx hir::Generics, walk: F) where @@ -581,156 +823,618 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { decl, generics); - let (late, early): (Vec<_>, _) = - generics.lifetimes - .iter() - .cloned() - .partition(|l| self.map.late_bound.contains_key(&l.lifetime.id)); - // Find the start of nested early scopes, e.g. in methods. - let mut start = 0; - if let EarlyScope(..) = *self.scope { - let parent = self.hir_map.expect_item(self.hir_map.get_parent(fn_id)); + let mut index = 0; + if let Some(parent_id) = parent_id { + let parent = self.hir_map.expect_item(parent_id); if let hir::ItemTrait(..) = parent.node { - start += 1; // Self comes first. + index += 1; // Self comes first. } match parent.node { hir::ItemTrait(_, ref generics, ..) | hir::ItemImpl(_, _, ref generics, ..) => { - start += generics.lifetimes.len() + generics.ty_params.len(); + index += (generics.lifetimes.len() + generics.ty_params.len()) as u32; } _ => {} } } - self.with(EarlyScope(&early, start as u32, self.scope), move |old_scope, this| { - this.with(LateScope(&late, this.scope), move |_, this| { - this.check_lifetime_defs(old_scope, &generics.lifetimes); - this.hack(walk); // FIXME(#37666) workaround in place of `walk(this)` - }); + let lifetimes = generics.lifetimes.iter().map(|def| { + if self.map.late_bound.contains_key(&def.lifetime.id) { + Region::late(def) + } else { + Region::early(&mut index, def) + } + }).collect(); + + let scope = Scope::Binder { + lifetimes: lifetimes, + s: self.scope + }; + self.with(scope, move |old_scope, this| { + this.check_lifetime_defs(old_scope, &generics.lifetimes); + this.hack(walk); // FIXME(#37666) workaround in place of `walk(this)` }); } fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) { // Walk up the scope chain, tracking the number of fn scopes // that we pass through, until we find a lifetime with the - // given name or we run out of scopes. If we encounter a code - // block, then the lifetime is not bound but free, so switch - // over to `resolve_free_lifetime_ref()` to complete the + // given name or we run out of scopes. // search. let mut late_depth = 0; let mut scope = self.scope; - loop { + let mut outermost_body = None; + let result = loop { match *scope { - FnScope {fn_id, body_id, s } => { - return self.resolve_free_lifetime_ref( - region::CallSiteScopeData { fn_id: fn_id, body_id: body_id }, - lifetime_ref, - s); + Scope::Body { id, s } => { + outermost_body = Some(id); + scope = s; } - RootScope => { - break; + Scope::Root => { + break None; } - EarlyScope(lifetimes, start, s) => { - match search_lifetimes(lifetimes, lifetime_ref) { - Some((index, lifetime_def)) => { - let decl_id = lifetime_def.id; - let def = DefEarlyBoundRegion(start + index, decl_id); - self.insert_lifetime(lifetime_ref, def); - return; - } - None => { + Scope::Binder { ref lifetimes, s } => { + if let Some(&def) = lifetimes.get(&lifetime_ref.name) { + break Some(def.shifted(late_depth)); + } else { + late_depth += 1; + scope = s; + } + } + + Scope::Elision { s, .. } | + Scope::ObjectLifetimeDefault { s, .. } => { + scope = s; + } + } + }; + + if let Some(mut def) = result { + if let Some(body_id) = outermost_body { + let fn_id = self.hir_map.body_owner(body_id); + let scope_data = region::CallSiteScopeData { + fn_id: fn_id, body_id: body_id.node_id + }; + match self.hir_map.get(fn_id) { + hir::map::NodeItem(&hir::Item { + node: hir::ItemFn(..), .. + }) | + hir::map::NodeTraitItem(&hir::TraitItem { + node: hir::TraitItemKind::Method(..), .. + }) | + hir::map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method(..), .. + }) => { + def = Region::Free(scope_data, def.id().unwrap()); + } + _ => {} + } + } + self.insert_lifetime(lifetime_ref, def); + } else { + struct_span_err!(self.sess, lifetime_ref.span, E0261, + "use of undeclared lifetime name `{}`", lifetime_ref.name) + .span_label(lifetime_ref.span, &format!("undeclared lifetime")) + .emit(); + } + } + + fn visit_segment_parameters(&mut self, + def: Def, + depth: usize, + params: &'tcx hir::PathParameters) { + let data = match *params { + hir::ParenthesizedParameters(ref data) => { + self.visit_fn_like_elision(&data.inputs, data.output.as_ref()); + return; + } + hir::AngleBracketedParameters(ref data) => data + }; + + if data.lifetimes.iter().all(|l| l.is_elided()) { + self.resolve_elided_lifetimes(&data.lifetimes); + } else { + for l in &data.lifetimes { self.visit_lifetime(l); } + } + + // Figure out if this is a type/trait segment, + // which requires object lifetime defaults. + let parent_def_id = |this: &mut Self, def_id: DefId| { + let def_key = if def_id.is_local() { + this.hir_map.def_key(def_id) + } else { + this.sess.cstore.def_key(def_id) + }; + DefId { + krate: def_id.krate, + index: def_key.parent.expect("missing parent") + } + }; + let type_def_id = match def { + Def::AssociatedTy(def_id) if depth == 1 => { + Some(parent_def_id(self, def_id)) + } + Def::Variant(def_id) if depth == 0 => { + Some(parent_def_id(self, def_id)) + } + Def::Struct(def_id) | + Def::Union(def_id) | + Def::Enum(def_id) | + Def::TyAlias(def_id) | + Def::Trait(def_id) if depth == 0 => Some(def_id), + _ => None + }; + + let object_lifetime_defaults = type_def_id.map_or(vec![], |def_id| { + let in_body = { + let mut scope = self.scope; + loop { + match *scope { + Scope::Root => break false, + + Scope::Body { .. } => break true, + + Scope::Binder { s, .. } | + Scope::Elision { s, .. } | + Scope::ObjectLifetimeDefault { s, .. } => { scope = s; } } } + }; + + let map = &self.map; + let unsubst = if let Some(id) = self.hir_map.as_local_node_id(def_id) { + &map.object_lifetime_defaults[&id] + } else { + let cstore = &self.sess.cstore; + self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| { + cstore.item_generics_object_lifetime_defaults(def_id) + }) + }; + unsubst.iter().map(|set| { + match *set { + Set1::Empty => { + if in_body { + None + } else { + Some(Region::Static) + } + } + Set1::One(r) => r.subst(&data.lifetimes, map), + Set1::Many => None + } + }).collect() + }); + + for (i, ty) in data.types.iter().enumerate() { + if let Some(<) = object_lifetime_defaults.get(i) { + let scope = Scope::ObjectLifetimeDefault { + lifetime: lt, + s: self.scope + }; + self.with(scope, |_, this| this.visit_ty(ty)); + } else { + self.visit_ty(ty); + } + } + + for b in &data.bindings { self.visit_assoc_type_binding(b); } + } + + fn visit_fn_like_elision(&mut self, inputs: &'tcx [P], + output: Option<&'tcx P>) { + let mut arg_elide = Elide::FreshLateAnon(Cell::new(0)); + let arg_scope = Scope::Elision { + elide: arg_elide.clone(), + s: self.scope + }; + self.with(arg_scope, |_, this| { + for input in inputs { + this.visit_ty(input); + } + match *this.scope { + Scope::Elision { ref elide, .. } => { + arg_elide = elide.clone(); + } + _ => bug!() + } + }); + + let output = match output { + Some(ty) => ty, + None => return + }; + + // Figure out if there's a body we can get argument names from, + // and whether there's a `self` argument (treated specially). + let mut assoc_item_kind = None; + let mut impl_self = None; + let parent = self.hir_map.get_parent_node(output.id); + let body = match self.hir_map.get(parent) { + // `fn` definitions and methods. + hir::map::NodeItem(&hir::Item { + node: hir::ItemFn(.., body), .. + }) => Some(body), + + hir::map::NodeTraitItem(&hir::TraitItem { + node: hir::TraitItemKind::Method(_, ref m), .. + }) => { + match self.hir_map.expect_item(self.hir_map.get_parent(parent)).node { + hir::ItemTrait(.., ref trait_items) => { + assoc_item_kind = trait_items.iter().find(|ti| ti.id.node_id == parent) + .map(|ti| ti.kind); + } + _ => {} + } + match *m { + hir::TraitMethod::Required(_) => None, + hir::TraitMethod::Provided(body) => Some(body), + } + } + + hir::map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method(_, body), .. + }) => { + match self.hir_map.expect_item(self.hir_map.get_parent(parent)).node { + hir::ItemImpl(.., ref self_ty, ref impl_items) => { + impl_self = Some(self_ty); + assoc_item_kind = impl_items.iter().find(|ii| ii.id.node_id == parent) + .map(|ii| ii.kind); + } + _ => {} + } + Some(body) + } + + // `fn(...) -> R` and `Trait(...) -> R` (both types and bounds). + hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => None, + + // Foreign `fn` decls are terrible because we messed up, + // and their return types get argument type elision. + // And now too much code out there is abusing this rule. + hir::map::NodeForeignItem(_) => { + let arg_scope = Scope::Elision { + elide: arg_elide, + s: self.scope + }; + self.with(arg_scope, |_, this| this.visit_ty(output)); + return; + } + + // Everything else (only closures?) doesn't + // actually enjoy elision in return types. + _ => { + self.visit_ty(output); + return; + } + }; + + let has_self = match assoc_item_kind { + Some(hir::AssociatedItemKind::Method { has_self }) => has_self, + _ => false + }; + + // In accordance with the rules for lifetime elision, we can determine + // what region to use for elision in the output type in two ways. + // First (determined here), if `self` is by-reference, then the + // implied output region is the region of the self parameter. + if has_self { + // Look for `self: &'a Self` - also desugared from `&'a self`, + // and if that matches, use it for elision and return early. + let is_self_ty = |def: Def| { + if let Def::SelfTy(..) = def { + return true; + } + + // Can't always rely on literal (or implied) `Self` due + // to the way elision rules were originally specified. + let impl_self = impl_self.map(|ty| &ty.node); + if let Some(&hir::TyPath(hir::QPath::Resolved(None, ref path))) = impl_self { + match path.def { + // Whitelist the types that unambiguously always + // result in the same type constructor being used + // (it can't differ between `Self` and `self`). + Def::Struct(_) | + Def::Union(_) | + Def::Enum(_) | + Def::PrimTy(_) => return def == path.def, + _ => {} + } + } - LateScope(lifetimes, s) => { - match search_lifetimes(lifetimes, lifetime_ref) { - Some((_index, lifetime_def)) => { - let decl_id = lifetime_def.id; - let debruijn = ty::DebruijnIndex::new(late_depth + 1); - let def = DefLateBoundRegion(debruijn, decl_id); - self.insert_lifetime(lifetime_ref, def); + false + }; + + if let hir::TyRptr(lifetime_ref, ref mt) = inputs[0].node { + if let hir::TyPath(hir::QPath::Resolved(None, ref path)) = mt.ty.node { + if is_self_ty(path.def) { + if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.id) { + let scope = Scope::Elision { + elide: Elide::Exact(lifetime), + s: self.scope + }; + self.with(scope, |_, this| this.visit_ty(output)); return; } + } + } + } + } - None => { - late_depth += 1; - scope = s; + // Second, if there was exactly one lifetime (either a substitution or a + // reference) in the arguments, then any anonymous regions in the output + // have that lifetime. + let mut possible_implied_output_region = None; + let mut lifetime_count = 0; + let arg_lifetimes = inputs.iter().enumerate().skip(has_self as usize).map(|(i, input)| { + let mut gather = GatherLifetimes { + map: self.map, + binder_depth: 1, + have_bound_regions: false, + lifetimes: FxHashSet() + }; + gather.visit_ty(input); + + lifetime_count += gather.lifetimes.len(); + + if lifetime_count == 1 && gather.lifetimes.len() == 1 { + // there's a chance that the unique lifetime of this + // iteration will be the appropriate lifetime for output + // parameters, so lets store it. + possible_implied_output_region = gather.lifetimes.iter().cloned().next(); + } + + ElisionFailureInfo { + parent: body, + index: i, + lifetime_count: gather.lifetimes.len(), + have_bound_regions: gather.have_bound_regions + } + }).collect(); + + let elide = if lifetime_count == 1 { + Elide::Exact(possible_implied_output_region.unwrap()) + } else { + Elide::Error(arg_lifetimes) + }; + + let scope = Scope::Elision { + elide: elide, + s: self.scope + }; + self.with(scope, |_, this| this.visit_ty(output)); + + struct GatherLifetimes<'a> { + map: &'a NamedRegionMap, + binder_depth: u32, + have_bound_regions: bool, + lifetimes: FxHashSet, + } + + impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { + NestedVisitorMap::None + } + + fn visit_ty(&mut self, ty: &hir::Ty) { + if let hir::TyBareFn(_) = ty.node { + self.binder_depth += 1; + } + if let hir::TyTraitObject(ref bounds, ref lifetime) = ty.node { + for bound in bounds { + self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); + } + + // Stay on the safe side and don't include the object + // lifetime default (which may not end up being used). + if !lifetime.is_elided() { + self.visit_lifetime(lifetime); + } + } else { + intravisit::walk_ty(self, ty); + } + if let hir::TyBareFn(_) = ty.node { + self.binder_depth -= 1; + } + } + + fn visit_poly_trait_ref(&mut self, + trait_ref: &hir::PolyTraitRef, + modifier: hir::TraitBoundModifier) { + self.binder_depth += 1; + intravisit::walk_poly_trait_ref(self, trait_ref, modifier); + self.binder_depth -= 1; + } + + fn visit_lifetime_def(&mut self, lifetime_def: &hir::LifetimeDef) { + for l in &lifetime_def.bounds { self.visit_lifetime(l); } + } + + fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { + if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.id) { + match lifetime { + Region::LateBound(debruijn, _) | + Region::LateBoundAnon(debruijn, _) + if debruijn.depth < self.binder_depth => { + self.have_bound_regions = true; + } + _ => { + self.lifetimes.insert(lifetime.from_depth(self.binder_depth)); } } } } } - self.unresolved_lifetime_ref(lifetime_ref); } - fn resolve_free_lifetime_ref(&mut self, - scope_data: region::CallSiteScopeData, - lifetime_ref: &hir::Lifetime, - scope: Scope) { - debug!("resolve_free_lifetime_ref \ - scope_data: {:?} lifetime_ref: {:?} scope: {:?}", - scope_data, lifetime_ref, scope); + fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[hir::Lifetime]) { + if lifetime_refs.is_empty() { + return; + } - // Walk up the scope chain, tracking the outermost free scope, - // until we encounter a scope that contains the named lifetime - // or we run out of scopes. - let mut scope_data = scope_data; - let mut scope = scope; - let mut search_result = None; - loop { - debug!("resolve_free_lifetime_ref \ - scope_data: {:?} scope: {:?} search_result: {:?}", - scope_data, scope, search_result); + let span = lifetime_refs[0].span; + let mut late_depth = 0; + let mut scope = self.scope; + let error = loop { match *scope { - FnScope { fn_id, body_id, s } => { - scope_data = region::CallSiteScopeData { - fn_id: fn_id, body_id: body_id - }; + // Do not assign any resolution, it will be inferred. + Scope::Body { .. } => return, + + Scope::Root => break None, + + Scope::Binder { s, .. } => { + late_depth += 1; scope = s; } - RootScope => { - break; + Scope::Elision { ref elide, .. } => { + let lifetime = match *elide { + Elide::FreshLateAnon(ref counter) => { + for lifetime_ref in lifetime_refs { + let lifetime = Region::late_anon(counter).shifted(late_depth); + self.insert_lifetime(lifetime_ref, lifetime); + } + return; + } + Elide::Exact(l) => l.shifted(late_depth), + Elide::Static => { + if !self.sess.features.borrow().static_in_const { + self.sess + .struct_span_err(span, + "this needs a `'static` lifetime or the \ + `static_in_const` feature, see #35897") + .emit(); + } + Region::Static + } + Elide::Error(ref e) => break Some(e) + }; + for lifetime_ref in lifetime_refs { + self.insert_lifetime(lifetime_ref, lifetime); + } + return; } - EarlyScope(lifetimes, _, s) | - LateScope(lifetimes, s) => { - search_result = search_lifetimes(lifetimes, lifetime_ref); - if search_result.is_some() { - break; - } + Scope::ObjectLifetimeDefault { s, .. } => { scope = s; } } - } + }; - match search_result { - Some((_depth, lifetime)) => { - let def = DefFreeRegion(scope_data, lifetime.id); - self.insert_lifetime(lifetime_ref, def); + let mut err = struct_span_err!(self.sess, span, E0106, + "missing lifetime specifier{}", + if lifetime_refs.len() > 1 { "s" } else { "" }); + let msg = if lifetime_refs.len() > 1 { + format!("expected {} lifetime parameters", lifetime_refs.len()) + } else { + format!("expected lifetime parameter") + }; + err.span_label(span, &msg); + + if let Some(params) = error { + if lifetime_refs.len() == 1 { + self.report_elision_failure(&mut err, params); } + } + err.emit(); + } - None => { - self.unresolved_lifetime_ref(lifetime_ref); + fn report_elision_failure(&mut self, + db: &mut DiagnosticBuilder, + params: &[ElisionFailureInfo]) { + let mut m = String::new(); + let len = params.len(); + + let elided_params: Vec<_> = params.iter().cloned() + .filter(|info| info.lifetime_count > 0) + .collect(); + + let elided_len = elided_params.len(); + + for (i, info) in elided_params.into_iter().enumerate() { + let ElisionFailureInfo { + parent, index, lifetime_count: n, have_bound_regions + } = info; + + let help_name = if let Some(body) = parent { + let arg = &self.hir_map.body(body).arguments[index]; + format!("`{}`", self.hir_map.node_to_pretty_string(arg.pat.id)) + } else { + format!("argument {}", index + 1) + }; + + m.push_str(&(if n == 1 { + help_name + } else { + format!("one of {}'s {} elided {}lifetimes", help_name, n, + if have_bound_regions { "free " } else { "" } ) + })[..]); + + if elided_len == 2 && i == 0 { + m.push_str(" or "); + } else if i + 2 == elided_len { + m.push_str(", or "); + } else if i != elided_len - 1 { + m.push_str(", "); } + } + if len == 0 { + help!(db, + "this function's return type contains a borrowed value, but \ + there is no value for it to be borrowed from"); + help!(db, + "consider giving it a 'static lifetime"); + } else if elided_len == 0 { + help!(db, + "this function's return type contains a borrowed value with \ + an elided lifetime, but the lifetime cannot be derived from \ + the arguments"); + help!(db, + "consider giving it an explicit bounded or 'static \ + lifetime"); + } else if elided_len == 1 { + help!(db, + "this function's return type contains a borrowed value, but \ + the signature does not say which {} it is borrowed from", + m); + } else { + help!(db, + "this function's return type contains a borrowed value, but \ + the signature does not say whether it is borrowed from {}", + m); + } } - fn unresolved_lifetime_ref(&self, lifetime_ref: &hir::Lifetime) { - struct_span_err!(self.sess, lifetime_ref.span, E0261, - "use of undeclared lifetime name `{}`", lifetime_ref.name) - .span_label(lifetime_ref.span, &format!("undeclared lifetime")) - .emit(); + fn resolve_object_lifetime_default(&mut self, lifetime_ref: &hir::Lifetime) { + let mut late_depth = 0; + let mut scope = self.scope; + let lifetime = loop { + match *scope { + Scope::Binder { s, .. } => { + late_depth += 1; + scope = s; + } + + Scope::Root | + Scope::Elision { .. } => break Region::Static, + + Scope::Body { .. } | + Scope::ObjectLifetimeDefault { lifetime: None, .. } => return, + + Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l + } + }; + self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth)); } - fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &[hir::LifetimeDef]) { + fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &[hir::LifetimeDef]) { for i in 0..lifetimes.len() { let lifetime_i = &lifetimes[i]; @@ -771,7 +1475,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn check_lifetime_def_for_shadowing(&self, - mut old_scope: Scope, + mut old_scope: ScopeRef, lifetime: &hir::Lifetime) { for &(label, label_span) in &self.labels_in_fn { @@ -787,21 +1491,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { loop { match *old_scope { - FnScope { s, .. } => { + Scope::Body { s, .. } | + Scope::Elision { s, .. } | + Scope::ObjectLifetimeDefault { s, .. } => { old_scope = s; } - RootScope => { + Scope::Root => { return; } - EarlyScope(lifetimes, _, s) | - LateScope(lifetimes, s) => { - if let Some((_, lifetime_def)) = search_lifetimes(lifetimes, lifetime) { + Scope::Binder { ref lifetimes, s } => { + if let Some(&def) = lifetimes.get(&lifetime.name) { signal_shadowing_problem( self.sess, lifetime.name, - original_lifetime(&lifetime_def), + original_lifetime(self.hir_map.span(def.id().unwrap())), shadower_lifetime(&lifetime)); return; } @@ -814,33 +1519,21 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn insert_lifetime(&mut self, lifetime_ref: &hir::Lifetime, - def: DefRegion) { + def: Region) { if lifetime_ref.id == ast::DUMMY_NODE_ID { span_bug!(lifetime_ref.span, "lifetime reference not renumbered, \ probably a bug in syntax::fold"); } - debug!("lifetime_ref={:?} id={:?} resolved to {:?} span={:?}", - lifetime_to_string(lifetime_ref), - lifetime_ref.id, + debug!("{} resolved to {:?} span={:?}", + self.hir_map.node_to_string(lifetime_ref.id), def, self.sess.codemap().span_to_string(lifetime_ref.span)); self.map.defs.insert(lifetime_ref.id, def); } } -fn search_lifetimes<'a>(lifetimes: &'a [hir::LifetimeDef], - lifetime_ref: &hir::Lifetime) - -> Option<(u32, &'a hir::Lifetime)> { - for (i, lifetime_decl) in lifetimes.iter().enumerate() { - if lifetime_decl.lifetime.name == lifetime_ref.name { - return Some((i as u32, &lifetime_decl.lifetime)); - } - } - return None; -} - /////////////////////////////////////////////////////////////////////////// /// Detects late-bound lifetimes and inserts them into @@ -860,8 +1553,8 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap, debug!("insert_late_bound_lifetimes(decl={:?}, generics={:?})", decl, generics); let mut constrained_by_input = ConstrainedCollector { regions: FxHashSet() }; - for arg in &decl.inputs { - constrained_by_input.visit_ty(&arg.ty); + for arg_ty in &decl.inputs { + constrained_by_input.visit_ty(arg_ty); } let mut appears_in_output = AllCollector { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index a2c4b59db1..487e13b47f 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } } - let def_id = self.tcx.map.local_def_id(id); + let def_id = self.tcx.hir.local_def_id(id); self.index.stab_map.insert(def_id, Some(stab)); let orig_parent_stab = replace(&mut self.parent_stab, Some(stab)); @@ -188,7 +188,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { debug!("annotate: not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { if stab.level.is_unstable() { - let def_id = self.tcx.map.local_def_id(id); + let def_id = self.tcx.hir.local_def_id(id); self.index.stab_map.insert(def_id, Some(stab)); } } @@ -211,7 +211,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } // `Deprecation` is just two pointers, no need to intern it - let def_id = self.tcx.map.local_def_id(id); + let def_id = self.tcx.hir.local_def_id(id); let depr_entry = Some(DeprecationEntry::local(depr, def_id)); self.index.depr_map.insert(def_id, depr_entry.clone()); @@ -219,7 +219,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { visit_children(self); self.parent_depr = orig_parent_depr; } else if let parent_depr @ Some(_) = self.parent_depr.clone() { - let def_id = self.tcx.map.local_def_id(id); + let def_id = self.tcx.hir.local_def_id(id); self.index.depr_map.insert(def_id, parent_depr); visit_children(self); } else { @@ -234,7 +234,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { /// nested items in the context of the outer item, so enable /// deep-walking. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::All(&self.tcx.map) + NestedVisitorMap::All(&self.tcx.hir) } fn visit_item(&mut self, i: &'tcx Item) { @@ -302,9 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) { - if md.imported_from.is_none() { - self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {}); - } + self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {}); } } @@ -315,7 +313,7 @@ struct MissingStabilityAnnotations<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> { fn check_missing_stability(&self, id: NodeId, span: Span) { - let def_id = self.tcx.map.local_def_id(id); + let def_id = self.tcx.hir.local_def_id(id); let is_error = !self.tcx.sess.opts.test && !self.tcx.stability.borrow().stab_map.contains_key(&def_id) && self.access_levels.is_reachable(id); @@ -327,7 +325,7 @@ impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::OnlyBodies(&self.tcx.hir) } fn visit_item(&mut self, i: &'tcx Item) { @@ -350,7 +348,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - let impl_def_id = self.tcx.map.local_def_id(self.tcx.map.get_parent(ii.id)); + let impl_def_id = self.tcx.hir.local_def_id(self.tcx.hir.get_parent(ii.id)); if self.tcx.impl_trait_ref(impl_def_id).is_none() { self.check_missing_stability(ii.id, ii.span); } @@ -373,9 +371,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) { - if md.imported_from.is_none() { - self.check_missing_stability(md.id, md.span); - } + self.check_missing_stability(md.id, md.span); } } @@ -388,7 +384,7 @@ impl<'a, 'tcx> Index<'tcx> { self.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect(); let _task = tcx.dep_graph.in_task(DepNode::StabilityIndex); - let krate = tcx.map.krate(); + let krate = tcx.hir.krate(); let mut annotator = Annotator { tcx: tcx, index: self, @@ -462,7 +458,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // these are not visible outside crate; therefore // stability markers are irrelevant, if even present. ty::Visibility::Restricted(..) | - ty::Visibility::PrivateExternal => true, + ty::Visibility::Invisible => true, } } @@ -488,7 +484,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let skip = if id == ast::DUMMY_NODE_ID { true } else { - let parent_def_id = self.map.local_def_id(self.map.get_parent(id)); + let parent_def_id = self.hir.local_def_id(self.hir.get_parent(id)); self.lookup_deprecation_entry(parent_def_id).map_or(false, |parent_depr| { parent_depr.same_origin(&depr_entry) }) @@ -559,7 +555,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { /// nested items in the context of the outer item, so enable /// deep-walking. fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::OnlyBodies(&self.tcx.hir) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -582,7 +578,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { hir::ItemImpl(.., Some(ref t), _, ref impl_item_refs) => { if let Def::Trait(trait_did) = t.path.def { for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.map.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir.impl_item(impl_item_ref.id); let trait_item_def_id = self.tcx.associated_items(trait_did) .find(|item| item.name == impl_item.name).map(|item| item.def_id); if let Some(def_id) = trait_item_def_id { @@ -662,7 +658,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if tcx.stability.borrow().staged_api[&LOCAL_CRATE] && tcx.sess.features.borrow().staged_api { let _task = tcx.dep_graph.in_task(DepNode::StabilityIndex); - let krate = tcx.map.krate(); + let krate = tcx.hir.krate(); let mut missing = MissingStabilityAnnotations { tcx: tcx, access_levels: access_levels, diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index c6df1497e6..acb506878e 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -75,8 +75,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { config::CrateTypeCdylib | config::CrateTypeExecutable | config::CrateTypeStaticlib => true, - config::CrateTypeRlib | - config::CrateTypeMetadata => false, + config::CrateTypeRlib => false, } }); if !needs_check { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3cd3580473..6e9091cf31 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -29,7 +29,7 @@ use std::fmt::{self, Debug, Formatter, Write}; use std::{iter, u32}; use std::ops::{Index, IndexMut}; use std::vec::IntoIter; -use syntax::ast::{self, Name}; +use syntax::ast::Name; use syntax_pos::Span; mod cache; @@ -888,6 +888,10 @@ impl<'tcx> Lvalue<'tcx> { self.elem(ProjectionElem::Deref) } + pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Lvalue<'tcx> { + self.elem(ProjectionElem::Downcast(adt_def, variant_index)) + } + pub fn index(self, index: Operand<'tcx>) -> Lvalue<'tcx> { self.elem(ProjectionElem::Index(index)) } @@ -1159,14 +1163,14 @@ impl<'tcx> Debug for Rvalue<'tcx> { } AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| { - if let Some(node_id) = tcx.map.as_local_node_id(def_id) { - let name = format!("[closure@{:?}]", tcx.map.span(node_id)); + if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { + let name = format!("[closure@{:?}]", tcx.hir.span(node_id)); let mut struct_fmt = fmt.debug_struct(&name); tcx.with_freevars(node_id, |freevars| { for (freevar, lv) in freevars.iter().zip(lvs) { let def_id = freevar.def.def_id(); - let var_id = tcx.map.as_local_node_id(def_id).unwrap(); + let var_id = tcx.hir.as_local_node_id(def_id).unwrap(); let var_name = tcx.local_var_name_str(var_id); struct_fmt.field(&var_name, lv); } @@ -1267,17 +1271,12 @@ fn fmt_const_val(fmt: &mut W, const_val: &ConstVal) -> fmt::Result { } Bool(b) => write!(fmt, "{:?}", b), Function(def_id) => write!(fmt, "{}", item_path_str(def_id)), - Struct(node_id) | Tuple(node_id) | Array(node_id, _) | Repeat(node_id, _) => - write!(fmt, "{}", node_to_string(node_id)), + Struct(_) | Tuple(_) | Array(_) | Repeat(..) => + bug!("ConstVal `{:?}` should not be in MIR", const_val), Char(c) => write!(fmt, "{:?}", c), - Dummy => bug!(), } } -fn node_to_string(node_id: ast::NodeId) -> String { - ty::tls::with(|tcx| tcx.map.node_to_user_string(node_id)) -} - fn item_path_str(def_id: DefId) -> String { ty::tls::with(|tcx| tcx.item_path_str(def_id)) } diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 3576ae662a..652fef76f2 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -40,15 +40,15 @@ impl<'a, 'tcx> MirSource { use hir::*; // Handle constants in enum discriminants, types, and repeat expressions. - let def_id = tcx.map.local_def_id(id); + let def_id = tcx.hir.local_def_id(id); let def_key = tcx.def_key(def_id); if def_key.disambiguated_data.data == DefPathData::Initializer { return MirSource::Const(id); } - match tcx.map.get(id) { + match tcx.hir.get(id) { map::NodeItem(&Item { node: ItemConst(..), .. }) | - map::NodeTraitItem(&TraitItem { node: ConstTraitItem(..), .. }) | + map::NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) | map::NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => { MirSource::Const(id) } @@ -124,7 +124,7 @@ impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T { let mir = &mut tcx.mir_map.borrow()[&def_id].borrow_mut(); tcx.dep_graph.write(DepNode::Mir(def_id)); - let id = tcx.map.as_local_node_id(def_id).unwrap(); + let id = tcx.hir.as_local_node_id(def_id).unwrap(); let src = MirSource::from_node(tcx, id); for hook in &mut *hooks { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 5e3c8bc147..7419d74287 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -25,6 +25,7 @@ use lint; use middle::cstore; use syntax::ast::{self, IntTy, UintTy}; +use syntax::parse::token; use syntax::parse; use syntax::symbol::Symbol; use syntax::feature_gate::UnstableFeatures; @@ -73,6 +74,7 @@ pub enum OutputType { Bitcode, Assembly, LlvmAssembly, + Metadata, Object, Exe, DepInfo, @@ -86,7 +88,8 @@ impl OutputType { OutputType::Bitcode | OutputType::Assembly | OutputType::LlvmAssembly | - OutputType::Object => false, + OutputType::Object | + OutputType::Metadata => false, } } @@ -96,6 +99,7 @@ impl OutputType { OutputType::Assembly => "asm", OutputType::LlvmAssembly => "llvm-ir", OutputType::Object => "obj", + OutputType::Metadata => "metadata", OutputType::Exe => "link", OutputType::DepInfo => "dep-info", } @@ -107,6 +111,7 @@ impl OutputType { OutputType::Assembly => "s", OutputType::LlvmAssembly => "ll", OutputType::Object => "o", + OutputType::Metadata => "rmeta", OutputType::DepInfo => "d", OutputType::Exe => "", } @@ -152,6 +157,19 @@ impl OutputTypes { pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option> { self.0.values() } + + // True if any of the output types require codegen or linking. + pub fn should_trans(&self) -> bool { + self.0.keys().any(|k| match *k { + OutputType::Bitcode | + OutputType::Assembly | + OutputType::LlvmAssembly | + OutputType::Object | + OutputType::Exe => true, + OutputType::Metadata | + OutputType::DepInfo => false, + }) + } } @@ -482,8 +500,6 @@ pub enum CrateType { CrateTypeStaticlib, CrateTypeCdylib, CrateTypeProcMacro, - // Should not be present. - CrateTypeMetadata, } #[derive(Clone, Hash)] @@ -883,6 +899,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "attempt to recover from parse errors (experimental)"), incremental: Option = (None, parse_opt_string, [UNTRACKED], "enable incremental compilation (experimental)"), + incremental_cc: bool = (false, parse_bool, [UNTRACKED], + "enable cross-crate incremental compilation (even more experimental)"), incremental_info: bool = (false, parse_bool, [UNTRACKED], "print high-level information about incremental reuse (or the lack thereof)"), incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED], @@ -944,33 +962,28 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { let os = &sess.target.target.target_os; let env = &sess.target.target.target_env; let vendor = &sess.target.target.target_vendor; + let min_atomic_width = sess.target.target.min_atomic_width(); let max_atomic_width = sess.target.target.max_atomic_width(); - let fam = if let Some(ref fam) = sess.target.target.options.target_family { - Symbol::intern(fam) - } else if sess.target.target.options.is_like_windows { - Symbol::intern("windows") - } else { - Symbol::intern("unix") - }; - let mut ret = HashSet::new(); // Target bindings. ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os)))); - ret.insert((Symbol::intern("target_family"), Some(fam))); + if let Some(ref fam) = sess.target.target.options.target_family { + ret.insert((Symbol::intern("target_family"), Some(Symbol::intern(fam)))); + if fam == "windows" || fam == "unix" { + ret.insert((Symbol::intern(fam), None)); + } + } ret.insert((Symbol::intern("target_arch"), Some(Symbol::intern(arch)))); ret.insert((Symbol::intern("target_endian"), Some(Symbol::intern(end)))); ret.insert((Symbol::intern("target_pointer_width"), Some(Symbol::intern(wordsz)))); ret.insert((Symbol::intern("target_env"), Some(Symbol::intern(env)))); ret.insert((Symbol::intern("target_vendor"), Some(Symbol::intern(vendor)))); - if fam == "windows" || fam == "unix" { - ret.insert((fam, None)); - } if sess.target.target.options.has_elf_tls { ret.insert((Symbol::intern("target_thread_local"), None)); } for &i in &[8, 16, 32, 64, 128] { - if i <= max_atomic_width { + if i >= min_atomic_width && i <= max_atomic_width { let s = i.to_string(); ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern(&s)))); if &s == wordsz { @@ -1165,12 +1178,12 @@ pub fn rustc_short_optgroups() -> Vec { assumed.", "[KIND=]NAME"), opt::multi_s("", "crate-type", "Comma separated list of types of crates for the compiler to emit", - "[bin|lib|rlib|dylib|cdylib|staticlib|metadata]"), + "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]"), opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"), opt::multi_s("", "emit", "Comma separated list of types of output for \ the compiler to emit", - "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"), + "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info]"), opt::multi_s("", "print", "Comma separated list of compiler information to \ print on stdout", &format!("[{}]", &print_opts.join("|"))), @@ -1249,7 +1262,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec ) -> ast::CrateConfig { let meta_item = panictry!(parser.parse_meta_item()); - if !parser.reader.is_eof() { + if parser.token != token::Eof { early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}", s)) } else if meta_item.is_meta_item_list() { let msg = @@ -1300,7 +1313,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) }; let unparsed_crate_types = matches.opt_strs("crate-type"); - let crate_types = parse_crate_types_from_list(unparsed_crate_types) + let (crate_types, emit_metadata) = parse_crate_types_from_list(unparsed_crate_types) .unwrap_or_else(|e| early_error(error_format, &e[..])); let mut lint_opts = vec![]; @@ -1334,6 +1347,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) "llvm-ir" => OutputType::LlvmAssembly, "llvm-bc" => OutputType::Bitcode, "obj" => OutputType::Object, + "metadata" => OutputType::Metadata, "link" => OutputType::Exe, "dep-info" => OutputType::DepInfo, part => { @@ -1346,7 +1360,9 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) } } }; - if output_types.is_empty() { + if emit_metadata { + output_types.insert(OutputType::Metadata, None); + } else if output_types.is_empty() { output_types.insert(OutputType::Exe, None); } @@ -1548,8 +1564,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) cfg) } -pub fn parse_crate_types_from_list(list_list: Vec) -> Result, String> { +pub fn parse_crate_types_from_list(list_list: Vec) + -> Result<(Vec, bool), String> { let mut crate_types: Vec = Vec::new(); + let mut emit_metadata = false; for unparsed_crate_type in &list_list { for part in unparsed_crate_type.split(',') { let new_part = match part { @@ -1560,6 +1578,13 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result CrateTypeCdylib, "bin" => CrateTypeExecutable, "proc-macro" => CrateTypeProcMacro, + // FIXME(#38640) remove this when Cargo is fixed. + "metadata" => { + early_warn(ErrorOutputType::default(), "--crate-type=metadata is deprecated, \ + prefer --emit=metadata"); + emit_metadata = true; + CrateTypeRlib + } _ => { return Err(format!("unknown crate type: `{}`", part)); @@ -1571,7 +1596,7 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result "staticlib".fmt(f), CrateTypeCdylib => "cdylib".fmt(f), CrateTypeProcMacro => "proc-macro".fmt(f), - CrateTypeMetadata => unreachable!(), } } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 91765e68ae..36a887e062 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -136,6 +136,8 @@ pub struct PerfStats { pub incr_comp_bytes_hashed: Cell, // The accumulated time spent on computing symbol hashes pub symbol_hash_time: Cell, + // The accumulated time spent decoding def path tables from metadata + pub decode_def_path_tables_time: Cell, } impl Session { @@ -501,6 +503,8 @@ impl Session { self.perf_stats.incr_comp_hashes_count.get()); println!("Total time spent computing symbol hashes: {}", duration_to_secs_str(self.perf_stats.symbol_hash_time.get())); + println!("Total time spent decoding DefPath tables: {}", + duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get())); } } @@ -635,6 +639,7 @@ pub fn build_session_(sopts: config::Options, incr_comp_hashes_count: Cell::new(0), incr_comp_bytes_hashed: Cell::new(0), symbol_hash_time: Cell::new(Duration::from_secs(0)), + decode_def_path_tables_time: Cell::new(Duration::from_secs(0)), }, code_stats: RefCell::new(CodeStats::new()), }; diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 58cb52e897..383fab3fcd 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -199,7 +199,7 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt, fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal) -> Vec> { - if ty_is_local_constructor(tcx, ty, infer_is_local) { + if ty_is_local_constructor(ty, infer_is_local) { vec![] } else if fundamental_ty(tcx, ty) { ty.walk_shallow() @@ -219,13 +219,13 @@ fn is_type_parameter(ty: Ty) -> bool { } fn ty_is_local(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal) -> bool { - ty_is_local_constructor(tcx, ty, infer_is_local) || + ty_is_local_constructor(ty, infer_is_local) || fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, infer_is_local)) } fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool { match ty.sty { - ty::TyBox(..) | ty::TyRef(..) => true, + ty::TyRef(..) => true, ty::TyAdt(def, _) => def.is_fundamental(), ty::TyDynamic(ref data, ..) => { data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental")) @@ -234,7 +234,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool { } } -fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> bool { +fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal)-> bool { debug!("ty_is_local_constructor({:?})", ty); match ty.sty { @@ -265,11 +265,6 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> def.did.is_local() } - ty::TyBox(_) => { // Box - let krate = tcx.lang_items.owned_box().map(|d| d.krate); - krate == Some(LOCAL_CRATE) - } - ty::TyDynamic(ref tt, ..) => { tt.principal().map_or(false, |p| p.def_id().is_local()) } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 0c0d0c010e..661d47199d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -154,7 +154,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::TyStr => Some(2), ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3), ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4), - ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5), + ty::TyRef(..) | ty::TyRawPtr(..) => Some(5), ty::TyArray(..) | ty::TySlice(..) => Some(6), ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7), ty::TyDynamic(..) => Some(8), @@ -366,15 +366,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return; } - err.help(&format!("the following implementations were found:")); - let end = cmp::min(4, impl_candidates.len()); - for candidate in &impl_candidates[0..end] { - err.help(&format!(" {:?}", candidate)); - } - if impl_candidates.len() > 4 { - err.help(&format!("and {} others", impl_candidates.len()-4)); - } + err.help(&format!("the following implementations were found:{}{}", + &impl_candidates[0..end].iter().map(|candidate| { + format!("\n {:?}", candidate) + }).collect::(), + if impl_candidates.len() > 4 { + format!("\nand {} others", impl_candidates.len() - 4) + } else { + "".to_owned() + } + )); } /// Reports that an overflow has occurred and halts compilation. We @@ -439,7 +441,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0276, "impl has stricter requirements than trait"); - if let Some(trait_item_span) = self.tcx.map.span_if_local(trait_item_def_id) { + if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) { err.span_label(trait_item_span, &format!("definition of `{}` from trait", item_name)); } @@ -458,11 +460,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err } + + /// Get the parent trait chain start + fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option { + match code { + &ObligationCauseCode::BuiltinDerivedObligation(ref data) => { + let parent_trait_ref = self.resolve_type_vars_if_possible( + &data.parent_trait_ref); + match self.get_parent_trait_ref(&data.parent_code) { + Some(t) => Some(t), + None => Some(format!("{}", parent_trait_ref.0.self_ty())), + } + } + _ => None, + } + } + pub fn report_selection_error(&self, obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>) { let span = obligation.cause.span; + let mut err = match *error { SelectionError::Unimplemented => { if let ObligationCauseCode::CompareImplMethodObligation { @@ -487,14 +506,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return; } else { let trait_ref = trait_predicate.to_poly_trait_ref(); - - let mut err = struct_span_err!(self.tcx.sess, span, E0277, - "the trait bound `{}` is not satisfied", - trait_ref.to_predicate()); - err.span_label(span, &format!("the trait `{}` is not implemented \ - for `{}`", - trait_ref, - trait_ref.self_ty())); + let (post_message, pre_message) = match self.get_parent_trait_ref( + &obligation.cause.code) + { + Some(t) => { + (format!(" in `{}`", t), format!("within `{}`, ", t)) + } + None => (String::new(), String::new()), + }; + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0277, + "the trait bound `{}` is not satisfied{}", + trait_ref.to_predicate(), + post_message); + err.span_label(span, + &format!("{}the trait `{}` is not \ + implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty())); // Try to report a help message @@ -562,7 +594,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Predicate::ClosureKind(closure_def_id, kind) => { let found_kind = self.closure_kind(closure_def_id).unwrap(); - let closure_span = self.tcx.map.span_if_local(closure_def_id).unwrap(); + let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap(); let mut err = struct_span_err!( self.tcx.sess, closure_span, E0525, "expected a closure that implements the `{}` trait, \ @@ -621,7 +653,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { -> DiagnosticBuilder<'tcx> { assert!(type_def_id.is_local()); - let span = self.map.span_if_local(type_def_id).unwrap(); + let span = self.hir.span_if_local(type_def_id).unwrap(); let mut err = struct_span_err!(self.sess, span, E0072, "recursive type `{}` has infinite size", self.item_path_str(type_def_id)); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 5c5bf130c3..4893e24091 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -474,7 +474,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let elaborated_env = unnormalized_env.with_caller_bounds(predicates); - tcx.infer_ctxt(None, Some(elaborated_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(elaborated_env, Reveal::NotSpecializable).enter(|infcx| { let predicates = match fully_normalize(&infcx, cause, &infcx.parameter_environment.caller_bounds) { Ok(predicates) => predicates, @@ -576,7 +576,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = FulfillmentContext::new(); let cause = ObligationCause::dummy(); diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 0d5c9b9894..60808fbc74 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -81,8 +81,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { let mut violations = vec![]; - if self.supertraits_reference_self(trait_def_id) { - violations.push(ObjectSafetyViolation::SupertraitSelf); + for def_id in traits::supertrait_def_ids(self, trait_def_id) { + if self.predicates_reference_self(def_id, true) { + violations.push(ObjectSafetyViolation::SupertraitSelf); + } } debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", @@ -115,7 +117,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if self.trait_has_sized_self(trait_def_id) { violations.push(ObjectSafetyViolation::SizedSelf); } - if self.supertraits_reference_self(trait_def_id) { + if self.predicates_reference_self(trait_def_id, false) { violations.push(ObjectSafetyViolation::SupertraitSelf); } @@ -126,12 +128,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { violations } - fn supertraits_reference_self(self, trait_def_id: DefId) -> bool { + fn predicates_reference_self( + self, + trait_def_id: DefId, + supertraits_only: bool) -> bool + { let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_def_id, substs: Substs::identity_for_item(self, trait_def_id) }); - let predicates = self.item_super_predicates(trait_def_id); + let predicates = if supertraits_only { + self.item_super_predicates(trait_def_id) + } else { + self.item_predicates(trait_def_id) + }; predicates .predicates .into_iter() diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 23cfc25175..d51332f833 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -204,7 +204,6 @@ enum SelectionCandidate<'tcx> { ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(DefId), DefaultImplCandidate(DefId), - DefaultImplObjectCandidate(DefId), /// This is a trait matching with a projected type as `Self`, and /// we found an applicable bound in the trait definition. @@ -237,9 +236,6 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> { } ImplCandidate(def_id) => ImplCandidate(def_id), DefaultImplCandidate(def_id) => DefaultImplCandidate(def_id), - DefaultImplObjectCandidate(def_id) => { - DefaultImplObjectCandidate(def_id) - } ProjectionCandidate => ProjectionCandidate, FnPointerCandidate => FnPointerCandidate, ObjectCandidate => ObjectCandidate, @@ -1431,17 +1427,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self_ty.sty { ty::TyDynamic(..) => { // For object types, we don't know what the closed - // over types are. For most traits, this means we - // conservatively say nothing; a candidate may be - // added by `assemble_candidates_from_object_ty`. - // However, for the kind of magic reflect trait, - // we consider it to be implemented even for - // object types, because it just lets you reflect - // onto the object type, not into the object's - // interior. - if self.tcx().has_attr(def_id, "rustc_reflect_like") { - candidates.vec.push(DefaultImplObjectCandidate(def_id)); - } + // over types are. This means we conservatively + // say nothing; a candidate may be added by + // `assemble_candidates_from_object_ty`. } ty::TyParam(..) | ty::TyProjection(..) | @@ -1671,7 +1659,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { FnPointerCandidate | BuiltinObjectCandidate | BuiltinUnsizeCandidate | - DefaultImplObjectCandidate(..) | BuiltinCandidate { .. } => { // We have a where-clause so don't go around looking // for impls. @@ -1748,7 +1735,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { 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::TyBox(_) | ty::TyRef(..) | + ty::TyChar | ty::TyRef(..) | ty::TyArray(..) | ty::TyClosure(..) | ty::TyNever | ty::TyError => { // safe for everything @@ -1801,7 +1788,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Where(ty::Binder(Vec::new())) } - ty::TyBox(_) | ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) | + ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) | ty::TyClosure(..) | ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { Never @@ -1878,10 +1865,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { t); } - ty::TyBox(referent_ty) => { // Box - vec![referent_ty] - } - ty::TyRawPtr(ty::TypeAndMut { ty: element_ty, ..}) | ty::TyRef(_, ty::TypeAndMut { ty: element_ty, ..}) => { vec![element_ty] @@ -1998,11 +1981,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(VtableDefaultImpl(data)) } - DefaultImplObjectCandidate(trait_def_id) => { - let data = self.confirm_default_impl_object_candidate(obligation, trait_def_id); - Ok(VtableDefaultImpl(data)) - } - ImplCandidate(impl_def_id) => { Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id))) } @@ -2138,42 +2116,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.vtable_default_impl(obligation, trait_def_id, ty::Binder(types)) } - fn confirm_default_impl_object_candidate(&mut self, - obligation: &TraitObligation<'tcx>, - trait_def_id: DefId) - -> VtableDefaultImplData> - { - debug!("confirm_default_impl_object_candidate({:?}, {:?})", - obligation, - trait_def_id); - - assert!(self.tcx().has_attr(trait_def_id, "rustc_reflect_like")); - - // OK to skip binder, it is reintroduced below - let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); - match self_ty.sty { - ty::TyDynamic(ref data, ..) => { - // OK to skip the binder, it is reintroduced below - let principal = data.principal().unwrap(); - let input_types = principal.input_types(); - let assoc_types = data.projection_bounds() - .map(|pb| pb.skip_binder().ty); - let all_types: Vec<_> = input_types.chain(assoc_types) - .collect(); - - // reintroduce the two binding levels we skipped, then flatten into one - let all_types = ty::Binder(ty::Binder(all_types)); - let all_types = self.tcx().flatten_late_bound_regions(&all_types); - - self.vtable_default_impl(obligation, trait_def_id, all_types) - } - _ => { - bug!("asked to confirm default object implementation for non-object type: {:?}", - self_ty); - } - } - } - /// See `confirm_default_impl_candidate` fn vtable_default_impl(&mut self, obligation: &TraitObligation<'tcx>, diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 59e3d398b2..0fe054b30b 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -123,7 +123,7 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ancestors = trait_def.ancestors(impl_data.impl_def_id); match ancestors.defs(tcx, name, ty::AssociatedKind::Method).next() { Some(node_item) => { - let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + let substs = tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs(&infcx, impl_data.impl_def_id, substs, node_item.node); @@ -189,7 +189,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .subst(tcx, &penv.free_substs); // Create a infcx, taking the predicates of impl1 as assumptions: - let result = tcx.infer_ctxt(None, Some(penv), Reveal::ExactMatch).enter(|infcx| { + let result = tcx.infer_ctxt(penv, Reveal::ExactMatch).enter(|infcx| { // Normalize the trait reference. The WF rules ought to ensure // that this always succeeds. let impl1_trait_ref = diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index a41523f2de..368b1fb4bc 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> Children { let possible_sibling = *slot; let tcx = tcx.global_tcx(); - let (le, ge) = tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| { + let (le, ge) = tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| { let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index 8c3cb79294..00c6dca21b 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -56,12 +56,8 @@ def_type_content_sets! { // InteriorAll = 0b00000000__00000000__1111, // Things that are owned by the value (second and third nibbles): - OwnsOwned = 0b0000_0000__0000_0001__0000, OwnsDtor = 0b0000_0000__0000_0010__0000, - OwnsAll = 0b0000_0000__1111_1111__0000, - - // Things that mean drop glue is necessary - NeedsDrop = 0b0000_0000__0000_0111__0000, + // OwnsAll = 0b0000_0000__1111_1111__0000, // All bits All = 0b1111_1111__1111_1111__1111 @@ -77,10 +73,6 @@ impl TypeContents { (self.bits & tc.bits) != 0 } - pub fn owns_owned(&self) -> bool { - self.intersects(TC::OwnsOwned) - } - pub fn interior_param(&self) -> bool { self.intersects(TC::InteriorParam) } @@ -90,12 +82,7 @@ impl TypeContents { } pub fn needs_drop(&self, _: TyCtxt) -> bool { - self.intersects(TC::NeedsDrop) - } - - /// Includes only those bits that still apply when indirected through a `Box` pointer - pub fn owned_pointer(&self) -> TypeContents { - TC::OwnsOwned | (*self & TC::OwnsAll) + self.intersects(TC::OwnsDtor) } pub fn union(v: I, mut f: F) -> TypeContents where @@ -104,10 +91,6 @@ impl TypeContents { { v.into_iter().fold(TC::None, |tc, ty| tc | f(ty)) } - - pub fn has_dtor(&self) -> bool { - self.intersects(TC::OwnsDtor) - } } impl ops::BitOr for TypeContents { @@ -191,10 +174,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> { TC::None } - ty::TyBox(typ) => { - tc_ty(tcx, typ, cache).owned_pointer() - } - ty::TyDynamic(..) => { TC::All - TC::InteriorParam } @@ -235,6 +214,11 @@ impl<'a, 'tcx> ty::TyS<'tcx> { }) }); + if def.is_union() { + // unions don't have destructors regardless of the child types + res = res - TC::OwnsDtor; + } + if def.has_dtor() { res = res | TC::OwnsDtor; } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4854a14f73..ce4a6a3182 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -15,10 +15,11 @@ use session::Session; use middle; use hir::TraitMap; use hir::def::Def; -use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; -use hir::map as ast_map; -use hir::map::{DefKey, DefPathData, DisambiguatedDefPathData}; +use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use hir::map as hir_map; +use hir::map::DisambiguatedDefPathData; use middle::free_region::FreeRegionMap; +use middle::lang_items; use middle::region::RegionMaps; use middle::resolve_lifetime; use middle::stability; @@ -33,13 +34,14 @@ use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; use ty::TypeVariants::*; use ty::layout::{Layout, TargetDataLayout}; +use ty::inhabitedness::DefIdForest; use ty::maps; use util::common::MemoizationMap; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::accumulate_vec::AccumulateVec; -use arena::TypedArena; +use arena::{TypedArena, DroplessArena}; use std::borrow::Borrow; use std::cell::{Cell, RefCell}; use std::hash::{Hash, Hasher}; @@ -55,47 +57,34 @@ use syntax::symbol::{Symbol, keywords}; use hir; /// Internal storage -pub struct CtxtArenas<'tcx> { +pub struct GlobalArenas<'tcx> { // internings - type_: TypedArena>, - type_list: TypedArena>, - substs: TypedArena>, - bare_fn: TypedArena>, - region: TypedArena, - stability: TypedArena, layout: TypedArena, - existential_predicates: TypedArena>, // references generics: TypedArena>, trait_def: TypedArena, adt_def: TypedArena, mir: TypedArena>>, + tables: TypedArena>, } -impl<'tcx> CtxtArenas<'tcx> { - pub fn new() -> CtxtArenas<'tcx> { - CtxtArenas { - type_: TypedArena::new(), - type_list: TypedArena::new(), - substs: TypedArena::new(), - bare_fn: TypedArena::new(), - region: TypedArena::new(), - stability: TypedArena::new(), +impl<'tcx> GlobalArenas<'tcx> { + pub fn new() -> GlobalArenas<'tcx> { + GlobalArenas { layout: TypedArena::new(), - existential_predicates: TypedArena::new(), - generics: TypedArena::new(), trait_def: TypedArena::new(), adt_def: TypedArena::new(), - mir: TypedArena::new() + mir: TypedArena::new(), + tables: TypedArena::new(), } } } pub struct CtxtInterners<'tcx> { - /// The arenas that types etc are allocated from. - arenas: &'tcx CtxtArenas<'tcx>, + /// The arena that types, regions, etc are allocated from + arena: &'tcx DroplessArena, /// Specifically use a speedy hash algorithm for these hash sets, /// they're accessed quite often. @@ -104,22 +93,18 @@ pub struct CtxtInterners<'tcx> { substs: RefCell>>>, bare_fn: RefCell>>>, region: RefCell>>, - stability: RefCell>, - layout: RefCell>, existential_predicates: RefCell>>>>, } impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { - fn new(arenas: &'tcx CtxtArenas<'tcx>) -> CtxtInterners<'tcx> { + fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> { CtxtInterners { - arenas: arenas, + arena: arena, type_: RefCell::new(FxHashSet()), type_list: RefCell::new(FxHashSet()), substs: RefCell::new(FxHashSet()), bare_fn: RefCell::new(FxHashSet()), region: RefCell::new(FxHashSet()), - stability: RefCell::new(FxHashSet()), - layout: RefCell::new(FxHashSet()), existential_predicates: RefCell::new(FxHashSet()), } } @@ -158,7 +143,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { let ty_struct: TyS<'gcx> = unsafe { mem::transmute(ty_struct) }; - let ty: Ty<'gcx> = interner.arenas.type_.alloc(ty_struct); + let ty: Ty<'gcx> = interner.arena.alloc(ty_struct); global_interner.unwrap().insert(Interned(ty)); return ty; } @@ -174,7 +159,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { } // Don't be &mut TyS. - let ty: Ty<'tcx> = self.arenas.type_.alloc(ty_struct); + let ty: Ty<'tcx> = self.arena.alloc(ty_struct); interner.insert(Interned(ty)); ty }; @@ -194,18 +179,21 @@ pub struct CommonTypes<'tcx> { pub i16: Ty<'tcx>, pub i32: Ty<'tcx>, pub i64: Ty<'tcx>, + pub i128: Ty<'tcx>, pub usize: Ty<'tcx>, pub u8: Ty<'tcx>, pub u16: Ty<'tcx>, pub u32: Ty<'tcx>, pub u64: Ty<'tcx>, + pub u128: Ty<'tcx>, pub f32: Ty<'tcx>, pub f64: Ty<'tcx>, pub never: Ty<'tcx>, pub err: Ty<'tcx>, } -pub struct Tables<'tcx> { +#[derive(RustcEncodable, RustcDecodable)] +pub struct TypeckTables<'tcx> { /// Resolved definitions for `::X` associated paths. pub type_relative_path_defs: NodeMap, @@ -227,13 +215,11 @@ pub struct Tables<'tcx> { /// Borrows pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_tys: DefIdMap>, + /// Records the type of each closure. + pub closure_tys: NodeMap>, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_kinds: DefIdMap, + /// Records the type of each closure. + pub closure_kinds: NodeMap, /// For each fn, records the "liberated" types of its arguments /// and return type. Liberated means that all bound regions @@ -246,22 +232,27 @@ pub struct Tables<'tcx> { /// of the struct - this is needed because it is non-trivial to /// normalize while preserving regions. This table is used only in /// MIR construction and hence is not serialized to metadata. - pub fru_field_types: NodeMap>> + pub fru_field_types: NodeMap>>, + + /// Maps a cast expression to its kind. This is keyed on the + /// *from* expression of the cast, not the cast itself. + pub cast_kinds: NodeMap, } -impl<'a, 'gcx, 'tcx> Tables<'tcx> { - pub fn empty() -> Tables<'tcx> { - Tables { +impl<'tcx> TypeckTables<'tcx> { + pub fn empty() -> TypeckTables<'tcx> { + TypeckTables { type_relative_path_defs: NodeMap(), node_types: FxHashMap(), item_substs: NodeMap(), adjustments: NodeMap(), method_map: FxHashMap(), upvar_capture_map: FxHashMap(), - closure_tys: DefIdMap(), - closure_kinds: DefIdMap(), + closure_tys: NodeMap(), + closure_kinds: NodeMap(), liberated_fn_sigs: NodeMap(), - fru_field_types: NodeMap() + fru_field_types: NodeMap(), + cast_kinds: NodeMap(), } } @@ -280,7 +271,7 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> { Some(ty) => ty, None => { bug!("node_id_to_type: no type for node `{}`", - tls::with(|tcx| tcx.map.node_to_string(id))) + tls::with(|tcx| tcx.hir.node_to_string(id))) } } } @@ -359,11 +350,13 @@ impl<'tcx> CommonTypes<'tcx> { 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::Us)), 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)), } @@ -387,6 +380,7 @@ impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> { } pub struct GlobalCtxt<'tcx> { + global_arenas: &'tcx GlobalArenas<'tcx>, global_interners: CtxtInterners<'tcx>, pub specializes_cache: RefCell, @@ -414,7 +408,7 @@ pub struct GlobalCtxt<'tcx> { free_region_maps: RefCell>, // FIXME: jroesch make this a refcell - pub tables: RefCell>, + pub tables: RefCell>>, /// Maps from a trait item to the trait item "descriptor" pub associated_items: RefCell>>, @@ -440,7 +434,7 @@ pub struct GlobalCtxt<'tcx> { /// additional acyclicity requirements). pub super_predicates: RefCell>>, - pub map: ast_map::Map<'tcx>, + pub hir: hir_map::Map<'tcx>, /// Maps from the def-id of a function/method or const/static /// to its MIR. Mutation is done at an item granularity to @@ -473,6 +467,8 @@ pub struct GlobalCtxt<'tcx> { // FIXME dep tracking -- should be harmless enough pub normalized_cache: RefCell, Ty<'tcx>>>, + pub inhabitedness_cache: RefCell, DefIdForest>>, + pub lang_items: middle::lang_items::LanguageItems, /// Maps from def-id of a type or region parameter to its @@ -508,14 +504,6 @@ pub struct GlobalCtxt<'tcx> { /// FIXME(arielb1): why is this separate from populated_external_types? pub populated_external_primitive_impls: RefCell, - /// Cache used by const_eval when decoding external constants. - /// Contains `None` when the constant has been fetched but doesn't exist. - /// Constains `Some(expr_id, type)` otherwise. - /// `type` is `None` in case it's not a primitive type - pub extern_const_statics: RefCell>)>>>, - /// Cache used by const_eval when decoding extern const fns - pub extern_const_fns: RefCell>, - /// Maps any item's def-id to its stability index. pub stability: RefCell>, @@ -537,15 +525,19 @@ pub struct GlobalCtxt<'tcx> { /// Caches the representation hints for struct definitions. repr_hint_cache: RefCell>>, - /// Maps Expr NodeId's to their constant qualification. - pub const_qualif_map: RefCell>, + /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime. + pub rvalue_promotable_to_static: RefCell>, /// Caches CoerceUnsized kinds for impls on custom types. pub custom_coerce_unsized_kinds: RefCell>, - /// Maps a cast expression to its kind. This is keyed on the - /// *from* expression of the cast, not the cast itself. - pub cast_kinds: RefCell>, + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_tys: RefCell>>, + + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_kinds: RefCell>>, /// Maps Fn items to a collection of fragment infos. /// @@ -590,6 +582,10 @@ pub struct GlobalCtxt<'tcx> { /// Map from function to the `#[derive]` mode that it's defining. Only used /// by `proc-macro` crates. pub derive_macros: RefCell>, + + stability_interner: RefCell>, + + layout_interner: RefCell>, } impl<'tcx> GlobalCtxt<'tcx> { @@ -627,50 +623,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - /// Given a def-key `key` and a crate `krate`, finds the def-index - /// that `krate` assigned to `key`. This `DefIndex` will always be - /// relative to `krate`. - /// - /// Returns `None` if there is no `DefIndex` with that key. - pub fn def_index_for_def_key(self, krate: CrateNum, key: DefKey) - -> Option { - if krate == LOCAL_CRATE { - self.map.def_index_for_def_key(key) - } else { - self.sess.cstore.def_index_for_def_key(krate, key) - } - } - pub fn retrace_path(self, krate: CrateNum, path_data: &[DisambiguatedDefPathData]) -> Option { debug!("retrace_path(path={:?}, krate={:?})", path_data, self.crate_name(krate)); - let root_key = DefKey { - parent: None, - disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::CrateRoot, - disambiguator: 0, - }, - }; - - let root_index = self.def_index_for_def_key(krate, root_key) - .expect("no root key?"); - - debug!("retrace_path: root_index={:?}", root_index); - - let mut index = root_index; - for data in path_data { - let key = DefKey { parent: Some(index), disambiguated_data: data.clone() }; - debug!("retrace_path: key={:?}", key); - match self.def_index_for_def_key(krate, key) { - Some(i) => index = i, - None => return None, - } + if krate == LOCAL_CRATE { + self.hir + .definitions() + .def_path_table() + .retrace_path(path_data) + .map(|def_index| DefId { krate: krate, index: def_index }) + } else { + self.sess.cstore.retrace_path(krate, path_data) } - - Some(DefId { krate: krate, index: index }) } pub fn type_parameter_def(self, @@ -682,15 +649,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn alloc_generics(self, generics: ty::Generics<'gcx>) -> &'gcx ty::Generics<'gcx> { - self.global_interners.arenas.generics.alloc(generics) + self.global_arenas.generics.alloc(generics) } pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx RefCell> { - self.global_interners.arenas.mir.alloc(RefCell::new(mir)) + self.global_arenas.mir.alloc(RefCell::new(mir)) + } + + pub fn alloc_tables(self, tables: ty::TypeckTables<'gcx>) -> &'gcx ty::TypeckTables<'gcx> { + self.global_arenas.tables.alloc(tables) } pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef { - self.global_interners.arenas.trait_def.alloc(def) + self.global_arenas.trait_def.alloc(def) } pub fn alloc_adt_def(self, @@ -699,32 +670,28 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { variants: Vec) -> &'gcx ty::AdtDef { let def = ty::AdtDef::new(self, did, kind, variants); - self.global_interners.arenas.adt_def.alloc(def) + self.global_arenas.adt_def.alloc(def) } pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability { - if let Some(st) = self.global_interners.stability.borrow().get(&stab) { + if let Some(st) = self.stability_interner.borrow().get(&stab) { return st; } - let interned = self.global_interners.arenas.stability.alloc(stab); - if let Some(prev) = self.global_interners.stability - .borrow_mut() - .replace(interned) { + let interned = self.global_interners.arena.alloc(stab); + if let Some(prev) = self.stability_interner.borrow_mut().replace(interned) { bug!("Tried to overwrite interned Stability: {:?}", prev) } interned } pub fn intern_layout(self, layout: Layout) -> &'gcx Layout { - if let Some(layout) = self.global_interners.layout.borrow().get(&layout) { + if let Some(layout) = self.layout_interner.borrow().get(&layout) { return layout; } - let interned = self.global_interners.arenas.layout.alloc(layout); - if let Some(prev) = self.global_interners.layout - .borrow_mut() - .replace(interned) { + let interned = self.global_arenas.layout.alloc(layout); + if let Some(prev) = self.layout_interner.borrow_mut().replace(interned) { bug!("Tried to overwrite interned Layout: {:?}", prev) } interned @@ -761,26 +728,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// value (types, substs, etc.) can only be used while `ty::tls` has a valid /// reference to the context, to allow formatting values that need it. pub fn create_and_enter(s: &'tcx Session, - arenas: &'tcx CtxtArenas<'tcx>, - trait_map: TraitMap, + arenas: &'tcx GlobalArenas<'tcx>, + arena: &'tcx DroplessArena, + resolutions: ty::Resolutions, named_region_map: resolve_lifetime::NamedRegionMap, - map: ast_map::Map<'tcx>, - freevars: FreevarMap, - maybe_unused_trait_imports: NodeSet, + hir: hir_map::Map<'tcx>, region_maps: RegionMaps, lang_items: middle::lang_items::LanguageItems, stability: stability::Index<'tcx>, - crate_name: &str, + crate_name: &str, f: F) -> R where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R { let data_layout = TargetDataLayout::parse(s); - let interners = CtxtInterners::new(arenas); + let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new(&interners); - let dep_graph = map.dep_graph.clone(); + let dep_graph = hir.dep_graph.clone(); let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone()); tls::enter_global(GlobalCtxt { specializes_cache: RefCell::new(traits::SpecializesCache::new()), + global_arenas: arenas, global_interners: interners, dep_graph: dep_graph.clone(), types: common_types, @@ -790,8 +757,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { item_variance_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())), variance_computed: Cell::new(false), sess: s, - trait_map: trait_map, - tables: RefCell::new(Tables::empty()), + trait_map: resolutions.trait_map, + tables: RefCell::new(DepTrackingMap::new(dep_graph.clone())), impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), @@ -800,10 +767,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), fulfilled_predicates: RefCell::new(fulfilled_predicates), - map: map, + hir: hir, mir_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - freevars: RefCell::new(freevars), - maybe_unused_trait_imports: maybe_unused_trait_imports, + freevars: RefCell::new(resolutions.freevars), + maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports, item_types: RefCell::new(DepTrackingMap::new(dep_graph.clone())), rcache: RefCell::new(FxHashMap()), tc_cache: RefCell::new(FxHashMap()), @@ -811,6 +778,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { associated_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), ty_param_defs: RefCell::new(NodeMap()), normalized_cache: RefCell::new(FxHashMap()), + inhabitedness_cache: RefCell::new(FxHashMap()), lang_items: lang_items, inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())), used_unsafe: RefCell::new(NodeSet()), @@ -818,31 +786,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { used_trait_imports: RefCell::new(NodeSet()), populated_external_types: RefCell::new(DefIdSet()), populated_external_primitive_impls: RefCell::new(DefIdSet()), - extern_const_statics: RefCell::new(DefIdMap()), - extern_const_fns: RefCell::new(DefIdMap()), stability: RefCell::new(stability), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), repr_hint_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - const_qualif_map: RefCell::new(NodeMap()), + rvalue_promotable_to_static: RefCell::new(NodeMap()), custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), - cast_kinds: RefCell::new(NodeMap()), + closure_tys: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + closure_kinds: RefCell::new(DepTrackingMap::new(dep_graph.clone())), fragment_infos: RefCell::new(DefIdMap()), crate_name: Symbol::intern(crate_name), data_layout: data_layout, layout_cache: RefCell::new(FxHashMap()), + layout_interner: RefCell::new(FxHashSet()), layout_depth: Cell::new(0), derive_macros: RefCell::new(NodeMap()), + stability_interner: RefCell::new(FxHashSet()), }, f) } } impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { - /// Call the closure with a local `TyCtxt` using the given arenas. - pub fn enter_local(&self, arenas: &'tcx CtxtArenas<'tcx>, f: F) -> R + /// Call the closure with a local `TyCtxt` using the given arena. + pub fn enter_local(&self, arena: &'tcx DroplessArena, f: F) -> R where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R { - let interners = CtxtInterners::new(arenas); + let interners = CtxtInterners::new(arena); tls::enter(self, &interners, f) } } @@ -872,10 +841,8 @@ pub trait Lift<'tcx> { impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { type Lifted = Ty<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - if let Some(&Interned(ty)) = tcx.interners.type_.borrow().get(&self.sty) { - if *self as *const _ == ty as *const _ { - return Some(ty); - } + if tcx.interners.arena.in_arena(*self as *const _) { + return Some(unsafe { mem::transmute(*self) }); } // Also try in the global tcx if we're not that. if !tcx.is_global() { @@ -892,10 +859,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { if self.len() == 0 { return Some(Slice::empty()); } - if let Some(&Interned(substs)) = tcx.interners.substs.borrow().get(&self[..]) { - if *self as *const _ == substs as *const _ { - return Some(substs); - } + if tcx.interners.arena.in_arena(&self[..] as *const _) { + return Some(unsafe { mem::transmute(*self) }); } // Also try in the global tcx if we're not that. if !tcx.is_global() { @@ -909,10 +874,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { impl<'a, 'tcx> Lift<'tcx> for &'a Region { type Lifted = &'tcx Region; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Region> { - if let Some(&Interned(region)) = tcx.interners.region.borrow().get(*self) { - if *self as *const _ == region as *const _ { - return Some(region); - } + if tcx.interners.arena.in_arena(*self as *const _) { + return Some(unsafe { mem::transmute(*self) }); } // Also try in the global tcx if we're not that. if !tcx.is_global() { @@ -930,10 +893,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { if self.len() == 0 { return Some(Slice::empty()); } - if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(&self[..]) { - if *self as *const _ == list as *const _ { - return Some(list); - } + if tcx.interners.arena.in_arena(*self as *const _) { + return Some(unsafe { mem::transmute(*self) }); } // Also try in the global tcx if we're not that. if !tcx.is_global() { @@ -951,10 +912,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { if self.is_empty() { return Some(Slice::empty()); } - if let Some(&Interned(eps)) = tcx.interners.existential_predicates.borrow().get(&self[..]) { - if *self as *const _ == eps as *const _ { - return Some(eps); - } + if tcx.interners.arena.in_arena(*self as *const _) { + return Some(unsafe { mem::transmute(*self) }); } // Also try in the global tcx if we're not that. if !tcx.is_global() { @@ -969,10 +928,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> { type Lifted = &'tcx BareFnTy<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx BareFnTy<'tcx>> { - if let Some(&Interned(fty)) = tcx.interners.bare_fn.borrow().get(*self) { - if *self as *const _ == fty as *const _ { - return Some(fty); - } + if tcx.interners.arena.in_arena(*self as *const _) { + return Some(unsafe { mem::transmute(*self) }); } // Also try in the global tcx if we're not that. if !tcx.is_global() { @@ -1132,14 +1089,14 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { pub fn print_debug_stats(self) { sty_debug_print!( self, - TyAdt, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, + TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon); println!("Substs interner: #{}", self.interners.substs.borrow().len()); println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len()); println!("Region interner: #{}", self.interners.region.borrow().len()); - println!("Stability interner: #{}", self.interners.stability.borrow().len()); - println!("Layout interner: #{}", self.interners.layout.borrow().len()); + println!("Stability interner: #{}", self.stability_interner.borrow().len()); + println!("Layout interner: #{}", self.layout_interner.borrow().len()); } } @@ -1242,8 +1199,7 @@ macro_rules! intern_method { let v = unsafe { mem::transmute(v) }; - let i = ($alloc_to_ret)(self.global_interners.arenas.$name - .$alloc_method(v)); + let i = ($alloc_to_ret)(self.global_interners.arena.$alloc_method(v)); self.global_interners.$name.borrow_mut().insert(Interned(i)); return i; } @@ -1257,7 +1213,7 @@ macro_rules! intern_method { } } - let i = ($alloc_to_ret)(self.interners.arenas.$name.$alloc_method(v)); + let i = ($alloc_to_ret)(self.interners.arena.$alloc_method(v)); self.interners.$name.borrow_mut().insert(Interned(i)); i } @@ -1345,6 +1301,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ast::IntTy::I16 => self.types.i16, ast::IntTy::I32 => self.types.i32, ast::IntTy::I64 => self.types.i64, + ast::IntTy::I128 => self.types.i128, } } @@ -1355,6 +1312,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ast::UintTy::U16 => self.types.u16, ast::UintTy::U32 => self.types.u32, ast::UintTy::U64 => self.types.u64, + ast::UintTy::U128 => self.types.u128, } } @@ -1379,7 +1337,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ty(TyBox(ty)) + let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); + let adt_def = self.lookup_adt_def(def_id); + let substs = self.mk_substs(iter::once(Kind::from(ty))); + self.mk_ty(TyAdt(adt_def, substs)) } pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index e95ce97e13..29d855a7fc 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -181,7 +181,6 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(), ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)), - ty::TyBox(_) => "box".to_string(), ty::TyArray(_, n) => format!("array of {} elements", n), ty::TySlice(_) => "slice".to_string(), ty::TyRawPtr(_) => "*-ptr".to_string(), @@ -283,7 +282,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { expected.ty, found.ty)); - match self.map.span_if_local(expected.def_id) { + match self.hir.span_if_local(expected.def_id) { Some(span) => { db.span_note(span, "a default was defined here..."); } @@ -297,7 +296,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { expected.origin_span, "...that was applied to an unconstrained type variable here"); - match self.map.span_if_local(found.def_id) { + match self.hir.span_if_local(found.def_id) { Some(span) => { db.span_note(span, "a second default was defined here..."); } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 7b4d76ad49..94b9abc720 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -11,7 +11,6 @@ use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use syntax::ast; -use middle::lang_items::OwnedBoxLangItem; use self::SimplifiedType::*; @@ -69,10 +68,6 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // view of possibly unifying simplify_type(tcx, mt.ty, can_simplify_params) } - ty::TyBox(_) => { - // treat like we would treat `Box` - Some(AdtSimplifiedType(tcx.require_lang_item(OwnedBoxLangItem))) - } ty::TyClosure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index a06d3ed6cf..0de77526b5 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -138,7 +138,7 @@ impl FlagComputation { self.add_region(r); } - &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { + &ty::TyArray(tt, _) | &ty::TySlice(tt) => { self.add_ty(tt) } diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs new file mode 100644 index 0000000000..6801e82fe7 --- /dev/null +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -0,0 +1,133 @@ +// 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 std::mem; +use rustc_data_structures::small_vec::SmallVec; +use syntax::ast::CRATE_NODE_ID; +use ty::context::TyCtxt; +use ty::{DefId, DefIdTree}; + +/// Represents a forest of DefIds closed under the ancestor relation. That is, +/// if a DefId representing a module is contained in the forest then all +/// DefIds defined in that module or submodules are also implicitly contained +/// in the forest. +/// +/// This is used to represent a set of modules in which a type is visibly +/// uninhabited. +#[derive(Clone)] +pub struct DefIdForest { + /// The minimal set of DefIds required to represent the whole set. + /// If A and B are DefIds in the DefIdForest, and A is a desecendant + /// of B, then only B will be in root_ids. + /// We use a SmallVec here because (for its use for cacheing inhabitedness) + /// its rare that this will contain even two ids. + root_ids: SmallVec<[DefId; 1]>, +} + +impl<'a, 'gcx, 'tcx> DefIdForest { + /// Create an empty forest. + pub fn empty() -> DefIdForest { + DefIdForest { + root_ids: SmallVec::new(), + } + } + + /// Create a forest consisting of a single tree representing the entire + /// crate. + #[inline] + pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest { + let crate_id = tcx.hir.local_def_id(CRATE_NODE_ID); + DefIdForest::from_id(crate_id) + } + + /// Create a forest containing a DefId and all its descendants. + pub fn from_id(id: DefId) -> DefIdForest { + let mut root_ids = SmallVec::new(); + root_ids.push(id); + DefIdForest { + root_ids: root_ids, + } + } + + /// Test whether the forest is empty. + pub fn is_empty(&self) -> bool { + self.root_ids.is_empty() + } + + /// Test whether the forest conains a given DefId. + pub fn contains(&self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + id: DefId) -> bool + { + for root_id in self.root_ids.iter() { + if tcx.is_descendant_of(id, *root_id) { + return true; + } + } + false + } + + /// Calculate the intersection of a collection of forests. + pub fn intersection(tcx: TyCtxt<'a, 'gcx, 'tcx>, + iter: I) -> DefIdForest + where I: IntoIterator + { + let mut ret = DefIdForest::full(tcx); + 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(..) { + if next_forest.contains(tcx, id) { + next_ret.push(id); + } else { + old_ret.push(id); + } + } + ret.root_ids.extend(old_ret.drain(..)); + + for id in next_forest.root_ids { + if ret.contains(tcx, id) { + next_ret.push(id); + } + } + + mem::swap(&mut next_ret, &mut ret.root_ids); + next_ret.drain(..); + } + ret + } + + /// Calculate the union of a collection of forests. + pub fn union(tcx: TyCtxt<'a, 'gcx, 'tcx>, + iter: I) -> DefIdForest + where I: IntoIterator + { + let mut ret = DefIdForest::empty(); + let mut next_ret = SmallVec::new(); + for next_forest in iter { + for id in ret.root_ids.drain(..) { + if !next_forest.contains(tcx, id) { + next_ret.push(id); + } + } + + for id in next_forest.root_ids { + if !next_ret.contains(&id) { + next_ret.push(id); + } + } + + mem::swap(&mut next_ret, &mut ret.root_ids); + next_ret.drain(..); + } + ret + } +} + diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs new file mode 100644 index 0000000000..6c49493a65 --- /dev/null +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -0,0 +1,201 @@ +// 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 util::nodemap::FxHashSet; +use ty::context::TyCtxt; +use ty::{AdtDef, VariantDef, FieldDef, TyS}; +use ty::{DefId, Substs}; +use ty::{AdtKind, Visibility}; +use ty::TypeVariants::*; + +pub use self::def_id_forest::DefIdForest; + +mod def_id_forest; + +// The methods in this module calculate DefIdForests of modules in which a +// AdtDef/VariantDef/FieldDef is visibly uninhabited. +// +// # Example +// ```rust +// enum Void {} +// mod a { +// pub mod b { +// pub struct SecretlyUninhabited { +// _priv: !, +// } +// } +// } +// +// mod c { +// pub struct AlsoSecretlyUninhabited { +// _priv: Void, +// } +// mod d { +// } +// } +// +// struct Foo { +// x: a::b::SecretlyUninhabited, +// y: c::AlsoSecretlyUninhabited, +// } +// ``` +// In this code, the type Foo will only be visibly uninhabited inside the +// modules b, c and d. Calling uninhabited_from on Foo or its AdtDef will +// return the forest of modules {b, c->d} (represented in a DefIdForest by the +// set {b, c}) +// +// We need this information for pattern-matching on Foo or types that contain +// Foo. +// +// # Example +// ```rust +// let foo_result: Result = ... ; +// let Ok(t) = foo_result; +// ``` +// This code should only compile in modules where the uninhabitedness of Foo is +// visible. + +impl<'a, 'gcx, 'tcx> AdtDef { + /// Calculate the forest of DefIds from which this adt is visibly uninhabited. + pub fn uninhabited_from( + &self, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>) -> DefIdForest + { + if !visited.insert((self.did, substs)) { + return DefIdForest::empty(); + } + + let ret = DefIdForest::intersection(tcx, self.variants.iter().map(|v| { + v.uninhabited_from(visited, tcx, substs, self.adt_kind()) + })); + visited.remove(&(self.did, substs)); + ret + } +} + +impl<'a, 'gcx, 'tcx> VariantDef { + /// Calculate the forest of DefIds from which this variant is visibly uninhabited. + pub fn uninhabited_from( + &self, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>, + adt_kind: AdtKind) -> DefIdForest + { + match adt_kind { + AdtKind::Union => { + DefIdForest::intersection(tcx, self.fields.iter().map(|f| { + f.uninhabited_from(visited, tcx, substs, false) + })) + }, + AdtKind::Struct => { + DefIdForest::union(tcx, self.fields.iter().map(|f| { + f.uninhabited_from(visited, tcx, substs, false) + })) + }, + AdtKind::Enum => { + DefIdForest::union(tcx, self.fields.iter().map(|f| { + f.uninhabited_from(visited, tcx, substs, true) + })) + }, + } + } +} + +impl<'a, 'gcx, 'tcx> FieldDef { + /// Calculate the forest of DefIds from which this field is visibly uninhabited. + pub fn uninhabited_from( + &self, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>, + is_enum: bool) -> DefIdForest + { + let mut data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(visited, tcx); + // FIXME(canndrew): Currently enum fields are (incorrectly) stored with + // Visibility::Invisible so we need to override self.vis if we're + // dealing with an enum. + if is_enum { + data_uninhabitedness() + } else { + match self.vis { + Visibility::Invisible => DefIdForest::empty(), + Visibility::Restricted(from) => { + let forest = DefIdForest::from_id(from); + let iter = Some(forest).into_iter().chain(Some(data_uninhabitedness())); + DefIdForest::intersection(tcx, iter) + }, + Visibility::Public => data_uninhabitedness(), + } + } + } +} + +impl<'a, 'gcx, 'tcx> TyS<'tcx> { + /// Calculate the forest of DefIds from which this type is visibly uninhabited. + pub fn uninhabited_from( + &self, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, + tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest + { + match tcx.lift_to_global(&self) { + Some(global_ty) => { + { + let cache = tcx.inhabitedness_cache.borrow(); + if let Some(forest) = cache.get(&global_ty) { + return forest.clone(); + } + } + let forest = global_ty.uninhabited_from_inner(visited, tcx); + let mut cache = tcx.inhabitedness_cache.borrow_mut(); + cache.insert(global_ty, forest.clone()); + forest + }, + None => { + let forest = self.uninhabited_from_inner(visited, tcx); + forest + }, + } + } + + fn uninhabited_from_inner( + &self, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, + tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest + { + match self.sty { + TyAdt(def, substs) => { + def.uninhabited_from(visited, tcx, substs) + }, + + TyNever => DefIdForest::full(tcx), + TyTuple(ref tys) => { + DefIdForest::union(tcx, tys.iter().map(|ty| { + ty.uninhabited_from(visited, tcx) + })) + }, + TyArray(ty, len) => { + if len == 0 { + DefIdForest::empty() + } else { + ty.uninhabited_from(visited, tcx) + } + } + TyRef(_, ref tm) => { + tm.ty.uninhabited_from(visited, tcx) + } + + _ => DefIdForest::empty(), + } + } +} + diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 440a391678..b719911d18 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -52,7 +52,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns a string identifying this local node-id. pub fn node_path_str(self, id: ast::NodeId) -> String { - self.item_path_str(self.map.local_def_id(id)) + self.item_path_str(self.hir.local_def_id(id)) } /// Returns a string identifying this def-id. This string is @@ -160,11 +160,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.push_krate_path(buffer, def_id.krate); } - DefPathData::InlinedRoot(ref root_path) => { - assert!(key.parent.is_none()); - self.push_item_path(buffer, root_path.def_id); - } - DefPathData::Impl => { self.push_impl_path(buffer, def_id); } @@ -291,8 +286,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // only occur very early in the compiler pipeline. let parent_def_id = self.parent_def_id(impl_def_id).unwrap(); self.push_item_path(buffer, parent_def_id); - let node_id = self.map.as_local_node_id(impl_def_id).unwrap(); - let item = self.map.expect_item(node_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); buffer.push(&format!("", span_str)); } @@ -319,8 +314,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { ty::TyDynamic(data, ..) => data.principal().map(|p| p.def_id()), ty::TyArray(subty, _) | - ty::TySlice(subty) | - ty::TyBox(subty) => characteristic_def_id_of_type(subty), + ty::TySlice(subty) => characteristic_def_id_of_type(subty), ty::TyRawPtr(mt) | ty::TyRef(_, mt) => characteristic_def_id_of_type(mt.ty), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index ebac30c8e5..78364abdae 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -20,6 +20,8 @@ use ty::{self, Ty, TyCtxt, TypeFoldable}; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr; use syntax_pos::DUMMY_SP; +use rustc_i128::u128; +use rustc_const_math::ConstInt; use std::cmp; use std::fmt; @@ -35,6 +37,7 @@ pub struct TargetDataLayout { pub i16_align: Align, pub i32_align: Align, pub i64_align: Align, + pub i128_align: Align, pub f32_align: Align, pub f64_align: Align, pub pointer_size: Size, @@ -55,6 +58,7 @@ impl Default for TargetDataLayout { i16_align: Align::from_bits(16, 16).unwrap(), i32_align: Align::from_bits(32, 32).unwrap(), i64_align: Align::from_bits(32, 64).unwrap(), + i128_align: Align::from_bits(32, 64).unwrap(), f32_align: Align::from_bits(32, 32).unwrap(), f64_align: Align::from_bits(64, 64).unwrap(), pointer_size: Size::from_bits(64), @@ -99,6 +103,7 @@ impl TargetDataLayout { }; let mut dl = TargetDataLayout::default(); + let mut i128_align_src = 64; for spec in sess.target.target.data_layout.split("-") { match &spec.split(":").collect::>()[..] { &["e"] => dl.endian = Endian::Little, @@ -111,19 +116,28 @@ impl TargetDataLayout { dl.pointer_align = align(a, p); } &[s, ref a..] if s.starts_with("i") => { - let ty_align = match s[1..].parse::() { - Ok(1) => &mut dl.i8_align, - Ok(8) => &mut dl.i8_align, - Ok(16) => &mut dl.i16_align, - Ok(32) => &mut dl.i32_align, - Ok(64) => &mut dl.i64_align, - Ok(_) => continue, + let bits = match s[1..].parse::() { + Ok(bits) => bits, Err(_) => { size(&s[1..], "i"); // For the user error. continue; } }; - *ty_align = align(a, s); + let a = align(a, s); + match bits { + 1 => dl.i1_align = a, + 8 => dl.i8_align = a, + 16 => dl.i16_align = a, + 32 => dl.i32_align = a, + 64 => dl.i64_align = a, + _ => {} + } + if bits >= i128_align_src && bits <= 128 { + // Default alignment for i128 is decided by taking the alignment of + // largest-sized i{64...128}. + i128_align_src = bits; + dl.i128_align = a; + } } &[s, ref a..] if s.starts_with("v") => { let v_size = size(&s[1..], "v"); @@ -325,7 +339,8 @@ pub enum Integer { I8, I16, I32, - I64 + I64, + I128, } impl Integer { @@ -336,6 +351,7 @@ impl Integer { I16 => Size::from_bytes(2), I32 => Size::from_bytes(4), I64 => Size::from_bytes(8), + I128 => Size::from_bytes(16), } } @@ -346,6 +362,7 @@ impl Integer { I16 => dl.i16_align, I32 => dl.i32_align, I64 => dl.i64_align, + I128 => dl.i128_align, } } @@ -357,33 +374,37 @@ impl Integer { (I16, false) => tcx.types.u16, (I32, false) => tcx.types.u32, (I64, false) => tcx.types.u64, + (I128, false) => tcx.types.u128, (I1, true) => tcx.types.i8, (I8, true) => tcx.types.i8, (I16, true) => tcx.types.i16, (I32, true) => tcx.types.i32, (I64, true) => tcx.types.i64, + (I128, true) => tcx.types.i128, } } /// Find the smallest Integer type which can represent the signed value. pub fn fit_signed(x: i64) -> Integer { match x { - -0x0000_0001...0x0000_0000 => I1, - -0x0000_0080...0x0000_007f => I8, - -0x0000_8000...0x0000_7fff => I16, - -0x8000_0000...0x7fff_ffff => I32, - _ => I64 + -0x0000_0000_0000_0001...0x0000_0000_0000_0000 => I1, + -0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8, + -0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16, + -0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32, + -0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64, + _ => I128 } } /// Find the smallest Integer type which can represent the unsigned value. pub fn fit_unsigned(x: u64) -> Integer { match x { - 0...0x0000_0001 => I1, - 0...0x0000_00ff => I8, - 0...0x0000_ffff => I16, - 0...0xffff_ffff => I32, - _ => I64 + 0...0x0000_0000_0000_0001 => I1, + 0...0x0000_0000_0000_00ff => I8, + 0...0x0000_0000_0000_ffff => I16, + 0...0x0000_0000_ffff_ffff => I32, + 0...0xffff_ffff_ffff_ffff => I64, + _ => I128, } } @@ -406,6 +427,7 @@ impl Integer { attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16, attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32, attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64, + attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128, attr::SignedInt(IntTy::Is) | attr::UnsignedInt(UintTy::Us) => { dl.ptr_sized_integer() } @@ -486,6 +508,7 @@ impl Primitive { Int(I16) => Size::from_bits(16), Int(I32) | F32 => Size::from_bits(32), Int(I64) | F64 => Size::from_bits(64), + Int(I128) => Size::from_bits(128), Pointer => dl.pointer_size } } @@ -497,6 +520,7 @@ impl Primitive { Int(I16) => dl.i16_align, Int(I32) => dl.i32_align, Int(I64) => dl.i64_align, + Int(I128) => dl.i128_align, F32 => dl.f32_align, F64 => dl.f64_align, Pointer => dl.pointer_align @@ -1029,6 +1053,23 @@ impl<'a, 'gcx, 'tcx> Layout { let dl = &tcx.data_layout; assert!(!ty.has_infer_types()); + let ptr_layout = |pointee: Ty<'gcx>| { + let non_zero = !ty.is_unsafe_ptr(); + let pointee = normalize_associated_type(infcx, pointee); + if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) { + Ok(Scalar { value: Pointer, non_zero: non_zero }) + } else { + let unsized_part = tcx.struct_tail(pointee); + let meta = match unsized_part.sty { + ty::TySlice(_) | ty::TyStr => { + Int(dl.ptr_sized_integer()) + } + ty::TyDynamic(..) => Pointer, + _ => return Err(LayoutError::Unknown(unsized_part)) + }; + Ok(FatPointer { metadata: meta, non_zero: non_zero }) + } + }; let layout = match ty.sty { // Basic scalars. @@ -1058,24 +1099,12 @@ impl<'a, 'gcx, 'tcx> Layout { }, // Potentially-fat pointers. - ty::TyBox(pointee) | ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) | ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => { - let non_zero = !ty.is_unsafe_ptr(); - let pointee = normalize_associated_type(infcx, pointee); - if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) { - Scalar { value: Pointer, non_zero: non_zero } - } else { - let unsized_part = tcx.struct_tail(pointee); - let meta = match unsized_part.sty { - ty::TySlice(_) | ty::TyStr => { - Int(dl.ptr_sized_integer()) - } - ty::TyDynamic(..) => Pointer, - _ => return Err(LayoutError::Unknown(unsized_part)) - }; - FatPointer { metadata: meta, non_zero: non_zero } - } + ptr_layout(pointee)? + } + ty::TyAdt(def, _) if def.is_box() => { + ptr_layout(ty.boxed_ty())? } // Arrays and slices. @@ -1175,19 +1204,30 @@ impl<'a, 'gcx, 'tcx> Layout { if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) { // All bodies empty -> intlike - let (mut min, mut max, mut non_zero) = (i64::MAX, i64::MIN, true); + let (mut min, mut max, mut non_zero) = (i64::max_value(), + i64::min_value(), + true); for v in &def.variants { - let x = v.disr_val.to_u64_unchecked() as i64; + let x = match v.disr_val.erase_type() { + ConstInt::InferSigned(i) => i as i64, + ConstInt::Infer(i) => i as u64 as i64, + _ => bug!() + }; if x == 0 { non_zero = false; } if x < min { min = x; } if x > max { max = x; } } - let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..], min, max); + // FIXME: should handle i128? signed-value based impl is weird and hard to + // grok. + let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..], + min, + max); return success(CEnum { discr: discr, signed: signed, non_zero: non_zero, + // FIXME: should be u128? min: min as u64, max: max as u64 }); @@ -1232,7 +1272,7 @@ impl<'a, 'gcx, 'tcx> Layout { // non-empty body, explicit discriminants should have // been rejected by a checker before this point. for (i, v) in def.variants.iter().enumerate() { - if i as u64 != v.disr_val.to_u64_unchecked() { + if i as u128 != v.disr_val.to_u128_unchecked() { bug!("non-C-like enum {} with specified discriminants", tcx.item_path_str(def.did)); } @@ -1525,26 +1565,32 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> { Err(err) => err }; + let ptr_skeleton = |pointee: Ty<'gcx>| { + 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()); + Ok(SizeSkeleton::Pointer { + non_zero: non_zero, + tail: tcx.erase_regions(&tail) + }) + } + _ => { + bug!("SizeSkeleton::compute({}): layout errored ({}), yet \ + tail `{}` is not a type parameter or a projection", + ty, err, tail) + } + } + }; + match ty.sty { - ty::TyBox(pointee) | ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) | ty::TyRawPtr(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()); - Ok(SizeSkeleton::Pointer { - non_zero: non_zero, - tail: tcx.erase_regions(&tail) - }) - } - _ => { - bug!("SizeSkeleton::compute({}): layout errored ({}), yet \ - tail `{}` is not a type parameter or a projection", - ty, err, tail) - } - } + ptr_skeleton(pointee) + } + ty::TyAdt(def, _) if def.is_box() => { + ptr_skeleton(ty.boxed_ty()) } ty::TyAdt(def, substs) => { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 42b3544421..c0cf1d7242 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -46,3 +46,6 @@ dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc> } dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec } dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc> } dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell> } +dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind } +dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> } +dep_map_ty! { TypeckTables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index dd1a6caa02..5ab45e746e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -9,7 +9,6 @@ // except according to those terms. pub use self::Variance::*; -pub use self::DtorKind::*; pub use self::AssociatedItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; @@ -17,7 +16,7 @@ pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; use dep_graph::{self, DepNode}; -use hir::map as ast_map; +use hir::{map as hir_map, FreevarMap, TraitMap}; use middle; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -29,7 +28,7 @@ use ty; use ty::subst::{Subst, Substs}; use ty::walk::TypeWalker; use util::common::MemoizationMap; -use util::nodemap::{NodeSet, NodeMap, FxHashMap, FxHashSet}; +use util::nodemap::{NodeSet, NodeMap, FxHashMap}; use serialize::{self, Encodable, Encoder}; use std::borrow::Cow; @@ -68,8 +67,8 @@ pub use self::sty::Region::*; pub use self::sty::TypeVariants::*; pub use self::contents::TypeContents; -pub use self::context::{TyCtxt, tls}; -pub use self::context::{CtxtArenas, Lift, Tables}; +pub use self::context::{TyCtxt, GlobalArenas, tls}; +pub use self::context::{Lift, TypeckTables}; pub use self::trait_def::{TraitDef, TraitFlags}; @@ -78,6 +77,7 @@ pub mod cast; pub mod error; pub mod fast_reject; pub mod fold; +pub mod inhabitedness; pub mod item_path; pub mod layout; pub mod _match; @@ -112,19 +112,11 @@ pub struct CrateAnalysis<'tcx> { pub hir_ty_to_ty: NodeMap>, } -#[derive(Copy, Clone)] -pub enum DtorKind { - NoDtor, - TraitDtor -} - -impl DtorKind { - pub fn is_present(&self) -> bool { - match *self { - TraitDtor => true, - _ => false - } - } +#[derive(Clone)] +pub struct Resolutions { + pub freevars: FreevarMap, + pub trait_map: TraitMap, + pub maybe_unused_trait_imports: NodeSet, } #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -212,63 +204,72 @@ pub enum Visibility { /// Visible everywhere (including in other crates). Public, /// Visible only in the given crate-local module. - Restricted(NodeId), + Restricted(DefId), /// Not visible anywhere in the local crate. This is the visibility of private external items. - PrivateExternal, + Invisible, } -pub trait NodeIdTree { - fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool; -} +pub trait DefIdTree: Copy { + fn parent(self, id: DefId) -> Option; -impl<'a> NodeIdTree for ast_map::Map<'a> { - fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool { - let mut node_ancestor = node; - while node_ancestor != ancestor { - let node_ancestor_parent = self.get_module_parent(node_ancestor); - if node_ancestor_parent == node_ancestor { - return false; + fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool { + if descendant.krate != ancestor.krate { + return false; + } + + while descendant != ancestor { + match self.parent(descendant) { + Some(parent) => descendant = parent, + None => return false, } - node_ancestor = node_ancestor_parent; } true } } +impl<'a, 'gcx, 'tcx> DefIdTree for TyCtxt<'a, 'gcx, 'tcx> { + fn parent(self, id: DefId) -> Option { + self.def_key(id).parent.map(|index| DefId { index: index, ..id }) + } +} + impl Visibility { pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self { match *visibility { hir::Public => Visibility::Public, - hir::Visibility::Crate => Visibility::Restricted(ast::CRATE_NODE_ID), + hir::Visibility::Crate => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)), hir::Visibility::Restricted { ref path, .. } => match path.def { // If there is no resolution, `resolve` will have already reported an error, so // assume that the visibility is public to avoid reporting more privacy errors. Def::Err => Visibility::Public, - def => Visibility::Restricted(tcx.map.as_local_node_id(def.def_id()).unwrap()), + def => Visibility::Restricted(def.def_id()), }, - hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)), + hir::Inherited => { + Visibility::Restricted(tcx.hir.local_def_id(tcx.hir.get_module_parent(id))) + } } } /// Returns true if an item with this visibility is accessible from the given block. - pub fn is_accessible_from(self, block: NodeId, tree: &T) -> bool { + pub fn is_accessible_from(self, module: DefId, tree: T) -> bool { let restriction = match self { // Public items are visible everywhere. Visibility::Public => return true, // Private items from other crates are visible nowhere. - Visibility::PrivateExternal => return false, + Visibility::Invisible => return false, // Restricted items are visible in an arbitrary local module. + Visibility::Restricted(other) if other.krate != module.krate => return false, Visibility::Restricted(module) => module, }; - tree.is_descendant_of(block, restriction) + tree.is_descendant_of(module, restriction) } /// Returns true if this visibility is at least as accessible as the given visibility - pub fn is_at_least(self, vis: Visibility, tree: &T) -> bool { + pub fn is_at_least(self, vis: Visibility, tree: T) -> bool { let vis_restriction = match vis { Visibility::Public => return self == Visibility::Public, - Visibility::PrivateExternal => return true, + Visibility::Invisible => return true, Visibility::Restricted(module) => module, }; @@ -304,7 +305,7 @@ pub struct MethodCallee<'tcx> { /// needed to add to the side tables. Thus to disambiguate /// we also keep track of whether there's an adjustment in /// our key. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct MethodCall { pub expr_id: NodeId, pub autoderef: u32 @@ -484,7 +485,7 @@ impl Slice { /// Upvars do not get their own node-id. Instead, we use the pair of /// the original var id (that is, the root variable that is referenced /// by the upvar) and the id of the closure expression. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct UpvarId { pub var_id: NodeId, pub closure_expr_id: NodeId, @@ -497,7 +498,7 @@ 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 + /// implicit closure bindings. It is needed when the closure /// is borrowing or mutating a mutable referent, e.g.: /// /// let x: &mut isize = ...; @@ -575,24 +576,6 @@ pub enum IntVarValue { UintType(ast::UintTy), } -/// Default region to use for the bound of objects that are -/// supplied as the value for this type parameter. This is derived -/// from `T:'a` annotations appearing in the type definition. If -/// this is `None`, then the default is inherited from the -/// surrounding context. See RFC #599 for details. -#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -pub enum ObjectLifetimeDefault<'tcx> { - /// Require an explicit annotation. Occurs when multiple - /// `T:'a` constraints are found. - Ambiguous, - - /// Use the base default, typically 'static, but in a fn body it is a fresh variable - BaseDefault, - - /// Use the given region as the default. - Specific(&'tcx Region), -} - #[derive(Clone, RustcEncodable, RustcDecodable)] pub struct TypeParameterDef<'tcx> { pub name: Name, @@ -600,7 +583,6 @@ pub struct TypeParameterDef<'tcx> { pub index: u32, pub default_def_id: DefId, // for use in error reporing about defaults pub default: Option>, - pub object_lifetime_default: ObjectLifetimeDefault<'tcx>, /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute /// on generic parameter `T`, asserts data behind the parameter @@ -608,12 +590,11 @@ pub struct TypeParameterDef<'tcx> { pub pure_wrt_drop: bool, } -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub struct RegionParameterDef<'tcx> { +#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] +pub struct RegionParameterDef { pub name: Name, pub def_id: DefId, pub index: u32, - pub bounds: Vec<&'tcx ty::Region>, /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute /// on generic parameter `'a`, asserts data of lifetime `'a` @@ -621,7 +602,7 @@ pub struct RegionParameterDef<'tcx> { pub pure_wrt_drop: bool, } -impl<'tcx> RegionParameterDef<'tcx> { +impl RegionParameterDef { pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion { ty::EarlyBoundRegion { index: self.index, @@ -642,7 +623,7 @@ pub struct Generics<'tcx> { pub parent: Option, pub parent_regions: u32, pub parent_types: u32, - pub regions: Vec>, + pub regions: Vec, pub types: Vec>, pub has_self: bool, } @@ -660,7 +641,7 @@ impl<'tcx> Generics<'tcx> { self.parent_count() + self.own_count() } - pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef<'tcx> { + pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef { &self.regions[param.index as usize - self.has_self as usize] } @@ -1181,14 +1162,14 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { /// Construct a parameter environment given an item, impl item, or trait item pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> ParameterEnvironment<'tcx> { - match tcx.map.find(id) { - Some(ast_map::NodeImplItem(ref impl_item)) => { + match tcx.hir.find(id) { + Some(hir_map::NodeImplItem(ref impl_item)) => { match impl_item.node { hir::ImplItemKind::Type(_) | hir::ImplItemKind::Const(..) => { // associated types don't have their own entry (for some reason), // so for now just grab environment for the impl - let impl_id = tcx.map.get_parent(id); - let impl_def_id = tcx.map.local_def_id(impl_id); + let impl_id = tcx.hir.get_parent(id); + let impl_def_id = tcx.hir.local_def_id(impl_id); tcx.construct_parameter_environment(impl_item.span, impl_def_id, tcx.region_maps.item_extent(id)) @@ -1196,50 +1177,50 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { hir::ImplItemKind::Method(_, ref body) => { tcx.construct_parameter_environment( impl_item.span, - tcx.map.local_def_id(id), - tcx.region_maps.call_site_extent(id, body.node_id())) + tcx.hir.local_def_id(id), + tcx.region_maps.call_site_extent(id, body.node_id)) } } } - Some(ast_map::NodeTraitItem(trait_item)) => { + Some(hir_map::NodeTraitItem(trait_item)) => { match trait_item.node { - hir::TypeTraitItem(..) | hir::ConstTraitItem(..) => { + hir::TraitItemKind::Type(..) | hir::TraitItemKind::Const(..) => { // associated types don't have their own entry (for some reason), // so for now just grab environment for the trait - let trait_id = tcx.map.get_parent(id); - let trait_def_id = tcx.map.local_def_id(trait_id); + let trait_id = tcx.hir.get_parent(id); + let trait_def_id = tcx.hir.local_def_id(trait_id); tcx.construct_parameter_environment(trait_item.span, trait_def_id, tcx.region_maps.item_extent(id)) } - hir::MethodTraitItem(_, ref body) => { + hir::TraitItemKind::Method(_, ref body) => { // Use call-site for extent (unless this is a // trait method with no default; then fallback // to the method id). - let extent = if let Some(body_id) = *body { + let extent = if let hir::TraitMethod::Provided(body_id) = *body { // default impl: use call_site extent as free_id_outlive bound. - tcx.region_maps.call_site_extent(id, body_id.node_id()) + tcx.region_maps.call_site_extent(id, body_id.node_id) } else { // no default impl: use item extent as free_id_outlive bound. tcx.region_maps.item_extent(id) }; tcx.construct_parameter_environment( trait_item.span, - tcx.map.local_def_id(id), + tcx.hir.local_def_id(id), extent) } } } - Some(ast_map::NodeItem(item)) => { + Some(hir_map::NodeItem(item)) => { match item.node { hir::ItemFn(.., body_id) => { // We assume this is a function. - let fn_def_id = tcx.map.local_def_id(id); + let fn_def_id = tcx.hir.local_def_id(id); tcx.construct_parameter_environment( item.span, fn_def_id, - tcx.region_maps.call_site_extent(id, body_id.node_id())) + tcx.region_maps.call_site_extent(id, body_id.node_id)) } hir::ItemEnum(..) | hir::ItemStruct(..) | @@ -1248,13 +1229,13 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { hir::ItemImpl(..) | hir::ItemConst(..) | hir::ItemStatic(..) => { - let def_id = tcx.map.local_def_id(id); + let def_id = tcx.hir.local_def_id(id); tcx.construct_parameter_environment(item.span, def_id, tcx.region_maps.item_extent(id)) } hir::ItemTrait(..) => { - let def_id = tcx.map.local_def_id(id); + let def_id = tcx.hir.local_def_id(id); tcx.construct_parameter_environment(item.span, def_id, tcx.region_maps.item_extent(id)) @@ -1267,21 +1248,21 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { } } } - Some(ast_map::NodeExpr(expr)) => { + Some(hir_map::NodeExpr(expr)) => { // This is a convenience to allow closures to work. if let hir::ExprClosure(.., body, _) = expr.node { - let def_id = tcx.map.local_def_id(id); + let def_id = tcx.hir.local_def_id(id); let base_def_id = tcx.closure_base_def_id(def_id); tcx.construct_parameter_environment( expr.span, base_def_id, - tcx.region_maps.call_site_extent(id, body.node_id())) + tcx.region_maps.call_site_extent(id, body.node_id)) } else { tcx.empty_parameter_environment() } } - Some(ast_map::NodeForeignItem(item)) => { - let def_id = tcx.map.local_def_id(id); + Some(hir_map::NodeForeignItem(item)) => { + let def_id = tcx.hir.local_def_id(id); tcx.construct_parameter_environment(item.span, def_id, ROOT_CODE_EXTENT) @@ -1289,7 +1270,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { _ => { bug!("ParameterEnvironment::from_item(): \ `{}` is not an item", - tcx.map.node_to_string(id)) + tcx.hir.node_to_string(id)) } } } @@ -1305,9 +1286,11 @@ bitflags! { const IS_SIMD = 1 << 4, const IS_FUNDAMENTAL = 1 << 5, const IS_UNION = 1 << 6, + const IS_BOX = 1 << 7, } } +#[derive(Debug)] pub struct VariantDef { /// The variant's DefId. If this is a tuple-like struct, /// this is the DefId of the struct's ctor. @@ -1318,6 +1301,7 @@ pub struct VariantDef { pub ctor_kind: CtorKind, } +#[derive(Debug)] pub struct FieldDef { pub did: DefId, pub name: Name, @@ -1377,6 +1361,9 @@ impl<'a, 'gcx, 'tcx> AdtDef { if Some(did) == tcx.lang_items.phantom_data() { flags = flags | AdtFlags::IS_PHANTOM_DATA; } + if Some(did) == tcx.lang_items.owned_box() { + flags = flags | AdtFlags::IS_BOX; + } match kind { AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM, AdtKind::Union => flags = flags | AdtFlags::IS_UNION, @@ -1397,20 +1384,6 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK_VALID) } - #[inline] - pub fn is_uninhabited_recurse(&self, - visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, - block: Option, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - substs: &'tcx Substs<'tcx>) -> bool { - if !visited.insert((self.did, substs)) { - return false; - }; - self.variants.iter().all(|v| { - v.is_uninhabited_recurse(visited, block, tcx, substs, self.is_union()) - }) - } - #[inline] pub fn is_struct(&self) -> bool { !self.is_union() && !self.is_enum() @@ -1483,9 +1456,15 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.flags.get().intersects(AdtFlags::IS_PHANTOM_DATA) } + /// Returns true if this is Box. + #[inline] + pub fn is_box(&self) -> bool { + self.flags.get().intersects(AdtFlags::IS_BOX) + } + /// Returns whether this type has a destructor. pub fn has_dtor(&self) -> bool { - self.dtor_kind().is_present() + self.destructor.get().is_some() } /// Asserts this is a struct and returns the struct's unique @@ -1548,13 +1527,6 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.destructor.set(Some(dtor)); } - pub fn dtor_kind(&self) -> DtorKind { - match self.destructor.get() { - Some(_) => TraitDtor, - None => NoDtor, - } - } - /// Returns a simpler type such that `Self: Sized` if and only /// if that type is Sized, or `TyErr` if this type is recursive. /// @@ -1656,7 +1628,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { -> Vec> { let result = match ty.sty { TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | - TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | + TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | TyArray(..) | TyClosure(..) | TyNever => { vec![] } @@ -1745,36 +1717,12 @@ impl<'a, 'gcx, 'tcx> VariantDef { pub fn field_named(&self, name: ast::Name) -> &FieldDef { self.find_field_named(name).unwrap() } - - #[inline] - pub fn is_uninhabited_recurse(&self, - visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, - block: Option, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - substs: &'tcx Substs<'tcx>, - is_union: bool) -> bool { - if is_union { - self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, block, tcx, substs)) - } else { - self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, block, tcx, substs)) - } - } } impl<'a, 'gcx, 'tcx> FieldDef { pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> { tcx.item_type(self.did).subst(tcx, subst) } - - #[inline] - pub fn is_uninhabited_recurse(&self, - visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, - block: Option, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - substs: &'tcx Substs<'tcx>) -> bool { - block.map_or(true, |b| self.vis.is_accessible_from(b, &tcx.map)) && - self.ty(tcx, substs).is_uninhabited_recurse(visited, block, tcx) - } } /// Records the substitutions used to translate the polytype for an @@ -1938,13 +1886,35 @@ impl BorrowKind { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn tables(self) -> Ref<'a, Tables<'gcx>> { - self.tables.borrow() + pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> { + self.item_tables(self.hir.body_owner_def_id(body)) + } + + pub fn item_tables(self, def_id: DefId) -> &'gcx TypeckTables<'gcx> { + self.tables.memoize(def_id, || { + if def_id.is_local() { + // Closures' tables come from their outermost function, + // as they are part of the same "inference environment". + let outer_def_id = self.closure_base_def_id(def_id); + if outer_def_id != def_id { + return self.item_tables(outer_def_id); + } + + bug!("No def'n found for {:?} in tcx.tables", def_id); + } + + // Cross-crate side-tables only exist alongside serialized HIR. + self.sess.cstore.maybe_get_item_body(self.global_tcx(), def_id).map(|_| { + self.tables.borrow()[&def_id] + }).unwrap_or_else(|| { + bug!("tcx.item_tables({:?}): missing from metadata", def_id) + }) + }) } pub fn expr_span(self, id: NodeId) -> Span { - match self.map.find(id) { - Some(ast_map::NodeExpr(e)) => { + match self.hir.find(id) { + Some(hir_map::NodeExpr(e)) => { e.span } Some(f) => { @@ -1957,8 +1927,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn local_var_name_str(self, id: NodeId) -> InternedString { - match self.map.find(id) { - Some(ast_map::NodeLocal(pat)) => { + match self.hir.find(id) { + Some(hir_map::NodeLocal(pat)) => { match pat.node { hir::PatKind::Binding(_, _, ref path1, _) => path1.node.as_str(), _ => { @@ -2030,8 +2000,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity { - if let Some(id) = self.map.as_local_node_id(id) { - match self.map.expect_item(id).node { + if let Some(id) = self.hir.as_local_node_id(id) { + match self.hir.expect_item(id).node { hir::ItemImpl(_, polarity, ..) => polarity, ref item => bug!("trait_impl_polarity: {:?} not an impl", item) } @@ -2076,10 +2046,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // those tasks that just need to scan the names of items // and so forth. - let id = self.map.as_local_node_id(def_id).unwrap(); - let parent_id = self.map.get_parent(id); - let parent_def_id = self.map.local_def_id(parent_id); - let parent_item = self.map.expect_item(parent_id); + let id = self.hir.as_local_node_id(def_id).unwrap(); + let parent_id = self.hir.get_parent(id); + let parent_def_id = self.hir.local_def_id(parent_id); + let parent_item = self.hir.expect_item(parent_id); match parent_item.node { hir::ItemImpl(.., ref impl_trait_ref, _, ref impl_item_refs) => { for impl_item_ref in impl_item_refs { @@ -2091,10 +2061,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - hir::ItemTrait(.., ref trait_items) => { - for trait_item in trait_items { + hir::ItemTrait(.., ref trait_item_refs) => { + for trait_item_ref in trait_item_refs { let assoc_item = - self.associated_item_from_trait_item_ref(parent_def_id, trait_item); + self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref); self.associated_items.borrow_mut().insert(assoc_item.def_id, assoc_item); } } @@ -2112,28 +2082,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fn associated_item_from_trait_item_ref(self, parent_def_id: DefId, - trait_item: &hir::TraitItem) + trait_item_ref: &hir::TraitItemRef) -> AssociatedItem { - let def_id = self.map.local_def_id(trait_item.id); - - let (kind, has_self, has_value) = match trait_item.node { - hir::MethodTraitItem(ref sig, ref body) => { - (AssociatedKind::Method, sig.decl.get_self().is_some(), - body.is_some()) - } - hir::ConstTraitItem(_, ref value) => { - (AssociatedKind::Const, false, value.is_some()) - } - hir::TypeTraitItem(_, ref ty) => { - (AssociatedKind::Type, false, ty.is_some()) + let def_id = self.hir.local_def_id(trait_item_ref.id.node_id); + let (kind, has_self) = match trait_item_ref.kind { + hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false), + hir::AssociatedItemKind::Method { has_self } => { + (ty::AssociatedKind::Method, has_self) } + hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false), }; AssociatedItem { - name: trait_item.name, + name: trait_item_ref.name, kind: kind, - vis: Visibility::from_hir(&hir::Inherited, trait_item.id, self), - defaultness: hir::Defaultness::Default { has_value: has_value }, + vis: Visibility::from_hir(&hir::Inherited, trait_item_ref.id.node_id, self), + defaultness: trait_item_ref.defaultness, def_id: def_id, container: TraitContainer(parent_def_id), method_has_self_argument: has_self @@ -2145,7 +2109,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { from_trait_impl: bool, impl_item_ref: &hir::ImplItemRef) -> AssociatedItem { - let def_id = self.map.local_def_id(impl_item_ref.id.node_id); + let def_id = self.hir.local_def_id(impl_item_ref.id.node_id); let (kind, has_self) = match impl_item_ref.kind { hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false), hir::AssociatedItemKind::Method { has_self } => { @@ -2175,19 +2139,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return Rc::new(self.sess.cstore.associated_item_def_ids(def_id)); } - let id = self.map.as_local_node_id(def_id).unwrap(); - let item = self.map.expect_item(id); + let id = self.hir.as_local_node_id(def_id).unwrap(); + let item = self.hir.expect_item(id); let vec: Vec<_> = match item.node { - hir::ItemTrait(.., ref trait_items) => { - trait_items.iter() - .map(|trait_item| trait_item.id) - .map(|id| self.map.local_def_id(id)) - .collect() + hir::ItemTrait(.., ref trait_item_refs) => { + trait_item_refs.iter() + .map(|trait_item_ref| trait_item_ref.id) + .map(|id| self.hir.local_def_id(id.node_id)) + .collect() } hir::ItemImpl(.., ref impl_item_refs) => { impl_item_refs.iter() .map(|impl_item_ref| impl_item_ref.id) - .map(|id| self.map.local_def_id(id.node_id)) + .map(|id| self.hir.local_def_id(id.node_id)) .collect() } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait") @@ -2230,9 +2194,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn def_key(self, id: DefId) -> ast_map::DefKey { + pub fn def_key(self, id: DefId) -> hir_map::DefKey { if id.is_local() { - self.map.def_key(id) + self.hir.def_key(id) } else { self.sess.cstore.def_key(id) } @@ -2241,60 +2205,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Convert a `DefId` into its fully expanded `DefPath` (every /// `DefId` is really just an interned def-path). /// - /// Note that if `id` is not local to this crate -- or is - /// inlined into this crate -- the result will be a non-local - /// `DefPath`. - /// - /// This function is only safe to use when you are sure that the - /// full def-path is accessible. Examples that are known to be - /// safe are local def-ids or items; see `opt_def_path` for more - /// details. - pub fn def_path(self, id: DefId) -> ast_map::DefPath { - self.opt_def_path(id).unwrap_or_else(|| { - bug!("could not load def-path for {:?}", id) - }) - } - - /// Convert a `DefId` into its fully expanded `DefPath` (every - /// `DefId` is really just an interned def-path). - /// - /// When going across crates, we do not save the full info for - /// every cross-crate def-id, and hence we may not always be able - /// to create a def-path. Therefore, this returns - /// `Option` to cover that possibility. It will always - /// return `Some` for local def-ids, however, as well as for - /// items. The problems arise with "minor" def-ids like those - /// associated with a pattern, `impl Trait`, or other internal - /// detail to a fn. - /// - /// Note that if `id` is not local to this crate -- or is - /// inlined into this crate -- the result will be a non-local - /// `DefPath`. - pub fn opt_def_path(self, id: DefId) -> Option { + /// Note that if `id` is not local to this crate, the result will + // be a non-local `DefPath`. + pub fn def_path(self, id: DefId) -> hir_map::DefPath { if id.is_local() { - Some(self.map.def_path(id)) + self.hir.def_path(id) } else { - self.sess.cstore.relative_def_path(id) + self.sess.cstore.def_path(id) } } pub fn def_span(self, def_id: DefId) -> Span { - if let Some(id) = self.map.as_local_node_id(def_id) { - self.map.span(id) + if let Some(id) = self.hir.as_local_node_id(def_id) { + self.hir.span(id) } else { self.sess.cstore.def_span(&self.sess, def_id) } } + pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool { + vis.is_accessible_from(self.hir.local_def_id(self.hir.get_module_parent(block)), self) + } + pub fn item_name(self, id: DefId) -> ast::Name { - if let Some(id) = self.map.as_local_node_id(id) { - self.map.name(id) + if let Some(id) = self.hir.as_local_node_id(id) { + self.hir.name(id) } else if id.index == CRATE_DEF_INDEX { self.sess.cstore.original_crate_name(id.krate) } else { let def_key = self.sess.cstore.def_key(id); // The name of a StructCtor is that of its struct parent. - if let ast_map::DefPathData::StructCtor = def_key.disambiguated_data.data { + if let hir_map::DefPathData::StructCtor = def_key.disambiguated_data.data { self.item_name(DefId { krate: id.krate, index: def_key.parent.unwrap() @@ -2400,8 +2341,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Get the attributes of a definition. pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> { - if let Some(id) = self.map.as_local_node_id(did) { - Cow::Borrowed(self.map.attrs(id)) + if let Some(id) = self.hir.as_local_node_id(did) { + Cow::Borrowed(self.hir.attrs(id)) } else { Cow::Owned(self.sess.cstore.item_attrs(did)) } @@ -2504,12 +2445,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If this is a local def-id, it should be inserted into the // tables by typeck; else, it will be retreived from // the external crate metadata. - if let Some(&kind) = self.tables.borrow().closure_kinds.get(&def_id) { + if let Some(&kind) = self.closure_kinds.borrow().get(&def_id) { return kind; } let kind = self.sess.cstore.closure_kind(def_id); - self.tables.borrow_mut().closure_kinds.insert(def_id, kind); + self.closure_kinds.borrow_mut().insert(def_id, kind); kind } @@ -2521,12 +2462,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If this is a local def-id, it should be inserted into the // tables by typeck; else, it will be retreived from // the external crate metadata. - if let Some(ty) = self.tables.borrow().closure_tys.get(&def_id) { + if let Some(ty) = self.closure_tys.borrow().get(&def_id) { return ty.subst(self, substs.substs); } let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id); - self.tables.borrow_mut().closure_tys.insert(def_id, ty.clone()); + self.closure_tys.borrow_mut().insert(def_id, ty.clone()); ty.subst(self, substs.substs) } @@ -2540,8 +2481,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// ID of the impl that the method belongs to. Otherwise, return `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { if def_id.krate != LOCAL_CRATE { - return self.sess.cstore.associated_item(def_id) - .and_then(|item| { + return self.sess.cstore.associated_item(def_id).and_then(|item| { match item.container { TraitContainer(_) => None, ImplContainer(def_id) => Some(def_id), @@ -2685,8 +2625,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// with the name of the crate containing the impl. pub fn span_of_impl(self, impl_did: DefId) -> Result { if impl_did.is_local() { - let node_id = self.map.as_local_node_id(impl_did).unwrap(); - Ok(self.map.span(node_id)) + let node_id = self.hir.as_local_node_id(impl_did).unwrap(); + Ok(self.hir.span(node_id)) } else { Err(self.sess.cstore.crate_name(impl_did.krate)) } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index eb384eec6a..bc30f1fb71 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -167,7 +167,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::TyFloat(..) | // OutlivesScalar ty::TyNever | // ... ty::TyAdt(..) | // OutlivesNominalType - ty::TyBox(..) | // OutlivesNominalType (ish) ty::TyAnon(..) | // OutlivesNominalType (ish) ty::TyStr | // OutlivesScalar (ish) ty::TyArray(..) | // ... diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 76c26d01ac..89514085e1 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -418,12 +418,6 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_closure_from_closure_substs(a_id, substs)) } - (&ty::TyBox(a_inner), &ty::TyBox(b_inner)) => - { - let typ = relation.relate(&a_inner, &b_inner)?; - Ok(tcx.mk_box(typ)) - } - (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) => { let mt = relation.relate(a_mt, b_mt)?; diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 0f0478bc8c..05f4abad46 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -353,7 +353,7 @@ macro_rules! CopyImpls { } } -CopyImpls! { (), hir::Unsafety, abi::Abi } +CopyImpls! { (), hir::Unsafety, abi::Abi, ty::RegionParameterDef } impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) { @@ -468,7 +468,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { 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::TyBox(typ) => ty::TyBox(typ.fold_with(folder)), ty::TyRawPtr(tm) => ty::TyRawPtr(tm.fold_with(folder)), ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz), ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)), @@ -506,7 +505,6 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { match self.sty { - ty::TyBox(typ) => typ.visit_with(visitor), ty::TyRawPtr(ref tm) => tm.visit_with(visitor), ty::TyArray(typ, _sz) => typ.visit_with(visitor), ty::TySlice(typ) => typ.visit_with(visitor), @@ -726,52 +724,12 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { index: self.index, default: self.default.fold_with(folder), default_def_id: self.default_def_id, - object_lifetime_default: self.object_lifetime_default.fold_with(folder), pure_wrt_drop: self.pure_wrt_drop, } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.default.visit_with(visitor) || - self.object_lifetime_default.visit_with(visitor) - } -} - -impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - ty::ObjectLifetimeDefault::Ambiguous => - ty::ObjectLifetimeDefault::Ambiguous, - - ty::ObjectLifetimeDefault::BaseDefault => - ty::ObjectLifetimeDefault::BaseDefault, - - ty::ObjectLifetimeDefault::Specific(r) => - ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - ty::ObjectLifetimeDefault::Specific(r) => r.visit_with(visitor), - _ => false, - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::RegionParameterDef { - name: self.name, - def_id: self.def_id, - index: self.index, - bounds: self.bounds.fold_with(folder), - pure_wrt_drop: self.pure_wrt_drop, - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.bounds.visit_with(visitor) + self.default.visit_with(visitor) } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3b7c46ef7f..113534e452 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -22,7 +22,7 @@ use std::fmt; use std::iter; use std::cmp::Ordering; use syntax::abi; -use syntax::ast::{self, Name, NodeId}; +use syntax::ast::{self, Name}; use syntax::symbol::{keywords, InternedString}; use util::nodemap::FxHashSet; @@ -115,12 +115,6 @@ pub enum TypeVariants<'tcx> { /// definition and not a concrete use of it. TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>), - /// `Box`; this is nominally a struct in the documentation, but is - /// special-cased internally. For example, it is possible to implicitly - /// move the contents of a box out of that box, and methods of any type - /// can have type `Box`. - TyBox(Ty<'tcx>), - /// The pointee of a string slice. Written as `str`. TyStr, @@ -134,7 +128,7 @@ pub enum TypeVariants<'tcx> { TyRawPtr(TypeAndMut<'tcx>), /// A reference; a pointer with an associated lifetime. Written as - /// `&a mut T` or `&'a T`. + /// `&'a mut T` or `&'a T`. TyRef(&'tcx Region, TypeAndMut<'tcx>), /// The anonymous type of a function declaration/definition. Each @@ -543,6 +537,7 @@ pub struct ProjectionTy<'tcx> { pub struct BareFnTy<'tcx> { pub unsafety: hir::Unsafety, pub abi: abi::Abi, + /// Signature (inputs and output) of this function type. pub sig: PolyFnSig<'tcx>, } @@ -978,29 +973,52 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - /// Checks whether a type is uninhabited. - /// If `block` is `Some(id)` it also checks that the uninhabited-ness is visible from `id`. - pub fn is_uninhabited(&self, block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { + /// Checks whether a type is visibly uninhabited from a particular module. + /// # Example + /// ```rust + /// enum Void {} + /// mod a { + /// pub mod b { + /// pub struct SecretlyUninhabited { + /// _priv: !, + /// } + /// } + /// } + /// + /// mod c { + /// pub struct AlsoSecretlyUninhabited { + /// _priv: Void, + /// } + /// mod d { + /// } + /// } + /// + /// struct Foo { + /// x: a::b::SecretlyUninhabited, + /// y: c::AlsoSecretlyUninhabited, + /// } + /// ``` + /// In this code, the type `Foo` will only be visibly uninhabited inside the + /// modules b, c and d. This effects pattern-matching on `Foo` or types that + /// contain `Foo`. + /// + /// # Example + /// ```rust + /// let foo_result: Result = ... ; + /// let Ok(t) = foo_result; + /// ``` + /// This code should only compile in modules where the uninhabitedness of Foo is + /// visible. + pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { let mut visited = FxHashSet::default(); - self.is_uninhabited_recurse(&mut visited, block, cx) - } + let forest = self.uninhabited_from(&mut visited, tcx); - pub fn is_uninhabited_recurse(&self, - visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, - block: Option, - cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { - match self.sty { - TyAdt(def, substs) => { - def.is_uninhabited_recurse(visited, block, cx, substs) - }, - - TyNever => true, - TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, block, cx)), - TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, block, cx), - TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, block, cx), - - _ => false, - } + // To check whether this type is uninhabited at all (not just from the + // given node) you could check whether the forest is empty. + // ``` + // forest.is_empty() + // ``` + forest.contains(tcx, module) } pub fn is_primitive(&self) -> bool { @@ -1097,6 +1115,17 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + pub fn is_mutable_pointer(&self) -> bool { + match self.sty { + TyRawPtr(tnm) | TyRef(_, tnm) => if let hir::Mutability::MutMutable = tnm.mutbl { + true + } else { + false + }, + _ => false + } + } + pub fn is_unsafe_ptr(&self) -> bool { match self.sty { TyRawPtr(_) => return true, @@ -1104,10 +1133,17 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn is_unique(&self) -> bool { + pub fn is_box(&self) -> bool { match self.sty { - TyBox(_) => true, - _ => false + TyAdt(def, _) => def.is_box(), + _ => false, + } + } + + pub fn boxed_ty(&self) -> Ty<'tcx> { + match self.sty { + TyAdt(def, substs) if def.is_box() => substs.type_at(0), + _ => bug!("`boxed_ty` is called on non-box type {:?}", self), } } @@ -1212,9 +1248,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { -> Option> { match self.sty { - TyBox(ty) => { + TyAdt(def, _) if def.is_box() => { Some(TypeAndMut { - ty: ty, + ty: self.boxed_ty(), mutbl: if pref == ty::PreferMutLvalue { hir::MutMutable } else { @@ -1314,7 +1350,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TyInt(_) | TyUint(_) | TyFloat(_) | - TyBox(_) | TyStr | TyArray(..) | TySlice(_) | diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index c6d862b23b..1dc494ca27 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -26,7 +26,7 @@ pub struct TraitDef { /// If `true`, then this trait had the `#[rustc_paren_sugar]` /// attribute, indicating that it should be used with `Foo()` - /// sugar. This is a temporary thing -- eventually any trait wil + /// sugar. This is a temporary thing -- eventually any trait will /// be usable with the sugar (or without it). pub paren_sugar: bool, diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index b4ac6b9d25..ba49aa1ef4 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -13,9 +13,9 @@ use hir::def_id::DefId; use hir::map::DefPathData; use infer::InferCtxt; -use hir::map as ast_map; +use hir::map as hir_map; use traits::{self, Reveal}; -use ty::{self, Ty, AdtKind, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable}; +use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable}; use ty::{Disr, ParameterEnvironment}; use ty::fold::TypeVisitor; use ty::layout::{Layout, LayoutError}; @@ -51,11 +51,13 @@ impl IntTypeExt for attr::IntType { SignedInt(ast::IntTy::I16) => tcx.types.i16, SignedInt(ast::IntTy::I32) => tcx.types.i32, SignedInt(ast::IntTy::I64) => tcx.types.i64, + SignedInt(ast::IntTy::I128) => tcx.types.i128, SignedInt(ast::IntTy::Is) => tcx.types.isize, UnsignedInt(ast::UintTy::U8) => tcx.types.u8, UnsignedInt(ast::UintTy::U16) => tcx.types.u16, UnsignedInt(ast::UintTy::U32) => tcx.types.u32, UnsignedInt(ast::UintTy::U64) => tcx.types.u64, + UnsignedInt(ast::UintTy::U128) => tcx.types.u128, UnsignedInt(ast::UintTy::Us) => tcx.types.usize, } } @@ -66,6 +68,7 @@ impl IntTypeExt for attr::IntType { SignedInt(ast::IntTy::I16) => ConstInt::I16(0), SignedInt(ast::IntTy::I32) => ConstInt::I32(0), SignedInt(ast::IntTy::I64) => ConstInt::I64(0), + SignedInt(ast::IntTy::I128) => ConstInt::I128(0), SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type { ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)), ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)), @@ -76,6 +79,7 @@ impl IntTypeExt for attr::IntType { UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0), UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0), UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0), + UnsignedInt(ast::UintTy::U128) => ConstInt::U128(0), UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type { ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)), ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)), @@ -91,11 +95,13 @@ impl IntTypeExt for attr::IntType { (SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => {}, (SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {}, (SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {}, + (SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {}, (SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {}, (UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {}, (UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {}, (UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {}, (UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {}, + (UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {}, (UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {}, _ => bug!("disr type mismatch: {:?} vs {:?}", self, val), } @@ -114,9 +120,8 @@ impl IntTypeExt for attr::IntType { #[derive(Copy, Clone)] -pub enum CopyImplementationError { - InfrigingField(Name), - InfrigingVariant(Name), +pub enum CopyImplementationError<'tcx> { + InfrigingField(&'tcx ty::FieldDef), NotAnAdt, HasDestructor } @@ -139,37 +144,30 @@ pub enum Representability { impl<'tcx> ParameterEnvironment<'tcx> { pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, self_type: Ty<'tcx>, span: Span) - -> Result<(),CopyImplementationError> { + -> Result<(), CopyImplementationError> { // FIXME: (@jroesch) float this code up - tcx.infer_ctxt(None, Some(self.clone()), Reveal::ExactMatch).enter(|infcx| { - let adt = match self_type.sty { - ty::TyAdt(adt, substs) => match adt.adt_kind() { - AdtKind::Struct | AdtKind::Union => { - for field in adt.all_fields() { - let field_ty = field.ty(tcx, substs); - if infcx.type_moves_by_default(field_ty, span) { - return Err(CopyImplementationError::InfrigingField( - field.name)) - } - } - adt - } - AdtKind::Enum => { - for variant in &adt.variants { - for field in &variant.fields { - let field_ty = field.ty(tcx, substs); - if infcx.type_moves_by_default(field_ty, span) { - return Err(CopyImplementationError::InfrigingVariant( - variant.name)) - } - } - } - adt - } - }, + tcx.infer_ctxt(self.clone(), Reveal::NotSpecializable).enter(|infcx| { + let (adt, substs) = match self_type.sty { + ty::TyAdt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt) }; + let field_implements_copy = |field: &ty::FieldDef| { + let cause = traits::ObligationCause::dummy(); + match traits::fully_normalize(&infcx, cause, &field.ty(tcx, substs)) { + Ok(ty) => !infcx.type_moves_by_default(ty, span), + Err(..) => false + } + }; + + for variant in &adt.variants { + for field in &variant.fields { + if !field_implements_copy(field) { + return Err(CopyImplementationError::InfrigingField(field)); + } + } + } + if adt.has_dtor() { return Err(CopyImplementationError::HasDestructor); } @@ -431,7 +429,7 @@ impl<'a, 'gcx, 'tcx, W> TypeIdHasher<'a, 'gcx, 'tcx, W> self.def_path(&path) } - pub fn def_path(&mut self, def_path: &ast_map::DefPath) { + pub fn def_path(&mut self, def_path: &hir_map::DefPath) { def_path.deterministic_hash_to(self.tcx, &mut self.state); } } @@ -483,7 +481,6 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> TyBool | TyChar | TyStr | - TyBox(_) | TySlice(_) => {} TyError | @@ -538,7 +535,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } } let result = - tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch) + tcx.infer_ctxt(param_env.clone(), Reveal::ExactMatch) .enter(|infcx| { traits::type_known_to_meet_bound(&infcx, self, def_id, span) }); @@ -565,7 +562,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { mutbl: hir::MutImmutable, .. }) => Some(false), - TyStr | TyBox(..) | TyRef(_, TypeAndMut { + TyStr | TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) => Some(true), @@ -608,7 +605,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { // Fast-path for primitive types let result = match self.sty { TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | - TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | + TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true), TyStr | TyDynamic(..) | TySlice(_) => Some(false), diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 3fa7a80314..0d1dc2e4d7 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -83,7 +83,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => { } - ty::TyBox(ty) | ty::TyArray(ty, _) | ty::TySlice(ty) => { + ty::TyArray(ty, _) | ty::TySlice(ty) => { stack.push(ty); } ty::TyRawPtr(ref mt) | ty::TyRef(_, ref mt) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index bab9964651..33b70b09dc 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -323,7 +323,6 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } } - ty::TyBox(_) | ty::TyRawPtr(_) => { // simple cases that are WF if their type args are WF } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index e01856b2a4..4ddccbfd4c 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -27,13 +27,27 @@ pub const FN_OUTPUT_NAME: &'static str = "Output"; #[derive(Clone, Copy, Debug)] pub struct ErrorReported; +thread_local!(static TIME_DEPTH: Cell = Cell::new(0)); + +/// Read the current depth of `time()` calls. This is used to +/// encourage indentation across threads. +pub fn time_depth() -> usize { + TIME_DEPTH.with(|slot| slot.get()) +} + +/// Set the current depth of `time()` calls. The idea is to call +/// `set_time_depth()` with the result from `time_depth()` in the +/// parent thread. +pub fn set_time_depth(depth: usize) { + TIME_DEPTH.with(|slot| slot.set(depth)); +} + pub fn time(do_it: bool, what: &str, f: F) -> T where F: FnOnce() -> T, { - thread_local!(static DEPTH: Cell = Cell::new(0)); if !do_it { return f(); } - let old = DEPTH.with(|slot| { + let old = TIME_DEPTH.with(|slot| { let r = slot.get(); slot.set(r + 1); r @@ -56,7 +70,7 @@ pub fn time(do_it: bool, what: &str, f: F) -> T where mem_string, what); - DEPTH.with(|slot| slot.set(old)); + TIME_DEPTH.with(|slot| slot.set(old)); rv } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 38b38e5b49..aa2eb2955d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -16,7 +16,7 @@ use ty::{TyBool, TyChar, TyAdt}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; use ty::{TyClosure, TyProjection, TyAnon}; -use ty::{TyBox, TyDynamic, TyInt, TyUint, TyInfer}; +use ty::{TyDynamic, TyInt, TyUint, TyInfer}; use ty::{self, Ty, TyCtxt, TypeFoldable}; use std::cell::Cell; @@ -285,7 +285,7 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, ty::BrEnv => { let name = Symbol::intern("'r"); let _ = write!(f, "{}", name); - ty::BrNamed(tcx.map.local_def_id(CRATE_NODE_ID), + ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID), name, ty::Issue32330::WontChange) } @@ -336,13 +336,12 @@ impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> { } } -impl<'tcx> fmt::Debug for ty::RegionParameterDef<'tcx> { +impl fmt::Debug for ty::RegionParameterDef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "RegionParameterDef({}, {:?}, {}, {:?})", + write!(f, "RegionParameterDef({}, {:?}, {})", self.name, self.def_id, - self.index, - self.bounds) + self.index) } } @@ -523,16 +522,6 @@ impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> { } } -impl<'tcx> fmt::Debug for ty::ObjectLifetimeDefault<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ty::ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"), - ty::ObjectLifetimeDefault::BaseDefault => write!(f, "BaseDefault"), - ty::ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r), - } - } -} - impl fmt::Display for ty::Region { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if verbose() { @@ -719,7 +708,6 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { TyInt(t) => write!(f, "{}", t.ty_to_string()), TyUint(t) => write!(f, "{}", t.ty_to_string()), TyFloat(t) => write!(f, "{}", t.ty_to_string()), - TyBox(typ) => write!(f, "Box<{}>", typ), TyRawPtr(ref tm) => { write!(f, "*{} {}", match tm.mutbl { hir::MutMutable => "mut", @@ -833,13 +821,13 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { let upvar_tys = substs.upvar_tys(did, tcx); write!(f, "[closure")?; - if let Some(node_id) = tcx.map.as_local_node_id(did) { - write!(f, "@{:?}", tcx.map.span(node_id))?; + if let Some(node_id) = tcx.hir.as_local_node_id(did) { + write!(f, "@{:?}", tcx.hir.span(node_id))?; let mut sep = " "; tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { let def_id = freevar.def.def_id(); - let node_id = tcx.map.as_local_node_id(def_id).unwrap(); + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); write!(f, "{}{}:{}", sep, diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 3dc577b3c6..000e4eb59b 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -28,7 +28,7 @@ #![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/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(box_syntax)] #![feature(const_fn)] diff --git a/src/librustc_back/target/apple_base.rs b/src/librustc_back/target/apple_base.rs index 70c7ea99e1..21a2d4293d 100644 --- a/src/librustc_back/target/apple_base.rs +++ b/src/librustc_back/target/apple_base.rs @@ -37,6 +37,7 @@ pub fn opts() -> TargetOptions { function_sections: false, dynamic_linking: true, executables: true, + target_family: Some("unix".to_string()), is_like_osx: true, has_rpath: true, dll_prefix: "lib".to_string(), diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs index d86a9b0932..2dbaeaf26e 100644 --- a/src/librustc_back/target/asmjs_unknown_emscripten.rs +++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs @@ -9,11 +9,12 @@ // except according to those terms. use super::{Target, TargetOptions}; +use super::emscripten_base::{cmd}; pub fn target() -> Result { let opts = TargetOptions { - linker: "emcc".to_string(), - ar: "emar".to_string(), + linker: cmd("emcc"), + ar: cmd("emar"), dynamic_linking: false, executables: true, @@ -23,6 +24,7 @@ pub fn target() -> Result { obj_is_bitcode: true, max_atomic_width: Some(32), post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], + target_family: Some("unix".to_string()), .. Default::default() }; Ok(Target { diff --git a/src/librustc_back/target/bitrig_base.rs b/src/librustc_back/target/bitrig_base.rs index 7baf80066b..62418e68d4 100644 --- a/src/librustc_back/target/bitrig_base.rs +++ b/src/librustc_back/target/bitrig_base.rs @@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions { TargetOptions { dynamic_linking: true, executables: true, + target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, position_independent_executables: true, diff --git a/src/librustc_back/target/dragonfly_base.rs b/src/librustc_back/target/dragonfly_base.rs index 7555181a15..dca33e45af 100644 --- a/src/librustc_back/target/dragonfly_base.rs +++ b/src/librustc_back/target/dragonfly_base.rs @@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions { TargetOptions { dynamic_linking: true, executables: true, + target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: vec![ diff --git a/src/librustc_back/target/emscripten_base.rs b/src/librustc_back/target/emscripten_base.rs new file mode 100644 index 0000000000..bacada3f5a --- /dev/null +++ b/src/librustc_back/target/emscripten_base.rs @@ -0,0 +1,17 @@ +// Copyright 2014-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. + +pub fn cmd(name: &str) -> String { + if cfg!(windows) { + format!("{}.bat", name) + } else { + name.to_string() + } +} diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_back/target/freebsd_base.rs index 7555181a15..dca33e45af 100644 --- a/src/librustc_back/target/freebsd_base.rs +++ b/src/librustc_back/target/freebsd_base.rs @@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions { TargetOptions { dynamic_linking: true, executables: true, + target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: vec![ diff --git a/src/librustc_back/target/fuchsia_base.rs b/src/librustc_back/target/fuchsia_base.rs index 69546684cb..8c51722420 100644 --- a/src/librustc_back/target/fuchsia_base.rs +++ b/src/librustc_back/target/fuchsia_base.rs @@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions { TargetOptions { dynamic_linking: true, executables: true, + target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: vec![ diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs index 5e319ba183..bfdc9faaa8 100644 --- a/src/librustc_back/target/haiku_base.rs +++ b/src/librustc_back/target/haiku_base.rs @@ -17,6 +17,7 @@ pub fn opts() -> TargetOptions { dynamic_linking: true, executables: true, has_rpath: true, + target_family: Some("unix".to_string()), linker_is_gnu: true, .. Default::default() } diff --git a/src/librustc_back/target/i686_pc_windows_gnu.rs b/src/librustc_back/target/i686_pc_windows_gnu.rs index 0c2c5433e6..2947726139 100644 --- a/src/librustc_back/target/i686_pc_windows_gnu.rs +++ b/src/librustc_back/target/i686_pc_windows_gnu.rs @@ -14,6 +14,7 @@ pub fn target() -> TargetResult { let mut base = super::windows_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); + base.eliminate_frame_pointer = false; // Required for backtraces // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. diff --git a/src/librustc_back/target/i686_unknown_linux_musl.rs b/src/librustc_back/target/i686_unknown_linux_musl.rs index 3d563fa6e5..ced59448f7 100644 --- a/src/librustc_back/target/i686_unknown_linux_musl.rs +++ b/src/librustc_back/target/i686_unknown_linux_musl.rs @@ -17,6 +17,20 @@ pub fn target() -> TargetResult { base.pre_link_args.push("-m32".to_string()); base.pre_link_args.push("-Wl,-melf_i386".to_string()); + // The unwinder used by i686-unknown-linux-musl, the LLVM libunwind + // implementation, apparently relies on frame pointers existing... somehow. + // It's not clear to me why nor where this dependency is introduced, but the + // test suite does not pass with frame pointers eliminated and it passes + // with frame pointers present. + // + // If you think that this is no longer necessary, then please feel free to + // ignore! If it still passes the test suite and the bots then sounds good + // to me. + // + // This may or may not be related to this bug: + // https://llvm.org/bugs/show_bug.cgi?id=30879 + base.eliminate_frame_pointer = false; + Ok(Target { llvm_target: "i686-unknown-linux-musl".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_back/target/linux_base.rs b/src/librustc_back/target/linux_base.rs index d1ab71e414..4b2ae9c8e6 100644 --- a/src/librustc_back/target/linux_base.rs +++ b/src/librustc_back/target/linux_base.rs @@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions { TargetOptions { dynamic_linking: true, executables: true, + target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: vec![ diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 351d469ea2..5afa85d155 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -58,6 +58,7 @@ mod apple_ios_base; mod arm_base; mod bitrig_base; mod dragonfly_base; +mod emscripten_base; mod freebsd_base; mod haiku_base; mod linux_base; @@ -69,6 +70,7 @@ mod windows_base; mod windows_msvc_base; mod thumb_base; mod fuchsia_base; +mod redox_base; pub type TargetResult = Result; @@ -156,6 +158,8 @@ supported_targets! { ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc), ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc), + ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu), + ("i686-linux-android", i686_linux_android), ("arm-linux-androideabi", arm_linux_androideabi), ("armv7-linux-androideabi", armv7_linux_androideabi), @@ -172,6 +176,7 @@ supported_targets! { ("i686-unknown-openbsd", i686_unknown_openbsd), ("x86_64-unknown-openbsd", x86_64_unknown_openbsd), + ("sparc64-unknown-netbsd", sparc64_unknown_netbsd), ("x86_64-unknown-netbsd", x86_64_unknown_netbsd), ("x86_64-rumprun-netbsd", x86_64_rumprun_netbsd), @@ -184,6 +189,8 @@ supported_targets! { ("aarch64-unknown-fuchsia", aarch64_unknown_fuchsia), ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia), + ("x86_64-unknown-redox", x86_64_unknown_redox), + ("i386-apple-ios", i386_apple_ios), ("x86_64-apple-ios", x86_64_apple_ios), ("aarch64-apple-ios", aarch64_apple_ios), @@ -267,6 +274,9 @@ pub struct TargetOptions { /// user-defined libraries. pub post_link_args: Vec, + /// Extra arguments to pass to the external assembler (when used) + pub asm_args: Vec, + /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults /// to "generic". pub cpu: String, @@ -370,6 +380,9 @@ pub struct TargetOptions { // file pub no_integrated_as: bool, + /// Don't use this field; instead use the `.min_atomic_width()` method. + pub min_atomic_width: Option, + /// Don't use this field; instead use the `.max_atomic_width()` method. pub max_atomic_width: Option, @@ -394,6 +407,7 @@ impl Default for TargetOptions { ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(), pre_link_args: Vec::new(), post_link_args: Vec::new(), + asm_args: Vec::new(), cpu: "generic".to_string(), features: "".to_string(), dynamic_linking: false, @@ -432,6 +446,7 @@ impl Default for TargetOptions { has_elf_tls: false, obj_is_bitcode: false, no_integrated_as: false, + min_atomic_width: None, max_atomic_width: None, panic_strategy: PanicStrategy::Unwind, abi_blacklist: vec![], @@ -455,6 +470,12 @@ impl Target { } } + /// Minimum integer size in bits that this target can perform atomic + /// operations on. + pub fn min_atomic_width(&self) -> u64 { + self.options.min_atomic_width.unwrap_or(8) + } + /// Maximum integer size in bits that this target can perform atomic /// operations on. pub fn max_atomic_width(&self) -> u64 { @@ -561,6 +582,7 @@ impl Target { key!(late_link_args, list); key!(post_link_objects, list); key!(post_link_args, list); + key!(asm_args, list); key!(cpu); key!(features); key!(dynamic_linking, bool); @@ -596,6 +618,7 @@ impl Target { key!(obj_is_bitcode, bool); key!(no_integrated_as, bool); key!(max_atomic_width, Option); + key!(min_atomic_width, Option); try!(key!(panic_strategy, PanicStrategy)); key!(crt_static_default, bool); @@ -723,6 +746,7 @@ impl ToJson for Target { target_option_val!(late_link_args); target_option_val!(post_link_objects); target_option_val!(post_link_args); + target_option_val!(asm_args); target_option_val!(cpu); target_option_val!(features); target_option_val!(dynamic_linking); @@ -757,6 +781,7 @@ impl ToJson for Target { target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(no_integrated_as); + target_option_val!(min_atomic_width); target_option_val!(max_atomic_width); target_option_val!(panic_strategy); target_option_val!(crt_static_default); diff --git a/src/librustc_back/target/netbsd_base.rs b/src/librustc_back/target/netbsd_base.rs index 6e038a7ed5..57179a68af 100644 --- a/src/librustc_back/target/netbsd_base.rs +++ b/src/librustc_back/target/netbsd_base.rs @@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions { TargetOptions { dynamic_linking: true, executables: true, + target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, pre_link_args: vec![ diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs index 1f74170e39..12b8e8bdc8 100644 --- a/src/librustc_back/target/openbsd_base.rs +++ b/src/librustc_back/target/openbsd_base.rs @@ -15,6 +15,7 @@ pub fn opts() -> TargetOptions { TargetOptions { dynamic_linking: true, executables: true, + target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, is_like_openbsd: true, diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_back/target/redox_base.rs new file mode 100644 index 0000000000..c5e1e10775 --- /dev/null +++ b/src/librustc_back/target/redox_base.rs @@ -0,0 +1,42 @@ +// 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 PanicStrategy; +use target::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + pre_link_args: vec![ + // We want to be able to strip as much executable code as possible + // from the linker command line, and this flag indicates to the + // linker that it can avoid linking in dynamic libraries that don't + // actually satisfy any symbols up to that point (as with many other + // resolutions the linker does). This option only applies to all + // following libraries so we're sure to pass it as one of the first + // arguments. + "-Wl,--as-needed".to_string(), + + // Always enable NX protection when it is available + "-Wl,-z,noexecstack".to_string() + ], + executables: true, + relocation_model: "static".to_string(), + disable_redzone: true, + eliminate_frame_pointer: false, + target_family: None, + linker_is_gnu: true, + lib_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: "alloc_system".to_string(), + has_elf_tls: true, + panic_strategy: PanicStrategy::Abort, + .. Default::default() + } +} diff --git a/src/librustc_back/target/s390x_unknown_linux_gnu.rs b/src/librustc_back/target/s390x_unknown_linux_gnu.rs index 6e2dd6cd67..671fb4f431 100644 --- a/src/librustc_back/target/s390x_unknown_linux_gnu.rs +++ b/src/librustc_back/target/s390x_unknown_linux_gnu.rs @@ -19,6 +19,8 @@ pub fn target() -> TargetResult { // Pass the -vector feature string to LLVM to respect this assumption. base.features = "-vector".to_string(); base.max_atomic_width = Some(64); + // see #36994 + base.exe_allocation_crate = "alloc_system".to_string(); Ok(Target { llvm_target: "s390x-unknown-linux-gnu".to_string(), diff --git a/src/librustc_back/target/solaris_base.rs b/src/librustc_back/target/solaris_base.rs index a7af0462e5..41323c9c26 100644 --- a/src/librustc_back/target/solaris_base.rs +++ b/src/librustc_back/target/solaris_base.rs @@ -16,6 +16,7 @@ pub fn opts() -> TargetOptions { dynamic_linking: true, executables: true, has_rpath: true, + target_family: Some("unix".to_string()), is_like_solaris: true, exe_allocation_crate: super::maybe_jemalloc(), diff --git a/src/librustc_back/target/sparc64_unknown_linux_gnu.rs b/src/librustc_back/target/sparc64_unknown_linux_gnu.rs new file mode 100644 index 0000000000..f627cc18f0 --- /dev/null +++ b/src/librustc_back/target/sparc64_unknown_linux_gnu.rs @@ -0,0 +1,30 @@ +// 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 target::{Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_base::opts(); + base.cpu = "v9".to_string(); + base.max_atomic_width = Some(64); + base.exe_allocation_crate = "alloc_system".to_string(); + + Ok(Target { + llvm_target: "sparc64-unknown-linux-gnu".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "64".to_string(), + data_layout: "E-m:e-i64:64-n32:64-S128".to_string(), + arch: "sparc64".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + options: base, + }) +} diff --git a/src/librustc_back/target/sparc64_unknown_netbsd.rs b/src/librustc_back/target/sparc64_unknown_netbsd.rs new file mode 100644 index 0000000000..f30cebbc2d --- /dev/null +++ b/src/librustc_back/target/sparc64_unknown_netbsd.rs @@ -0,0 +1,30 @@ +// 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 target::{Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::netbsd_base::opts(); + base.cpu = "v9".to_string(); + base.pre_link_args.push("-m64".to_string()); + base.max_atomic_width = Some(64); + + Ok(Target { + llvm_target: "sparc64-unknown-netbsd".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "64".to_string(), + 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_vendor: "unknown".to_string(), + options: base, + }) +} diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs index 77ab4fcae7..a06980767f 100644 --- a/src/librustc_back/target/wasm32_unknown_emscripten.rs +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -9,11 +9,12 @@ // except according to those terms. use super::{Target, TargetOptions}; +use super::emscripten_base::{cmd}; pub fn target() -> Result { let opts = TargetOptions { - linker: "emcc".to_string(), - ar: "emar".to_string(), + linker: cmd("emcc"), + ar: cmd("emar"), dynamic_linking: false, executables: true, @@ -26,6 +27,7 @@ pub fn target() -> Result { max_atomic_width: Some(32), post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(), "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], + target_family: Some("unix".to_string()), .. Default::default() }; Ok(Target { diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index 19ca0df51b..db02e142fc 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -24,6 +24,7 @@ pub fn opts() -> TargetOptions { staticlib_prefix: "".to_string(), staticlib_suffix: ".lib".to_string(), no_default_libraries: true, + target_family: Some("windows".to_string()), is_like_windows: true, allows_weak_linkage: false, pre_link_args: vec![ diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index 84e22e84fd..efa215b419 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -53,6 +53,7 @@ pub fn opts() -> TargetOptions { exe_suffix: ".exe".to_string(), staticlib_prefix: "".to_string(), staticlib_suffix: ".lib".to_string(), + target_family: Some("windows".to_string()), is_like_windows: true, is_like_msvc: true, pre_link_args: vec![ diff --git a/src/librustc_back/target/x86_64_unknown_redox.rs b/src/librustc_back/target/x86_64_unknown_redox.rs new file mode 100644 index 0000000000..cecac06b23 --- /dev/null +++ b/src/librustc_back/target/x86_64_unknown_redox.rs @@ -0,0 +1,30 @@ +// 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 target::{Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::redox_base::opts(); + base.cpu = "x86-64".to_string(); + base.max_atomic_width = Some(64); + base.pre_link_args.push("-m64".to_string()); + + Ok(Target { + llvm_target: "x86_64-unknown-redox".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".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: "redox".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + options: base, + }) +} diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs index e65d112430..edd474b2e9 100644 --- a/src/librustc_bitflags/lib.rs +++ b/src/librustc_bitflags/lib.rs @@ -15,7 +15,7 @@ #![crate_type = "rlib"] #![no_std] #![unstable(feature = "rustc_private", issue = "27812")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] //! A typesafe bitmask flag generator. diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 5ed628d7dc..e3dec97472 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -188,13 +188,10 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, dfcx_loans: &LoanDataFlow<'b, 'tcx>, move_data: &move_data::FlowedMoveData<'c, 'tcx>, all_loans: &[Loan<'tcx>], - fn_id: ast::NodeId, - decl: &hir::FnDecl, - body: &hir::Expr) { - debug!("check_loans(body id={})", body.id); + body: &hir::Body) { + debug!("check_loans(body id={})", body.value.id); - let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id()); let mut clcx = CheckLoanCtxt { bccx: bccx, dfcx_loans: dfcx_loans, @@ -202,7 +199,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans: all_loans, param_env: &infcx.parameter_environment }; - euv::ExprUseVisitor::new(&mut clcx, &infcx).walk_fn(decl, body); + euv::ExprUseVisitor::new(&mut clcx, &infcx).consume_body(body); } #[derive(PartialEq)] @@ -463,7 +460,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // 3. Where does old loan expire. let previous_end_span = - self.tcx().map.span(old_loan.kill_scope.node_id(&self.tcx().region_maps)) + self.tcx().hir.span(old_loan.kill_scope.node_id(&self.tcx().region_maps)) .end_point(); let mut err = match (new_loan.kind, old_loan.kind) { @@ -707,7 +704,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { borrow_kind: ty::BorrowKind) -> UseError<'tcx> { debug!("analyze_restrictions_on_use(expr_id={}, use_path={:?})", - self.tcx().map.node_to_string(expr_id), + self.tcx().hir.node_to_string(expr_id), use_path); let mut ret = UseOk; diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index b0a1b34985..285f3ab904 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -132,7 +132,7 @@ pub fn build_unfragmented_map(this: &mut borrowck::BorrowckCtxt, } let mut fraginfo_map = this.tcx.fragment_infos.borrow_mut(); - let fn_did = this.tcx.map.local_def_id(id); + let fn_did = this.tcx.hir.local_def_id(id); let prev = fraginfo_map.insert(fn_did, fragment_infos); assert!(prev.is_none()); } @@ -202,7 +202,7 @@ pub fn instrument_move_fragments<'a, 'tcx>(this: &MoveData<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, id: ast::NodeId) { - let span_err = tcx.map.attrs(id).iter() + let span_err = tcx.hir.attrs(id).iter() .any(|a| a.check_name("rustc_move_fragments")); let print = tcx.sess.opts.debugging_opts.print_move_fragments; @@ -496,7 +496,7 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>, }, ref ty => { - let span = origin_id.map_or(DUMMY_SP, |id| tcx.map.span(id)); + let span = origin_id.map_or(DUMMY_SP, |id| tcx.hir.span(id)); span_bug!(span, "type {:?} ({:?}) is not fragmentable", parent_ty, ty); diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 2c277c04a5..c33ced52e2 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -18,7 +18,7 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::InteriorOffsetKind as Kind; -use rustc::ty; +use rustc::ty::{self, Ty}; use std::rc::Rc; use syntax::ast; @@ -34,12 +34,10 @@ struct GatherMoveInfo<'tcx> { pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, - decl_id: ast::NodeId, - _decl_span: Span, - var_id: ast::NodeId) { - let ty = bccx.tcx.tables().node_id_to_type(var_id); - let loan_path = Rc::new(LoanPath::new(LpVar(var_id), ty)); - move_data.add_move(bccx.tcx, loan_path, decl_id, Declared); + var_id: ast::NodeId, + var_ty: Ty<'tcx>) { + let loan_path = Rc::new(LoanPath::new(LpVar(var_id), var_ty)); + move_data.add_move(bccx.tcx, loan_path, var_id, Declared); } pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 5970d6e4f2..bbfb7e5874 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -108,7 +108,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { //! rooting etc, and presuming `cmt` is not mutated. match cmt.cat { - Categorization::Rvalue(temp_scope) => { + Categorization::Rvalue(temp_scope, _) => { temp_scope } Categorization::Upvar(..) => { diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 5d59b58b84..1783ca74a2 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -18,6 +18,7 @@ use borrowck::*; use borrowck::move_data::MoveData; +use rustc::infer::InferCtxt; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; @@ -25,7 +26,6 @@ use rustc::middle::region; use rustc::ty::{self, TyCtxt}; use syntax::ast; -use syntax::ast::NodeId; use syntax_pos::Span; use rustc::hir; use rustc::hir::Expr; @@ -40,22 +40,21 @@ mod gather_moves; mod move_error; pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, - fn_id: NodeId, - decl: &hir::FnDecl, - body: &hir::Expr) + body: hir::BodyId) -> (Vec>, move_data::MoveData<'tcx>) { + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body); let mut glcx = GatherLoanCtxt { bccx: bccx, + infcx: &infcx, all_loans: Vec::new(), - item_ub: bccx.tcx.region_maps.node_extent(body.id), + item_ub: bccx.tcx.region_maps.node_extent(body.node_id), move_data: MoveData::new(), move_error_collector: move_error::MoveErrorCollector::new(), }; - let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); - euv::ExprUseVisitor::new(&mut glcx, &infcx).walk_fn(decl, body); + let body = glcx.bccx.tcx.hir.body(body); + euv::ExprUseVisitor::new(&mut glcx, &infcx).consume_body(body); glcx.report_potential_errors(); let GatherLoanCtxt { all_loans, move_data, .. } = glcx; @@ -64,6 +63,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, struct GatherLoanCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, + infcx: &'a InferCtxt<'a, 'tcx, 'tcx>, move_data: move_data::MoveData<'tcx>, move_error_collector: move_error::MoveErrorCollector<'tcx>, all_loans: Vec>, @@ -159,8 +159,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { mode); } - fn decl_without_init(&mut self, id: ast::NodeId, span: Span) { - gather_moves::gather_decl(self.bccx, &self.move_data, id, span, id); + fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) { + let ty = self.infcx.tables.borrow().node_id_to_type(id); + gather_moves::gather_decl(self.bccx, &self.move_data, id, ty); } } @@ -194,7 +195,8 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, bccx.report_aliasability_violation( borrow_span, loan_cause, - mc::AliasableReason::UnaliasableImmutable); + mc::AliasableReason::UnaliasableImmutable, + cmt); Err(()) } (mc::Aliasability::FreelyAliasable(alias_cause), ty::UniqueImmBorrow) | @@ -202,7 +204,8 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, bccx.report_aliasability_violation( borrow_span, loan_cause, - alias_cause); + alias_cause, + cmt); Err(()) } (..) => { @@ -517,19 +520,17 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { /// sure the loans being taken are sound. struct StaticInitializerCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, - item_id: ast::NodeId + body_id: hir::BodyId, } impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.bccx.tcx.map) + NestedVisitorMap::None } fn visit_expr(&mut self, ex: &'tcx Expr) { if let hir::ExprAddrOf(mutbl, ref base) = ex.node { - let param_env = ty::ParameterEnvironment::for_item(self.bccx.tcx, - self.item_id); - let infcx = self.bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let infcx = self.bccx.tcx.borrowck_fake_infer_ctxt(self.body_id); let mc = mc::MemCategorizationContext::new(&infcx); let base_cmt = mc.cat_expr(&base).unwrap(); let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); @@ -546,16 +547,14 @@ impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { } } -pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>, - item_id: ast::NodeId, - expr: &'tcx hir::Expr) { - - debug!("gather_loans_in_static_initializer(expr={:?})", expr); +pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, body: hir::BodyId) { + debug!("gather_loans_in_static_initializer(expr={:?})", body); let mut sicx = StaticInitializerCtxt { bccx: bccx, - item_id: item_id + body_id: body }; - sicx.visit_expr(expr); + let body = sicx.bccx.tcx.hir.body(body); + sicx.visit_body(body); } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs index 8461f6d061..b15c1873f9 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs @@ -27,16 +27,15 @@ use std::marker::PhantomData; use std::mem; use std::path::Path; -use super::super::MoveDataParamEnv; use super::super::MirBorrowckCtxtPreDataflow; use super::{BitDenotation, DataflowState}; impl DataflowState { - fn each_bit(&self, ctxt: &O::Ctxt, words: &IdxSet, mut f: F) + fn each_bit(&self, words: &IdxSet, mut f: F) where F: FnMut(O::Idx) { //! Helper for iterating over the bits in a bitvector. - let bits_per_block = self.operator.bits_per_block(ctxt); + let bits_per_block = self.operator.bits_per_block(); let usize_bits: usize = mem::size_of::() * 8; for (word_index, &word) in words.words().iter().enumerate() { @@ -65,35 +64,33 @@ impl DataflowState { } pub fn interpret_set<'c, P>(&self, - ctxt: &'c O::Ctxt, + o: &'c O, words: &IdxSet, render_idx: &P) -> Vec<&'c Debug> - where P: for <'b> Fn(&'b O::Ctxt, O::Idx) -> &'b Debug + where P: Fn(&O, O::Idx) -> &Debug { let mut v = Vec::new(); - self.each_bit(ctxt, words, |i| { - v.push(render_idx(ctxt, i)); + self.each_bit(words, |i| { + v.push(render_idx(o, i)); }); v } } pub trait MirWithFlowState<'tcx> { - type BD: BitDenotation>; + type BD: BitDenotation; fn node_id(&self) -> NodeId; fn mir(&self) -> &Mir<'tcx>; - fn analysis_ctxt(&self) -> &::Ctxt; fn flow_state(&self) -> &DataflowState; } impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> - where 'tcx: 'a, BD: BitDenotation> + where 'tcx: 'a, BD: BitDenotation { type BD = BD; fn node_id(&self) -> NodeId { self.node_id } fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() } - fn analysis_ctxt(&self) -> &BD::Ctxt { &self.flow_state.ctxt } fn flow_state(&self) -> &DataflowState { &self.flow_state.flow_state } } @@ -110,8 +107,8 @@ pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>( path: &Path, render_idx: P) -> io::Result<()> - where BD: BitDenotation>, - P: for <'b> Fn(&'b BD::Ctxt, BD::Idx) -> &'b Debug + where BD: BitDenotation, + P: Fn(&BD, BD::Idx) -> &Debug { let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx }; let mut v = Vec::new(); @@ -133,9 +130,7 @@ fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec { impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> where MWF: MirWithFlowState<'tcx>, - P: for <'b> Fn(&'b ::Ctxt, - ::Idx) - -> &'b Debug, + P: for <'b> Fn(&'b MWF::BD, ::Idx) -> &'b Debug, { type Node = Node; type Edge = Edge; @@ -227,9 +222,8 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> ::rustc_mir::graphviz::write_node_label( *n, self.mbcx.mir(), &mut v, 4, |w| { - let ctxt = self.mbcx.analysis_ctxt(); let flow = self.mbcx.flow_state(); - let entry_interp = flow.interpret_set(ctxt, + let entry_interp = flow.interpret_set(&flow.operator, flow.sets.on_entry_set_for(i), &self.render_idx); chunked_present_left(w, &entry_interp[..], chunk_size)?; @@ -244,12 +238,11 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> entrybits=bits_to_string(entry.words(), bits_per_block)) }, |w| { - let ctxt = self.mbcx.analysis_ctxt(); let flow = self.mbcx.flow_state(); let gen_interp = - flow.interpret_set(ctxt, flow.sets.gen_set_for(i), &self.render_idx); + flow.interpret_set(&flow.operator, flow.sets.gen_set_for(i), &self.render_idx); let kill_interp = - flow.interpret_set(ctxt, flow.sets.kill_set_for(i), &self.render_idx); + flow.interpret_set(&flow.operator, flow.sets.kill_set_for(i), &self.render_idx); chunked_present_left(w, &gen_interp[..], chunk_size)?; let bits_per_block = flow.sets.bits_per_block(); { diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs index fcb453d81a..1fa4da94dd 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -15,7 +15,7 @@ use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; -use super::super::gather_moves::{MoveOutIndex, MovePathIndex}; +use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex}; use super::super::MoveDataParamEnv; use super::super::DropFlagState; use super::super::drop_flag_effects_for_function_entry; @@ -66,14 +66,23 @@ use super::{BitDenotation, BlockSets, DataflowOperator}; pub struct MaybeInitializedLvals<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>, } impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { - MaybeInitializedLvals { tcx: tcx, mir: mir } + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>) + -> Self + { + MaybeInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } } } +impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'tcx> { + fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } +} + /// `MaybeUninitializedLvals` tracks all l-values that might be /// uninitialized upon reaching a particular point in the control flow /// for a function. @@ -112,14 +121,23 @@ impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> { pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>, } impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { - MaybeUninitializedLvals { tcx: tcx, mir: mir } + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>) + -> Self + { + MaybeUninitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } } } +impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'tcx> { + fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } +} + /// `DefinitelyInitializedLvals` tracks all l-values that are definitely /// initialized upon reaching a particular point in the control flow /// for a function. @@ -164,14 +182,23 @@ impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> { pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>, } impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { - DefinitelyInitializedLvals { tcx: tcx, mir: mir } + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>) + -> Self + { + DefinitelyInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe } } } +impl<'a, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'tcx> { + fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } +} + /// `MovingOutStatements` tracks the statements that perform moves out /// of particular l-values. More precisely, it tracks whether the /// *effect* of such moves (namely, the uninitialization of the @@ -189,6 +216,11 @@ impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> { pub struct MovingOutStatements<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, + mdpe: &'a MoveDataParamEnv<'tcx>, +} + +impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> { + fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> { @@ -226,16 +258,15 @@ impl<'a, 'tcx> DefinitelyInitializedLvals<'a, 'tcx> { impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> { type Idx = MovePathIndex; - type Ctxt = MoveDataParamEnv<'tcx>; fn name() -> &'static str { "maybe_init" } - fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize { - ctxt.move_data.move_paths.len() + fn bits_per_block(&self) -> usize { + self.move_data().move_paths.len() } - fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets) + fn start_block_effect(&self, sets: &mut BlockSets) { drop_flag_effects_for_function_entry( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); sets.on_entry.add(&path); @@ -243,60 +274,56 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> { } fn statement_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, idx: usize) { drop_flag_effects_for_location( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, Location { block: bb, statement_index: idx }, |path, s| Self::update_bits(sets, path, s) ) } fn terminator_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, statements_len: usize) { drop_flag_effects_for_location( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, Location { block: bb, statement_index: statements_len }, |path, s| Self::update_bits(sets, path, s) ) } fn propagate_call_return(&self, - ctxt: &Self::Ctxt, in_out: &mut IdxSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, dest_lval: &mir::Lvalue) { // when a call returns successfully, that means we need to set // the bits for that dest_lval to 1 (initialized). - on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data, - ctxt.move_data.rev_lookup.find(dest_lval), + on_lookup_result_bits(self.tcx, self.mir, self.move_data(), + self.move_data().rev_lookup.find(dest_lval), |mpi| { in_out.add(&mpi); }); } } impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> { type Idx = MovePathIndex; - type Ctxt = MoveDataParamEnv<'tcx>; fn name() -> &'static str { "maybe_uninit" } - fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize { - ctxt.move_data.move_paths.len() + fn bits_per_block(&self) -> usize { + self.move_data().move_paths.len() } // sets on_entry bits for Arg lvalues - fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets) { + fn start_block_effect(&self, sets: &mut BlockSets) { // set all bits to 1 (uninit) before gathering counterevidence for e in sets.on_entry.words_mut() { *e = !0; } drop_flag_effects_for_function_entry( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); sets.on_entry.remove(&path); @@ -304,59 +331,55 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> { } fn statement_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, idx: usize) { drop_flag_effects_for_location( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, Location { block: bb, statement_index: idx }, |path, s| Self::update_bits(sets, path, s) ) } fn terminator_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, statements_len: usize) { drop_flag_effects_for_location( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, Location { block: bb, statement_index: statements_len }, |path, s| Self::update_bits(sets, path, s) ) } fn propagate_call_return(&self, - ctxt: &Self::Ctxt, in_out: &mut IdxSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, dest_lval: &mir::Lvalue) { // when a call returns successfully, that means we need to set // the bits for that dest_lval to 0 (initialized). - on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data, - ctxt.move_data.rev_lookup.find(dest_lval), + on_lookup_result_bits(self.tcx, self.mir, self.move_data(), + self.move_data().rev_lookup.find(dest_lval), |mpi| { in_out.remove(&mpi); }); } } impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> { type Idx = MovePathIndex; - type Ctxt = MoveDataParamEnv<'tcx>; fn name() -> &'static str { "definite_init" } - fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize { - ctxt.move_data.move_paths.len() + fn bits_per_block(&self) -> usize { + self.move_data().move_paths.len() } // sets on_entry bits for Arg lvalues - fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets) { + fn start_block_effect(&self, sets: &mut BlockSets) { for e in sets.on_entry.words_mut() { *e = 0; } drop_flag_effects_for_function_entry( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); sets.on_entry.add(&path); @@ -364,63 +387,58 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> { } fn statement_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, idx: usize) { drop_flag_effects_for_location( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, Location { block: bb, statement_index: idx }, |path, s| Self::update_bits(sets, path, s) ) } fn terminator_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, statements_len: usize) { drop_flag_effects_for_location( - self.tcx, self.mir, ctxt, + self.tcx, self.mir, self.mdpe, Location { block: bb, statement_index: statements_len }, |path, s| Self::update_bits(sets, path, s) ) } fn propagate_call_return(&self, - ctxt: &Self::Ctxt, in_out: &mut IdxSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, dest_lval: &mir::Lvalue) { // when a call returns successfully, that means we need to set // the bits for that dest_lval to 1 (initialized). - on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data, - ctxt.move_data.rev_lookup.find(dest_lval), + on_lookup_result_bits(self.tcx, self.mir, self.move_data(), + self.move_data().rev_lookup.find(dest_lval), |mpi| { in_out.add(&mpi); }); } } impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { type Idx = MoveOutIndex; - type Ctxt = MoveDataParamEnv<'tcx>; fn name() -> &'static str { "moving_out" } - fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize { - ctxt.move_data.moves.len() + fn bits_per_block(&self) -> usize { + self.move_data().moves.len() } - fn start_block_effect(&self,_move_data: &Self::Ctxt, _sets: &mut BlockSets) { + fn start_block_effect(&self, _sets: &mut BlockSets) { // no move-statements have been executed prior to function // execution, so this method has no effect on `_sets`. } fn statement_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, idx: usize) { - let (tcx, mir, move_data) = (self.tcx, self.mir, &ctxt.move_data); + let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data()); let stmt = &mir[bb].statements[idx]; let loc_map = &move_data.loc_map; let path_map = &move_data.path_map; @@ -435,7 +453,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { // here, in dataflow vector zero_to_one(sets.gen_set.words_mut(), *move_index); } - let bits_per_block = self.bits_per_block(ctxt); + let bits_per_block = self.bits_per_block(); match stmt.kind { mir::StatementKind::SetDiscriminant { .. } => { span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck"); @@ -460,18 +478,17 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { } fn terminator_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, statements_len: usize) { - let (mir, move_data) = (self.mir, &ctxt.move_data); + let (mir, move_data) = (self.mir, self.move_data()); let term = mir[bb].terminator(); let loc_map = &move_data.loc_map; let loc = Location { block: bb, statement_index: statements_len }; debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", term, loc, &loc_map[loc]); - let bits_per_block = self.bits_per_block(ctxt); + let bits_per_block = self.bits_per_block(); for move_index in &loc_map[loc] { assert!(move_index.index() < bits_per_block); zero_to_one(sets.gen_set.words_mut(), *move_index); @@ -479,13 +496,12 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { } fn propagate_call_return(&self, - ctxt: &Self::Ctxt, in_out: &mut IdxSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, dest_lval: &mir::Lvalue) { - let move_data = &ctxt.move_data; - let bits_per_block = self.bits_per_block(ctxt); + 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, diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs index 51817afbfe..f11cf90834 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs @@ -22,7 +22,6 @@ use std::path::PathBuf; use std::usize; use super::MirBorrowckCtxtPreDataflow; -use super::MoveDataParamEnv; pub use self::sanity_check::sanity_check_via_rustc_peek; pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; @@ -33,13 +32,13 @@ mod sanity_check; mod impls; pub trait Dataflow { - fn dataflow

(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug; + fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug; } impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> - where BD: BitDenotation> + DataflowOperator + where BD: BitDenotation + DataflowOperator { - fn dataflow

(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug { + fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug { self.flow_state.build_sets(); self.pre_dataflow_instrumentation(|c,i| p(c,i)).unwrap(); self.flow_state.propagate(); @@ -48,7 +47,7 @@ impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> } struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> - where O: 'b + BitDenotation, O::Ctxt: 'a + where O: 'b + BitDenotation { builder: &'b mut DataflowAnalysis<'a, 'tcx, O>, changed: bool, @@ -79,7 +78,7 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> { let sets = &mut self.flow_state.sets.for_block(mir::START_BLOCK.index()); - self.flow_state.operator.start_block_effect(&self.ctxt, sets); + self.flow_state.operator.start_block_effect(sets); } for (bb, data) in self.mir.basic_blocks().iter_enumerated() { @@ -87,12 +86,12 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> let sets = &mut self.flow_state.sets.for_block(bb.index()); for j_stmt in 0..statements.len() { - self.flow_state.operator.statement_effect(&self.ctxt, sets, bb, j_stmt); + self.flow_state.operator.statement_effect(sets, bb, j_stmt); } if terminator.is_some() { let stmts_len = statements.len(); - self.flow_state.operator.terminator_effect(&self.ctxt, sets, bb, stmts_len); + self.flow_state.operator.terminator_effect(sets, bb, stmts_len); } } } @@ -137,10 +136,10 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf { } impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> - where BD: BitDenotation> + where BD: BitDenotation { fn pre_dataflow_instrumentation

(&self, p: P) -> io::Result<()> - where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug + where P: Fn(&BD, BD::Idx) -> &Debug { if let Some(ref path_str) = self.print_preflow_to { let path = dataflow_path(BD::name(), "preflow", path_str); @@ -151,7 +150,7 @@ impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> } fn post_dataflow_instrumentation

(&self, p: P) -> io::Result<()> - where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug + where P: Fn(&BD, BD::Idx) -> &Debug { if let Some(ref path_str) = self.print_postflow_to { let path = dataflow_path(BD::name(), "postflow", path_str); @@ -179,11 +178,10 @@ impl Bits { } pub struct DataflowAnalysis<'a, 'tcx: 'a, O> - where O: BitDenotation, O::Ctxt: 'a + where O: BitDenotation { flow_state: DataflowState, mir: &'a Mir<'tcx>, - ctxt: &'a O::Ctxt, } impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> @@ -295,9 +293,6 @@ pub trait BitDenotation { /// Specifies what index type is used to access the bitvector. type Idx: Idx; - /// Specifies what, if any, separate context needs to be supplied for methods below. - type Ctxt; - /// A name describing the dataflow analysis that this /// BitDenotation is supporting. The name should be something /// suitable for plugging in as part of a filename e.g. avoid @@ -308,7 +303,7 @@ pub trait BitDenotation { fn name() -> &'static str; /// Size of each bitvector allocated for each block in the analysis. - fn bits_per_block(&self, &Self::Ctxt) -> usize; + fn bits_per_block(&self) -> usize; /// Mutates the block-sets (the flow sets for the given /// basic block) according to the effects that have been @@ -319,7 +314,7 @@ pub trait BitDenotation { /// (Typically this should only modify `sets.on_entry`, since the /// gen and kill sets should reflect the effects of *executing* /// the start block itself.) - fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets); + fn start_block_effect(&self, sets: &mut BlockSets); /// Mutates the block-sets (the flow sets for the given /// basic block) according to the effects of evaluating statement. @@ -332,7 +327,6 @@ pub trait BitDenotation { /// `bb_data` is the sequence of statements identifed by `bb` in /// the MIR. fn statement_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, idx_stmt: usize); @@ -348,7 +342,6 @@ pub trait BitDenotation { /// The effects applied here cannot depend on which branch the /// terminator took. fn terminator_effect(&self, - ctxt: &Self::Ctxt, sets: &mut BlockSets, bb: mir::BasicBlock, idx_term: usize); @@ -373,7 +366,6 @@ pub trait BitDenotation { /// kill-sets associated with each edge coming out of the basic /// block. fn propagate_call_return(&self, - ctxt: &Self::Ctxt, in_out: &mut IdxSet, call_bb: mir::BasicBlock, dest_bb: mir::BasicBlock, @@ -385,9 +377,8 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> { pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, - ctxt: &'a D::Ctxt, denotation: D) -> Self { - let bits_per_block = denotation.bits_per_block(&ctxt); + let bits_per_block = denotation.bits_per_block(); let usize_bits = mem::size_of::() * 8; let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; @@ -405,7 +396,6 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> }); DataflowAnalysis { - ctxt: ctxt, mir: mir, flow_state: DataflowState { sets: AllSets { @@ -482,7 +472,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> // N.B.: This must be done *last*, after all other // propagation, as documented in comment above. self.flow_state.operator.propagate_call_return( - &self.ctxt, in_out, bb, *dest_bb, dest_lval); + in_out, bb, *dest_bb, dest_lval); self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb); } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index 916d17dcc9..ea6ef423c9 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -17,9 +17,9 @@ use rustc::mir::{self, Mir}; use rustc_data_structures::indexed_vec::Idx; use super::super::gather_moves::{MovePathIndex, LookupResult}; -use super::super::MoveDataParamEnv; use super::BitDenotation; use super::DataflowResults; +use super::super::gather_moves::HasMoveData; /// This function scans `mir` for all calls to the intrinsic /// `rustc_peek` that have the expression form `rustc_peek(&expr)`. @@ -41,9 +41,8 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, id: ast::NodeId, _attributes: &[ast::Attribute], - flow_ctxt: &O::Ctxt, results: &DataflowResults) - where O: BitDenotation, Idx=MovePathIndex> + where O: BitDenotation + HasMoveData<'tcx> { debug!("sanity_check_via_rustc_peek id: {:?}", id); // FIXME: this is not DRY. Figure out way to abstract this and @@ -51,18 +50,17 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // stuff, so such generalization may not be realistic.) for bb in mir.basic_blocks().indices() { - each_block(tcx, mir, flow_ctxt, results, bb); + each_block(tcx, mir, results, bb); } } fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, - ctxt: &O::Ctxt, results: &DataflowResults, bb: mir::BasicBlock) where - O: BitDenotation, Idx=MovePathIndex> + O: BitDenotation + HasMoveData<'tcx> { - let move_data = &ctxt.move_data; + let move_data = results.0.operator.move_data(); let mir::BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = mir[bb]; let (args, span) = match is_rustc_peek(tcx, terminator) { @@ -146,7 +144,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // 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; } - results.0.operator.statement_effect(ctxt, &mut sets, bb, j); + results.0.operator.statement_effect(&mut sets, bb, j); sets.on_entry.union(sets.gen_set); sets.on_entry.subtract(sets.kill_set); } diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 88e5bae483..9e89a3689c 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::gather_moves::{MoveData, MovePathIndex, LookupResult}; +use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult}; use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use super::dataflow::{DataflowResults}; use super::{drop_flag_effects_for_location, on_all_children_bits}; @@ -51,11 +51,13 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { param_env: param_env }; let flow_inits = - super::do_dataflow(tcx, mir, id, &[], &env, - MaybeInitializedLvals::new(tcx, mir)); + super::do_dataflow(tcx, mir, id, &[], + MaybeInitializedLvals::new(tcx, mir, &env), + |bd, p| &bd.move_data().move_paths[p]); let flow_uninits = - super::do_dataflow(tcx, mir, id, &[], &env, - MaybeUninitializedLvals::new(tcx, mir)); + super::do_dataflow(tcx, mir, id, &[], + MaybeUninitializedLvals::new(tcx, mir, &env), + |bd, p| &bd.move_data().move_paths[p]); ElaborateDropsCtxt { tcx: tcx, @@ -707,9 +709,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock { let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx); match ty.sty { - ty::TyAdt(def, substs) => { - self.open_drop_for_adt(c, def, substs) - } ty::TyClosure(def_id, substs) => { let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx).collect(); self.open_drop_for_tuple(c, &tys) @@ -717,8 +716,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { ty::TyTuple(tys) => { self.open_drop_for_tuple(c, tys) } - ty::TyBox(ty) => { - self.open_drop_for_box(c, ty) + ty::TyAdt(def, _) if def.is_box() => { + self.open_drop_for_box(c, ty.boxed_ty()) + } + ty::TyAdt(def, substs) => { + self.open_drop_for_adt(c, def, substs) } _ => bug!("open drop from non-ADT `{:?}`", ty) } @@ -893,7 +895,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { match ty.sty { ty::TyAdt(def, _) => { - if def.has_dtor() { + if def.has_dtor() && !def.is_box() { self.tcx.sess.span_warn( c.source_info.span, &format!("dataflow bug??? moving out of type with dtor {:?}", diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index 02064b52cb..7cf6ab2999 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -120,6 +120,10 @@ pub struct MoveData<'tcx> { pub rev_lookup: MovePathLookup<'tcx>, } +pub trait HasMoveData<'tcx> { + fn move_data(&self) -> &MoveData<'tcx>; +} + #[derive(Debug)] pub struct LocationMap { /// Location-indexed (BasicBlock for outer index, index within BB @@ -285,7 +289,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { // error: can't move out of borrowed content ty::TyRef(..) | ty::TyRawPtr(..) => return Err(MovePathError::IllegalMove), // error: can't move out of struct with destructor - ty::TyAdt(adt, _) if adt.has_dtor() => + ty::TyAdt(adt, _) if adt.has_dtor() && !adt.is_box() => return Err(MovePathError::IllegalMove), // move out of union - always move the entire union ty::TyAdt(adt, _) if adt.is_union() => diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index 9035c2ab3c..a0c36139dd 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -11,10 +11,7 @@ use borrowck::BorrowckCtxt; use syntax::ast::{self, MetaItem}; -use syntax_pos::{Span, DUMMY_SP}; - -use rustc::hir; -use rustc::hir::intravisit::{FnKind}; +use syntax_pos::DUMMY_SP; use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location}; use rustc::session::Session; @@ -32,7 +29,9 @@ use self::dataflow::{DataflowOperator}; use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults}; use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use self::dataflow::{DefinitelyInitializedLvals}; -use self::gather_moves::{MoveData, MovePathIndex, LookupResult}; +use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult}; + +use std::fmt; fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { for attr in attrs { @@ -55,44 +54,34 @@ pub struct MoveDataParamEnv<'tcx> { } pub fn borrowck_mir(bcx: &mut BorrowckCtxt, - fk: FnKind, - _decl: &hir::FnDecl, - body: &hir::Expr, - _sp: Span, id: ast::NodeId, attributes: &[ast::Attribute]) { - match fk { - FnKind::ItemFn(name, ..) | - FnKind::Method(name, ..) => { - debug!("borrowck_mir({}) UNIMPLEMENTED", name); - } - FnKind::Closure(_) => { - debug!("borrowck_mir closure (body.id={}) UNIMPLEMENTED", body.id); - } - } - let tcx = bcx.tcx; - let param_env = ty::ParameterEnvironment::for_item(tcx, id); - - let mir = &tcx.item_mir(tcx.map.local_def_id(id)); + let def_id = tcx.hir.local_def_id(id); + debug!("borrowck_mir({}) UNIMPLEMENTED", tcx.item_path_str(def_id)); + let mir = &tcx.item_mir(def_id); + let param_env = ty::ParameterEnvironment::for_item(tcx, id); let move_data = MoveData::gather_moves(mir, tcx, ¶m_env); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let flow_inits = - do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeInitializedLvals::new(tcx, mir)); + do_dataflow(tcx, mir, id, attributes, MaybeInitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); let flow_uninits = - do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeUninitializedLvals::new(tcx, mir)); + do_dataflow(tcx, mir, id, attributes, MaybeUninitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); let flow_def_inits = - do_dataflow(tcx, mir, id, attributes, &mdpe, DefinitelyInitializedLvals::new(tcx, mir)); + do_dataflow(tcx, mir, id, attributes, DefinitelyInitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_inits); + dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_inits); } if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_uninits); + dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_uninits); } if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() { - dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_def_inits); + dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_def_inits); } if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() { @@ -103,7 +92,7 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt, bcx: bcx, mir: mir, node_id: id, - move_data: mdpe.move_data, + move_data: &mdpe.move_data, flow_inits: flow_inits, flow_uninits: flow_uninits, }; @@ -115,13 +104,15 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt, debug!("borrowck_mir done"); } -fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir: &Mir<'tcx>, - node_id: ast::NodeId, - attributes: &[ast::Attribute], - ctxt: &BD::Ctxt, - bd: BD) -> DataflowResults - where BD: BitDenotation> + DataflowOperator +fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + node_id: ast::NodeId, + attributes: &[ast::Attribute], + bd: BD, + p: P) + -> DataflowResults + where BD: BitDenotation + DataflowOperator, + P: Fn(&BD, BD::Idx) -> &fmt::Debug { let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option { if let Some(item) = has_rustc_mir_with(attrs, name) { @@ -146,16 +137,15 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: node_id, print_preflow_to: print_preflow_to, print_postflow_to: print_postflow_to, - flow_state: DataflowAnalysis::new(tcx, mir, ctxt, bd), + flow_state: DataflowAnalysis::new(tcx, mir, bd), }; - mbcx.dataflow(|ctxt, i| &ctxt.move_data.move_paths[i]); + mbcx.dataflow(p); mbcx.flow_state.results() } -pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> - where BD: BitDenotation, BD::Ctxt: 'a +pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation { node_id: ast::NodeId, flow_state: DataflowAnalysis<'a, 'tcx, BD>, @@ -168,7 +158,7 @@ pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> { bcx: &'b mut BorrowckCtxt<'a, 'tcx>, mir: &'b Mir<'tcx>, node_id: ast::NodeId, - move_data: MoveData<'tcx>, + move_data: &'b MoveData<'tcx>, flow_inits: DataflowResults>, flow_uninits: DataflowResults> } @@ -258,7 +248,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx lv, ty); true } - ty::TyAdt(def, _) if def.has_dtor() || def.is_union() => { + ty::TyAdt(def, _) if (def.has_dtor() && !def.is_box()) || def.is_union() => { debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} Drop => true", lv, ty); true diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index ecf5c3ef17..46179b31d5 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -24,7 +24,7 @@ use self::InteriorKind::*; use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; -use rustc::hir::map::blocks::{FnParts, FnLikeNode}; +use rustc::hir::map::blocks::FnLikeNode; use rustc::cfg; use rustc::middle::dataflow::DataFlowContext; use rustc::middle::dataflow::BitwiseOperator; @@ -64,11 +64,11 @@ pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::OnlyBodies(&self.tcx.hir) } fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::ExprId, s: Span, id: ast::NodeId) { + b: hir::BodyId, s: Span, id: ast::NodeId) { match fk { FnKind::ItemFn(..) | FnKind::Method(..) => { @@ -88,15 +88,15 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> { } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node { - gather_loans::gather_loans_in_static_initializer(self, ti.id, &expr); + if let hir::TraitItemKind::Const(_, Some(expr)) = ti.node { + gather_loans::gather_loans_in_static_initializer(self, expr); } intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(_, ref expr) = ii.node { - gather_loans::gather_loans_in_static_initializer(self, ii.id, &expr); + if let hir::ImplItemKind::Const(_, expr) = ii.node { + gather_loans::gather_loans_in_static_initializer(self, expr); } intravisit::walk_impl_item(self, ii); } @@ -141,9 +141,9 @@ fn borrowck_item<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, item: &'tcx hir::I // loan step is intended for things that have a data // flow dependent conditions. match item.node { - hir::ItemStatic(.., ref ex) | - hir::ItemConst(_, ref ex) => { - gather_loans::gather_loans_in_static_initializer(this, item.id, &ex); + hir::ItemStatic(.., ex) | + hir::ItemConst(_, ex) => { + gather_loans::gather_loans_in_static_initializer(this, ex); } _ => { } } @@ -161,25 +161,25 @@ pub struct AnalysisData<'a, 'tcx: 'a> { fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, sp: Span, id: ast::NodeId, attributes: &[ast::Attribute]) { debug!("borrowck_fn(id={})", id); - let body = this.tcx.map.expr(body_id); + let body = this.tcx.hir.body(body_id); if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) { this.with_temp_region_map(id, |this| { - mir::borrowck_mir(this, fk, decl, body, sp, id, attributes) + mir::borrowck_mir(this, id, attributes) }); } - let cfg = cfg::CFG::new(this.tcx, body); + let cfg = cfg::CFG::new(this.tcx, &body.value); let AnalysisData { all_loans, loans: loan_dfcx, move_data: flowed_moves } = - build_borrowck_dataflow_data(this, fk, decl, &cfg, body, sp, id); + build_borrowck_dataflow_data(this, &cfg, body_id); move_data::fragments::instrument_move_fragments(&flowed_moves.move_data, this.tcx, @@ -189,36 +189,31 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, &flowed_moves.move_data, id); - check_loans::check_loans(this, - &loan_dfcx, - &flowed_moves, - &all_loans[..], - id, - decl, - body); + check_loans::check_loans(this, &loan_dfcx, &flowed_moves, &all_loans[..], body); intravisit::walk_fn(this, fk, decl, body_id, sp, id); } fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, - fk: FnKind<'tcx>, - decl: &'tcx hir::FnDecl, cfg: &cfg::CFG, - body: &'tcx hir::Expr, - sp: Span, - id: ast::NodeId) + body_id: hir::BodyId) -> AnalysisData<'a, 'tcx> { // Check the body of fn items. let tcx = this.tcx; - let id_range = intravisit::compute_id_range_for_fn_body(fk, decl, body, sp, id, &tcx.map); + let body = tcx.hir.body(body_id); + let id_range = { + let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.hir); + visitor.visit_body(body); + visitor.result() + }; let (all_loans, move_data) = - gather_loans::gather_loans_in_fn(this, id, decl, body); + gather_loans::gather_loans_in_fn(this, body_id); let mut loan_dfcx = DataFlowContext::new(this.tcx, "borrowck", - Some(decl), + Some(body), cfg, LoanDataFlowOperator, id_range, @@ -235,7 +230,6 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, this.tcx, cfg, id_range, - decl, body); AnalysisData { all_loans: all_loans, @@ -247,7 +241,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, /// the `BorrowckCtxt` itself , e.g. the flowgraph visualizer. pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - fn_parts: FnParts<'tcx>, + body: hir::BodyId, cfg: &cfg::CFG) -> (BorrowckCtxt<'a, 'tcx>, AnalysisData<'a, 'tcx>) { @@ -263,16 +257,7 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( } }; - let body = tcx.map.expr(fn_parts.body); - - let dataflow_data = build_borrowck_dataflow_data(&mut bccx, - fn_parts.kind, - &fn_parts.decl, - cfg, - body, - fn_parts.span, - fn_parts.id); - + let dataflow_data = build_borrowck_dataflow_data(&mut bccx, cfg, body); (bccx, dataflow_data) } @@ -413,10 +398,10 @@ pub enum LoanPathElem<'tcx> { pub fn closure_to_block(closure_id: ast::NodeId, tcx: TyCtxt) -> ast::NodeId { - match tcx.map.get(closure_id) { + match tcx.hir.get(closure_id) { hir_map::NodeExpr(expr) => match expr.node { hir::ExprClosure(.., body_id, _) => { - body_id.node_id() + body_id.node_id } _ => { bug!("encountered non-closure id: {}", closure_id) @@ -555,7 +540,7 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option>> { // Errors // Errors that can occur -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] pub enum bckerr_code<'tcx> { err_mutbl, /// superscope, subscope, loan cause @@ -565,7 +550,7 @@ pub enum bckerr_code<'tcx> { // Combination of an error code and the categorization of the expression // that caused it -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] pub struct BckError<'tcx> { span: Span, cause: AliasableViolationKind, @@ -616,12 +601,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { _ => { } } - // General fallback. - let span = err.span.clone(); - let mut db = self.struct_span_err( - err.span, - &self.bckerr_to_string(&err)); - self.note_and_explain_bckerr(&mut db, err, span); + let mut db = self.bckerr_to_diag(&err); + self.note_and_explain_bckerr(&mut db, err); db.emit(); } @@ -700,10 +681,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { move_data::MoveExpr | move_data::MovePat => - (self.tcx.map.span(the_move.id), ""), + (self.tcx.hir.span(the_move.id), ""), move_data::Captured => - (match self.tcx.map.expect_expr(the_move.id).node { + (match self.tcx.hir.expect_expr(the_move.id).node { hir::ExprClosure(.., fn_decl_span) => fn_decl_span, ref r => bug!("Captured({}) maps to non-closure: {:?}", the_move.id, r), @@ -786,8 +767,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_err_with_code(s, msg, code); } - pub fn bckerr_to_string(&self, err: &BckError<'tcx>) -> String { - match err.code { + pub fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> { + let span = err.span.clone(); + let mut immutable_field = None; + + let msg = &match err.code { err_mutbl => { let descr = match err.cmt.note { mc::NoteClosureEnv(_) | mc::NoteUpvarRef(_) => { @@ -798,6 +782,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { format!("{} {}", err.cmt.mutbl.to_user_str(), self.cmt_to_string(&err.cmt)) + } Some(lp) => { format!("{} {} `{}`", @@ -822,6 +807,19 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { BorrowViolation(euv::AutoUnsafe) | BorrowViolation(euv::ForLoop) | BorrowViolation(euv::MatchDiscriminant) => { + // Check for this field's definition to see if it is an immutable reference + // and suggest making it mutable if that is the case. + immutable_field = err.cmt.get_field_name() + .and_then(|name| err.cmt.get_field(name)) + .and_then(|did| self.tcx.hir.as_local_node_id(did)) + .and_then(|nid| { + if let hir_map::Node::NodeField(ref field) = self.tcx.hir.get(nid) { + return self.suggest_mut_for_immutable(&field.ty) + .map(|msg| (self.tcx.hir.span(nid), msg)); + } + None + }); + format!("cannot borrow {} as mutable", descr) } BorrowViolation(euv::ClosureInvocation) => { @@ -845,13 +843,20 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { its contents can be safely reborrowed", descr) } + }; + + let mut db = self.struct_span_err(span, msg); + if let Some((span, msg)) = immutable_field { + db.span_label(span, &msg); } + db } pub fn report_aliasability_violation(&self, span: Span, kind: AliasableViolationKind, - cause: mc::AliasableReason) { + cause: mc::AliasableReason, + cmt: mc::cmt<'tcx>) { let mut is_closure = false; let prefix = match kind { MutabilityViolation => { @@ -897,10 +902,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { // happen for nested closures, so we know the enclosing // closure incorrectly accepts an `Fn` while it needs to // be `FnMut`. - span_help!(&mut err, self.tcx.map.span(id), + span_help!(&mut err, self.tcx.hir.span(id), "consider changing this to accept closures that implement `FnMut`"); } else { - span_help!(&mut err, self.tcx.map.span(id), + span_help!(&mut err, self.tcx.hir.span(id), "consider changing this closure to take self by mutable reference"); } err @@ -918,6 +923,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess, span, E0389, "{} in a `&` reference", prefix); e.span_label(span, &"assignment into an immutable reference"); + if let Some(nid) = cmt.get_arg_if_immutable(&self.tcx.hir) { + self.immutable_argument_should_be_mut(nid, &mut e); + } e } }; @@ -928,6 +936,55 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { err.emit(); } + /// Given a type, if it is an immutable reference, return a suggestion to make it mutable + fn suggest_mut_for_immutable(&self, pty: &hir::Ty) -> Option { + // Check wether the argument is an immutable reference + if let hir::TyRptr(lifetime, hir::MutTy { + mutbl: hir::Mutability::MutImmutable, + ref ty + }) = pty.node { + // Account for existing lifetimes when generating the message + if !lifetime.is_elided() { + if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(ty.span) { + if let Ok(lifetime_snippet) = self.tcx.sess.codemap() + .span_to_snippet(lifetime.span) { + return Some(format!("use `&{} mut {}` here to make mutable", + lifetime_snippet, + snippet)); + } + } + } else if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(pty.span) { + if snippet.starts_with("&") { + return Some(format!("use `{}` here to make mutable", + snippet.replace("&", "&mut "))); + } + } else { + bug!("couldn't find a snippet for span: {:?}", pty.span); + } + } + None + } + + fn immutable_argument_should_be_mut(&self, nid: ast::NodeId, db: &mut DiagnosticBuilder) { + let parent = self.tcx.hir.get_parent_node(nid); + let parent_node = self.tcx.hir.get(parent); + + // The parent node is like a fn + if let Some(fn_like) = FnLikeNode::from_node(parent_node) { + // `nid`'s parent's `Body` + let fn_body = self.tcx.hir.body(fn_like.body()); + // Get the position of `nid` in the arguments list + let arg_pos = fn_body.arguments.iter().position(|arg| arg.pat.id == nid); + if let Some(i) = arg_pos { + // The argument's `Ty` + let arg_ty = &fn_like.decl().inputs[i]; + if let Some(msg) = self.suggest_mut_for_immutable(&arg_ty) { + db.span_label(arg_ty.span, &msg); + } + } + } + } + fn report_out_of_scope_escaping_closure_capture(&self, err: &BckError<'tcx>, capture_span: Span) @@ -963,7 +1020,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { fn region_end_span(&self, region: &'tcx ty::Region) -> Option { match *region { ty::ReScope(scope) => { - match scope.span(&self.tcx.region_maps, &self.tcx.map) { + match scope.span(&self.tcx.region_maps, &self.tcx.hir) { Some(s) => { Some(s.end_point()) } @@ -976,13 +1033,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } } - pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>, - error_span: Span) { + pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>) { + let error_span = err.span.clone(); match err.code { err_mutbl => self.note_and_explain_mutbl_error(db, &err, &error_span), err_out_of_scope(super_scope, sub_scope, cause) => { let (value_kind, value_msg) = match err.cmt.cat { - mc::Categorization::Rvalue(_) => + mc::Categorization::Rvalue(..) => ("temporary value", "temporary value created here"), _ => ("borrowed value", "borrow occurs here") @@ -1076,6 +1133,17 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let Some(_) = statement_scope_span(self.tcx, super_scope) { db.note("consider using a `let` binding to increase its lifetime"); } + + + + match err.cmt.cat { + mc::Categorization::Rvalue(r, or) if r != or => { + db.note("\ +before rustc 1.16, this temporary lived longer - see issue #39283 \ +(https://github.com/rust-lang/rust/issues/39283)"); + } + _ => {} + } } err_borrowed_pointer_too_short(loan_scope, ptr_scope) => { @@ -1112,52 +1180,23 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { _ => bug!() }; if kind == ty::ClosureKind::Fn { - db.span_help(self.tcx.map.span(upvar_id.closure_expr_id), + db.span_help(self.tcx.hir.span(upvar_id.closure_expr_id), "consider changing this closure to take \ self by mutable reference"); } } _ => { - if let Categorization::Deref(ref inner_cmt, ..) = err.cmt.cat { - if let Categorization::Local(local_id) = inner_cmt.cat { - let parent = self.tcx.map.get_parent_node(local_id); - let opt_fn_decl = FnLikeNode::from_node(self.tcx.map.get(parent)) - .map(|fn_like| fn_like.decl()); - - if let Some(fn_decl) = opt_fn_decl { - if let Some(ref arg) = fn_decl.inputs.iter() - .find(|ref arg| arg.pat.id == local_id) { - if let hir::TyRptr( - opt_lifetime, - hir::MutTy{mutbl: hir::Mutability::MutImmutable, ref ty}) = - arg.ty.node { - if let Some(lifetime) = opt_lifetime { - if let Ok(snippet) = self.tcx.sess.codemap() - .span_to_snippet(ty.span) { - if let Ok(lifetime_snippet) = self.tcx.sess.codemap() - .span_to_snippet(lifetime.span) { - db.span_label(arg.ty.span, - &format!("use `&{} mut {}` \ - here to make mutable", - lifetime_snippet, - snippet)); - } - } - } - else if let Ok(snippet) = self.tcx.sess.codemap() - .span_to_snippet(arg.ty.span) { - if snippet.starts_with("&") { - db.span_label(arg.ty.span, - &format!("use `{}` here to make mutable", - snippet.replace("&", "&mut "))); - } - } - } - } + if let Categorization::Deref(..) = err.cmt.cat { + db.span_label(*error_span, &"cannot borrow as mutable"); + if let Some(local_id) = err.cmt.get_arg_if_immutable(&self.tcx.hir) { + self.immutable_argument_should_be_mut(local_id, db); + } else if let Categorization::Deref(ref inner_cmt, ..) = err.cmt.cat { + if let Categorization::Local(local_id) = inner_cmt.cat { + self.immutable_argument_should_be_mut(local_id, db); } } } else if let Categorization::Local(local_id) = err.cmt.cat { - let span = self.tcx.map.span(local_id); + let span = self.tcx.hir.span(local_id); if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { if snippet.starts_with("ref mut ") || snippet.starts_with("&mut ") { db.span_label(*error_span, &format!("cannot reborrow mutably")); @@ -1269,7 +1308,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { fn statement_scope_span(tcx: TyCtxt, region: &ty::Region) -> Option { match *region { ty::ReScope(scope) => { - match tcx.map.find(scope.node_id(&tcx.region_maps)) { + match tcx.hir.find(scope.node_id(&tcx.region_maps)) { Some(hir_map::NodeStmt(stmt)) => Some(stmt.span), _ => None } @@ -1318,11 +1357,11 @@ impl<'tcx> fmt::Debug for LoanPath<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.kind { LpVar(id) => { - write!(f, "$({})", ty::tls::with(|tcx| tcx.map.node_to_string(id))) + write!(f, "$({})", ty::tls::with(|tcx| tcx.hir.node_to_string(id))) } LpUpvar(ty::UpvarId{ var_id, closure_expr_id }) => { - let s = ty::tls::with(|tcx| tcx.map.node_to_string(var_id)); + let s = ty::tls::with(|tcx| tcx.hir.node_to_string(var_id)); write!(f, "$({} captured by id={})", s, closure_expr_id) } @@ -1350,11 +1389,11 @@ impl<'tcx> fmt::Display for LoanPath<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.kind { LpVar(id) => { - write!(f, "$({})", ty::tls::with(|tcx| tcx.map.node_to_user_string(id))) + write!(f, "$({})", ty::tls::with(|tcx| tcx.hir.node_to_user_string(id))) } LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => { - let s = ty::tls::with(|tcx| tcx.map.node_to_user_string(var_id)); + let s = ty::tls::with(|tcx| tcx.hir.node_to_user_string(var_id)); write!(f, "$({} captured by closure)", s) } diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 32bda5e116..2047a58f8e 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -490,7 +490,7 @@ impl<'a, 'tcx> MoveData<'tcx> { /// Adds a new record for a match of `base_lp`, downcast to /// variant `lp`, that occurs at location `pattern_id`. (One /// should be able to recover the span info from the - /// `pattern_id` and the ast_map, I think.) + /// `pattern_id` and the hir_map, I think.) pub fn add_variant_match(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, lp: Rc>, pattern_id: ast::NodeId, @@ -655,13 +655,12 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { tcx: TyCtxt<'a, 'tcx, 'tcx>, cfg: &cfg::CFG, id_range: IdRange, - decl: &hir::FnDecl, - body: &hir::Expr) + body: &hir::Body) -> FlowedMoveData<'a, 'tcx> { let mut dfcx_moves = DataFlowContext::new(tcx, "flowed_move_data_moves", - Some(decl), + Some(body), cfg, MoveDataFlowOperator, id_range, @@ -669,7 +668,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { let mut dfcx_assign = DataFlowContext::new(tcx, "flowed_move_data_assigns", - Some(decl), + Some(body), cfg, AssignDataFlowOperator, id_range, diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 1ff232da42..d3b22884a3 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -15,7 +15,7 @@ #![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/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![allow(non_camel_case_types)] diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml index 0e5cbce863..ff028c202a 100644 --- a/src/librustc_const_eval/Cargo.toml +++ b/src/librustc_const_eval/Cargo.toml @@ -11,7 +11,6 @@ crate-type = ["dylib"] [dependencies] arena = { path = "../libarena" } log = { path = "../liblog" } -serialize = { path = "../libserialize" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_const_math = { path = "../librustc_const_math" } @@ -19,4 +18,5 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } syntax = { path = "../libsyntax" } graphviz = { path = "../libgraphviz" } -syntax_pos = { path = "../libsyntax_pos" } \ No newline at end of file +syntax_pos = { path = "../libsyntax_pos" } +rustc_i128 = { path = "../librustc_i128" } diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index 23771f4bae..5476e99c94 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -17,24 +17,19 @@ use eval::{compare_const_vals}; use rustc_const_math::ConstInt; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::Idx; use pattern::{FieldPattern, Pattern, PatternKind}; use pattern::{PatternFoldable, PatternFolder}; -use rustc::hir::def::Def; use rustc::hir::def_id::DefId; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::hir::RangeEnd; +use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable}; -use rustc::hir; -use rustc::hir::def::CtorKind; -use rustc::hir::{Pat, PatKind}; +use rustc::mir::Field; use rustc::util::common::ErrorReported; -use syntax::ast::{self, DUMMY_NODE_ID}; -use syntax::codemap::Spanned; -use syntax::ptr::P; use syntax_pos::{Span, DUMMY_SP}; use arena::TypedArena; @@ -74,12 +69,6 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander { } } -pub const DUMMY_WILD_PAT: &'static Pat = &Pat { - id: DUMMY_NODE_ID, - node: PatKind::Wild, - span: DUMMY_SP -}; - impl<'tcx> Pattern<'tcx> { fn is_wildcard(&self) -> bool { match *self.kind { @@ -156,9 +145,13 @@ 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>, - /// A wild pattern with an error type - it exists to avoid having to normalize - /// associated types to get field types. - pub wild_pattern: &'a Pattern<'tcx>, + /// The module in which the match occurs. This is necessary for + /// checking inhabited-ness of types because whether a type is (visibly) + /// inhabited can depend on whether it was defined in the current module or + /// not. eg. `struct Foo { _private: ! }` cannot be seen to be empty + /// outside it's module and should not be matchable with an empty match + /// statement. + pub module: DefId, pub pattern_arena: &'a TypedArena>, pub byte_array_map: FxHashMap<*const Pattern<'tcx>, Vec<&'a Pattern<'tcx>>>, } @@ -166,27 +159,24 @@ pub struct MatchCheckCtxt<'a, 'tcx: 'a> { impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { pub fn create_and_enter( tcx: TyCtxt<'a, 'tcx, 'tcx>, + module: DefId, f: F) -> R where F: for<'b> FnOnce(MatchCheckCtxt<'b, 'tcx>) -> R { - let wild_pattern = Pattern { - ty: tcx.types.err, - span: DUMMY_SP, - kind: box PatternKind::Wild - }; - let pattern_arena = TypedArena::new(); f(MatchCheckCtxt { tcx: tcx, - wild_pattern: &wild_pattern, + module: module, pattern_arena: &pattern_arena, byte_array_map: FxHashMap(), }) } // convert a byte-string pattern to a list of u8 patterns. - fn lower_byte_str_pattern(&mut self, pat: &'a Pattern<'tcx>) -> Vec<&'a Pattern<'tcx>> { + fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Pattern<'tcx>> + where 'a: 'p + { let pattern_arena = &*self.pattern_arena; let tcx = self.tcx; self.byte_array_map.entry(pat).or_insert_with(|| { @@ -206,6 +196,28 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } }).clone() } + + fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { + if self.tcx.sess.features.borrow().never_type { + ty.is_uninhabited_from(self.module, self.tcx) + } else { + false + } + } + + fn is_variant_uninhabited(&self, + variant: &'tcx ty::VariantDef, + substs: &'tcx ty::subst::Substs<'tcx>) -> bool + { + if self.tcx.sess.features.borrow().never_type { + let forest = variant.uninhabited_from( + &mut FxHashSet::default(), self.tcx, substs, AdtKind::Enum + ); + forest.contains(self.tcx, self.module) + } else { + false + } + } } #[derive(Clone, Debug, PartialEq)] @@ -217,32 +229,41 @@ pub enum Constructor { Variant(DefId), /// Literal values. ConstantValue(ConstVal), - /// Ranges of literal values (2..5). - ConstantRange(ConstVal, ConstVal), + /// Ranges of literal values (`2...5` and `2..5`). + ConstantRange(ConstVal, ConstVal, RangeEnd), /// Array patterns of length n. Slice(usize), } impl<'tcx> Constructor { - fn variant_for_adt(&self, adt: &'tcx ty::AdtDef) -> &'tcx ty::VariantDef { + fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize { match self { - &Variant(vid) => adt.variant_with_id(vid), + &Variant(vid) => adt.variant_index_with_id(vid), &Single => { assert_eq!(adt.variants.len(), 1); - &adt.variants[0] + 0 } _ => bug!("bad constructor {:?} for adt {:?}", self, adt) } } } -#[derive(Clone, PartialEq)] -pub enum Usefulness { +#[derive(Clone)] +pub enum Usefulness<'tcx> { Useful, - UsefulWithWitness(Vec), + UsefulWithWitness(Vec>), NotUseful } +impl<'tcx> Usefulness<'tcx> { + fn is_useful(&self) -> bool { + match *self { + NotUseful => false, + _ => true + } + } +} + #[derive(Copy, Clone)] pub enum WitnessPreference { ConstructWitness, @@ -255,39 +276,31 @@ struct PatternContext<'tcx> { max_slice_length: usize, } - -fn const_val_to_expr(value: &ConstVal) -> P { - let node = match value { - &ConstVal::Bool(b) => ast::LitKind::Bool(b), - _ => bug!() - }; - P(hir::Expr { - id: DUMMY_NODE_ID, - node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })), - span: DUMMY_SP, - attrs: ast::ThinVec::new(), - }) -} - /// A stack of patterns in reverse order of construction -#[derive(Clone, PartialEq, Eq)] -pub struct Witness(Vec>); +#[derive(Clone)] +pub struct Witness<'tcx>(Vec>); -impl Witness { - pub fn single_pattern(&self) -> &Pat { +impl<'tcx> Witness<'tcx> { + pub fn single_pattern(&self) -> &Pattern<'tcx> { assert_eq!(self.0.len(), 1); &self.0[0] } - fn push_wild_constructor<'a, 'tcx>( + fn push_wild_constructor<'a>( mut self, cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor, ty: Ty<'tcx>) -> Self { - let arity = constructor_arity(cx, ctor, ty); - self.0.extend(repeat(DUMMY_WILD_PAT).take(arity).map(|p| P(p.clone()))); + let sub_pattern_tys = constructor_sub_pattern_tys(cx, ctor, ty); + self.0.extend(sub_pattern_tys.into_iter().map(|ty| { + Pattern { + ty: ty, + span: DUMMY_SP, + kind: box PatternKind::Wild, + } + })); self.apply_constructor(cx, ctor, ty) } @@ -305,7 +318,7 @@ impl Witness { /// /// left_ty: struct X { a: (bool, &'static str), b: usize} /// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 } - fn apply_constructor<'a, 'tcx>( + fn apply_constructor<'a>( mut self, cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, @@ -318,111 +331,114 @@ impl Witness { let mut pats = self.0.drain(len-arity..).rev(); match ty.sty { - ty::TyTuple(..) => PatKind::Tuple(pats.collect(), None), - - ty::TyAdt(adt, _) => { - let v = ctor.variant_for_adt(adt); - let qpath = hir::QPath::Resolved(None, P(hir::Path { - span: DUMMY_SP, - global: false, - def: Def::Err, - segments: vec![hir::PathSegment::from_name(v.name)].into(), - })); - match v.ctor_kind { - CtorKind::Fictive => { - let field_pats: hir::HirVec<_> = v.fields.iter() - .zip(pats) - .filter(|&(_, ref pat)| pat.node != PatKind::Wild) - .map(|(field, pat)| Spanned { - span: DUMMY_SP, - node: hir::FieldPat { - name: field.name, - pat: pat, - is_shorthand: false, - } - }).collect(); - let has_more_fields = field_pats.len() < arity; - PatKind::Struct(qpath, field_pats, has_more_fields) + ty::TyAdt(..) | + ty::TyTuple(..) => { + let pats = pats.enumerate().map(|(i, p)| { + FieldPattern { + field: Field::new(i), + pattern: p } - CtorKind::Fn => { - PatKind::TupleStruct(qpath, pats.collect(), None) + }).collect(); + + if let ty::TyAdt(adt, substs) = ty.sty { + if adt.variants.len() > 1 { + PatternKind::Variant { + adt_def: adt, + substs: substs, + variant_index: ctor.variant_index_for_adt(adt), + subpatterns: pats + } + } else { + PatternKind::Leaf { subpatterns: pats } } - CtorKind::Const => PatKind::Path(qpath) + } else { + PatternKind::Leaf { subpatterns: pats } } } - ty::TyRef(_, ty::TypeAndMut { mutbl, .. }) => { - PatKind::Ref(pats.nth(0).unwrap(), mutbl) + ty::TyRef(..) => { + PatternKind::Deref { subpattern: pats.nth(0).unwrap() } } ty::TySlice(_) | ty::TyArray(..) => { - PatKind::Slice(pats.collect(), None, hir::HirVec::new()) + PatternKind::Slice { + prefix: pats.collect(), + slice: None, + suffix: vec![] + } } _ => { match *ctor { - ConstantValue(ref v) => PatKind::Lit(const_val_to_expr(v)), - _ => PatKind::Wild, + ConstantValue(ref v) => PatternKind::Constant { value: v.clone() }, + _ => PatternKind::Wild, } } } }; - self.0.push(P(hir::Pat { - id: DUMMY_NODE_ID, - node: pat, - span: DUMMY_SP - })); + self.0.push(Pattern { + ty: ty, + span: DUMMY_SP, + kind: Box::new(pat), + }); self } } -/// Return the set of constructors from the same type as the first column of `matrix`, -/// that are matched only by wildcard patterns from that first column. -/// -/// Therefore, if there is some pattern that is unmatched by `matrix`, it will -/// still be unmatched if the first constructor is replaced by any of the constructors -/// in the return value. -fn missing_constructors(cx: &mut MatchCheckCtxt, - matrix: &Matrix, - pcx: PatternContext) -> Vec { - let used_constructors: Vec = - matrix.0.iter() - .flat_map(|row| pat_constructors(cx, row[0], pcx).unwrap_or(vec![])) - .collect(); - debug!("used_constructors = {:?}", used_constructors); - all_constructors(cx, pcx).into_iter() - .filter(|c| !used_constructors.contains(c)) - .collect() -} - /// This determines the set of all possible constructors of a pattern matching /// values of type `left_ty`. For vectors, this would normally be an infinite set +/// 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. /// -/// but is instead bounded by the maximum fixed length of slice patterns in -/// the column of patterns being analyzed. -fn all_constructors(_cx: &mut MatchCheckCtxt, pcx: PatternContext) -> Vec { +/// 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>, + pcx: PatternContext<'tcx>) -> Vec +{ + debug!("all_constructors({:?})", pcx.ty); match pcx.ty.sty { ty::TyBool => [true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(), - ty::TySlice(_) => - (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect(), - ty::TyArray(_, length) => vec![Slice(length)], - ty::TyAdt(def, _) if def.is_enum() && def.variants.len() > 1 => - def.variants.iter().map(|v| Variant(v.did)).collect(), - _ => vec![Single] + ty::TySlice(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::TyArray(ref sub_ty, length) => { + if length > 0 && cx.is_uninhabited(sub_ty) { + vec![] + } else { + vec![Slice(length)] + } + } + ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => { + def.variants.iter() + .filter(|v| !cx.is_variant_uninhabited(v, substs)) + .map(|v| Variant(v.did)) + .collect() + } + _ => { + if cx.is_uninhabited(pcx.ty) { + vec![] + } else { + vec![Single] + } + } } } -fn max_slice_length<'a, 'tcx, I>( +fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( _cx: &mut MatchCheckCtxt<'a, 'tcx>, patterns: I) -> usize - where I: Iterator> + where I: Iterator> { // The exhaustiveness-checking paper does not include any details on // checking variable-length slice patterns. However, they are matched @@ -513,6 +529,12 @@ fn max_slice_length<'a, 'tcx, I>( } /// 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: +/// (0) We don't exit early if the pattern matrix has zero rows. We just +/// continue to recurse over columns. +/// (1) all_constructors will only return constructors that are statically +/// possible. eg. it will only return Ok for Result /// /// Whether a vector `v` of patterns is 'useful' in relation to a set of such /// vectors `m` is defined as there being a set of inputs that will match `v` @@ -522,31 +544,31 @@ fn max_slice_length<'a, 'tcx, I>( /// relation to preceding patterns, it is not reachable) and exhaustiveness /// checking (if a wildcard pattern is useful in relation to a matrix, the /// matrix isn't exhaustive). -/// -/// Note: is_useful doesn't work on empty types, as the paper notes. -/// So it assumes that v is non-empty. -pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, - matrix: &Matrix<'a, 'tcx>, - v: &[&'a Pattern<'tcx>], +pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, + matrix: &Matrix<'p, 'tcx>, + v: &[&'p Pattern<'tcx>], witness: WitnessPreference) - -> Usefulness { + -> Usefulness<'tcx> { let &Matrix(ref rows) = matrix; debug!("is_useful({:?}, {:?})", matrix, v); - if rows.is_empty() { - return match witness { - ConstructWitness => UsefulWithWitness(vec![Witness( - repeat(DUMMY_WILD_PAT).take(v.len()).map(|p| P(p.clone())).collect() - )]), - LeaveOutWitness => Useful - }; - } - if rows[0].is_empty() { - return NotUseful; - } - let &Matrix(ref rows) = matrix; - assert!(rows.iter().all(|r| r.len() == v.len())); + // The base case. We are pattern-matching on () and the return value is + // based on whether our matrix has a row or not. + // NOTE: This could potentially be optimized by checking rows.is_empty() + // first and then, if v is non-empty, the return value is based on whether + // the type of the tuple we're checking is inhabited or not. + if v.is_empty() { + return if rows.is_empty() { + match witness { + ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]), + LeaveOutWitness => Useful, + } + } else { + NotUseful + } + }; + assert!(rows.iter().all(|r| r.len() == v.len())); let pcx = PatternContext { ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error()) @@ -560,15 +582,47 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, debug!("is_useful - expanding constructors: {:?}", constructors); constructors.into_iter().map(|c| is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) - ).find(|result| result != &NotUseful).unwrap_or(NotUseful) + ).find(|result| result.is_useful()).unwrap_or(NotUseful) } else { debug!("is_useful - expanding wildcard"); - let constructors = missing_constructors(cx, matrix, pcx); - debug!("is_useful - missing_constructors = {:?}", constructors); - if constructors.is_empty() { - all_constructors(cx, pcx).into_iter().map(|c| { + + let used_ctors: Vec = rows.iter().flat_map(|row| { + pat_constructors(cx, row[0], pcx).unwrap_or(vec![]) + }).collect(); + debug!("used_ctors = {:?}", used_ctors); + 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 + // from the first column. + // + // Therefore, if there is some pattern that is unmatched by `matrix`, + // it will still be unmatched if the first constructor is replaced by + // any of the constructors in `missing_ctors` + // + // However, if our scrutinee is *privately* an empty enum, we + // must treat it as though it had an "unknown" constructor (in + // that case, all other patterns obviously can't be variants) + // to avoid exposing its emptyness. See the `match_privately_empty` + // test for details. + // + // FIXME: currently the only way I know of something can + // be a privately-empty enum is when the never_type + // 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); + debug!("missing_ctors={:?} is_privately_empty={:?}", missing_ctors, + is_privately_empty); + if missing_ctors.is_empty() && !is_privately_empty { + all_ctors.into_iter().map(|c| { is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) - }).find(|result| result != &NotUseful).unwrap_or(NotUseful) + }).find(|result| result.is_useful()).unwrap_or(NotUseful) } else { let matrix = rows.iter().filter_map(|r| { if r[0].is_wildcard() { @@ -580,11 +634,25 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, match is_useful(cx, &matrix, &v[1..], witness) { UsefulWithWitness(pats) => { let cx = &*cx; - UsefulWithWitness(pats.into_iter().flat_map(|witness| { - constructors.iter().map(move |ctor| { - witness.clone().push_wild_constructor(cx, ctor, pcx.ty) - }) - }).collect()) + let new_witnesses = if used_ctors.is_empty() { + // All constructors are unused. Add wild patterns + // rather than each individual constructor + pats.into_iter().map(|mut witness| { + witness.0.push(Pattern { + ty: pcx.ty, + span: DUMMY_SP, + kind: box PatternKind::Wild, + }); + witness + }).collect() + } else { + pats.into_iter().flat_map(|witness| { + missing_ctors.iter().map(move |ctor| { + witness.clone().push_wild_constructor(cx, ctor, pcx.ty) + }) + }).collect() + }; + UsefulWithWitness(new_witnesses) } result => result } @@ -592,19 +660,28 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, } } -fn is_useful_specialized<'a, 'tcx>( +fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>( cx: &mut MatchCheckCtxt<'a, 'tcx>, - &Matrix(ref m): &Matrix<'a, 'tcx>, - v: &[&'a Pattern<'tcx>], + &Matrix(ref m): &Matrix<'p, 'tcx>, + v: &[&'p Pattern<'tcx>], ctor: Constructor, lty: Ty<'tcx>, - witness: WitnessPreference) -> Usefulness + witness: WitnessPreference) -> Usefulness<'tcx> { - let arity = constructor_arity(cx, &ctor, lty); + 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| { + Pattern { + ty: ty, + span: DUMMY_SP, + kind: box PatternKind::Wild, + } + }).collect(); + let wild_patterns: Vec<_> = wild_patterns_owned.iter().collect(); let matrix = Matrix(m.iter().flat_map(|r| { - specialize(cx, &r[..], &ctor, 0, arity) + specialize(cx, &r[..], &ctor, &wild_patterns) }).collect()); - match specialize(cx, v, &ctor, 0, arity) { + match specialize(cx, v, &ctor, &wild_patterns) { Some(v) => match is_useful(cx, &matrix, &v[..], witness) { UsefulWithWitness(witnesses) => UsefulWithWitness( witnesses.into_iter() @@ -639,8 +716,8 @@ fn pat_constructors(_cx: &mut MatchCheckCtxt, Some(vec![Variant(adt_def.variants[variant_index].did)]), PatternKind::Constant { ref value } => Some(vec![ConstantValue(value.clone())]), - PatternKind::Range { ref lo, ref hi } => - Some(vec![ConstantRange(lo.clone(), hi.clone())]), + PatternKind::Range { ref lo, ref hi, ref end } => + Some(vec![ConstantRange(lo.clone(), hi.clone(), end.clone())]), PatternKind::Array { .. } => match pcx.ty.sty { ty::TyArray(_, length) => Some(vec![Slice(length)]), _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty) @@ -665,7 +742,6 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize debug!("constructor_arity({:?}, {:?})", ctor, ty); match ty.sty { ty::TyTuple(ref fs) => fs.len(), - ty::TyBox(_) => 1, ty::TySlice(..) | ty::TyArray(..) => match *ctor { Slice(length) => length, ConstantValue(_) => 0, @@ -673,12 +749,50 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize }, ty::TyRef(..) => 1, ty::TyAdt(adt, _) => { - ctor.variant_for_adt(adt).fields.len() + adt.variants[ctor.variant_index_for_adt(adt)].fields.len() } _ => 0 } } +/// This computes the types of the sub patterns that a constructor should be +/// expanded to. +/// +/// For instance, a tuple pattern (43u32, 'a') has sub pattern types [u32, char]. +fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, + ctor: &Constructor, + ty: Ty<'tcx>) -> Vec> +{ + 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 { + Slice(length) => repeat(ty).take(length).collect(), + ConstantValue(_) => vec![], + _ => bug!("bad slice pattern {:?} {:?}", ctor, ty) + }, + ty::TyRef(_, ref ty_and_mut) => vec![ty_and_mut.ty], + ty::TyAdt(adt, substs) => { + adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| { + let is_visible = adt.is_enum() + || field.vis.is_accessible_from(cx.module, cx.tcx); + if is_visible { + field.ty(cx.tcx, substs) + } else { + // Treat all non-visible fields as nil. They + // can't appear in any other pattern from + // this match (because they are private), + // so their type does not matter - but + // we don't want to know they are + // uninhabited. + cx.tcx.mk_nil() + } + }).collect() + } + _ => vec![], + } +} + fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span, ctor: &Constructor, prefix: &[Pattern], @@ -717,32 +831,47 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span, fn range_covered_by_constructor(tcx: TyCtxt, span: Span, ctor: &Constructor, - from: &ConstVal, to: &ConstVal) + from: &ConstVal, to: &ConstVal, + end: RangeEnd) -> Result { - let (c_from, c_to) = match *ctor { - ConstantValue(ref value) => (value, value), - ConstantRange(ref from, ref to) => (from, to), - Single => return Ok(true), - _ => bug!() - }; - let cmp_from = compare_const_vals(tcx, span, c_from, from)?; - let cmp_to = compare_const_vals(tcx, span, c_to, to)?; - Ok(cmp_from != Ordering::Less && cmp_to != Ordering::Greater) + let cmp_from = |c_from| Ok(compare_const_vals(tcx, span, c_from, from)? != Ordering::Less); + let cmp_to = |c_to| compare_const_vals(tcx, span, c_to, to); + match *ctor { + ConstantValue(ref value) => { + let to = cmp_to(value)?; + let end = (to != Ordering::Greater) || + (end == RangeEnd::Excluded && to == Ordering::Equal); + Ok(cmp_from(value)? && end) + }, + ConstantRange(ref from, ref to, RangeEnd::Included) => { + let to = cmp_to(to)?; + let end = (to != Ordering::Greater) || + (end == RangeEnd::Excluded && to == Ordering::Equal); + Ok(cmp_from(from)? && end) + }, + ConstantRange(ref from, ref to, RangeEnd::Excluded) => { + let to = cmp_to(to)?; + let end = (to == Ordering::Less) || + (end == RangeEnd::Excluded && to == Ordering::Equal); + Ok(cmp_from(from)? && end) + } + Single => Ok(true), + _ => bug!(), + } } -fn patterns_for_variant<'a, 'tcx>( - cx: &mut MatchCheckCtxt<'a, 'tcx>, - subpatterns: &'a [FieldPattern<'tcx>], - arity: usize) - -> Vec<&'a Pattern<'tcx>> +fn patterns_for_variant<'p, 'a: 'p, 'tcx: 'a>( + subpatterns: &'p [FieldPattern<'tcx>], + wild_patterns: &[&'p Pattern<'tcx>]) + -> Vec<&'p Pattern<'tcx>> { - let mut result = vec![cx.wild_pattern; arity]; + let mut result = wild_patterns.to_owned(); for subpat in subpatterns { result[subpat.field.index()] = &subpat.pattern; } - debug!("patterns_for_variant({:?}, {:?}) = {:?}", subpatterns, arity, result); + debug!("patterns_for_variant({:?}, {:?}) = {:?}", subpatterns, wild_patterns, result); result } @@ -754,35 +883,41 @@ fn patterns_for_variant<'a, 'tcx>( /// different patterns. /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing /// fields filled with wild patterns. -fn specialize<'a, 'tcx>( +fn specialize<'p, 'a: 'p, 'tcx: 'a>( cx: &mut MatchCheckCtxt<'a, 'tcx>, - r: &[&'a Pattern<'tcx>], - constructor: &Constructor, col: usize, arity: usize) - -> Option>> + r: &[&'p Pattern<'tcx>], + constructor: &Constructor, + wild_patterns: &[&'p Pattern<'tcx>]) + -> Option>> { - let pat = &r[col]; + let pat = &r[0]; let head: Option> = match *pat.kind { - PatternKind::Binding { .. } | PatternKind::Wild => - Some(vec![cx.wild_pattern; arity]), + PatternKind::Binding { .. } | PatternKind::Wild => { + Some(wild_patterns.to_owned()) + }, - PatternKind::Variant { adt_def, variant_index, ref subpatterns } => { + PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { let ref variant = adt_def.variants[variant_index]; if *constructor == Variant(variant.did) { - Some(patterns_for_variant(cx, subpatterns, arity)) + Some(patterns_for_variant(subpatterns, wild_patterns)) } else { None } } - PatternKind::Leaf { ref subpatterns } => Some(patterns_for_variant(cx, subpatterns, arity)), - PatternKind::Deref { ref subpattern } => Some(vec![subpattern]), + PatternKind::Leaf { ref subpatterns } => { + Some(patterns_for_variant(subpatterns, wild_patterns)) + } + PatternKind::Deref { ref subpattern } => { + Some(vec![subpattern]) + } PatternKind::Constant { ref value } => { match *constructor { Slice(..) => match *value { ConstVal::ByteStr(ref data) => { - if arity == data.len() { + if wild_patterns.len() == data.len() { Some(cx.lower_byte_str_pattern(pat)) } else { None @@ -793,7 +928,7 @@ fn specialize<'a, 'tcx>( }, _ => { match range_covered_by_constructor( - cx.tcx, pat.span, constructor, value, value + cx.tcx, pat.span, constructor, value, value, RangeEnd::Included ) { Ok(true) => Some(vec![]), Ok(false) => None, @@ -803,9 +938,9 @@ fn specialize<'a, 'tcx>( } } - PatternKind::Range { ref lo, ref hi } => { + PatternKind::Range { ref lo, ref hi, ref end } => { match range_covered_by_constructor( - cx.tcx, pat.span, constructor, lo, hi + cx.tcx, pat.span, constructor, lo, hi, end.clone() ) { Ok(true) => Some(vec![]), Ok(false) => None, @@ -818,11 +953,14 @@ fn specialize<'a, 'tcx>( match *constructor { Slice(..) => { let pat_len = prefix.len() + suffix.len(); - if let Some(slice_count) = arity.checked_sub(pat_len) { + if let Some(slice_count) = wild_patterns.len().checked_sub(pat_len) { if slice_count == 0 || slice.is_some() { Some( prefix.iter().chain( - repeat(cx.wild_pattern).take(slice_count).chain( + wild_patterns.iter().map(|p| *p) + .skip(prefix.len()) + .take(slice_count) + .chain( suffix.iter() )).collect()) } else { @@ -846,11 +984,10 @@ fn specialize<'a, 'tcx>( } } }; - debug!("specialize({:?}, {:?}) = {:?}", r[col], arity, head); + debug!("specialize({:?}, {:?}) = {:?}", r[0], wild_patterns, head); head.map(|mut head| { - head.extend_from_slice(&r[..col]); - head.extend_from_slice(&r[col + 1..]); + head.extend_from_slice(&r[1 ..]); head }) } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 786b59e818..9b30946c0b 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -9,11 +9,10 @@ // except according to those terms. use _match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful}; -use _match::{DUMMY_WILD_PAT}; use _match::Usefulness::*; use _match::WitnessPreference::*; -use pattern::{Pattern, PatternContext, PatternError}; +use pattern::{Pattern, PatternContext, PatternError, PatternKind}; use eval::report_const_eval_err; @@ -25,57 +24,36 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization::{cmt}; use rustc::session::Session; use rustc::traits::Reveal; -use rustc::ty::{self, TyCtxt}; -use rustc_errors::DiagnosticBuilder; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::lint; +use rustc_errors::{Diagnostic, Level, DiagnosticBuilder}; use rustc::hir::def::*; use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; -use rustc::hir::print::pat_to_string; use rustc::hir::{self, Pat, PatKind}; use rustc_back::slice; use syntax::ast; use syntax::ptr::P; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; struct OuterVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_expr(&mut self, _expr: &'tcx hir::Expr) { - return // const, static and N in [T; N] - shouldn't contain anything - } - - fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::ConstTraitItem(..) = item.node { - return // nothing worth match checking in a constant - } else { - intravisit::walk_trait_item(self, item); - } - } - - fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(..) = item.node { - return // nothing worth match checking in a constant - } else { - intravisit::walk_impl_item(self, item); - } + NestedVisitorMap::OnlyBodies(&self.tcx.hir) } fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::ExprId, s: Span, id: ast::NodeId) { - if let FnKind::Closure(..) = fk { - span_bug!(s, "check_match: closure outside of function") - } + b: hir::BodyId, s: Span, id: ast::NodeId) { + intravisit::walk_fn(self, fk, fd, b, s, id); MatchVisitor { tcx: self.tcx, + tables: self.tcx.body_tables(b), param_env: &ty::ParameterEnvironment::for_item(self.tcx, id) - }.visit_fn(fk, fd, b, s, id); + }.visit_body(self.tcx.hir.body(b)); } } @@ -91,12 +69,13 @@ fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> Diagn struct MatchVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, param_env: &'a ty::ParameterEnvironment<'tcx> } impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None } fn visit_expr(&mut self, ex: &'tcx hir::Expr) { @@ -104,7 +83,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { match ex.node { hir::ExprMatch(ref scrut, ref arms, source) => { - self.check_match(scrut, arms, source, ex.span); + self.check_match(scrut, arms, source); } _ => {} } @@ -119,13 +98,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { self.check_patterns(false, slice::ref_slice(&loc.pat)); } - fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::ExprId, s: Span, n: ast::NodeId) { - intravisit::walk_fn(self, fk, fd, b, s, n); + fn visit_body(&mut self, body: &'tcx hir::Body) { + intravisit::walk_body(self, body); - for input in &fd.inputs { - self.check_irrefutable(&input.pat, true); - self.check_patterns(false, slice::ref_slice(&input.pat)); + for arg in &body.arguments { + self.check_irrefutable(&arg.pat, true); + self.check_patterns(false, slice::ref_slice(&arg.pat)); } } } @@ -141,13 +119,6 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn report_inlining_errors(&self, patcx: PatternContext, pat_span: Span) { for error in patcx.errors { match error { - PatternError::BadConstInPattern(span, def_id) => { - self.tcx.sess.span_err( - span, - &format!("constants of the type `{}` \ - cannot be used in patterns", - self.tcx.item_path_str(def_id))); - } PatternError::StaticInPattern(span) => { span_err!(self.tcx.sess, span, E0158, "statics cannot be referenced in patterns"); @@ -163,8 +134,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { &self, scrut: &hir::Expr, arms: &[hir::Arm], - source: hir::MatchSource, - span: Span) + source: hir::MatchSource) { for arm in arms { // First, check legality of move bindings. @@ -182,12 +152,13 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { } } - MatchCheckCtxt::create_and_enter(self.tcx, |ref mut cx| { + let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id)); + MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| { let mut have_errors = false; let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| ( arm.pats.iter().map(|pat| { - let mut patcx = PatternContext::new(self.tcx); + let mut patcx = PatternContext::new(self.tcx, self.tables); let pattern = expand_pattern(cx, patcx.lower_pattern(&pat)); if !patcx.errors.is_empty() { self.report_inlining_errors(patcx, pat.span); @@ -206,17 +177,23 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Fourth, check for unreachable arms. check_arms(cx, &inlined_arms, source); - // Finally, check if the whole match expression is exhaustive. - // Check for empty enum, because is_useful only works on inhabited types. - let pat_ty = self.tcx.tables().node_id_to_type(scrut.id); + // Then, if the match has no arms, check whether the scrutinee + // is uninhabited. + let pat_ty = self.tables.node_id_to_type(scrut.id); + let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id)); if inlined_arms.is_empty() { - if !pat_ty.is_uninhabited(Some(scrut.id), self.tcx) { + let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type { + pat_ty.is_uninhabited_from(module, self.tcx) + } else { + self.conservative_is_uninhabited(pat_ty) + }; + if !scrutinee_is_uninhabited { // We know the type is inhabited, so this must be wrong - let mut err = create_e0004(self.tcx.sess, span, + let mut err = create_e0004(self.tcx.sess, scrut.span, format!("non-exhaustive patterns: type {} \ is non-empty", pat_ty)); - span_help!(&mut err, span, + span_help!(&mut err, scrut.span, "Please ensure that all possible cases are being handled; \ possibly adding wildcards or more match arms."); err.emit(); @@ -231,10 +208,20 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { .flat_map(|arm| &arm.0) .map(|pat| vec![pat.0]) .collect(); - check_exhaustive(cx, scrut.span, &matrix, source); + let scrut_ty = self.tables.node_id_to_type(scrut.id); + check_exhaustive(cx, scrut_ty, scrut.span, &matrix, source); }) } + 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(), + _ => false + } + } + fn check_irrefutable(&self, pat: &Pat, is_fn_arg: bool) { let origin = if is_fn_arg { "function argument" @@ -242,19 +229,27 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { "local binding" }; - MatchCheckCtxt::create_and_enter(self.tcx, |ref mut cx| { - let mut patcx = PatternContext::new(self.tcx); + let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(pat.id)); + MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| { + let mut patcx = PatternContext::new(self.tcx, self.tables); + let pattern = patcx.lower_pattern(pat); + let pattern_ty = pattern.ty; let pats : Matrix = vec![vec![ - expand_pattern(cx, patcx.lower_pattern(pat)) + expand_pattern(cx, pattern) ]].into_iter().collect(); - let witness = match is_useful(cx, &pats, &[cx.wild_pattern], ConstructWitness) { + let wild_pattern = Pattern { + ty: pattern_ty, + span: DUMMY_SP, + kind: box PatternKind::Wild, + }; + let witness = match is_useful(cx, &pats, &[&wild_pattern], ConstructWitness) { UsefulWithWitness(witness) => witness, NotUseful => return, Useful => bug!() }; - let pattern_string = pat_to_string(witness[0].single_pattern()); + let pattern_string = witness[0].single_pattern().to_string(); let mut diag = struct_span_err!( self.tcx.sess, pat.span, E0005, "refutable pattern in {}: `{}` not covered", @@ -269,7 +264,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), _, name, None) = p.node { - let pat_ty = cx.tcx.tables().pat_ty(p); + let pat_ty = cx.tables.pat_ty(p); if let ty::TyAdt(edef, _) = pat_ty.sty { if edef.is_enum() && edef.variants.iter().any(|variant| { variant.name == name.node && variant.ctor_kind == CtorKind::Const @@ -312,7 +307,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let mut seen = Matrix::empty(); let mut catchall = None; let mut printed_if_let_err = false; - for &(ref pats, guard) in arms { + for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() { for &(pat, hir_pat) in pats { let v = vec![pat]; @@ -341,34 +336,46 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let &(ref first_arm_pats, _) = &arms[0]; let first_pat = &first_arm_pats[0]; let span = first_pat.0.span; - struct_span_err!(cx.tcx.sess, span, E0165, - "irrefutable while-let pattern") - .span_label(span, &format!("irrefutable pattern")) - .emit(); - }, - hir::MatchSource::ForLoopDesugar => { - // this is a bug, because on `match iter.next()` we cover - // `Some()` and `None`. It's impossible to have an unreachable - // pattern - // (see libsyntax/ext/expand.rs for the full expansion of a for loop) - span_bug!(pat.span, "unreachable for-loop pattern") + // check which arm we're on. + match arm_index { + // The arm with the user-specified pattern. + 0 => { + let mut diagnostic = Diagnostic::new(Level::Warning, + "unreachable pattern"); + diagnostic.set_span(pat.span); + cx.tcx.sess.add_lint_diagnostic( + lint::builtin::UNREACHABLE_PATTERNS, + hir_pat.id, diagnostic); + }, + // The arm with the wildcard pattern. + 1 => { + struct_span_err!(cx.tcx.sess, span, E0165, + "irrefutable while-let pattern") + .span_label(span, &format!("irrefutable pattern")) + .emit(); + }, + _ => bug!(), + } }, + hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { - let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001, - "unreachable pattern"); - err.span_label(pat.span, &"this is an unreachable pattern"); + let mut diagnostic = Diagnostic::new(Level::Warning, + "unreachable pattern"); + diagnostic.set_span(pat.span); // if we had a catchall pattern, hint at that if let Some(catchall) = catchall { - err.span_note(catchall, "this pattern matches any value"); + diagnostic.span_label(pat.span, &"this is an unreachable pattern"); + diagnostic.span_note(catchall, "this pattern matches any value"); } - err.emit(); + cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS, + hir_pat.id, diagnostic); }, - hir::MatchSource::TryDesugar => { - span_bug!(pat.span, "unreachable try pattern") - }, + // Unreachable patterns in try expressions occur when one of the arms + // are an uninhabited type. Which is OK. + hir::MatchSource::TryDesugar => {} } } Useful => (), @@ -385,27 +392,33 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, } fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, + scrut_ty: Ty<'tcx>, sp: Span, matrix: &Matrix<'a, 'tcx>, source: hir::MatchSource) { - match is_useful(cx, matrix, &[cx.wild_pattern], ConstructWitness) { + let wild_pattern = Pattern { + ty: scrut_ty, + span: DUMMY_SP, + kind: box PatternKind::Wild, + }; + match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) { UsefulWithWitness(pats) => { let witnesses = if pats.is_empty() { - vec![DUMMY_WILD_PAT] + vec![&wild_pattern] } else { pats.iter().map(|w| w.single_pattern()).collect() }; match source { hir::MatchSource::ForLoopDesugar => { // `witnesses[0]` has the form `Some()`, peel off the `Some` - let witness = match witnesses[0].node { - PatKind::TupleStruct(_, ref pats, _) => match &pats[..] { - &[ref pat] => &**pat, + let witness = match *witnesses[0].kind { + PatternKind::Variant { ref subpatterns, .. } => match &subpatterns[..] { + &[ref pat] => &pat.pattern, _ => bug!(), }, _ => bug!(), }; - let pattern_string = pat_to_string(witness); + let pattern_string = witness.to_string(); struct_span_err!(cx.tcx.sess, sp, E0297, "refutable pattern in `for` loop binding: \ `{}` not covered", @@ -414,24 +427,23 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, .emit(); }, _ => { - let pattern_strings: Vec<_> = witnesses.iter().map(|w| { - pat_to_string(w) - }).collect(); const LIMIT: usize = 3; - let joined_patterns = match pattern_strings.len() { + let joined_patterns = match witnesses.len() { 0 => bug!(), - 1 => format!("`{}`", pattern_strings[0]), + 1 => format!("`{}`", witnesses[0]), 2...LIMIT => { - let (tail, head) = pattern_strings.split_last().unwrap(); - format!("`{}`", head.join("`, `") + "` and `" + tail) + let (tail, head) = witnesses.split_last().unwrap(); + let head: Vec<_> = head.iter().map(|w| w.to_string()).collect(); + format!("`{}` and `{}`", head.join("`, `"), tail) }, _ => { - let (head, tail) = pattern_strings.split_at(LIMIT); + let (head, tail) = witnesses.split_at(LIMIT); + let head: Vec<_> = head.iter().map(|w| w.to_string()).collect(); format!("`{}` and {} more", head.join("`, `"), tail.len()) } }; - let label_text = match pattern_strings.len(){ + let label_text = match witnesses.len() { 1 => format!("pattern {} not covered", joined_patterns), _ => format!("patterns {} not covered", joined_patterns) }; @@ -489,7 +501,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(..), _, _, ref sub) = p.node { - let pat_ty = cx.tcx.tables().node_id_to_type(p.id); + let pat_ty = cx.tables.node_id_to_type(p.id); if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { check_move(p, sub.as_ref().map(|p| &**p)); } @@ -504,13 +516,11 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { - cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()), - Reveal::NotSpecializable).enter(|infcx| { + cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::NotSpecializable).enter(|infcx| { let mut checker = MutationChecker { cx: cx, }; - let mut visitor = ExprUseVisitor::new(&mut checker, &infcx); - visitor.walk_expr(guard); + ExprUseVisitor::new(&mut checker, &infcx).walk_expr(guard); }); } diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 83b0d9dec6..8c8b2b5da3 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -16,6 +16,8 @@ register_long_diagnostics! { E0001: r##" +## Note: this error code is no longer emitted by the compiler. + This error suggests that the expression arm corresponding to the noted pattern will never be reached as for all possible values of the expression being matched, one of the preceding patterns will match. @@ -25,10 +27,10 @@ one is too specific or the ordering is incorrect. For example, the following `match` block has too many arms: -```compile_fail,E0001 +``` match Some(0) { Some(bar) => {/* ... */} - None => {/* ... */} + x => {/* ... */} // This handles the `None` case _ => {/* ... */} // All possible cases have already been handled } ``` @@ -576,18 +578,18 @@ https://doc.rust-lang.org/reference.html#ffi-attributes E0306: r##" -In an array literal `[x; N]`, `N` is the number of elements in the array. This +In an array type `[T; N]`, `N` is the number of elements in the array. This must be an unsigned integer. Erroneous code example: ```compile_fail,E0306 -let x = [0i32; true]; // error: expected positive integer for repeat count, - // found boolean +const X: [i32; true] = [0]; // error: expected `usize` for array length, + // found boolean ``` Working example: ``` -let x = [0i32; 2]; +const X: [i32; 1] = [0]; ``` "##, } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 9fcab12398..a9dcb1ed89 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -15,11 +15,10 @@ use rustc::middle::const_val::ConstVal; use self::ErrKind::*; use self::EvalHint::*; -use rustc::hir::map as ast_map; +use rustc::hir::map as hir_map; use rustc::hir::map::blocks::FnLikeNode; -use rustc::middle::cstore::InlinedItem; use rustc::traits; -use rustc::hir::def::{Def, CtorKind}; +use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::util::IntTypeExt; @@ -27,16 +26,12 @@ use rustc::ty::subst::Substs; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; use rustc::util::nodemap::DefIdMap; -use rustc::lint; use graphviz::IntoCow; use syntax::ast; -use rustc::hir::{Expr, PatKind}; -use rustc::hir; -use syntax::ptr::P; -use syntax::codemap; +use rustc::hir::{self, Expr}; use syntax::attr::IntType; -use syntax_pos::{self, Span}; +use syntax_pos::Span; use std::borrow::Cow; use std::cmp::Ordering; @@ -44,6 +39,8 @@ use std::cmp::Ordering; use rustc_const_math::*; use rustc_errors::DiagnosticBuilder; +use rustc_i128::{i128, u128}; + macro_rules! math { ($e:expr, $op:expr) => { match $op { @@ -55,32 +52,24 @@ macro_rules! math { fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, variant_def: DefId) - -> Option<&'tcx Expr> { - fn variant_expr<'a>(variants: &'a [hir::Variant], id: ast::NodeId) - -> Option<&'a Expr> { - for variant in variants { - if variant.node.data.id() == id { - return variant.node.disr_expr.as_ref().map(|e| &**e); - } - } - None - } - - if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) { - let enum_node_id = tcx.map.get_parent(variant_node_id); - match tcx.map.find(enum_node_id) { - None => None, - Some(ast_map::NodeItem(it)) => match it.node { - hir::ItemEnum(hir::EnumDef { ref variants }, _) => { - variant_expr(variants, variant_node_id) + -> Option<(&'tcx Expr, Option<&'a ty::TypeckTables<'tcx>>)> { + if let Some(variant_node_id) = tcx.hir.as_local_node_id(variant_def) { + let enum_node_id = tcx.hir.get_parent(variant_node_id); + if let Some(hir_map::NodeItem(it)) = tcx.hir.find(enum_node_id) { + if let hir::ItemEnum(ref edef, _) = it.node { + for variant in &edef.variants { + if variant.node.data.id() == variant_node_id { + return variant.node.disr_expr.map(|e| { + let def_id = tcx.hir.body_owner_def_id(e); + (&tcx.hir.body(e).value, + tcx.tables.borrow().get(&def_id).cloned()) + }); + } } - _ => None - }, - Some(_) => None + } } - } else { - None } + None } /// * `def_id` is the id of the constant. @@ -91,26 +80,35 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>) - -> Option<(&'tcx Expr, Option>)> { - if let Some(node_id) = tcx.map.as_local_node_id(def_id) { - match tcx.map.find(node_id) { + -> Option<(&'tcx Expr, + Option<&'a ty::TypeckTables<'tcx>>, + Option>)> { + if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { + match tcx.hir.find(node_id) { None => None, - Some(ast_map::NodeItem(it)) => match it.node { - hir::ItemConst(ref ty, ref const_expr) => { - Some((&const_expr, tcx.ast_ty_to_prim_ty(ty))) - } - _ => None - }, - Some(ast_map::NodeTraitItem(ti)) => match ti.node { - hir::ConstTraitItem(ref ty, ref expr_option) => { + Some(hir_map::NodeItem(&hir::Item { + node: hir::ItemConst(ref ty, body), .. + })) | + Some(hir_map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Const(ref ty, body), .. + })) => { + Some((&tcx.hir.body(body).value, + tcx.tables.borrow().get(&def_id).cloned(), + tcx.ast_ty_to_prim_ty(ty))) + } + Some(hir_map::NodeTraitItem(ti)) => match ti.node { + hir::TraitItemKind::Const(ref ty, default) => { if let Some(substs) = substs { // If we have a trait item and the substitutions for it, // `resolve_trait_associated_const` will select an impl // or the default. - let trait_id = tcx.map.get_parent(node_id); - let trait_id = tcx.map.local_def_id(trait_id); - let default_value = expr_option.as_ref() - .map(|expr| (&**expr, tcx.ast_ty_to_prim_ty(ty))); + let trait_id = tcx.hir.get_parent(node_id); + let trait_id = tcx.hir.local_def_id(trait_id); + let default_value = default.map(|body| { + (&tcx.hir.body(body).value, + tcx.tables.borrow().get(&def_id).cloned(), + tcx.ast_ty_to_prim_ty(ty)) + }); resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) } else { // Technically, without knowing anything about the @@ -124,30 +122,14 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } _ => None }, - Some(ast_map::NodeImplItem(ii)) => match ii.node { - hir::ImplItemKind::Const(ref ty, ref expr) => { - Some((&expr, tcx.ast_ty_to_prim_ty(ty))) - } - _ => None - }, Some(_) => None } } else { - match tcx.extern_const_statics.borrow().get(&def_id) { - Some(&None) => return None, - Some(&Some((expr_id, ty))) => { - return Some((tcx.map.expect_expr(expr_id), ty)); - } - None => {} - } - let mut used_substs = false; - let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) { - Some((&InlinedItem { body: ref const_expr, .. }, _)) => { - Some((&**const_expr, Some(tcx.sess.cstore.item_type(tcx, def_id)))) - } - _ => None - }; - let expr_ty = match tcx.sess.cstore.describe_def(def_id) { + let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { + (&body.value, Some(tcx.item_tables(def_id)), + Some(tcx.sess.cstore.item_type(tcx, def_id))) + }); + match tcx.sess.cstore.describe_def(def_id) { Some(Def::AssociatedConst(_)) => { let trait_id = tcx.sess.cstore.trait_of_item(def_id); // As mentioned in the comments above for in-crate @@ -155,206 +137,45 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // trait-associated const if the caller gives us the // substitutions for the reference to it. if let Some(trait_id) = trait_id { - used_substs = true; - if let Some(substs) = substs { - resolve_trait_associated_const(tcx, def_id, expr_ty, trait_id, substs) + resolve_trait_associated_const(tcx, def_id, expr_tables_ty, + trait_id, substs) } else { None } } else { - expr_ty + expr_tables_ty } }, - Some(Def::Const(..)) => expr_ty, + Some(Def::Const(..)) => expr_tables_ty, _ => None - }; - // If we used the substitutions, particularly to choose an impl - // of a trait-associated const, don't cache that, because the next - // lookup with the same def_id may yield a different result. - if !used_substs { - tcx.extern_const_statics - .borrow_mut() - .insert(def_id, expr_ty.map(|(e, t)| (e.id, t))); } - expr_ty - } -} - -fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> Option { - match tcx.extern_const_fns.borrow().get(&def_id) { - Some(&ast::DUMMY_NODE_ID) => return None, - Some(&fn_id) => return Some(fn_id), - None => {} - } - - if !tcx.sess.cstore.is_const_fn(def_id) { - tcx.extern_const_fns.borrow_mut().insert(def_id, ast::DUMMY_NODE_ID); - return None; } - - let fn_id = tcx.sess.cstore.maybe_get_item_ast(tcx, def_id).map(|t| t.1); - tcx.extern_const_fns.borrow_mut().insert(def_id, - fn_id.unwrap_or(ast::DUMMY_NODE_ID)); - fn_id -} - -pub enum ConstFnNode<'tcx> { - Local(FnLikeNode<'tcx>), - Inlined(&'tcx InlinedItem) } -pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option> +fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> Option<(&'tcx hir::Body, Option<&'a ty::TypeckTables<'tcx>>)> { - let fn_id = if let Some(node_id) = tcx.map.as_local_node_id(def_id) { - node_id - } else { - if let Some(fn_id) = inline_const_fn_from_external_crate(tcx, def_id) { - if let ast_map::NodeInlinedItem(ii) = tcx.map.get(fn_id) { - return Some(ConstFnNode::Inlined(ii)); + if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { + FnLikeNode::from_node(tcx.hir.get(node_id)).and_then(|fn_like| { + if fn_like.constness() == hir::Constness::Const { + Some((tcx.hir.body(fn_like.body()), + tcx.tables.borrow().get(&def_id).cloned())) } else { - bug!("Got const fn from external crate, but it's not inlined") + None } + }) + } else { + if tcx.sess.cstore.is_const_fn(def_id) { + tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { + (body, Some(tcx.item_tables(def_id))) + }) } else { - return None; + None } - }; - - let fn_like = match FnLikeNode::from_node(tcx.map.get(fn_id)) { - Some(fn_like) => fn_like, - None => return None - }; - - if fn_like.constness() == hir::Constness::Const { - Some(ConstFnNode::Local(fn_like)) - } else { - None } } -pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - expr: &Expr, - pat_id: ast::NodeId, - span: Span) - -> Result, DefId> { - let pat_ty = tcx.tables().expr_ty(expr); - debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id); - match pat_ty.sty { - ty::TyFloat(_) => { - tcx.sess.add_lint( - lint::builtin::ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN, - pat_id, - span, - format!("floating point constants cannot be used in patterns")); - } - ty::TyAdt(adt_def, _) if adt_def.is_union() => { - // Matching on union fields is unsafe, we can't hide it in constants - tcx.sess.span_err(span, "cannot use unions in constant patterns"); - } - ty::TyAdt(adt_def, _) => { - if !tcx.has_attr(adt_def.did, "structural_match") { - tcx.sess.add_lint( - lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN, - pat_id, - span, - format!("to use a constant of type `{}` \ - in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - tcx.item_path_str(adt_def.did), - tcx.item_path_str(adt_def.did))); - } - } - _ => { } - } - let pat = match expr.node { - hir::ExprTup(ref exprs) => - PatKind::Tuple(exprs.iter() - .map(|expr| const_expr_to_pat(tcx, &expr, pat_id, span)) - .collect::>()?, None), - - hir::ExprCall(ref callee, ref args) => { - let qpath = match callee.node { - hir::ExprPath(ref qpath) => qpath, - _ => bug!() - }; - let def = tcx.tables().qpath_def(qpath, callee.id); - let ctor_path = if let hir::QPath::Resolved(_, ref path) = *qpath { - match def { - Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Fn) => { - Some(path.clone()) - } - _ => None - } - } else { - None - }; - match (def, ctor_path) { - (Def::Fn(..), None) | (Def::Method(..), None) => { - PatKind::Lit(P(expr.clone())) - } - (_, Some(ctor_path)) => { - let pats = args.iter() - .map(|expr| const_expr_to_pat(tcx, expr, pat_id, span)) - .collect::>()?; - PatKind::TupleStruct(hir::QPath::Resolved(None, ctor_path), pats, None) - } - _ => bug!() - } - } - - hir::ExprStruct(ref qpath, ref fields, None) => { - let field_pats = - fields.iter() - .map(|field| Ok(codemap::Spanned { - span: syntax_pos::DUMMY_SP, - node: hir::FieldPat { - name: field.name.node, - pat: const_expr_to_pat(tcx, &field.expr, pat_id, span)?, - is_shorthand: false, - }, - })) - .collect::>()?; - PatKind::Struct(qpath.clone(), field_pats, false) - } - - hir::ExprArray(ref exprs) => { - let pats = exprs.iter() - .map(|expr| const_expr_to_pat(tcx, &expr, pat_id, span)) - .collect::>()?; - PatKind::Slice(pats, None, hir::HirVec::new()) - } - - hir::ExprPath(ref qpath) => { - let def = tcx.tables().qpath_def(qpath, expr.id); - match def { - Def::StructCtor(_, CtorKind::Const) | - Def::VariantCtor(_, CtorKind::Const) => { - match expr.node { - hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { - PatKind::Path(hir::QPath::Resolved(None, path.clone())) - } - _ => bug!() - } - } - Def::Const(def_id) | Def::AssociatedConst(def_id) => { - let substs = Some(tcx.tables().node_id_item_substs(expr.id) - .unwrap_or_else(|| tcx.intern_substs(&[]))); - let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap(); - return const_expr_to_pat(tcx, expr, pat_id, span); - }, - _ => bug!(), - } - } - - _ => PatKind::Lit(P(expr.clone())) - }; - Ok(P(hir::Pat { id: expr.id, node: pat, span: span })) -} - pub fn report_const_eval_err<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, err: &ConstEvalErr, @@ -403,30 +224,38 @@ pub fn note_const_eval_err<'a, 'tcx>( } } -pub fn eval_const_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr) -> ConstVal { - match eval_const_expr_checked(tcx, e) { - Ok(r) => r, - // non-const path still needs to be a fatal error, because enums are funky - Err(s) => { - report_const_eval_err(tcx, &s, e.span, "expression").emit(); - match s.kind { - NonConstPath | - UnimplementedConstVal(_) => tcx.sess.abort_if_errors(), - _ => {} - } - Dummy - }, - } +pub struct ConstContext<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: Option<&'a ty::TypeckTables<'tcx>>, + fn_args: Option> } -pub fn eval_const_expr_checked<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr) -> EvalResult -{ - eval_const_expr_partial(tcx, e, ExprTypeChecked, None) -} +impl<'a, 'tcx> ConstContext<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self { + let def_id = tcx.hir.body_owner_def_id(body); + ConstContext { + tcx: tcx, + tables: tcx.tables.borrow().get(&def_id).cloned(), + fn_args: None + } + } -pub type FnArgMap<'a> = Option<&'a DefIdMap>; + pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>) -> Self { + ConstContext { + tcx: tcx, + tables: Some(tables), + fn_args: None + } + } + + /// Evaluate a constant expression in a context where the expression isn't + /// guaranteed to be evaluatable. `ty_hint` is usually ExprTypeChecked, + /// but a few places need to evaluate constants during type-checking, like + /// computing the length of an array. (See also the FIXME above EvalHint.) + pub fn eval(&self, e: &Expr, ty_hint: EvalHint<'tcx>) -> EvalResult { + eval_const_expr_partial(self, e, ty_hint) + } +} #[derive(Clone, Debug)] pub struct ConstEvalErr { @@ -606,20 +435,16 @@ macro_rules! signal { } } -/// Evaluate a constant expression in a context where the expression isn't -/// guaranteed to be evaluatable. `ty_hint` is usually ExprTypeChecked, -/// but a few places need to evaluate constants during type-checking, like -/// computing the length of an array. (See also the FIXME above EvalHint.) -pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr, - ty_hint: EvalHint<'tcx>, - fn_args: FnArgMap) -> EvalResult { +fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, + e: &Expr, + ty_hint: EvalHint<'tcx>) -> EvalResult { + let tcx = cx.tcx; // Try to compute the type of the expression based on the EvalHint. // (See also the definition of EvalHint, and the FIXME above EvalHint.) let ety = match ty_hint { ExprTypeChecked => { // After type-checking, expr_ty is guaranteed to succeed. - Some(tcx.tables().expr_ty(e)) + cx.tables.map(|tables| tables.expr_ty(e)) } UncheckedExprHint(ty) => { // Use the type hint; it's not guaranteed to be right, but it's @@ -630,7 +455,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // This expression might not be type-checked, and we have no hint. // Try to query the context for a type anyway; we might get lucky // (for example, if the expression was imported from another crate). - tcx.tables().expr_ty_opt(e) + cx.tables.and_then(|tables| tables.expr_ty_opt(e)) } }; let result = match e.node { @@ -639,38 +464,46 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let hir::ExprLit(ref lit) = inner.node { use syntax::ast::*; use syntax::ast::LitIntType::*; - const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1; - const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1; - const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1; - const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1; + const I8_OVERFLOW: u128 = i8::min_value() as u8 as u128; + const I16_OVERFLOW: u128 = i16::min_value() as u16 as u128; + const I32_OVERFLOW: u128 = i32::min_value() as u32 as u128; + const I64_OVERFLOW: u128 = i64::min_value() as u64 as u128; + const I128_OVERFLOW: u128 = i128::min_value() as u128; match (&lit.node, ety.map(|t| &t.sty)) { - (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) | + (&LitKind::Int(I8_OVERFLOW, _), Some(&ty::TyInt(IntTy::I8))) | (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { - return Ok(Integral(I8(::std::i8::MIN))) + return Ok(Integral(I8(i8::min_value()))) }, - (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) | + (&LitKind::Int(I16_OVERFLOW, _), Some(&ty::TyInt(IntTy::I16))) | (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { - return Ok(Integral(I16(::std::i16::MIN))) + return Ok(Integral(I16(i16::min_value()))) }, - (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) | + (&LitKind::Int(I32_OVERFLOW, _), Some(&ty::TyInt(IntTy::I32))) | (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { - return Ok(Integral(I32(::std::i32::MIN))) + return Ok(Integral(I32(i32::min_value()))) }, - (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) | + (&LitKind::Int(I64_OVERFLOW, _), Some(&ty::TyInt(IntTy::I64))) | (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { - return Ok(Integral(I64(::std::i64::MIN))) + return Ok(Integral(I64(i64::min_value()))) + }, + (&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::I128))) | + (&LitKind::Int(n, Signed(IntTy::I128)), _) => { + // SNAP: replace n in pattern with I128_OVERFLOW and remove this if. + if n == I128_OVERFLOW { + return Ok(Integral(I128(i128::min_value()))) + } }, - (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) | + (&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::Is))) | (&LitKind::Int(n, Signed(IntTy::Is)), _) => { match tcx.sess.target.int_type { IntTy::I16 => if n == I16_OVERFLOW { - return Ok(Integral(Isize(Is16(::std::i16::MIN)))); + return Ok(Integral(Isize(Is16(i16::min_value())))); }, IntTy::I32 => if n == I32_OVERFLOW { - return Ok(Integral(Isize(Is32(::std::i32::MIN)))); + return Ok(Integral(Isize(Is32(i32::min_value())))); }, IntTy::I64 => if n == I64_OVERFLOW { - return Ok(Integral(Isize(Is64(::std::i64::MIN)))); + return Ok(Integral(Isize(Is64(i64::min_value())))); }, _ => bug!(), } @@ -678,14 +511,14 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => {}, } } - match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { + match cx.eval(inner, ty_hint)? { Float(f) => Float(-f), Integral(i) => Integral(math!(e, -i)), const_val => signal!(e, NegateOn(const_val)), } } hir::ExprUnary(hir::UnNot, ref inner) => { - match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { + match cx.eval(inner, ty_hint)? { Integral(i) => Integral(math!(e, !i)), Bool(b) => Bool(!b), const_val => signal!(e, NotOn(const_val)), @@ -701,8 +534,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // gives us a type through a type-suffix, cast or const def type // we need to re-eval the other value of the BinOp if it was // not inferred - match (eval_const_expr_partial(tcx, &a, ty_hint, fn_args)?, - eval_const_expr_partial(tcx, &b, b_ty, fn_args)?) { + match (cx.eval(a, ty_hint)?, + cx.eval(b, b_ty)?) { (Float(a), Float(b)) => { use std::cmp::Ordering::*; match op.node { @@ -772,13 +605,13 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let base_hint = if let ExprTypeChecked = ty_hint { ExprTypeChecked } else { - match tcx.tables().expr_ty_opt(&base) { + match cx.tables.and_then(|tables| tables.expr_ty_opt(&base)) { Some(t) => UncheckedExprHint(t), None => ty_hint } }; - let val = match eval_const_expr_partial(tcx, &base, base_hint, fn_args) { + let val = match cx.eval(base, base_hint) { Ok(val) => val, Err(ConstEvalErr { kind: ErroneousReferencedConstant( box ConstEvalErr { kind: TypeMismatch(_, val), .. }), .. }) | @@ -791,7 +624,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // we had a type hint, so we can't have an unknown type None => bug!(), }; - eval_const_expr_partial(tcx, &base, hint, fn_args)? + cx.eval(base, hint)? }, Err(e) => return Err(e), }; @@ -801,22 +634,29 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } hir::ExprPath(ref qpath) => { - let def = tcx.tables().qpath_def(qpath, e.id); + let def = cx.tables.map(|tables| tables.qpath_def(qpath, e.id)).unwrap_or_else(|| { + // There are no tables so we can only handle already-resolved HIR. + match *qpath { + hir::QPath::Resolved(_, ref path) => path.def, + hir::QPath::TypeRelative(..) => Def::Err + } + }); match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = if let ExprTypeChecked = ty_hint { - Some(tcx.tables().node_id_item_substs(e.id) + Some(cx.tables.and_then(|tables| tables.node_id_item_substs(e.id)) .unwrap_or_else(|| tcx.intern_substs(&[]))) } else { None }; - if let Some((expr, ty)) = lookup_const_by_id(tcx, def_id, substs) { + if let Some((expr, tables, ty)) = lookup_const_by_id(tcx, def_id, substs) { let item_hint = match ty { Some(ty) => ty_hint.checked_or(ty), None => ty_hint, }; - match eval_const_expr_partial(tcx, expr, item_hint, None) { + let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; + match cx.eval(expr, item_hint) { Ok(val) => val, Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); @@ -828,8 +668,9 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }, Def::VariantCtor(variant_def, ..) => { - if let Some(const_expr) = lookup_variant_by_id(tcx, variant_def) { - match eval_const_expr_partial(tcx, const_expr, ty_hint, None) { + if let Some((expr, tables)) = lookup_variant_by_id(tcx, variant_def) { + let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; + match cx.eval(expr, ty_hint) { Ok(val) => val, Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); @@ -841,11 +682,11 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } Def::StructCtor(..) => { - ConstVal::Struct(e.id) + ConstVal::Struct(Default::default()) } Def::Local(def_id) => { - debug!("Def::Local({:?}): {:?}", def_id, fn_args); - if let Some(val) = fn_args.and_then(|args| args.get(&def_id)) { + debug!("Def::Local({:?}): {:?}", def_id, cx.fn_args); + if let Some(val) = cx.fn_args.as_ref().and_then(|args| args.get(&def_id)) { val.clone() } else { signal!(e, NonConstPath); @@ -858,42 +699,39 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } hir::ExprCall(ref callee, ref args) => { let sub_ty_hint = ty_hint.erase_hint(); - let callee_val = eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)?; + let callee_val = cx.eval(callee, sub_ty_hint)?; let did = match callee_val { Function(did) => did, Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")), callee => signal!(e, CallOn(callee)), }; - let (arg_defs, body_id) = match lookup_const_fn_by_id(tcx, did) { - Some(ConstFnNode::Inlined(ii)) => (ii.const_fn_args.clone(), ii.body.expr_id()), - Some(ConstFnNode::Local(fn_like)) => - (fn_like.decl().inputs.iter() - .map(|arg| match arg.pat.node { - hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), - _ => None - }).collect(), - fn_like.body()), + let (body, tables) = match lookup_const_fn_by_id(tcx, did) { + Some(x) => x, None => signal!(e, NonConstPath), }; - let result = tcx.map.expr(body_id); + + let arg_defs = body.arguments.iter().map(|arg| match arg.pat.node { + hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), + _ => None + }).collect::>(); assert_eq!(arg_defs.len(), args.len()); let mut call_args = DefIdMap(); for (arg, arg_expr) in arg_defs.into_iter().zip(args.iter()) { let arg_hint = ty_hint.erase_hint(); - let arg_val = eval_const_expr_partial( - tcx, - arg_expr, - arg_hint, - fn_args - )?; + let arg_val = cx.eval(arg_expr, arg_hint)?; debug!("const call arg: {:?}", arg); if let Some(def_id) = arg { assert!(call_args.insert(def_id, arg_val).is_none()); } } debug!("const call({:?})", call_args); - eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args))? + let callee_cx = ConstContext { + tcx: tcx, + tables: tables, + fn_args: Some(call_args) + }; + callee_cx.eval(&body.value, ty_hint)? }, hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) { Ok(val) => val, @@ -901,46 +739,49 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }, hir::ExprBlock(ref block) => { match block.expr { - Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?, + Some(ref expr) => cx.eval(expr, ty_hint)?, None => signal!(e, UnimplementedConstVal("empty block")), } } - hir::ExprType(ref e, _) => eval_const_expr_partial(tcx, &e, ty_hint, fn_args)?, - hir::ExprTup(_) => Tuple(e.id), - hir::ExprStruct(..) => Struct(e.id), + hir::ExprType(ref e, _) => cx.eval(e, ty_hint)?, + hir::ExprTup(ref fields) => { + let field_hint = ty_hint.erase_hint(); + Tuple(fields.iter().map(|e| cx.eval(e, field_hint)).collect::>()?) + } + hir::ExprStruct(_, ref fields, _) => { + let field_hint = ty_hint.erase_hint(); + Struct(fields.iter().map(|f| { + cx.eval(&f.expr, field_hint).map(|v| (f.name.node, v)) + }).collect::>()?) + } hir::ExprIndex(ref arr, ref idx) => { if !tcx.sess.features.borrow().const_indexing { signal!(e, IndexOpFeatureGated); } let arr_hint = ty_hint.erase_hint(); - let arr = eval_const_expr_partial(tcx, arr, arr_hint, fn_args)?; + let arr = cx.eval(arr, arr_hint)?; let idx_hint = ty_hint.checked_or(tcx.types.usize); - let idx = match eval_const_expr_partial(tcx, idx, idx_hint, fn_args)? { + let idx = match cx.eval(idx, idx_hint)? { Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), Integral(_) => bug!(), _ => signal!(idx, IndexNotInt), }; assert_eq!(idx as usize as u64, idx); match arr { - Array(_, n) if idx >= n => { - signal!(e, IndexOutOfBounds { len: n, index: idx }) + Array(ref v) => { + if let Some(elem) = v.get(idx as usize) { + elem.clone() + } else { + let n = v.len() as u64; + assert_eq!(n as usize as u64, n); + signal!(e, IndexOutOfBounds { len: n, index: idx }) + } } - Array(v, n) => if let hir::ExprArray(ref v) = tcx.map.expect_expr(v).node { - assert_eq!(n as usize as u64, n); - eval_const_expr_partial(tcx, &v[idx as usize], ty_hint, fn_args)? - } else { - bug!() - }, - Repeat(_, n) if idx >= n => { + Repeat(.., n) if idx >= n => { signal!(e, IndexOutOfBounds { len: n, index: idx }) } - Repeat(elem, _) => eval_const_expr_partial( - tcx, - &tcx.map.expect_expr(elem), - ty_hint, - fn_args, - )?, + Repeat(ref elem, _) => (**elem).clone(), ByteStr(ref data) if idx >= data.len() as u64 => { signal!(e, IndexOutOfBounds { len: data.len() as u64, index: idx }) @@ -952,30 +793,38 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => signal!(e, IndexedNonVec), } } - hir::ExprArray(ref v) => Array(e.id, v.len() as u64), - hir::ExprRepeat(_, ref n) => { + hir::ExprArray(ref v) => { + let elem_hint = ty_hint.erase_hint(); + Array(v.iter().map(|e| cx.eval(e, elem_hint)).collect::>()?) + } + hir::ExprRepeat(ref elem, count) => { + let elem_hint = ty_hint.erase_hint(); let len_hint = ty_hint.checked_or(tcx.types.usize); - Repeat( - e.id, - match eval_const_expr_partial(tcx, &n, len_hint, fn_args)? { - Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), - Integral(_) => signal!(e, RepeatCountNotNatural), - _ => signal!(e, RepeatCountNotInt), - }, - ) + let n = if let Some(ty) = ety { + // For cross-crate constants, we have the type already, + // but not the body for `count`, so use the type. + match ty.sty { + ty::TyArray(_, n) => n as u64, + _ => bug!() + } + } else { + let n = &tcx.hir.body(count).value; + match ConstContext::new(tcx, count).eval(n, len_hint)? { + Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), + Integral(_) => signal!(e, RepeatCountNotNatural), + _ => signal!(e, RepeatCountNotInt), + } + }; + Repeat(Box::new(cx.eval(elem, elem_hint)?), n) }, hir::ExprTupField(ref base, index) => { let base_hint = ty_hint.erase_hint(); - let c = eval_const_expr_partial(tcx, base, base_hint, fn_args)?; - if let Tuple(tup_id) = c { - if let hir::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node { - if index.node < fields.len() { - eval_const_expr_partial(tcx, &fields[index.node], ty_hint, fn_args)? - } else { - signal!(e, TupleIndexOutOfBounds); - } + let c = cx.eval(base, base_hint)?; + if let Tuple(ref fields) = c { + if let Some(elem) = fields.get(index.node) { + elem.clone() } else { - bug!() + signal!(e, TupleIndexOutOfBounds); } } else { signal!(base, ExpectedConstTuple); @@ -983,20 +832,12 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } hir::ExprField(ref base, field_name) => { let base_hint = ty_hint.erase_hint(); - // Get the base expression if it is a struct and it is constant - let c = eval_const_expr_partial(tcx, base, base_hint, fn_args)?; - if let Struct(struct_id) = c { - if let hir::ExprStruct(_, ref fields, _) = tcx.map.expect_expr(struct_id).node { - // Check that the given field exists and evaluate it - // if the idents are compared run-pass/issue-19244 fails - if let Some(f) = fields.iter().find(|f| f.name.node - == field_name.node) { - eval_const_expr_partial(tcx, &f.expr, ty_hint, fn_args)? - } else { - signal!(e, MissingStructField); - } + let c = cx.eval(base, base_hint)?; + if let Struct(ref fields) = c { + if let Some(f) = fields.get(&field_name.node) { + f.clone() } else { - bug!() + signal!(e, MissingStructField); } } else { signal!(base, ExpectedConstStruct); @@ -1026,26 +867,30 @@ fn infer<'a, 'tcx>(i: ConstInt, (&ty::TyInt(IntTy::I16), result @ I16(_)) => Ok(result), (&ty::TyInt(IntTy::I32), result @ I32(_)) => Ok(result), (&ty::TyInt(IntTy::I64), result @ I64(_)) => Ok(result), + (&ty::TyInt(IntTy::I128), result @ I128(_)) => Ok(result), (&ty::TyInt(IntTy::Is), result @ Isize(_)) => Ok(result), (&ty::TyUint(UintTy::U8), result @ U8(_)) => Ok(result), (&ty::TyUint(UintTy::U16), result @ U16(_)) => Ok(result), (&ty::TyUint(UintTy::U32), result @ U32(_)) => Ok(result), (&ty::TyUint(UintTy::U64), result @ U64(_)) => Ok(result), + (&ty::TyUint(UintTy::U128), result @ U128(_)) => Ok(result), (&ty::TyUint(UintTy::Us), result @ Usize(_)) => Ok(result), - (&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i64 as i8)), - (&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i64 as i16)), - (&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i64 as i32)), - (&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i64)), + (&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i128 as i8)), + (&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i128 as i16)), + (&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i128 as i32)), + (&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i128 as i64)), + (&ty::TyInt(IntTy::I128), Infer(i)) => Ok(I128(i as i128)), (&ty::TyInt(IntTy::Is), Infer(i)) => { - Ok(Isize(ConstIsize::new_truncating(i as i64, tcx.sess.target.int_type))) + Ok(Isize(ConstIsize::new_truncating(i as i128, tcx.sess.target.int_type))) }, (&ty::TyInt(IntTy::I8), InferSigned(i)) => Ok(I8(i as i8)), (&ty::TyInt(IntTy::I16), InferSigned(i)) => Ok(I16(i as i16)), (&ty::TyInt(IntTy::I32), InferSigned(i)) => Ok(I32(i as i32)), - (&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i)), + (&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i as i64)), + (&ty::TyInt(IntTy::I128), InferSigned(i)) => Ok(I128(i)), (&ty::TyInt(IntTy::Is), InferSigned(i)) => { Ok(Isize(ConstIsize::new_truncating(i, tcx.sess.target.int_type))) }, @@ -1053,7 +898,8 @@ fn infer<'a, 'tcx>(i: ConstInt, (&ty::TyUint(UintTy::U8), Infer(i)) => Ok(U8(i as u8)), (&ty::TyUint(UintTy::U16), Infer(i)) => Ok(U16(i as u16)), (&ty::TyUint(UintTy::U32), Infer(i)) => Ok(U32(i as u32)), - (&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i)), + (&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i as u64)), + (&ty::TyUint(UintTy::U128), Infer(i)) => Ok(U128(i)), (&ty::TyUint(UintTy::Us), Infer(i)) => { Ok(Usize(ConstUsize::new_truncating(i, tcx.sess.target.uint_type))) }, @@ -1074,17 +920,17 @@ fn infer<'a, 'tcx>(i: ConstInt, fn resolve_trait_associated_const<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: DefId, - default_value: Option<(&'tcx Expr, Option>)>, + default_value: Option<(&'tcx Expr, Option<&'a ty::TypeckTables<'tcx>>, Option>)>, trait_id: DefId, rcvr_substs: &'tcx Substs<'tcx> -) -> Option<(&'tcx Expr, Option>)> +) -> Option<(&'tcx Expr, Option<&'a ty::TypeckTables<'tcx>>, Option>)> { let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs)); debug!("resolve_trait_associated_const: trait_ref={:?}", trait_ref); tcx.populate_implementations_for_trait_if_necessary(trait_id); - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), trait_ref.to_poly_trait_predicate()); @@ -1124,21 +970,23 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>( } fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::Ty) -> CastResult { - let v = val.to_u64_unchecked(); + let v = val.to_u128_unchecked(); match ty.sty { ty::TyBool if v == 0 => Ok(Bool(false)), ty::TyBool if v == 1 => Ok(Bool(true)), - ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i64 as i8))), - ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i64 as i16))), - ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i64 as i32))), - ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i64))), + ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i128 as i8))), + ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i128 as i16))), + ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i128 as i32))), + ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i128 as i64))), + ty::TyInt(ast::IntTy::I128) => Ok(Integral(I128(v as i128))), ty::TyInt(ast::IntTy::Is) => { - Ok(Integral(Isize(ConstIsize::new_truncating(v as i64, tcx.sess.target.int_type)))) + Ok(Integral(Isize(ConstIsize::new_truncating(v as i128, tcx.sess.target.int_type)))) }, ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))), ty::TyUint(ast::UintTy::U16) => Ok(Integral(U16(v as u16))), ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))), - ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v))), + ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))), + ty::TyUint(ast::UintTy::U128) => Ok(Integral(U128(v as u128))), ty::TyUint(ast::UintTy::Us) => { Ok(Integral(Usize(ConstUsize::new_truncating(v, tcx.sess.target.uint_type)))) }, @@ -1168,13 +1016,13 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match ty.sty { ty::TyInt(_) | ty::TyUint(_) => { let i = match val { - F32(f) if f >= 0.0 => Infer(f as u64), + F32(f) if f >= 0.0 => Infer(f as u128), FInfer { f64: f, .. } | - F64(f) if f >= 0.0 => Infer(f as u64), + F64(f) if f >= 0.0 => Infer(f as u128), - F32(f) => InferSigned(f as i64), + F32(f) => InferSigned(f as i128), FInfer { f64: f, .. } | - F64(f) => InferSigned(f as i64) + F64(f) => InferSigned(f as i128) }; if let (InferSigned(_), &ty::TyUint(_)) = (i, &ty.sty) { @@ -1198,9 +1046,9 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult { match val { Integral(i) => cast_const_int(tcx, i, ty), - Bool(b) => cast_const_int(tcx, Infer(b as u64), ty), + Bool(b) => cast_const_int(tcx, Infer(b as u128), ty), Float(f) => cast_const_float(tcx, f, ty), - Char(c) => cast_const_int(tcx, Infer(c as u64), ty), + Char(c) => cast_const_int(tcx, Infer(c as u128), ty), Function(_) => Err(UnimplementedConstVal("casting fn pointers")), ByteStr(b) => match ty.sty { ty::TyRawPtr(_) => { @@ -1238,28 +1086,29 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind, LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())), LitKind::Byte(n) => Ok(Integral(U8(n))), LitKind::Int(n, Signed(ity)) => { - infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral) + infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral) }, + // FIXME: this should become u128. LitKind::Int(n, Unsuffixed) => { match ty_hint.map(|t| &t.sty) { Some(&ty::TyInt(ity)) => { - infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral) + infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral) }, Some(&ty::TyUint(uty)) => { - infer(Infer(n), tcx, &ty::TyUint(uty)).map(Integral) + infer(Infer(n as u128), tcx, &ty::TyUint(uty)).map(Integral) }, - None => Ok(Integral(Infer(n))), + None => Ok(Integral(Infer(n as u128))), Some(&ty::TyAdt(adt, _)) => { let hints = tcx.lookup_repr_hints(adt.did); let int_ty = tcx.enum_repr_type(hints.iter().next()); - infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty).map(Integral) + infer(Infer(n as u128), tcx, &int_ty.to_ty(tcx).sty).map(Integral) }, Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit), } }, LitKind::Int(n, Unsigned(ity)) => { - infer(Infer(n), tcx, &ty::TyUint(ity)).map(Integral) + infer(Infer(n as u128), tcx, &ty::TyUint(ity)).map(Integral) }, LitKind::Float(n, fty) => { @@ -1322,36 +1171,40 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal) } } -pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - span: Span, - a: &Expr, - b: &Expr) -> Result { - let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked, None) { - Ok(a) => a, - Err(e) => { - report_const_eval_err(tcx, &e, a.span, "expression").emit(); - return Err(ErrorReported); - } - }; - let b = match eval_const_expr_partial(tcx, b, ExprTypeChecked, None) { - Ok(b) => b, - Err(e) => { - report_const_eval_err(tcx, &e, b.span, "expression").emit(); - return Err(ErrorReported); - } - }; - compare_const_vals(tcx, span, &a, &b) +impl<'a, 'tcx> ConstContext<'a, 'tcx> { + pub fn compare_lit_exprs(&self, + span: Span, + a: &Expr, + b: &Expr) -> Result { + let tcx = self.tcx; + let a = match self.eval(a, ExprTypeChecked) { + Ok(a) => a, + Err(e) => { + report_const_eval_err(tcx, &e, a.span, "expression").emit(); + return Err(ErrorReported); + } + }; + let b = match self.eval(b, ExprTypeChecked) { + Ok(b) => b, + Err(e) => { + report_const_eval_err(tcx, &e, b.span, "expression").emit(); + return Err(ErrorReported); + } + }; + compare_const_vals(tcx, span, &a, &b) + } } /// Returns the value of the length-valued expression pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - count_expr: &hir::Expr, + count: hir::BodyId, reason: &str) -> Result { let hint = UncheckedExprHint(tcx.types.usize); - match eval_const_expr_partial(tcx, count_expr, hint, None) { + let count_expr = &tcx.hir.body(count).value; + match ConstContext::new(tcx, count).eval(count_expr, hint) { Ok(Integral(Usize(count))) => { let val = count.as_u64(tcx.sess.target.uint_type); assert_eq!(val as usize as u64, val); @@ -1373,7 +1226,8 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node { if let Def::Local(..) = path.def { - diag.note(&format!("`{}` is a variable", path)); + diag.note(&format!("`{}` is a variable", + tcx.hir.node_to_pretty_string(count_expr.id))); } } diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 7a6cc49372..2b6f487c2c 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -28,6 +28,7 @@ #![feature(slice_patterns)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_fn)] extern crate arena; #[macro_use] extern crate syntax; @@ -39,7 +40,8 @@ extern crate rustc_data_structures; extern crate rustc_errors; extern crate graphviz; extern crate syntax_pos; -extern crate serialize as rustc_serialize; // used by deriving + +extern crate rustc_i128; // NB: This module needs to be declared first so diagnostics are // registered before they are used. diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index e93178c89c..e96b88f0c5 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -10,16 +10,18 @@ use eval; +use rustc::lint; use rustc::middle::const_val::ConstVal; use rustc::mir::{Field, BorrowKind, Mutability}; -use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region}; -use rustc::hir::{self, PatKind}; -use rustc::hir::def::Def; -use rustc::hir::def_id::DefId; +use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region}; +use rustc::ty::subst::{Substs, Kind}; +use rustc::hir::{self, PatKind, RangeEnd}; +use rustc::hir::def::{Def, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc_data_structures::indexed_vec::Idx; +use std::fmt; use syntax::ast; use syntax::ptr::P; use syntax_pos::Span; @@ -27,7 +29,6 @@ use syntax_pos::Span; #[derive(Clone, Debug)] pub enum PatternError { StaticInPattern(Span), - BadConstInPattern(Span, DefId), ConstEval(eval::ConstEvalErr), } @@ -67,6 +68,7 @@ pub enum PatternKind<'tcx> { /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants Variant { adt_def: &'tcx AdtDef, + substs: &'tcx Substs<'tcx>, variant_index: usize, subpatterns: Vec>, }, @@ -88,6 +90,7 @@ pub enum PatternKind<'tcx> { Range { lo: ConstVal, hi: ConstVal, + end: RangeEnd, }, /// matches against a slice, checking the length and extracting elements @@ -105,14 +108,175 @@ pub enum PatternKind<'tcx> { }, } +fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result { + match *value { + ConstVal::Float(ref x) => write!(f, "{}", x), + ConstVal::Integral(ref i) => write!(f, "{}", i), + ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]), + ConstVal::ByteStr(ref b) => write!(f, "{:?}", &b[..]), + ConstVal::Bool(b) => write!(f, "{:?}", b), + ConstVal::Char(c) => write!(f, "{:?}", c), + ConstVal::Struct(_) | + ConstVal::Tuple(_) | + ConstVal::Function(_) | + ConstVal::Array(..) | + ConstVal::Repeat(..) => bug!("{:?} not printable in a pattern", value) + } +} + +impl<'tcx> fmt::Display for Pattern<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self.kind { + PatternKind::Wild => write!(f, "_"), + PatternKind::Binding { mutability, name, mode, ref subpattern, .. } => { + let is_mut = match mode { + BindingMode::ByValue => mutability == Mutability::Mut, + BindingMode::ByRef(_, bk) => { + write!(f, "ref ")?; + bk == BorrowKind::Mut + } + }; + if is_mut { + write!(f, "mut ")?; + } + write!(f, "{}", name)?; + if let Some(ref subpattern) = *subpattern { + write!(f, " @ {}", subpattern)?; + } + Ok(()) + } + PatternKind::Variant { ref subpatterns, .. } | + PatternKind::Leaf { ref subpatterns } => { + let variant = match *self.kind { + PatternKind::Variant { adt_def, variant_index, .. } => { + Some(&adt_def.variants[variant_index]) + } + _ => if let ty::TyAdt(adt, _) = self.ty.sty { + if adt.is_univariant() { + Some(&adt.variants[0]) + } else { + None + } + } else { + None + } + }; + + let mut first = true; + let mut start_or_continue = || if first { first = false; "" } else { ", " }; + + if let Some(variant) = variant { + write!(f, "{}", variant.name)?; + + // Only for TyAdt we can have `S {...}`, + // which we handle separately here. + if variant.ctor_kind == CtorKind::Fictive { + write!(f, " {{ ")?; + + let mut printed = 0; + for p in subpatterns { + if let PatternKind::Wild = *p.pattern.kind { + continue; + } + let name = variant.fields[p.field.index()].name; + write!(f, "{}{}: {}", start_or_continue(), name, p.pattern)?; + printed += 1; + } + + if printed < variant.fields.len() { + write!(f, "{}..", start_or_continue())?; + } + + return write!(f, " }}"); + } + } + + let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len()); + if num_fields != 0 || variant.is_none() { + write!(f, "(")?; + for i in 0..num_fields { + write!(f, "{}", start_or_continue())?; + + // Common case: the field is where we expect it. + if let Some(p) = subpatterns.get(i) { + if p.field.index() == i { + write!(f, "{}", p.pattern)?; + continue; + } + } + + // Otherwise, we have to go looking for it. + if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) { + write!(f, "{}", p.pattern)?; + } else { + write!(f, "_")?; + } + } + write!(f, ")")?; + } + + Ok(()) + } + PatternKind::Deref { ref subpattern } => { + match self.ty.sty { + ty::TyAdt(def, _) if def.is_box() => write!(f, "box ")?, + ty::TyRef(_, mt) => { + write!(f, "&")?; + if mt.mutbl == hir::MutMutable { + write!(f, "mut ")?; + } + } + _ => bug!("{} is a bad Deref pattern type", self.ty) + } + write!(f, "{}", subpattern) + } + PatternKind::Constant { ref value } => { + print_const_val(value, f) + } + PatternKind::Range { ref lo, ref hi, ref end } => { + print_const_val(lo, f)?; + match *end { + RangeEnd::Included => write!(f, "...")?, + RangeEnd::Excluded => write!(f, "..")?, + } + print_const_val(hi, f) + } + PatternKind::Slice { ref prefix, ref slice, ref suffix } | + PatternKind::Array { ref prefix, ref slice, ref suffix } => { + let mut first = true; + let mut start_or_continue = || if first { first = false; "" } else { ", " }; + write!(f, "[")?; + for p in prefix { + write!(f, "{}{}", start_or_continue(), p)?; + } + if let Some(ref slice) = *slice { + write!(f, "{}", start_or_continue())?; + match *slice.kind { + PatternKind::Wild => {} + _ => write!(f, "{}", slice)? + } + write!(f, "..")?; + } + for p in suffix { + write!(f, "{}{}", start_or_continue(), p)?; + } + write!(f, "]") + } + } + } +} + pub struct PatternContext<'a, 'gcx: 'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub tables: &'a ty::TypeckTables<'gcx>, pub errors: Vec, } impl<'a, 'gcx, 'tcx> Pattern<'tcx> { - pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>, pat: &hir::Pat) -> Self { - let mut pcx = PatternContext::new(tcx); + pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>, + tables: &'a ty::TypeckTables<'gcx>, + pat: &hir::Pat) -> Self { + let mut pcx = PatternContext::new(tcx, tables); let result = pcx.lower_pattern(pat); if !pcx.errors.is_empty() { span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors) @@ -123,74 +287,30 @@ impl<'a, 'gcx, 'tcx> Pattern<'tcx> { } impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { - PatternContext { tcx: tcx, errors: vec![] } + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, tables: &'a ty::TypeckTables<'gcx>) -> Self { + PatternContext { tcx: tcx, tables: tables, errors: vec![] } } pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { - let mut ty = self.tcx.tables().node_id_to_type(pat.id); + let mut ty = self.tables.node_id_to_type(pat.id); let kind = match pat.node { PatKind::Wild => PatternKind::Wild, - PatKind::Lit(ref value) => { - match eval::eval_const_expr_checked(self.tcx.global_tcx(), value) { - Ok(value) => { - PatternKind::Constant { value: value } - } - Err(e) => { - self.errors.push(PatternError::ConstEval(e)); - PatternKind::Wild - } - } - } - - PatKind::Range(ref lo, ref hi) => { - let r_lo = eval::eval_const_expr_checked(self.tcx.global_tcx(), lo); - if let Err(ref e_lo) = r_lo { - self.errors.push(PatternError::ConstEval(e_lo.clone())); - } - - let r_hi = eval::eval_const_expr_checked(self.tcx.global_tcx(), hi); - if let Err(ref e_hi) = r_hi { - self.errors.push(PatternError::ConstEval(e_hi.clone())); - } + PatKind::Lit(ref value) => self.lower_lit(value), - if let (Ok(lo), Ok(hi)) = (r_lo, r_hi) { - PatternKind::Range { lo: lo, hi: hi } - } else { - PatternKind::Wild + PatKind::Range(ref lo, ref hi, ref end) => { + match (self.lower_lit(lo), self.lower_lit(hi)) { + (PatternKind::Constant { value: lo }, + PatternKind::Constant { value: hi }) => { + PatternKind::Range { lo: lo, hi: hi, end: end.clone() } + } + _ => PatternKind::Wild } } PatKind::Path(ref qpath) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); - match def { - Def::Const(def_id) | Def::AssociatedConst(def_id) => { - let tcx = self.tcx.global_tcx(); - let substs = tcx.tables().node_id_item_substs(pat.id) - .unwrap_or_else(|| tcx.intern_substs(&[])); - match eval::lookup_const_by_id(tcx, def_id, Some(substs)) { - Some((const_expr, _const_ty)) => { - match eval::const_expr_to_pat( - tcx, const_expr, pat.id, pat.span) - { - Ok(pat) => return self.lower_pattern(&pat), - Err(_) => { - self.errors.push(PatternError::BadConstInPattern( - pat.span, def_id)); - PatternKind::Wild - } - } - } - None => { - self.errors.push(PatternError::StaticInPattern(pat.span)); - PatternKind::Wild - } - } - } - _ => self.lower_variant_or_leaf(def, vec![]) - } + return self.lower_path(qpath, pat.id, pat.id, pat.span); } PatKind::Ref(ref subpattern, _) | @@ -199,7 +319,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Slice(ref prefix, ref slice, ref suffix) => { - let ty = self.tcx.tables().node_id_to_type(pat.id); + let ty = self.tables.node_id_to_type(pat.id); match ty.sty { ty::TyRef(_, mt) => PatternKind::Deref { @@ -224,7 +344,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Tuple(ref subpatterns, ddpos) => { - let ty = self.tcx.tables().node_id_to_type(pat.id); + let ty = self.tables.node_id_to_type(pat.id); match ty.sty { ty::TyTuple(ref tys) => { let subpatterns = @@ -244,8 +364,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Binding(bm, def_id, ref ident, ref sub) => { - let id = self.tcx.map.as_local_node_id(def_id).unwrap(); - let var_ty = self.tcx.tables().node_id_to_type(pat.id); + let id = self.tcx.hir.as_local_node_id(def_id).unwrap(); + let var_ty = self.tables.node_id_to_type(pat.id); let region = match var_ty.sty { ty::TyRef(r, _) => Some(r), _ => None, @@ -282,9 +402,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); - let pat_ty = self.tcx.tables().node_id_to_type(pat.id); - let adt_def = match pat_ty.sty { + let def = self.tables.qpath_def(qpath, pat.id); + let adt_def = match ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"), }; @@ -298,13 +417,12 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { pattern: self.lower_pattern(field), }) .collect(); - self.lower_variant_or_leaf(def, subpatterns) + self.lower_variant_or_leaf(def, ty, subpatterns) } PatKind::Struct(ref qpath, ref fields, _) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); - let pat_ty = self.tcx.tables().node_id_to_type(pat.id); - let adt_def = match pat_ty.sty { + let def = self.tables.qpath_def(qpath, pat.id); + let adt_def = match ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { span_bug!( @@ -331,7 +449,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { }) .collect(); - self.lower_variant_or_leaf(def, subpatterns) + self.lower_variant_or_leaf(def, ty, subpatterns) } }; @@ -421,6 +539,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { fn lower_variant_or_leaf( &mut self, def: Def, + ty: Ty<'tcx>, subpatterns: Vec>) -> PatternKind<'tcx> { @@ -429,8 +548,14 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { let enum_id = self.tcx.parent_def_id(variant_id).unwrap(); let adt_def = self.tcx.lookup_adt_def(enum_id); if adt_def.variants.len() > 1 { + let substs = match ty.sty { + TypeVariants::TyAdt(_, substs) => substs, + TypeVariants::TyFnDef(_, substs, _) => substs, + _ => bug!("inappropriate type for def: {:?}", ty.sty), + }; PatternKind::Variant { adt_def: adt_def, + substs: substs, variant_index: adt_def.variant_index_with_id(variant_id), subpatterns: subpatterns, } @@ -447,6 +572,181 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { _ => bug!() } } + + fn lower_path(&mut self, + qpath: &hir::QPath, + id: ast::NodeId, + pat_id: ast::NodeId, + span: Span) + -> Pattern<'tcx> { + let ty = self.tables.node_id_to_type(id); + let def = self.tables.qpath_def(qpath, id); + let kind = match def { + Def::Const(def_id) | Def::AssociatedConst(def_id) => { + let tcx = self.tcx.global_tcx(); + let substs = self.tables.node_id_item_substs(id) + .unwrap_or_else(|| tcx.intern_substs(&[])); + match eval::lookup_const_by_id(tcx, def_id, Some(substs)) { + Some((const_expr, const_tables, _const_ty)) => { + // Enter the inlined constant's tables temporarily. + let old_tables = self.tables; + self.tables = const_tables.expect("missing tables after typeck"); + let pat = self.lower_const_expr(const_expr, pat_id, span); + self.tables = old_tables; + return pat; + } + None => { + self.errors.push(PatternError::StaticInPattern(span)); + PatternKind::Wild + } + } + } + _ => self.lower_variant_or_leaf(def, ty, vec![]), + }; + + Pattern { + span: span, + ty: ty, + kind: Box::new(kind), + } + } + + fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> { + let const_cx = eval::ConstContext::with_tables(self.tcx.global_tcx(), self.tables); + match const_cx.eval(expr, eval::EvalHint::ExprTypeChecked) { + Ok(value) => { + PatternKind::Constant { value: value } + } + Err(e) => { + self.errors.push(PatternError::ConstEval(e)); + PatternKind::Wild + } + } + } + + fn lower_const_expr(&mut self, + expr: &hir::Expr, + pat_id: ast::NodeId, + span: Span) + -> Pattern<'tcx> { + let pat_ty = self.tables.expr_ty(expr); + debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id); + match pat_ty.sty { + ty::TyFloat(_) => { + self.tcx.sess.add_lint( + lint::builtin::ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN, + pat_id, + span, + format!("floating point constants cannot be used in patterns")); + } + ty::TyAdt(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"); + } + ty::TyAdt(adt_def, _) => { + if !self.tcx.has_attr(adt_def.did, "structural_match") { + self.tcx.sess.add_lint( + lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN, + pat_id, + span, + 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), + self.tcx.item_path_str(adt_def.did))); + } + } + _ => { } + } + let kind = match expr.node { + hir::ExprTup(ref exprs) => { + PatternKind::Leaf { + subpatterns: exprs.iter().enumerate().map(|(i, expr)| { + FieldPattern { + field: Field::new(i), + pattern: self.lower_const_expr(expr, pat_id, span) + } + }).collect() + } + } + + hir::ExprCall(ref callee, ref args) => { + let qpath = match callee.node { + hir::ExprPath(ref qpath) => qpath, + _ => bug!() + }; + let ty = self.tables.node_id_to_type(callee.id); + let def = self.tables.qpath_def(qpath, callee.id); + match def { + Def::Fn(..) | Def::Method(..) => self.lower_lit(expr), + _ => { + let subpatterns = args.iter().enumerate().map(|(i, expr)| { + FieldPattern { + field: Field::new(i), + pattern: self.lower_const_expr(expr, pat_id, span) + } + }).collect(); + self.lower_variant_or_leaf(def, ty, subpatterns) + } + } + } + + hir::ExprStruct(ref qpath, ref fields, None) => { + let def = self.tables.qpath_def(qpath, expr.id); + let adt_def = match pat_ty.sty { + ty::TyAdt(adt_def, _) => adt_def, + _ => { + span_bug!( + expr.span, + "struct expr without ADT type"); + } + }; + let variant_def = adt_def.variant_of_def(def); + + let subpatterns = + fields.iter() + .map(|field| { + let index = variant_def.index_of_field_named(field.name.node); + let index = index.unwrap_or_else(|| { + span_bug!( + expr.span, + "no field with name {:?}", + field.name); + }); + FieldPattern { + field: Field::new(index), + pattern: self.lower_const_expr(&field.expr, pat_id, span), + } + }) + .collect(); + + self.lower_variant_or_leaf(def, pat_ty, subpatterns) + } + + hir::ExprArray(ref exprs) => { + let pats = exprs.iter() + .map(|expr| self.lower_const_expr(expr, pat_id, span)) + .collect(); + PatternKind::Array { + prefix: pats, + slice: None, + suffix: vec![] + } + } + + hir::ExprPath(ref qpath) => { + return self.lower_path(qpath, expr.id, pat_id, span); + } + + _ => self.lower_lit(expr) + }; + + Pattern { + span: span, + ty: pat_ty, + kind: Box::new(kind), + } + } } pub trait PatternFoldable<'tcx> : Sized { @@ -500,8 +800,9 @@ macro_rules! CloneImpls { } CloneImpls!{ <'tcx> - Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal, - Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef + Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal, Region, + Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef, + &'tcx Substs<'tcx>, &'tcx Kind<'tcx> } impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> { @@ -552,10 +853,12 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { }, PatternKind::Variant { adt_def, + substs, variant_index, ref subpatterns, } => PatternKind::Variant { adt_def: adt_def.fold_with(folder), + substs: substs.fold_with(folder), variant_index: variant_index.fold_with(folder), subpatterns: subpatterns.fold_with(folder) }, @@ -576,10 +879,12 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { }, PatternKind::Range { ref lo, - ref hi + ref hi, + ref end, } => PatternKind::Range { lo: lo.fold_with(folder), - hi: hi.fold_with(folder) + hi: hi.fold_with(folder), + end: end.clone(), }, PatternKind::Slice { ref prefix, diff --git a/src/librustc_const_math/Cargo.toml b/src/librustc_const_math/Cargo.toml index 10aadabe22..e6db1557fb 100644 --- a/src/librustc_const_math/Cargo.toml +++ b/src/librustc_const_math/Cargo.toml @@ -9,6 +9,6 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] -log = { path = "../liblog" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } +rustc_i128 = { path = "../librustc_i128" } diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index e2e30ef026..1e9c2badd6 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -74,11 +74,13 @@ impl ConstMathErr { ULitOutOfRange(ast::UintTy::U16) => "literal out of range for u16", ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32", ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64", + ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128", ULitOutOfRange(ast::UintTy::Us) => "literal out of range for usize", LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8", LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16", LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32", LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64", + LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128", LitOutOfRange(ast::IntTy::Is) => "literal out of range for isize", } } diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs index 28a5887847..53f185b661 100644 --- a/src/librustc_const_math/int.rs +++ b/src/librustc_const_math/int.rs @@ -11,6 +11,7 @@ use std::cmp::Ordering; use syntax::attr::IntType; use syntax::ast::{IntTy, UintTy}; +use rustc_i128::{i128, u128}; use super::is::*; use super::us::*; @@ -22,45 +23,98 @@ pub enum ConstInt { I16(i16), I32(i32), I64(i64), + I128(i128), Isize(ConstIsize), U8(u8), U16(u16), U32(u32), U64(u64), + U128(u128), Usize(ConstUsize), - Infer(u64), - InferSigned(i64), + Infer(u128), + InferSigned(i128), } pub use self::ConstInt::*; macro_rules! bounds { - ($($t:ident $min:ident $max:ident)*) => { - mod as_u64 { - $( - #[allow(dead_code)] - pub const $min: u64 = ::std::$t::MIN as u64; - #[allow(dead_code)] - pub const $max: u64 = ::std::$t::MAX as u64; - )* - } - mod as_i64 { - $( - #[allow(dead_code)] - pub const $min: i64 = ::std::$t::MIN as i64; - #[allow(dead_code)] - pub const $max: i64 = ::std::$t::MAX as i64; - )* - } + ($ct: ty, $($t:ident $min:ident $max:ident)*) => { + $( + pub const $min: $ct = $t::min_value() as $ct; + pub const $max: $ct = $t::max_value() as $ct; + )* + }; + ($ct: ty: $min_val: expr, $($t:ident $min:ident $max:ident)*) => { + $( + pub const $min: $ct = $min_val; + pub const $max: $ct = $t::max_value() as $ct; + )* + } +} + +mod ubounds { + #![allow(dead_code)] + use rustc_i128::{u128, i128}; + bounds!{u128: 0, + i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX + u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX + // do not add constants for isize/usize, because these are guaranteed to be wrong for + // arbitrary host/target combinations } } -bounds!{ - i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX isize IMIN IMAX - u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX usize UMIN UMAX +mod ibounds { + #![allow(dead_code)] + use rustc_i128::i128; + #[cfg(stage0)] + pub const U64MIN: i128 = 0; + #[cfg(stage0)] + pub const U64MAX: i128 = i128::max_value(); + #[cfg(not(stage0))] + bounds!(i128, u64 U64MIN U64MAX); + + pub const U128MIN: i128 = 0; + pub const U128MAX: i128 = i128::max_value(); + + bounds!{i128, + i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX + u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX + // do not add constants for isize/usize, because these are guaranteed to be wrong for + // arbitrary host/target combinations + } } impl ConstInt { + /// Creates a new unsigned ConstInt with matching type while also checking that overflow does + /// not happen. + pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option { + match ty { + UintTy::U8 if val <= ubounds::U8MAX => Some(U8(val as u8)), + UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)), + UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)), + UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)), + UintTy::Us if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok() + .map(Usize), + UintTy::U128 => Some(U128(val)), + _ => None + } + } + + /// Creates a new unsigned ConstInt with matching type while also checking that overflow does + /// not happen. + pub fn new_signed(val: i128, ty: IntTy, isize_ty: IntTy) -> Option { + match ty { + IntTy::I8 if val <= ibounds::I8MAX => Some(I8(val as i8)), + IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)), + IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)), + IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)), + IntTy::Is if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok() + .map(Isize), + IntTy::I128 => Some(I128(val)), + _ => None + } + } + /// If either value is `Infer` or `InferSigned`, try to turn the value into the type of /// the other value. If both values have no type, don't do anything pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> { @@ -68,46 +122,54 @@ impl ConstInt { (InferSigned(_), InferSigned(_)) | (Infer(_), Infer(_)) => self, // no inference possible // kindof wrong, you could have had values > I64MAX during computation of a - (Infer(a @ 0...as_u64::I64MAX), InferSigned(_)) => InferSigned(a as i64), + (Infer(a @ 0...ubounds::I64MAX), InferSigned(_)) => InferSigned(a as i128), (Infer(_), InferSigned(_)) => return Err(ConstMathErr::NotInRange), (_, InferSigned(_)) | (_, Infer(_)) => return other.infer(self).map(|(b, a)| (a, b)), - (Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i64 as i8), - (Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i64 as i16), - (Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i64 as i32), - (Infer(a @ 0...as_u64::I64MAX), I64(_)) => I64(a as i64), - (Infer(a @ 0...as_u64::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)), - (Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)), - (Infer(a @ 0...as_u64::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)), - (Infer(a @ 0...as_u64::U8MAX), U8(_)) => U8(a as u8), - (Infer(a @ 0...as_u64::U16MAX), U16(_)) => U16(a as u16), - (Infer(a @ 0...as_u64::U32MAX), U32(_)) => U32(a as u32), - (Infer(a), U64(_)) => U64(a), - (Infer(a @ 0...as_u64::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)), - (Infer(a @ 0...as_u64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)), - (Infer(a), Usize(Us64(_))) => Usize(Us64(a)), + (Infer(a @ 0...ubounds::I8MAX), I8(_)) => I8(a as i64 as i8), + (Infer(a @ 0...ubounds::I16MAX), I16(_)) => I16(a as i64 as i16), + (Infer(a @ 0...ubounds::I32MAX), I32(_)) => I32(a as i64 as i32), + (Infer(a @ 0...ubounds::I64MAX), I64(_)) => I64(a as i64), + (Infer(a @ 0...ubounds::I128MAX), I128(_)) => I128(a as i128), + (Infer(a @ 0...ubounds::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)), + (Infer(a @ 0...ubounds::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)), + (Infer(a @ 0...ubounds::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)), + (Infer(a @ 0...ubounds::U8MAX), U8(_)) => U8(a as u8), + (Infer(a @ 0...ubounds::U16MAX), U16(_)) => U16(a as u16), + (Infer(a @ 0...ubounds::U32MAX), U32(_)) => U32(a as u32), + (Infer(a @ 0...ubounds::U64MAX), U64(_)) => U64(a as u64), + (Infer(a @ 0...ubounds::U128MAX), U128(_)) => U128(a as u128), + (Infer(a @ 0...ubounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)), + (Infer(a @ 0...ubounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)), + (Infer(a @ 0...ubounds::U64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)), (Infer(_), _) => return Err(ConstMathErr::NotInRange), - (InferSigned(a @ as_i64::I8MIN...as_i64::I8MAX), I8(_)) => I8(a as i8), - (InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), I16(_)) => I16(a as i16), - (InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), I32(_)) => I32(a as i32), - (InferSigned(a), I64(_)) => I64(a), - (InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), Isize(Is16(_))) => { + (InferSigned(a @ ibounds::I8MIN...ibounds::I8MAX), I8(_)) => I8(a as i8), + (InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), I16(_)) => I16(a as i16), + (InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), I32(_)) => I32(a as i32), + (InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), I64(_)) => I64(a as i64), + (InferSigned(a @ ibounds::I128MIN...ibounds::I128MAX), I128(_)) => I128(a as i128), + (InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), Isize(Is16(_))) => { Isize(Is16(a as i16)) }, - (InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), Isize(Is32(_))) => { + (InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), Isize(Is32(_))) => { Isize(Is32(a as i32)) }, - (InferSigned(a), Isize(Is64(_))) => Isize(Is64(a)), - (InferSigned(a @ 0...as_i64::U8MAX), U8(_)) => U8(a as u8), - (InferSigned(a @ 0...as_i64::U16MAX), U16(_)) => U16(a as u16), - (InferSigned(a @ 0...as_i64::U32MAX), U32(_)) => U32(a as u32), - (InferSigned(a @ 0...as_i64::I64MAX), U64(_)) => U64(a as u64), - (InferSigned(a @ 0...as_i64::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)), - (InferSigned(a @ 0...as_i64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)), - (InferSigned(a @ 0...as_i64::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)), + (InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), Isize(Is64(_))) => { + Isize(Is64(a as i64)) + }, + (InferSigned(a @ 0...ibounds::U8MAX), U8(_)) => U8(a as u8), + (InferSigned(a @ 0...ibounds::U16MAX), U16(_)) => U16(a as u16), + (InferSigned(a @ 0...ibounds::U32MAX), U32(_)) => U32(a as u32), + // SNAP: replace with U64MAX + (InferSigned(a @ 0...ibounds::I64MAX), U64(_)) => U64(a as u64), + (InferSigned(a @ 0...ibounds::I128MAX), U128(_)) => U128(a as u128), + (InferSigned(a @ 0...ibounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)), + (InferSigned(a @ 0...ibounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)), + // SNAP: replace with U64MAX + (InferSigned(a @ 0...ibounds::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)), (InferSigned(_), _) => return Err(ConstMathErr::NotInRange), _ => self, // already known types }; @@ -119,28 +181,31 @@ impl ConstInt { match self { Infer(i) => Infer(i), InferSigned(i) if i < 0 => InferSigned(i), - I8(i) if i < 0 => InferSigned(i as i64), - I16(i) if i < 0 => InferSigned(i as i64), - I32(i) if i < 0 => InferSigned(i as i64), - I64(i) if i < 0 => InferSigned(i as i64), - Isize(Is16(i)) if i < 0 => InferSigned(i as i64), - Isize(Is32(i)) if i < 0 => InferSigned(i as i64), - Isize(Is64(i)) if i < 0 => InferSigned(i as i64), - InferSigned(i) => Infer(i as u64), - I8(i) => Infer(i as u64), - I16(i) => Infer(i as u64), - I32(i) => Infer(i as u64), - I64(i) => Infer(i as u64), - Isize(Is16(i)) => Infer(i as u64), - Isize(Is32(i)) => Infer(i as u64), - Isize(Is64(i)) => Infer(i as u64), - U8(i) => Infer(i as u64), - U16(i) => Infer(i as u64), - U32(i) => Infer(i as u64), - U64(i) => Infer(i as u64), - Usize(Us16(i)) => Infer(i as u64), - Usize(Us32(i)) => Infer(i as u64), - Usize(Us64(i)) => Infer(i), + I8(i) if i < 0 => InferSigned(i as i128), + I16(i) if i < 0 => InferSigned(i as i128), + I32(i) if i < 0 => InferSigned(i as i128), + I64(i) if i < 0 => InferSigned(i as i128), + I128(i) if i < 0 => InferSigned(i as i128), + Isize(Is16(i)) if i < 0 => InferSigned(i as i128), + Isize(Is32(i)) if i < 0 => InferSigned(i as i128), + Isize(Is64(i)) if i < 0 => InferSigned(i as i128), + InferSigned(i) => Infer(i as u128), + I8(i) => Infer(i as u128), + I16(i) => Infer(i as u128), + I32(i) => Infer(i as u128), + I64(i) => Infer(i as u128), + I128(i) => Infer(i as u128), + Isize(Is16(i)) => Infer(i as u128), + Isize(Is32(i)) => Infer(i as u128), + Isize(Is64(i)) => Infer(i as u128), + U8(i) => Infer(i as u128), + U16(i) => Infer(i as u128), + U32(i) => Infer(i as u128), + U64(i) => Infer(i as u128), + U128(i) => Infer(i as u128), + Usize(Us16(i)) => Infer(i as u128), + Usize(Us32(i)) => Infer(i as u128), + Usize(Us64(i)) => Infer(i as u128), } } @@ -153,67 +218,66 @@ impl ConstInt { I16(_) => "i16", I32(_) => "i32", I64(_) => "i64", + I128(_) => "i128", Isize(_) => "isize", U8(_) => "u8", U16(_) => "u16", U32(_) => "u32", U64(_) => "u64", + U128(_) => "u128", Usize(_) => "usize", } } - /// Erases the type and returns a u64. - /// This is not the same as `-5i8 as u64` but as `-5i8 as i64 as u64` - pub fn to_u64_unchecked(self) -> u64 { + /// Erases the type and returns a u128. + /// This is not the same as `-5i8 as u128` but as `-5i8 as i128 as u128` + pub fn to_u128_unchecked(self) -> u128 { match self.erase_type() { ConstInt::Infer(i) => i, - ConstInt::InferSigned(i) => i as u64, + ConstInt::InferSigned(i) => i as u128, _ => unreachable!(), } } /// Converts the value to a `u32` if it's in the range 0...std::u32::MAX pub fn to_u32(&self) -> Option { - match *self { - I8(v) if v >= 0 => Some(v as u32), - I16(v) if v >= 0 => Some(v as u32), - I32(v) if v >= 0 => Some(v as u32), - InferSigned(v) - | Isize(Is64(v)) - | I64(v) if v >= 0 && v <= ::std::u32::MAX as i64 => Some(v as u32), - Isize(Is32(v)) if v >= 0 => Some(v as u32), - Isize(Is16(v)) if v >= 0 => Some(v as u32), - U8(v) => Some(v as u32), - U16(v) => Some(v as u32), - U32(v) => Some(v), - Infer(v) - | Usize(Us64(v)) - | U64(v) if v <= ::std::u32::MAX as u64 => Some(v as u32), - Usize(Us32(v)) => Some(v), - Usize(Us16(v)) => Some(v as u32), - _ => None, - } + self.to_u128().and_then(|v| if v <= u32::max_value() as u128 { + Some(v as u32) + } else { + None + }) } - /// Converts the value to a `u64` if it's >= 0 + /// Converts the value to a `u64` if it's in the range 0...std::u64::MAX pub fn to_u64(&self) -> Option { + self.to_u128().and_then(|v| if v <= u64::max_value() as u128 { + Some(v as u64) + } else { + None + }) + } + + /// Converts the value to a `u128` if it's in the range 0...std::u128::MAX + pub fn to_u128(&self) -> Option { match *self { Infer(v) => Some(v), - InferSigned(v) if v >= 0 => Some(v as u64), - I8(v) if v >= 0 => Some(v as u64), - I16(v) if v >= 0 => Some(v as u64), - I32(v) if v >= 0 => Some(v as u64), - I64(v) if v >= 0 => Some(v as u64), - Isize(Is16(v)) if v >= 0 => Some(v as u64), - Isize(Is32(v)) if v >= 0 => Some(v as u64), - Isize(Is64(v)) if v >= 0 => Some(v as u64), - U8(v) => Some(v as u64), - U16(v) => Some(v as u64), - U32(v) => Some(v as u64), - U64(v) => Some(v), - Usize(Us16(v)) => Some(v as u64), - Usize(Us32(v)) => Some(v as u64), - Usize(Us64(v)) => Some(v), + InferSigned(v) if v >= 0 => Some(v as u128), + I8(v) if v >= 0 => Some(v as u128), + I16(v) if v >= 0 => Some(v as u128), + I32(v) if v >= 0 => Some(v as u128), + I64(v) if v >= 0 => Some(v as u128), + I128(v) if v >= 0 => Some(v as u128), + Isize(Is16(v)) if v >= 0 => Some(v as u128), + Isize(Is32(v)) if v >= 0 => Some(v as u128), + Isize(Is64(v)) if v >= 0 => Some(v as u128), + U8(v) => Some(v as u128), + U16(v) => Some(v as u128), + U32(v) => Some(v as u128), + U64(v) => Some(v as u128), + U128(v) => Some(v as u128), + Usize(Us16(v)) => Some(v as u128), + Usize(Us32(v)) => Some(v as u128), + Usize(Us64(v)) => Some(v as u128), _ => None, } } @@ -224,6 +288,7 @@ impl ConstInt { I16(v) => v < 0, I32(v) => v < 0, I64(v) => v < 0, + I128(v) => v < 0, Isize(Is16(v)) => v < 0, Isize(Is32(v)) => v < 0, Isize(Is64(v)) => v < 0, @@ -239,6 +304,7 @@ impl ConstInt { (I16(a), I16(b)) => Ok(a.cmp(&b)), (I32(a), I32(b)) => Ok(a.cmp(&b)), (I64(a), I64(b)) => Ok(a.cmp(&b)), + (I128(a), I128(b)) => Ok(a.cmp(&b)), (Isize(Is16(a)), Isize(Is16(b))) => Ok(a.cmp(&b)), (Isize(Is32(a)), Isize(Is32(b))) => Ok(a.cmp(&b)), (Isize(Is64(a)), Isize(Is64(b))) => Ok(a.cmp(&b)), @@ -246,6 +312,7 @@ impl ConstInt { (U16(a), U16(b)) => Ok(a.cmp(&b)), (U32(a), U32(b)) => Ok(a.cmp(&b)), (U64(a), U64(b)) => Ok(a.cmp(&b)), + (U128(a), U128(b)) => Ok(a.cmp(&b)), (Usize(Us16(a)), Usize(Us16(b))) => Ok(a.cmp(&b)), (Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)), (Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)), @@ -265,6 +332,7 @@ impl ConstInt { ConstInt::I16(i) => ConstInt::I16(add1!(i)), ConstInt::I32(i) => ConstInt::I32(add1!(i)), ConstInt::I64(i) => ConstInt::I64(add1!(i)), + ConstInt::I128(i) => ConstInt::I128(add1!(i)), ConstInt::Isize(ConstIsize::Is16(i)) => ConstInt::Isize(ConstIsize::Is16(add1!(i))), ConstInt::Isize(ConstIsize::Is32(i)) => ConstInt::Isize(ConstIsize::Is32(add1!(i))), ConstInt::Isize(ConstIsize::Is64(i)) => ConstInt::Isize(ConstIsize::Is64(add1!(i))), @@ -272,6 +340,7 @@ impl ConstInt { ConstInt::U16(i) => ConstInt::U16(add1!(i)), ConstInt::U32(i) => ConstInt::U32(add1!(i)), ConstInt::U64(i) => ConstInt::U64(add1!(i)), + ConstInt::U128(i) => ConstInt::U128(add1!(i)), ConstInt::Usize(ConstUsize::Us16(i)) => ConstInt::Usize(ConstUsize::Us16(add1!(i))), ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))), ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))), @@ -285,11 +354,13 @@ impl ConstInt { ConstInt::I16(_) => Some(IntType::SignedInt(IntTy::I16)), ConstInt::I32(_) => Some(IntType::SignedInt(IntTy::I32)), ConstInt::I64(_) => Some(IntType::SignedInt(IntTy::I64)), + ConstInt::I128(_) => Some(IntType::SignedInt(IntTy::I128)), ConstInt::Isize(_) => Some(IntType::SignedInt(IntTy::Is)), ConstInt::U8(_) => Some(IntType::UnsignedInt(UintTy::U8)), ConstInt::U16(_) => Some(IntType::UnsignedInt(UintTy::U16)), ConstInt::U32(_) => Some(IntType::UnsignedInt(UintTy::U32)), ConstInt::U64(_) => Some(IntType::UnsignedInt(UintTy::U64)), + ConstInt::U128(_) => Some(IntType::UnsignedInt(UintTy::U128)), ConstInt::Usize(_) => Some(IntType::UnsignedInt(UintTy::Us)), _ => None, } @@ -317,6 +388,7 @@ impl ::std::fmt::Display for ConstInt { I16(i) => write!(fmt, "{}i16", i), I32(i) => write!(fmt, "{}i32", i), I64(i) => write!(fmt, "{}i64", i), + I128(i) => write!(fmt, "{}i128", i), Isize(ConstIsize::Is64(i)) => write!(fmt, "{}isize", i), Isize(ConstIsize::Is32(i)) => write!(fmt, "{}isize", i), Isize(ConstIsize::Is16(i)) => write!(fmt, "{}isize", i), @@ -324,6 +396,7 @@ impl ::std::fmt::Display for ConstInt { U16(i) => write!(fmt, "{}u16", i), U32(i) => write!(fmt, "{}u32", i), U64(i) => write!(fmt, "{}u64", i), + U128(i) => write!(fmt, "{}u128", i), Usize(ConstUsize::Us64(i)) => write!(fmt, "{}usize", i), Usize(ConstUsize::Us32(i)) => write!(fmt, "{}usize", i), Usize(ConstUsize::Us16(i)) => write!(fmt, "{}usize", i), @@ -351,6 +424,7 @@ macro_rules! impl_binop { (I16(a), I16(b)) => a.$checked_func(b).map(I16), (I32(a), I32(b)) => a.$checked_func(b).map(I32), (I64(a), I64(b)) => a.$checked_func(b).map(I64), + (I128(a), I128(b)) => a.$checked_func(b).map(I128), (Isize(Is16(a)), Isize(Is16(b))) => a.$checked_func(b).map(Is16).map(Isize), (Isize(Is32(a)), Isize(Is32(b))) => a.$checked_func(b).map(Is32).map(Isize), (Isize(Is64(a)), Isize(Is64(b))) => a.$checked_func(b).map(Is64).map(Isize), @@ -358,6 +432,7 @@ macro_rules! impl_binop { (U16(a), U16(b)) => a.$checked_func(b).map(U16), (U32(a), U32(b)) => a.$checked_func(b).map(U32), (U64(a), U64(b)) => a.$checked_func(b).map(U64), + (U128(a), U128(b)) => a.$checked_func(b).map(U128), (Usize(Us16(a)), Usize(Us16(b))) => a.$checked_func(b).map(Us16).map(Usize), (Usize(Us32(a)), Usize(Us32(b))) => a.$checked_func(b).map(Us32).map(Usize), (Usize(Us64(a)), Usize(Us64(b))) => a.$checked_func(b).map(Us64).map(Usize), @@ -380,6 +455,7 @@ macro_rules! derive_binop { (I16(a), I16(b)) => Ok(I16(a.$func(b))), (I32(a), I32(b)) => Ok(I32(a.$func(b))), (I64(a), I64(b)) => Ok(I64(a.$func(b))), + (I128(a), I128(b)) => Ok(I128(a.$func(b))), (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a.$func(b)))), (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a.$func(b)))), (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a.$func(b)))), @@ -387,6 +463,7 @@ macro_rules! derive_binop { (U16(a), U16(b)) => Ok(U16(a.$func(b))), (U32(a), U32(b)) => Ok(U32(a.$func(b))), (U64(a), U64(b)) => Ok(U64(a.$func(b))), + (U128(a), U128(b)) => Ok(U128(a.$func(b))), (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a.$func(b)))), (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a.$func(b)))), (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a.$func(b)))), @@ -406,6 +483,11 @@ derive_binop!(BitAnd, bitand); derive_binop!(BitOr, bitor); derive_binop!(BitXor, bitxor); +#[cfg(not(stage0))] +const I128_MIN: i128 = ::std::i128::MIN; +#[cfg(stage0)] +const I128_MIN: i128 = ::std::i64::MIN; + fn check_division( lhs: ConstInt, rhs: ConstInt, @@ -417,6 +499,7 @@ fn check_division( (I16(_), I16(0)) => Err(zerr), (I32(_), I32(0)) => Err(zerr), (I64(_), I64(0)) => Err(zerr), + (I128(_), I128(0)) => Err(zerr), (Isize(_), Isize(Is16(0))) => Err(zerr), (Isize(_), Isize(Is32(0))) => Err(zerr), (Isize(_), Isize(Is64(0))) => Err(zerr), @@ -426,6 +509,7 @@ fn check_division( (U16(_), U16(0)) => Err(zerr), (U32(_), U32(0)) => Err(zerr), (U64(_), U64(0)) => Err(zerr), + (U128(_), U128(0)) => Err(zerr), (Usize(_), Usize(Us16(0))) => Err(zerr), (Usize(_), Usize(Us32(0))) => Err(zerr), (Usize(_), Usize(Us64(0))) => Err(zerr), @@ -435,10 +519,11 @@ fn check_division( (I16(::std::i16::MIN), I16(-1)) => Err(Overflow(op)), (I32(::std::i32::MIN), I32(-1)) => Err(Overflow(op)), (I64(::std::i64::MIN), I64(-1)) => Err(Overflow(op)), + (I128(I128_MIN), I128(-1)) => Err(Overflow(op)), (Isize(Is16(::std::i16::MIN)), Isize(Is16(-1))) => Err(Overflow(op)), (Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)), (Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)), - (InferSigned(::std::i64::MIN), InferSigned(-1)) => Err(Overflow(op)), + (InferSigned(I128_MIN), InferSigned(-1)) => Err(Overflow(op)), _ => Ok(()), } @@ -454,6 +539,7 @@ impl ::std::ops::Div for ConstInt { (I16(a), I16(b)) => Ok(I16(a/b)), (I32(a), I32(b)) => Ok(I32(a/b)), (I64(a), I64(b)) => Ok(I64(a/b)), + (I128(a), I128(b)) => Ok(I128(a/b)), (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a/b))), (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))), (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))), @@ -463,6 +549,7 @@ impl ::std::ops::Div for ConstInt { (U16(a), U16(b)) => Ok(U16(a/b)), (U32(a), U32(b)) => Ok(U32(a/b)), (U64(a), U64(b)) => Ok(U64(a/b)), + (U128(a), U128(b)) => Ok(U128(a/b)), (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a/b))), (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))), (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))), @@ -484,6 +571,7 @@ impl ::std::ops::Rem for ConstInt { (I16(a), I16(b)) => Ok(I16(a%b)), (I32(a), I32(b)) => Ok(I32(a%b)), (I64(a), I64(b)) => Ok(I64(a%b)), + (I128(a), I128(b)) => Ok(I128(a%b)), (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a%b))), (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))), (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))), @@ -493,6 +581,7 @@ impl ::std::ops::Rem for ConstInt { (U16(a), U16(b)) => Ok(U16(a%b)), (U32(a), U32(b)) => Ok(U32(a%b)), (U64(a), U64(b)) => Ok(U64(a%b)), + (U128(a), U128(b)) => Ok(U128(a%b)), (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a%b))), (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))), (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))), @@ -512,6 +601,7 @@ impl ::std::ops::Shl for ConstInt { I16(a) => Ok(I16(overflowing!(a.overflowing_shl(b), Op::Shl))), I32(a) => Ok(I32(overflowing!(a.overflowing_shl(b), Op::Shl))), I64(a) => Ok(I64(overflowing!(a.overflowing_shl(b), Op::Shl))), + I128(a) => Ok(I128(overflowing!(a.overflowing_shl(b), Op::Shl))), Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shl(b), Op::Shl)))), Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shl(b), Op::Shl)))), Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shl(b), Op::Shl)))), @@ -519,6 +609,7 @@ impl ::std::ops::Shl for ConstInt { U16(a) => Ok(U16(overflowing!(a.overflowing_shl(b), Op::Shl))), U32(a) => Ok(U32(overflowing!(a.overflowing_shl(b), Op::Shl))), U64(a) => Ok(U64(overflowing!(a.overflowing_shl(b), Op::Shl))), + U128(a) => Ok(U128(overflowing!(a.overflowing_shl(b), Op::Shl))), Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shl(b), Op::Shl)))), Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shl(b), Op::Shl)))), Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shl(b), Op::Shl)))), @@ -537,6 +628,7 @@ impl ::std::ops::Shr for ConstInt { I16(a) => Ok(I16(overflowing!(a.overflowing_shr(b), Op::Shr))), I32(a) => Ok(I32(overflowing!(a.overflowing_shr(b), Op::Shr))), I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shr))), + I128(a) => Ok(I128(overflowing!(a.overflowing_shr(b), Op::Shr))), Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shr(b), Op::Shr)))), Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shr(b), Op::Shr)))), Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shr(b), Op::Shr)))), @@ -544,6 +636,7 @@ impl ::std::ops::Shr for ConstInt { U16(a) => Ok(U16(overflowing!(a.overflowing_shr(b), Op::Shr))), U32(a) => Ok(U32(overflowing!(a.overflowing_shr(b), Op::Shr))), U64(a) => Ok(U64(overflowing!(a.overflowing_shr(b), Op::Shr))), + U128(a) => Ok(U128(overflowing!(a.overflowing_shr(b), Op::Shr))), Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shr(b), Op::Shr)))), Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shr(b), Op::Shr)))), Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shr(b), Op::Shr)))), @@ -561,22 +654,14 @@ impl ::std::ops::Neg for ConstInt { I16(a) => Ok(I16(overflowing!(a.overflowing_neg(), Op::Neg))), I32(a) => Ok(I32(overflowing!(a.overflowing_neg(), Op::Neg))), I64(a) => Ok(I64(overflowing!(a.overflowing_neg(), Op::Neg))), + I128(a) => Ok(I128(overflowing!(a.overflowing_neg(), Op::Neg))), Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_neg(), Op::Neg)))), Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_neg(), Op::Neg)))), Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_neg(), Op::Neg)))), - U8(0) => Ok(U8(0)), - U16(0) => Ok(U16(0)), - U32(0) => Ok(U32(0)), - U64(0) => Ok(U64(0)), - Usize(Us16(0)) => Ok(Usize(Us16(0))), - Usize(Us32(0)) => Ok(Usize(Us32(0))), - Usize(Us64(0)) => Ok(Usize(Us64(0))), - U8(_) => Err(UnsignedNegation), - U16(_) => Err(UnsignedNegation), - U32(_) => Err(UnsignedNegation), - U64(_) => Err(UnsignedNegation), - Usize(_) => Err(UnsignedNegation), - Infer(a @ 0...as_u64::I64MAX) => Ok(InferSigned(-(a as i64))), + a@U8(0) | a@U16(0) | a@U32(0) | a@U64(0) | a@U128(0) | + a@Usize(Us16(0)) | a@Usize(Us32(0)) | a@Usize(Us64(0)) => Ok(a), + U8(_) | U16(_) | U32(_) | U64(_) | U128(_) | Usize(_) => Err(UnsignedNegation), + Infer(a @ 0...ubounds::I128MAX) => Ok(InferSigned(-(a as i128))), Infer(_) => Err(Overflow(Op::Neg)), InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_neg(), Op::Neg))), } @@ -591,6 +676,7 @@ impl ::std::ops::Not for ConstInt { I16(a) => Ok(I16(!a)), I32(a) => Ok(I32(!a)), I64(a) => Ok(I64(!a)), + I128(a) => Ok(I128(!a)), Isize(Is16(a)) => Ok(Isize(Is16(!a))), Isize(Is32(a)) => Ok(Isize(Is32(!a))), Isize(Is64(a)) => Ok(Isize(Is64(!a))), @@ -598,6 +684,7 @@ impl ::std::ops::Not for ConstInt { U16(a) => Ok(U16(!a)), U32(a) => Ok(U32(!a)), U64(a) => Ok(U64(!a)), + U128(a) => Ok(U128(!a)), Usize(Us16(a)) => Ok(Usize(Us16(!a))), Usize(Us32(a)) => Ok(Usize(Us32(!a))), Usize(Us64(a)) => Ok(Usize(Us64(!a))), diff --git a/src/librustc_const_math/is.rs b/src/librustc_const_math/is.rs index ef92b62852..19ae0c91fc 100644 --- a/src/librustc_const_math/is.rs +++ b/src/librustc_const_math/is.rs @@ -10,6 +10,7 @@ use syntax::ast; use super::err::*; +use rustc_i128::i128; /// Depending on the target only one variant is ever used in a compilation. /// Anything else is an error. This invariant is checked at several locations @@ -41,11 +42,11 @@ impl ConstIsize { _ => unreachable!(), } } - pub fn new_truncating(i: i64, target_int_ty: ast::IntTy) -> Self { + pub fn new_truncating(i: i128, target_int_ty: ast::IntTy) -> Self { match target_int_ty { ast::IntTy::I16 => Is16(i as i16), ast::IntTy::I32 => Is32(i as i32), - ast::IntTy::I64 => Is64(i), + ast::IntTy::I64 => Is64(i as i64), _ => unreachable!(), } } diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index f667ff23b2..d40a6aa32f 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -25,9 +25,13 @@ #![feature(rustc_private)] #![feature(staged_api)] +#![feature(const_fn)] +#![cfg_attr(not(stage0), feature(i128))] -#[macro_use] extern crate log; -#[macro_use] extern crate syntax; +extern crate syntax; + +// SNAP: remove use of this crate +extern crate rustc_i128; extern crate serialize as rustc_serialize; // used by deriving diff --git a/src/librustc_const_math/us.rs b/src/librustc_const_math/us.rs index bf73ff03c9..9ebf5cab6b 100644 --- a/src/librustc_const_math/us.rs +++ b/src/librustc_const_math/us.rs @@ -10,6 +10,7 @@ use syntax::ast; use super::err::*; +use rustc_i128::u128; /// Depending on the target only one variant is ever used in a compilation. /// Anything else is an error. This invariant is checked at several locations @@ -41,11 +42,11 @@ impl ConstUsize { _ => unreachable!(), } } - pub fn new_truncating(i: u64, target_uint_ty: ast::UintTy) -> Self { + pub fn new_truncating(i: u128, target_uint_ty: ast::UintTy) -> Self { match target_uint_ty { ast::UintTy::U16 => Us16(i as u16), ast::UintTy::U32 => Us32(i as u32), - ast::UintTy::U64 => Us64(i), + ast::UintTy::U64 => Us64(i as u64), _ => unreachable!(), } } diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index e2e16059d9..bb61037481 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -11,3 +11,4 @@ crate-type = ["dylib"] [dependencies] log = { path = "../liblog" } serialize = { path = "../libserialize" } +rustc_i128 = { path = "../librustc_i128" } diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs index 937cb3f600..d4bd9e707f 100644 --- a/src/librustc_data_structures/accumulate_vec.rs +++ b/src/librustc_data_structures/accumulate_vec.rs @@ -19,12 +19,13 @@ use std::ops::{Deref, DerefMut}; use std::iter::{self, IntoIterator, FromIterator}; use std::slice; use std::vec; +use std::collections::range::RangeArgument; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use array_vec::{self, Array, ArrayVec}; -#[derive(PartialEq, Eq, Hash, Debug)] +#[derive(Hash, Debug)] pub enum AccumulateVec { Array(ArrayVec), Heap(Vec) @@ -71,6 +72,19 @@ impl AccumulateVec { AccumulateVec::Heap(ref mut vec) => vec.pop(), } } + + pub fn drain(&mut self, range: R) -> Drain + where R: RangeArgument + { + 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 { @@ -132,6 +146,31 @@ impl Iterator for IntoIter { } } +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; diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index 631cf2cfcf..51e6e09ab5 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -12,12 +12,14 @@ use std::marker::Unsize; use std::iter::Extend; -use std::ptr::{self, drop_in_place}; +use std::ptr::{self, drop_in_place, Shared}; use std::ops::{Deref, DerefMut, Range}; use std::hash::{Hash, Hasher}; use std::slice; use std::fmt; use std::mem; +use std::collections::range::RangeArgument; +use std::collections::Bound::{Excluded, Included, Unbounded}; pub unsafe trait Array { type Element; @@ -50,14 +52,6 @@ impl Hash for ArrayVec } } -impl PartialEq for ArrayVec { - fn eq(&self, other: &Self) -> bool { - self == other - } -} - -impl Eq for ArrayVec {} - impl Clone for ArrayVec where A: Array, A::Element: Clone { @@ -103,6 +97,52 @@ impl ArrayVec { None } } + + pub fn drain(&mut self, range: R) -> Drain + where R: RangeArgument + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitalized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let start = match range.start() { + Included(&n) => n, + Excluded(&n) => n + 1, + Unbounded => 0, + }; + let end = match range.end() { + Included(&n) => n + 1, + Excluded(&n) => n, + Unbounded => len, + }; + assert!(start <= end); + assert!(end <= len); + + unsafe { + // set self.vec length's to start, to be safe in case Drain is leaked + 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 = { + let arr = &mut self.values as &mut [ManuallyDrop<_>]; + slice::from_raw_parts_mut(arr.as_mut_ptr().offset(start as isize), + end - start) + }; + Drain { + tail_start: end, + tail_len: len - end, + iter: range_slice.iter(), + array_vec: Shared::new(self as *mut _), + } + } + } } impl Default for ArrayVec @@ -179,6 +219,51 @@ impl Iterator for Iter { } } +pub struct Drain<'a, A: Array> + where A::Element: 'a +{ + tail_start: usize, + tail_len: usize, + iter: slice::Iter<'a, ManuallyDrop>, + array_vec: Shared>, +} + +impl<'a, A: Array> Iterator for Drain<'a, A> { + type Item = A::Element; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt as *const ManuallyDrop<_>).value }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, A: Array> Drop for Drain<'a, A> { + fn drop(&mut self) { + // exhaust self first + while let Some(_) = self.next() {} + + if self.tail_len > 0 { + unsafe { + let source_array_vec = &mut **self.array_vec; + // memmove back untouched tail, update to new length + let start = source_array_vec.len(); + let tail = self.tail_start; + { + let mut arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>]; + let src = arr.as_ptr().offset(tail as isize); + let dst = arr.as_mut_ptr().offset(start as isize); + ptr::copy(src, dst, self.tail_len); + }; + source_array_vec.set_len(start + self.tail_len); + } + } + } +} + impl IntoIterator for ArrayVec { type Item = A::Element; type IntoIter = Iter; diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 0dab230f47..3700d46c34 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -17,23 +17,27 @@ pub struct BitVector { } impl BitVector { + #[inline] pub fn new(num_bits: usize) -> BitVector { let num_words = u64s(num_bits); BitVector { data: vec![0; num_words] } } + #[inline] pub fn clear(&mut self) { for p in &mut self.data { *p = 0; } } + #[inline] pub fn contains(&self, bit: usize) -> bool { let (word, mask) = word_mask(bit); (self.data[word] & mask) != 0 } /// Returns true if the bit has changed. + #[inline] pub fn insert(&mut self, bit: usize) -> bool { let (word, mask) = word_mask(bit); let data = &mut self.data[word]; @@ -43,6 +47,7 @@ impl BitVector { new_value != value } + #[inline] pub fn insert_all(&mut self, all: &BitVector) -> bool { assert!(self.data.len() == all.data.len()); let mut changed = false; @@ -56,6 +61,7 @@ impl BitVector { changed } + #[inline] pub fn grow(&mut self, num_bits: usize) { let num_words = u64s(num_bits); if self.data.len() < num_words { @@ -64,6 +70,7 @@ impl BitVector { } /// Iterates over indexes of set bits in a sorted order + #[inline] pub fn iter<'a>(&'a self) -> BitVectorIter<'a> { BitVectorIter { iter: self.data.iter(), @@ -226,10 +233,12 @@ impl BitMatrix { } } +#[inline] fn u64s(elements: usize) -> usize { (elements + 63) / 64 } +#[inline] fn word_mask(index: usize) -> (usize, u64) { let word = index / 64; let mask = 1 << (index % 64); diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 86f244d65d..b003cba292 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -23,8 +23,11 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] +#![feature(shared)] +#![feature(collections_range)] +#![feature(collections_bound)] #![feature(nonzero)] #![feature(rustc_private)] #![feature(staged_api)] @@ -44,6 +47,8 @@ extern crate serialize as rustc_serialize; // used by deriving #[cfg(unix)] extern crate libc; +extern crate rustc_i128; + pub use rustc_serialize::hex::ToHex; pub mod array_vec; diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index ed97c3dde5..87048eff5b 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -13,13 +13,14 @@ use std::marker::PhantomData; use std::mem; use blake2b::Blake2bHasher; use rustc_serialize::leb128; +use rustc_i128::{u128,i128}; fn write_unsigned_leb128_to_buf(buf: &mut [u8; 16], value: u64) -> usize { - leb128::write_unsigned_leb128_to(value, |i, v| buf[i] = v) + leb128::write_unsigned_leb128_to(value as u128, |i, v| buf[i] = v) } fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize { - leb128::write_signed_leb128_to(value, |i, v| buf[i] = v) + leb128::write_signed_leb128_to(value as i128, |i, v| buf[i] = v) } /// When hashing something that ends up affecting properties like symbol names. We diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 99d3e155e8..caa5c8b7e0 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -10,7 +10,6 @@ crate-type = ["dylib"] [dependencies] arena = { path = "../libarena" } -flate = { path = "../libflate" } graphviz = { path = "../libgraphviz" } log = { path = "../liblog" } proc_macro_plugin = { path = "../libproc_macro_plugin" } diff --git a/src/librustc_driver/derive_registrar.rs b/src/librustc_driver/derive_registrar.rs index 4db620b2be..6a884bafce 100644 --- a/src/librustc_driver/derive_registrar.rs +++ b/src/librustc_driver/derive_registrar.rs @@ -35,6 +35,9 @@ impl<'v> ItemLikeVisitor<'v> for Finder { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 7a12569266..a7188f6da1 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir; -use rustc::hir::{map as hir_map, FreevarMap, TraitMap}; +use rustc::hir::{self, map as hir_map}; use rustc::hir::lowering::lower_crate; use rustc_data_structures::stable_hasher::StableHasher; use rustc_mir as mir; @@ -20,7 +19,7 @@ use rustc::session::search_paths::PathKind; use rustc::lint; use rustc::middle::{self, dependency_format, stability, reachable}; use rustc::middle::privacy::AccessLevels; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::util::common::time; use rustc::util::nodemap::{NodeSet, NodeMap}; use rustc_borrowck as borrowck; @@ -47,6 +46,7 @@ use std::mem; use std::ffi::{OsString, OsStr}; use std::fs; use std::io::{self, Write}; +use std::iter; use std::path::{Path, PathBuf}; use syntax::{ast, diagnostics, visit}; use syntax::attr; @@ -56,16 +56,10 @@ use syntax::symbol::Symbol; use syntax::util::node_count::NodeCounter; use syntax; use syntax_ext; +use arena::DroplessArena; use derive_registrar; -#[derive(Clone)] -pub struct Resolutions { - pub freevars: FreevarMap, - pub trait_map: TraitMap, - pub maybe_unused_trait_imports: NodeSet, -} - pub fn compile_input(sess: &Session, cstore: &CStore, input: &Input, @@ -131,7 +125,8 @@ pub fn compile_input(sess: &Session, write_out_deps(sess, &outputs, &crate_name); - let arenas = ty::CtxtArenas::new(); + let arena = DroplessArena::new(); + let arenas = GlobalArenas::new(); // Construct the HIR map let hir_map = time(sess.time_passes(), @@ -146,6 +141,7 @@ pub fn compile_input(sess: &Session, sess, outdir, output, + &arena, &arenas, &cstore, &hir_map, @@ -172,6 +168,7 @@ pub fn compile_input(sess: &Session, hir_map, analysis, resolutions, + &arena, &arenas, &crate_name, |tcx, analysis, incremental_hashes_map, result| { @@ -184,7 +181,7 @@ pub fn compile_input(sess: &Session, outdir, output, opt_crate, - tcx.map.krate(), + tcx.hir.krate(), &analysis, tcx, &crate_name); @@ -339,10 +336,11 @@ pub struct CompileState<'a, 'tcx: 'a> { pub output_filenames: Option<&'a OutputFilenames>, pub out_dir: Option<&'a Path>, pub out_file: Option<&'a Path>, - pub arenas: Option<&'tcx ty::CtxtArenas<'tcx>>, + pub arena: Option<&'tcx DroplessArena>, + pub arenas: Option<&'tcx GlobalArenas<'tcx>>, pub expanded_crate: Option<&'a ast::Crate>, pub hir_crate: Option<&'a hir::Crate>, - pub ast_map: Option<&'a hir_map::Map<'tcx>>, + pub hir_map: Option<&'a hir_map::Map<'tcx>>, pub resolutions: Option<&'a Resolutions>, pub analysis: Option<&'a ty::CrateAnalysis<'tcx>>, pub tcx: Option>, @@ -359,6 +357,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { session: session, out_dir: out_dir.as_ref().map(|s| &**s), out_file: None, + arena: None, arenas: None, krate: None, registry: None, @@ -367,7 +366,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { output_filenames: None, expanded_crate: None, hir_crate: None, - ast_map: None, + hir_map: None, resolutions: None, analysis: None, tcx: None, @@ -413,7 +412,8 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { session: &'tcx Session, out_dir: &'a Option, out_file: &'a Option, - arenas: &'tcx ty::CtxtArenas<'tcx>, + arena: &'tcx DroplessArena, + arenas: &'tcx GlobalArenas<'tcx>, cstore: &'a CStore, hir_map: &'a hir_map::Map<'tcx>, analysis: &'a ty::CrateAnalysis<'static>, @@ -424,9 +424,10 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { -> Self { CompileState { crate_name: Some(crate_name), + arena: Some(arena), arenas: Some(arenas), cstore: Some(cstore), - ast_map: Some(hir_map), + hir_map: Some(hir_map), analysis: Some(analysis), resolutions: Some(resolutions), expanded_crate: Some(krate), @@ -600,6 +601,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, } }); + let whitelisted_legacy_custom_derives = registry.take_whitelisted_custom_derives(); let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, mir_passes, .. } = registry; @@ -639,6 +641,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, let resolver_arenas = Resolver::arenas(); let mut resolver = Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas); + resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives; syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote); krate = time(time_passes, "expansion", || { @@ -665,7 +668,10 @@ pub fn phase_2_configure_and_expand(sess: &Session, new_path.push(path); } } - env::set_var("PATH", &env::join_paths(new_path).unwrap()); + env::set_var("PATH", + &env::join_paths(new_path.iter() + .filter(|p| env::join_paths(iter::once(p)).is_ok())) + .unwrap()); } let features = sess.features.borrow(); let cfg = syntax::ext::expand::ExpansionConfig { @@ -675,6 +681,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, should_test: sess.opts.test, ..syntax::ext::expand::ExpansionConfig::default(crate_name.to_string()) }; + let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver); let err_count = ecx.parse_sess.span_diagnostic.err_count(); @@ -734,17 +741,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, "checking for inline asm in case the target doesn't support it", || no_asm::check_crate(sess, &krate)); - // Needs to go *after* expansion to be able to check the results of macro expansion. - time(time_passes, "complete gated feature checking", || { - sess.track_errors(|| { - syntax::feature_gate::check_crate(&krate, - &sess.parse_sess, - &sess.features.borrow(), - &attributes, - sess.opts.unstable_features); - }) - })?; - time(sess.time_passes(), "early lint checks", || lint::check_ast_crate(sess, &krate)); @@ -762,6 +758,17 @@ pub fn phase_2_configure_and_expand(sess: &Session, Ok(()) })?; + // Needs to go *after* expansion to be able to check the results of macro expansion. + time(time_passes, "complete gated feature checking", || { + sess.track_errors(|| { + syntax::feature_gate::check_crate(&krate, + &sess.parse_sess, + &sess.features.borrow(), + &attributes, + sess.opts.unstable_features); + }) + })?; + // Lower ast -> hir. let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { let hir_crate = lower_crate(sess, &krate, &mut resolver); @@ -805,7 +812,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, hir_map: hir_map::Map<'tcx>, mut analysis: ty::CrateAnalysis<'tcx>, resolutions: Resolutions, - arenas: &'tcx ty::CtxtArenas<'tcx>, + arena: &'tcx DroplessArena, + arenas: &'tcx GlobalArenas<'tcx>, name: &str, f: F) -> Result @@ -863,11 +871,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, TyCtxt::create_and_enter(sess, arenas, - resolutions.trait_map, + arena, + resolutions, named_region_map, hir_map, - resolutions.freevars, - resolutions.maybe_unused_trait_imports, region_map, lang_items, index, @@ -1189,9 +1196,6 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { Some(config::CrateTypeRlib) } - Some(ref n) if *n == "metadata" => { - Some(config::CrateTypeMetadata) - } Some(ref n) if *n == "dylib" => { Some(config::CrateTypeDylib) } @@ -1335,9 +1339,10 @@ pub fn build_output_filenames(input: &Input, .values() .filter(|a| a.is_none()) .count(); - let ofile = if unnamed_output_types > 1 { - sess.warn("ignoring specified output filename because multiple outputs were \ - requested"); + let ofile = if unnamed_output_types > 1 && + sess.opts.output_types.contains_key(&OutputType::Exe) { + sess.warn("ignoring specified output filename for 'link' output because multiple \ + outputs were requested"); None } else { Some(out_file.clone()) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f84622c2f0..7fd4fa44ca 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -21,7 +21,7 @@ #![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/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(box_syntax)] #![feature(libc)] @@ -32,7 +32,6 @@ #![feature(staged_api)] extern crate arena; -extern crate flate; extern crate getopts; extern crate graphviz; extern crate libc; @@ -57,7 +56,6 @@ extern crate serialize; extern crate rustc_llvm as llvm; #[macro_use] extern crate log; -#[macro_use] extern crate syntax; extern crate syntax_ext; extern crate syntax_pos; @@ -82,6 +80,7 @@ use rustc::util::common::time; use serialize::json::ToJson; +use std::any::Any; use std::cmp::max; use std::cmp::Ordering::Equal; use std::default::Default; @@ -455,13 +454,14 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { }; control.after_hir_lowering.callback = box move |state| { pretty::print_after_hir_lowering(state.session, - state.ast_map.unwrap(), + state.hir_map.unwrap(), state.analysis.unwrap(), state.resolutions.unwrap(), state.input, &state.expanded_crate.take().unwrap(), state.crate_name.unwrap(), ppm, + state.arena.unwrap(), state.arenas.unwrap(), opt_uii.clone(), state.out_file); @@ -493,7 +493,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_hir_lowering.stop = Compilation::Stop; } - if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) { + if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe || + i == OutputType::Metadata) { control.after_llvm.stop = Compilation::Stop; } @@ -903,7 +904,7 @@ fn print_flag_list(cmdline_opt: &str, /// should continue, returns a getopts::Matches object parsed from args, /// otherwise returns None. /// -/// The compiler's handling of options is a little complication as it ties into +/// The compiler's handling of options is a little complicated as it ties into /// our stability story, and it's even *more* complicated by historical /// accidents. The current intention of each compiler option is to have one of /// three modes: @@ -1016,15 +1017,34 @@ fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec(f: F) -> Result> + where F: FnOnce() -> R + Send + 'static, + R: Send + 'static, +{ + // Temporarily have stack size set to 16MB to deal with nom-using crates failing + const STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB + + let mut cfg = thread::Builder::new().name("rustc".to_string()); + + // FIXME: Hacks on hacks. If the env is trying to override the stack size + // then *don't* set it explicitly. + if env::var_os("RUST_MIN_STACK").is_none() { + cfg = cfg.stack_size(STACK_SIZE); + } + + let thread = cfg.spawn(f); + thread.unwrap().join() +} + /// Run a procedure which will detect panics in the compiler and print nicer /// error messages rather than just failing the test. /// /// The diagnostic emitter yielded to the procedure should be used for reporting /// errors of the compiler. pub fn monitor(f: F) { - // Temporarily have stack size set to 16MB to deal with nom-using crates failing - const STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB - struct Sink(Arc>>); impl Write for Sink { fn write(&mut self, data: &[u8]) -> io::Result { @@ -1038,20 +1058,12 @@ pub fn monitor(f: F) { let data = Arc::new(Mutex::new(Vec::new())); let err = Sink(data.clone()); - let mut cfg = thread::Builder::new().name("rustc".to_string()); - - // FIXME: Hacks on hacks. If the env is trying to override the stack size - // then *don't* set it explicitly. - if env::var_os("RUST_MIN_STACK").is_none() { - cfg = cfg.stack_size(STACK_SIZE); - } - - let thread = cfg.spawn(move || { - io::set_panic(Some(box err)); - f() - }); + let result = in_rustc_thread(move || { + io::set_panic(Some(box err)); + f() + }); - if let Err(value) = thread.unwrap().join() { + if let Err(value) = result { // Thread panicked without emitting a fatal diagnostic if !value.is::() { let emitter = diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index b055b04372..21fe13997b 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -15,10 +15,9 @@ pub use self::PpSourceMode::*; pub use self::PpMode::*; use self::NodesMatchingUII::*; -use abort_on_err; -use driver::{self, Resolutions}; +use {abort_on_err, driver}; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, GlobalArenas, Resolutions}; use rustc::cfg; use rustc::cfg::graphviz::LabelledCFG; use rustc::dep_graph::DepGraph; @@ -40,6 +39,7 @@ use syntax_pos; use graphviz as dot; +use std::cell::Cell; use std::fs::File; use std::io::{self, Write}; use std::iter; @@ -48,10 +48,12 @@ use std::path::Path; use std::str::FromStr; use rustc::hir::map as hir_map; -use rustc::hir::map::{blocks, NodePrinter}; +use rustc::hir::map::blocks; use rustc::hir; use rustc::hir::print as pprust_hir; +use arena::DroplessArena; + #[derive(Copy, Clone, PartialEq, Debug)] pub enum PpSourceMode { PpmNormal, @@ -165,7 +167,7 @@ impl PpSourceMode { /// Constructs a `PrinterSupport` object and passes it to `f`. fn call_with_pp_support<'tcx, A, B, F>(&self, sess: &'tcx Session, - ast_map: Option<&hir_map::Map<'tcx>>, + hir_map: Option<&hir_map::Map<'tcx>>, payload: B, f: F) -> A @@ -175,7 +177,7 @@ impl PpSourceMode { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { let annotation = NoAnn { sess: sess, - ast_map: ast_map.map(|m| m.clone()), + hir_map: hir_map.map(|m| m.clone()), }; f(&annotation, payload) } @@ -183,14 +185,13 @@ impl PpSourceMode { PpmIdentified | PpmExpandedIdentified => { let annotation = IdentifiedAnnotation { sess: sess, - ast_map: ast_map.map(|m| m.clone()), + hir_map: hir_map.map(|m| m.clone()), }; f(&annotation, payload) } PpmExpandedHygiene => { let annotation = HygieneAnnotation { sess: sess, - ast_map: ast_map.map(|m| m.clone()), }; f(&annotation, payload) } @@ -199,10 +200,11 @@ impl PpSourceMode { } fn call_with_pp_support_hir<'tcx, A, B, F>(&self, sess: &'tcx Session, - ast_map: &hir_map::Map<'tcx>, + hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis<'tcx>, resolutions: &Resolutions, - arenas: &'tcx ty::CtxtArenas<'tcx>, + arena: &'tcx DroplessArena, + arenas: &'tcx GlobalArenas<'tcx>, id: &str, payload: B, f: F) @@ -213,29 +215,34 @@ impl PpSourceMode { PpmNormal => { let annotation = NoAnn { sess: sess, - ast_map: Some(ast_map.clone()), + hir_map: Some(hir_map.clone()), }; - f(&annotation, payload, ast_map.forest.krate()) + f(&annotation, payload, hir_map.forest.krate()) } PpmIdentified => { let annotation = IdentifiedAnnotation { sess: sess, - ast_map: Some(ast_map.clone()), + hir_map: Some(hir_map.clone()), }; - f(&annotation, payload, ast_map.forest.krate()) + f(&annotation, payload, hir_map.forest.krate()) } PpmTyped => { abort_on_err(driver::phase_3_run_analysis_passes(sess, - ast_map.clone(), + hir_map.clone(), analysis.clone(), resolutions.clone(), + arena, arenas, id, |tcx, _, _, _| { - let annotation = TypedAnnotation { tcx: tcx }; + let empty_tables = ty::TypeckTables::empty(); + let annotation = TypedAnnotation { + tcx: tcx, + tables: Cell::new(&empty_tables) + }; let _ignore = tcx.dep_graph.in_ignore(); - f(&annotation, payload, ast_map.forest.krate()) + f(&annotation, payload, hir_map.forest.krate()) }), sess) } @@ -244,15 +251,11 @@ impl PpSourceMode { } } -trait PrinterSupport<'ast>: pprust::PpAnn { +trait PrinterSupport: pprust::PpAnn { /// Provides a uniform interface for re-extracting a reference to a /// `Session` from a value that now owns it. fn sess<'a>(&'a self) -> &'a Session; - /// Provides a uniform interface for re-extracting a reference to an - /// `hir_map::Map` from a value that now owns it. - fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>>; - /// Produces the pretty-print annotation object. /// /// (Rust does not yet support upcasting from a trait object to @@ -260,14 +263,14 @@ trait PrinterSupport<'ast>: pprust::PpAnn { fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn; } -trait HirPrinterSupport<'ast>: pprust_hir::PpAnn { +trait HirPrinterSupport<'hir>: pprust_hir::PpAnn { /// Provides a uniform interface for re-extracting a reference to a /// `Session` from a value that now owns it. fn sess<'a>(&'a self) -> &'a Session; /// Provides a uniform interface for re-extracting a reference to an /// `hir_map::Map` from a value that now owns it. - fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>>; + fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>>; /// Produces the pretty-print annotation object. /// @@ -277,7 +280,7 @@ trait HirPrinterSupport<'ast>: pprust_hir::PpAnn { /// Computes an user-readable representation of a path, if possible. fn node_path(&self, id: ast::NodeId) -> Option { - self.ast_map().and_then(|map| map.def_path_from_id(id)).map(|path| { + self.hir_map().and_then(|map| map.def_path_from_id(id)).map(|path| { path.data .into_iter() .map(|elem| elem.data.to_string()) @@ -287,32 +290,28 @@ trait HirPrinterSupport<'ast>: pprust_hir::PpAnn { } } -struct NoAnn<'ast> { - sess: &'ast Session, - ast_map: Option>, +struct NoAnn<'hir> { + sess: &'hir Session, + hir_map: Option>, } -impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> { +impl<'hir> PrinterSupport for NoAnn<'hir> { fn sess<'a>(&'a self) -> &'a Session { self.sess } - fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { - self.ast_map.as_ref() - } - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } } -impl<'ast> HirPrinterSupport<'ast> for NoAnn<'ast> { +impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> { fn sess<'a>(&'a self) -> &'a Session { self.sess } - fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { - self.ast_map.as_ref() + fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> { + self.hir_map.as_ref() } fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { @@ -320,29 +319,34 @@ impl<'ast> HirPrinterSupport<'ast> for NoAnn<'ast> { } } -impl<'ast> pprust::PpAnn for NoAnn<'ast> {} -impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {} +impl<'hir> pprust::PpAnn for NoAnn<'hir> {} +impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> { + fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + -> io::Result<()> { + if let Some(ref map) = self.hir_map { + pprust_hir::PpAnn::nested(map, state, nested) + } else { + Ok(()) + } + } +} -struct IdentifiedAnnotation<'ast> { - sess: &'ast Session, - ast_map: Option>, +struct IdentifiedAnnotation<'hir> { + sess: &'hir Session, + hir_map: Option>, } -impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> { +impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> { fn sess<'a>(&'a self) -> &'a Session { self.sess } - fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { - self.ast_map.as_ref() - } - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self } } -impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { +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(), @@ -379,13 +383,13 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { } } -impl<'ast> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast> { +impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> { fn sess<'a>(&'a self) -> &'a Session { self.sess } - fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { - self.ast_map.as_ref() + fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> { + self.hir_map.as_ref() } fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { @@ -393,7 +397,15 @@ impl<'ast> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast> { } } -impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> { +impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { + fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + -> io::Result<()> { + if let Some(ref map) = self.hir_map { + pprust_hir::PpAnn::nested(map, state, nested) + } else { + Ok(()) + } + } fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(_) => s.popen(), @@ -428,26 +440,21 @@ impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> { } } -struct HygieneAnnotation<'ast> { - sess: &'ast Session, - ast_map: Option>, +struct HygieneAnnotation<'a> { + sess: &'a Session } -impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> { - fn sess<'a>(&'a self) -> &'a Session { +impl<'a> PrinterSupport for HygieneAnnotation<'a> { + fn sess(&self) -> &Session { self.sess } - fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> { - self.ast_map.as_ref() - } - - fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { + fn pp_ann(&self) -> &pprust::PpAnn { self } } -impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { +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, ctxt }) => { @@ -468,6 +475,7 @@ impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { struct TypedAnnotation<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: Cell<&'a ty::TypeckTables<'tcx>>, } impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { @@ -475,8 +483,8 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { &self.tcx.sess } - fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> { - Some(&self.tcx.map) + fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> { + Some(&self.tcx.hir) } fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { @@ -489,6 +497,16 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { } impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { + fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + -> io::Result<()> { + let old_tables = self.tables.get(); + if let pprust_hir::Nested::Body(id) = nested { + self.tables.set(self.tcx.body_tables(id)); + } + pprust_hir::PpAnn::nested(&self.tcx.hir, state, nested)?; + self.tables.set(old_tables); + Ok(()) + } fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(_) => s.popen(), @@ -501,7 +519,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { pp::space(&mut s.s)?; pp::word(&mut s.s, "as")?; pp::space(&mut s.s)?; - pp::word(&mut s.s, &self.tcx.tables().expr_ty(expr).to_string())?; + pp::word(&mut s.s, &self.tables.get().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), @@ -543,12 +561,12 @@ impl FromStr for UserIdentifiedItem { } } -enum NodesMatchingUII<'a, 'ast: 'a> { +enum NodesMatchingUII<'a, 'hir: 'a> { NodesMatchingDirect(option::IntoIter), - NodesMatchingSuffix(hir_map::NodesMatchingSuffix<'a, 'ast>), + NodesMatchingSuffix(hir_map::NodesMatchingSuffix<'a, 'hir>), } -impl<'a, 'ast> Iterator for NodesMatchingUII<'a, 'ast> { +impl<'a, 'hir> Iterator for NodesMatchingUII<'a, 'hir> { type Item = ast::NodeId; fn next(&mut self) -> Option { @@ -567,9 +585,9 @@ impl UserIdentifiedItem { } } - fn all_matching_node_ids<'a, 'ast>(&'a self, - map: &'a hir_map::Map<'ast>) - -> NodesMatchingUII<'a, 'ast> { + fn all_matching_node_ids<'a, 'hir>(&'a self, + map: &'a hir_map::Map<'hir>) + -> NodesMatchingUII<'a, 'hir> { match *self { ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts[..])), @@ -703,13 +721,13 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, let cfg = match code { blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr), blocks::Code::FnLike(fn_like) => { - let body = tcx.map.expr(fn_like.body()); - cfg::CFG::new(tcx, body) + let body = tcx.hir.body(fn_like.body()); + cfg::CFG::new(tcx, &body.value) }, }; let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; let lcfg = LabelledCFG { - ast_map: &tcx.map, + hir_map: &tcx.hir, cfg: &cfg, name: format!("node_{}", code.id()), labelled_edges: labelled_edges, @@ -727,7 +745,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, } blocks::Code::FnLike(fn_like) => { let (bccx, analysis_data) = - borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.to_fn_parts(), &cfg); + borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.body(), &cfg); let lcfg = borrowck_dot::DataflowLabeller { inner: lcfg, @@ -802,7 +820,7 @@ pub fn print_after_parsing(sess: &Session, debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust::print_crate(sess.codemap(), - sess.diagnostic(), + &sess.parse_sess, krate, src_name.to_string(), &mut rdr, @@ -819,14 +837,15 @@ pub fn print_after_parsing(sess: &Session, } pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, - ast_map: &hir_map::Map<'tcx>, + hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis<'tcx>, resolutions: &Resolutions, input: &Input, krate: &ast::Crate, crate_name: &str, ppm: PpMode, - arenas: &'tcx ty::CtxtArenas<'tcx>, + arena: &'tcx DroplessArena, + arenas: &'tcx GlobalArenas<'tcx>, opt_uii: Option, ofile: Option<&Path>) { let dep_graph = DepGraph::new(false); @@ -834,10 +853,11 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, if ppm.needs_analysis() { print_with_analysis(sess, - ast_map, + hir_map, analysis, resolutions, crate_name, + arena, arenas, ppm, opt_uii, @@ -854,11 +874,11 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, (PpmSource(s), _) => { // Silently ignores an identified node. let out: &mut Write = &mut out; - s.call_with_pp_support(sess, Some(ast_map), box out, |annotation, out| { + s.call_with_pp_support(sess, Some(hir_map), box out, |annotation, out| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust::print_crate(sess.codemap(), - sess.diagnostic(), + &sess.parse_sess, krate, src_name.to_string(), &mut rdr, @@ -871,9 +891,10 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, (PpmHir(s), None) => { let out: &mut Write = &mut out; s.call_with_pp_support_hir(sess, - ast_map, + hir_map, analysis, resolutions, + arena, arenas, crate_name, box out, @@ -881,7 +902,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust_hir::print_crate(sess.codemap(), - sess.diagnostic(), + &sess.parse_sess, krate, src_name.to_string(), &mut rdr, @@ -894,27 +915,27 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, (PpmHir(s), Some(uii)) => { let out: &mut Write = &mut out; s.call_with_pp_support_hir(sess, - ast_map, + hir_map, analysis, resolutions, + arena, arenas, crate_name, (out, uii), |annotation, (out, uii), _| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); - let ast_map = annotation.ast_map().expect("--unpretty missing HIR map"); + let hir_map = annotation.hir_map().expect("--unpretty missing HIR map"); let mut pp_state = pprust_hir::State::new_from_input(sess.codemap(), - sess.diagnostic(), + &sess.parse_sess, src_name.to_string(), &mut rdr, box out, annotation.pp_ann(), - true, - Some(ast_map.krate())); - for node_id in uii.all_matching_node_ids(ast_map) { - let node = ast_map.get(node_id); - pp_state.print_node(&node)?; + true); + for node_id in uii.all_matching_node_ids(hir_map) { + let node = hir_map.get(node_id); + pp_state.print_node(node)?; pp::space(&mut pp_state.s)?; let path = annotation.node_path(node_id) .expect("--unpretty missing node paths"); @@ -936,17 +957,18 @@ 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, - ast_map: &hir_map::Map<'tcx>, + hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis<'tcx>, resolutions: &Resolutions, crate_name: &str, - arenas: &'tcx ty::CtxtArenas<'tcx>, + arena: &'tcx DroplessArena, + arenas: &'tcx GlobalArenas<'tcx>, ppm: PpMode, uii: Option, ofile: Option<&Path>) { let nodeid = if let Some(uii) = uii { debug!("pretty printing for {:?}", uii); - Some(uii.to_one_node_id("--unpretty", sess, &ast_map)) + Some(uii.to_one_node_id("--unpretty", sess, &hir_map)) } else { debug!("pretty printing for whole crate"); None @@ -955,16 +977,17 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, let mut out = Vec::new(); abort_on_err(driver::phase_3_run_analysis_passes(sess, - ast_map.clone(), + hir_map.clone(), analysis.clone(), resolutions.clone(), + arena, arenas, crate_name, |tcx, _, _, _| { match ppm { PpmMir | PpmMirCFG => { if let Some(nodeid) = nodeid { - let def_id = tcx.map.local_def_id(nodeid); + let def_id = tcx.hir.local_def_id(nodeid); match ppm { PpmMir => write_mir_pretty(tcx, iter::once(def_id), &mut out), PpmMirCFG => write_mir_graphviz(tcx, iter::once(def_id), &mut out), @@ -989,11 +1012,11 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, let nodeid = nodeid.expect("`pretty flowgraph=..` needs NodeId (int) or unique path \ suffix (b::c::d)"); - let node = tcx.map.find(nodeid).unwrap_or_else(|| { + let node = tcx.hir.find(nodeid).unwrap_or_else(|| { tcx.sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", nodeid)) }); - match blocks::Code::from_node(&tcx.map, nodeid) { + match blocks::Code::from_node(&tcx.hir, nodeid) { Some(code) => { let variants = gather_flowgraph_variants(tcx.sess); @@ -1006,7 +1029,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, got {:?}", node); - tcx.sess.span_fatal(tcx.map.span(nodeid), &message) + tcx.sess.span_fatal(tcx.hir.span(nodeid), &message) } } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 2f8550e5ac..1086d75f02 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -38,6 +38,7 @@ use errors::{Level, DiagnosticBuilder}; use syntax::feature_gate::UnstableFeatures; use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; +use arena::DroplessArena; use rustc::hir; @@ -78,9 +79,9 @@ fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) { impl Emitter for ExpectErrorEmitter { fn emit(&mut self, db: &DiagnosticBuilder) { - remove_message(self, &db.message, db.level); + remove_message(self, &db.message(), db.level); for child in &db.children { - remove_message(self, &child.message, child.level); + remove_message(self, &child.message(), child.level); } } } @@ -128,27 +129,27 @@ fn test_env(source_string: &str, }; let _ignore = dep_graph.in_ignore(); - let arenas = ty::CtxtArenas::new(); - let ast_map = hir_map::map_crate(&mut hir_forest, defs); + let arena = DroplessArena::new(); + let arenas = ty::GlobalArenas::new(); + let hir_map = hir_map::map_crate(&mut hir_forest, defs); // run just enough stuff to build a tcx: - let lang_items = lang_items::collect_language_items(&sess, &ast_map); - let named_region_map = resolve_lifetime::krate(&sess, &ast_map); - let region_map = region::resolve_crate(&sess, &ast_map); - let index = stability::Index::new(&ast_map); + let lang_items = lang_items::collect_language_items(&sess, &hir_map); + let named_region_map = resolve_lifetime::krate(&sess, &hir_map); + let region_map = region::resolve_crate(&sess, &hir_map); + let index = stability::Index::new(&hir_map); TyCtxt::create_and_enter(&sess, &arenas, - resolutions.trait_map, + &arena, + resolutions, named_region_map.unwrap(), - ast_map, - resolutions.freevars, - resolutions.maybe_unused_trait_imports, + hir_map, region_map, lang_items, index, "test_crate", |tcx| { - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { body(Env { infcx: &infcx }); let free_regions = FreeRegionMap::new(); @@ -196,7 +197,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { #[allow(dead_code)] // this seems like it could be useful, even if we don't use it now pub fn lookup_item(&self, names: &[String]) -> ast::NodeId { - return match search_mod(self, &self.infcx.tcx.map.krate().module, 0, names) { + return match search_mod(self, &self.infcx.tcx.hir.krate().module, 0, names) { Some(id) => id, None => { panic!("no item found: `{}`", names.join("::")); @@ -210,7 +211,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { -> Option { assert!(idx < names.len()); for item in &m.item_ids { - let item = this.infcx.tcx.map.expect_item(item.id); + let item = this.infcx.tcx.hir.expect_item(item.id); if item.name.to_string() == names[idx] { return search(this, item, idx + 1, names); } @@ -804,10 +805,9 @@ fn walk_ty() { let uint_ty = tcx.types.usize; let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]); let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]); - let uniq_ty = tcx.mk_box(tup2_ty); - let walked: Vec<_> = uniq_ty.walk().collect(); + let walked: Vec<_> = tup2_ty.walk().collect(); assert_eq!(walked, - [uniq_ty, tup2_ty, tup1_ty, int_ty, uint_ty, int_ty, uint_ty, tup1_ty, int_ty, + [tup2_ty, tup1_ty, int_ty, uint_ty, int_ty, uint_ty, tup1_ty, int_ty, uint_ty, int_ty, uint_ty, uint_ty]); }) } @@ -820,12 +820,10 @@ fn walk_ty_skip_subtree() { let uint_ty = tcx.types.usize; let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]); let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]); - let uniq_ty = tcx.mk_box(tup2_ty); // types we expect to see (in order), plus a boolean saying // whether to skip the subtree. - let mut expected = vec![(uniq_ty, false), - (tup2_ty, false), + let mut expected = vec![(tup2_ty, false), (tup1_ty, false), (int_ty, false), (uint_ty, false), @@ -835,7 +833,7 @@ fn walk_ty_skip_subtree() { (uint_ty, false)]; expected.reverse(); - let mut walker = uniq_ty.walk(); + let mut walker = tup2_ty.walk(); while let Some(t) = walker.next() { debug!("walked to {:?}", t); let (expected_ty, skip) = expected.pop().unwrap(); diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index c92e4d8f5a..2ba1f501a6 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -9,6 +9,4 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] -log = { path = "../liblog" } -serialize = { path = "../libserialize" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 730ca8f9e2..ac39af2018 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -14,12 +14,13 @@ use RenderSpan; use RenderSpan::Suggestion; use std::fmt; use syntax_pos::{MultiSpan, Span}; +use snippet::Style; #[must_use] #[derive(Clone, Debug, PartialEq)] pub struct Diagnostic { pub level: Level, - pub message: String, + pub message: Vec<(String, Style)>, pub code: Option, pub span: MultiSpan, pub children: Vec, @@ -29,7 +30,7 @@ pub struct Diagnostic { #[derive(Clone, Debug, PartialEq)] pub struct SubDiagnostic { pub level: Level, - pub message: String, + pub message: Vec<(String, Style)>, pub span: MultiSpan, pub render_span: Option, } @@ -42,7 +43,7 @@ impl Diagnostic { pub fn new_with_code(level: Level, code: Option, message: &str) -> Self { Diagnostic { level: level, - message: message.to_owned(), + message: vec![(message.to_owned(), Style::NoStyle)], code: code, span: MultiSpan::new(), children: vec![], @@ -96,8 +97,14 @@ impl Diagnostic { -> &mut Self { // For now, just attach these as notes - self.note(&format!("expected {} `{}`{}", label, expected, expected_extra)); - self.note(&format!(" found {} `{}`{}", label, found, found_extra)); + self.highlighted_note(vec![ + (format!("expected {} `", label), Style::NoStyle), + (format!("{}", expected), Style::Highlight), + (format!("`{}\n", expected_extra), Style::NoStyle), + (format!(" found {} `", label), Style::NoStyle), + (format!("{}", found), Style::Highlight), + (format!("`{}", found_extra), Style::NoStyle), + ]); self } @@ -106,6 +113,11 @@ impl Diagnostic { self } + pub fn highlighted_note(&mut self, msg: Vec<(String, Style)>) -> &mut Self { + self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None); + self + } + pub fn span_note>(&mut self, sp: S, msg: &str) @@ -168,7 +180,11 @@ impl Diagnostic { self } - pub fn message(&self) -> &str { + pub fn message(&self) -> String { + self.message.iter().map(|i| i.0.to_owned()).collect::() + } + + pub fn styled_message(&self) -> &Vec<(String, Style)> { &self.message } @@ -193,10 +209,36 @@ impl Diagnostic { render_span: Option) { let sub = SubDiagnostic { level: level, - message: message.to_owned(), + message: vec![(message.to_owned(), Style::NoStyle)], span: span, render_span: render_span, }; self.children.push(sub); } + + /// Convenience function for internal use, clients should use one of the + /// public methods above. + fn sub_with_highlights(&mut self, + level: Level, + message: Vec<(String, Style)>, + span: MultiSpan, + render_span: Option) { + let sub = SubDiagnostic { + level: level, + message: message, + span: span, + render_span: render_span, + }; + self.children.push(sub); + } +} + +impl SubDiagnostic { + pub fn message(&self) -> String { + self.message.iter().map(|i| i.0.to_owned()).collect::() + } + + pub fn styled_message(&self) -> &Vec<(String, Style)> { + &self.message + } } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 808fe504b9..0b0a9e51ca 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -33,7 +33,11 @@ impl Emitter for EmitterWriter { let mut primary_span = db.span.clone(); let mut children = db.children.clone(); self.fix_multispans_in_std_macros(&mut primary_span, &mut children); - self.emit_messages_default(&db.level, &db.message, &db.code, &primary_span, &children); + self.emit_messages_default(&db.level, + &db.styled_message(), + &db.code, + &primary_span, + &children); } } @@ -335,43 +339,56 @@ impl EmitterWriter { // which is...less weird, at least. In fact, in general, if // the rightmost span overlaps with any other span, we should // use the "hang below" version, so we can at least make it - // clear where the span *starts*. + // clear where the span *starts*. There's an exception for this + // logic, when the labels do not have a message: + // + // fn foo(x: u32) { + // -------------- + // | + // x_span + // + // instead of: + // + // fn foo(x: u32) { + // -------------- + // | | + // | x_span + // + // let mut annotations_position = vec![]; let mut line_len = 0; let mut p = 0; let mut ann_iter = annotations.iter().peekable(); while let Some(annotation) = ann_iter.next() { - let is_line = if let AnnotationType::MultilineLine(_) = annotation.annotation_type { - true - } else { - false - }; let peek = ann_iter.peek(); if let Some(next) = peek { - let next_is_line = if let AnnotationType::MultilineLine(_) = next.annotation_type { - true - } else { - false - }; - - if overlaps(next, annotation) && !is_line && !next_is_line { + if overlaps(next, annotation) && !annotation.is_line() && !next.is_line() + && annotation.has_label() + { + // This annotation needs a new line in the output. p += 1; } } annotations_position.push((p, annotation)); if let Some(next) = peek { - let next_is_line = if let AnnotationType::MultilineLine(_) = next.annotation_type { - true - } else { - false - }; let l = if let Some(ref label) = next.label { label.len() + 2 } else { 0 }; - if (overlaps(next, annotation) || next.end_col + l > annotation.start_col) - && !is_line && !next_is_line + if (overlaps(next, annotation) // Do not allow two labels to be in the same line + || next.end_col + l > annotation.start_col) // if they overlap including + // padding, to avoid situations like: + // + // fn foo(x: u32) { + // -------^------ + // | | + // fn_spanx_span + // + && !annotation.is_line() // Do not add a new line if this annotation or the + && !next.is_line() // next are vertical line placeholders. + && annotation.has_label() // Both labels must have some text, otherwise + && next.has_label() // they are not overlapping. { p += 1; } @@ -408,6 +425,17 @@ impl EmitterWriter { return; } + // Write the colunmn separator. + // + // After this we will have: + // + // 2 | fn foo() { + // | + // | + // | + // 3 | + // 4 | } + // | for pos in 0..line_len + 1 { draw_col_separator(buffer, line_offset + pos + 1, width_offset - 2); buffer.putc(line_offset + pos + 1, @@ -468,7 +496,8 @@ impl EmitterWriter { Style::UnderlineSecondary }; let pos = pos + 1; - if pos > 1 { + + if pos > 1 && annotation.has_label() { for p in line_offset + 1..line_offset + pos + 1 { buffer.putc(p, code_offset + annotation.start_col, @@ -546,16 +575,8 @@ impl EmitterWriter { // | | something about `foo` // | something about `fn foo()` annotations_position.sort_by(|a, b| { - fn len(a: &Annotation) -> usize { - // Account for usize underflows - if a.end_col > a.start_col { - a.end_col - a.start_col - } else { - a.start_col - a.end_col - } - } // Decreasing order - len(a.1).cmp(&len(b.1)).reverse() + a.1.len().cmp(&b.1.len()).reverse() }); // Write the underlines. @@ -695,17 +716,93 @@ impl EmitterWriter { if spans_updated { children.push(SubDiagnostic { level: Level::Note, - message: "this error originates in a macro outside of the current crate" - .to_string(), + message: vec![("this error originates in a macro outside of the current crate" + .to_string(), Style::NoStyle)], span: MultiSpan::new(), render_span: None, }); } } + /// Add a left margin to every line but the first, given a padding length and the label being + /// displayed, keeping the provided highlighting. + fn msg_to_buffer(&self, + buffer: &mut StyledBuffer, + msg: &Vec<(String, Style)>, + padding: usize, + label: &str, + override_style: Option